]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/dev/vnic/nicvf_main.c
Update llvm to trunk r256633.
[FreeBSD/FreeBSD.git] / sys / dev / vnic / nicvf_main.c
1 /*
2  * Copyright (C) 2015 Cavium Inc.
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
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24  * SUCH DAMAGE.
25  *
26  * $FreeBSD$
27  *
28  */
29 #include <sys/cdefs.h>
30 __FBSDID("$FreeBSD$");
31
32 #include "opt_inet.h"
33 #include "opt_inet6.h"
34
35 #include <sys/param.h>
36 #include <sys/systm.h>
37 #include <sys/bitset.h>
38 #include <sys/bitstring.h>
39 #include <sys/bus.h>
40 #include <sys/endian.h>
41 #include <sys/kernel.h>
42 #include <sys/malloc.h>
43 #include <sys/mbuf.h>
44 #include <sys/module.h>
45 #include <sys/rman.h>
46 #include <sys/pciio.h>
47 #include <sys/pcpu.h>
48 #include <sys/proc.h>
49 #include <sys/socket.h>
50 #include <sys/sockio.h>
51 #include <sys/stdatomic.h>
52 #include <sys/cpuset.h>
53 #include <sys/lock.h>
54 #include <sys/mutex.h>
55 #include <sys/smp.h>
56 #include <sys/taskqueue.h>
57
58 #include <net/bpf.h>
59 #include <net/ethernet.h>
60 #include <net/if.h>
61 #include <net/if_var.h>
62 #include <net/if_arp.h>
63 #include <net/if_dl.h>
64 #include <net/if_media.h>
65 #include <net/if_types.h>
66 #include <net/if_vlan_var.h>
67
68 #include <netinet/in.h>
69 #include <netinet/if_ether.h>
70
71 #include <dev/pci/pcireg.h>
72 #include <dev/pci/pcivar.h>
73
74 #include <sys/dnv.h>
75 #include <sys/nv.h>
76 #include <sys/iov_schema.h>
77
78 #include <machine/bus.h>
79
80 #include "thunder_bgx.h"
81 #include "nic_reg.h"
82 #include "nic.h"
83 #include "nicvf_queues.h"
84
85 #define VNIC_VF_DEVSTR          "Cavium Thunder NIC Virtual Function Driver"
86
87 #define VNIC_VF_REG_RID         PCIR_BAR(PCI_CFG_REG_BAR_NUM)
88
89 /* Lock for core interface settings */
90 #define NICVF_CORE_LOCK_INIT(nic)                               \
91     sx_init(&(nic)->core_sx, device_get_nameunit((nic)->dev))
92
93 #define NICVF_CORE_LOCK_DESTROY(nic)                            \
94     sx_destroy(&(nic)->core_sx)
95
96 #define NICVF_CORE_LOCK(nic)            sx_xlock(&(nic)->core_sx)
97 #define NICVF_CORE_UNLOCK(nic)          sx_xunlock(&(nic)->core_sx)
98
99 #define NICVF_CORE_LOCK_ASSERT(nic)     sx_assert(&(nic)->core_sx, SA_XLOCKED)
100
101 #define SPEED_10        10
102 #define SPEED_100       100
103 #define SPEED_1000      1000
104 #define SPEED_10000     10000
105 #define SPEED_40000     40000
106
107 MALLOC_DEFINE(M_NICVF, "nicvf", "ThunderX VNIC VF dynamic memory");
108
109 static int nicvf_probe(device_t);
110 static int nicvf_attach(device_t);
111 static int nicvf_detach(device_t);
112
113 static device_method_t nicvf_methods[] = {
114         /* Device interface */
115         DEVMETHOD(device_probe,         nicvf_probe),
116         DEVMETHOD(device_attach,        nicvf_attach),
117         DEVMETHOD(device_detach,        nicvf_detach),
118
119         DEVMETHOD_END,
120 };
121
122 static driver_t nicvf_driver = {
123         "vnic",
124         nicvf_methods,
125         sizeof(struct nicvf),
126 };
127
128 static devclass_t nicvf_devclass;
129
130 DRIVER_MODULE(nicvf, pci, nicvf_driver, nicvf_devclass, 0, 0);
131 MODULE_DEPEND(nicvf, pci, 1, 1, 1);
132 MODULE_DEPEND(nicvf, ether, 1, 1, 1);
133 MODULE_DEPEND(nicvf, vnic_pf, 1, 1, 1);
134
135 static int nicvf_allocate_misc_interrupt(struct nicvf *);
136 static int nicvf_enable_misc_interrupt(struct nicvf *);
137 static int nicvf_allocate_net_interrupts(struct nicvf *);
138 static void nicvf_release_all_interrupts(struct nicvf *);
139 static int nicvf_hw_set_mac_addr(struct nicvf *, uint8_t *);
140 static void nicvf_config_cpi(struct nicvf *);
141 static int nicvf_init_resources(struct nicvf *);
142
143 static int nicvf_setup_ifnet(struct nicvf *);
144 static int nicvf_setup_ifmedia(struct nicvf *);
145 static void nicvf_hw_addr_random(uint8_t *);
146
147 static int nicvf_if_ioctl(struct ifnet *, u_long, caddr_t);
148 static void nicvf_if_init(void *);
149 static void nicvf_if_init_locked(struct nicvf *);
150 static int nicvf_if_transmit(struct ifnet *, struct mbuf *);
151 static void nicvf_if_qflush(struct ifnet *);
152 static uint64_t nicvf_if_getcounter(struct ifnet *, ift_counter);
153
154 static int nicvf_stop_locked(struct nicvf *);
155
156 static void nicvf_media_status(struct ifnet *, struct ifmediareq *);
157 static int nicvf_media_change(struct ifnet *);
158
159 static void nicvf_tick_stats(void *);
160
161 static int
162 nicvf_probe(device_t dev)
163 {
164         uint16_t vendor_id;
165         uint16_t device_id;
166
167         vendor_id = pci_get_vendor(dev);
168         device_id = pci_get_device(dev);
169
170         if (vendor_id != PCI_VENDOR_ID_CAVIUM)
171                 return (ENXIO);
172
173         if (device_id == PCI_DEVICE_ID_THUNDER_NIC_VF ||
174             device_id == PCI_DEVICE_ID_THUNDER_PASS1_NIC_VF) {
175                 device_set_desc(dev, VNIC_VF_DEVSTR);
176                 return (BUS_PROBE_DEFAULT);
177         }
178
179         return (ENXIO);
180 }
181
182 static int
183 nicvf_attach(device_t dev)
184 {
185         struct nicvf *nic;
186         int rid, qcount;
187         int err = 0;
188         uint8_t hwaddr[ETHER_ADDR_LEN];
189         uint8_t zeromac[] = {[0 ... (ETHER_ADDR_LEN - 1)] = 0};
190
191         nic = device_get_softc(dev);
192         nic->dev = dev;
193         nic->pnicvf = nic;
194
195         NICVF_CORE_LOCK_INIT(nic);
196
197         rid = VNIC_VF_REG_RID;
198         nic->reg_base = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
199             RF_ACTIVE);
200         if (nic->reg_base == NULL) {
201                 device_printf(dev, "Could not allocate registers memory\n");
202                 return (ENXIO);
203         }
204
205         qcount = MAX_CMP_QUEUES_PER_QS;
206         nic->max_queues = qcount;
207
208         err = nicvf_set_qset_resources(nic);
209         if (err != 0)
210                 goto err_free_res;
211
212         /* Check if PF is alive and get MAC address for this VF */
213         err = nicvf_allocate_misc_interrupt(nic);
214         if (err != 0)
215                 goto err_free_res;
216
217         NICVF_CORE_LOCK(nic);
218         err = nicvf_enable_misc_interrupt(nic);
219         NICVF_CORE_UNLOCK(nic);
220         if (err != 0)
221                 goto err_release_intr;
222
223         err = nicvf_allocate_net_interrupts(nic);
224         if (err != 0) {
225                 device_printf(dev,
226                     "Could not allocate network interface interrupts\n");
227                 goto err_free_ifnet;
228         }
229
230         /* If no MAC address was obtained we generate random one */
231         if (memcmp(nic->hwaddr, zeromac, ETHER_ADDR_LEN) == 0) {
232                 nicvf_hw_addr_random(hwaddr);
233                 memcpy(nic->hwaddr, hwaddr, ETHER_ADDR_LEN);
234                 NICVF_CORE_LOCK(nic);
235                 nicvf_hw_set_mac_addr(nic, hwaddr);
236                 NICVF_CORE_UNLOCK(nic);
237         }
238
239         /* Configure CPI alorithm */
240         nic->cpi_alg = CPI_ALG_NONE;
241         NICVF_CORE_LOCK(nic);
242         nicvf_config_cpi(nic);
243         NICVF_CORE_UNLOCK(nic);
244
245         err = nicvf_setup_ifnet(nic);
246         if (err != 0) {
247                 device_printf(dev, "Could not set-up ifnet\n");
248                 goto err_release_intr;
249         }
250
251         err = nicvf_setup_ifmedia(nic);
252         if (err != 0) {
253                 device_printf(dev, "Could not set-up ifmedia\n");
254                 goto err_free_ifnet;
255         }
256
257         mtx_init(&nic->stats_mtx, "VNIC stats", NULL, MTX_DEF);
258         callout_init_mtx(&nic->stats_callout, &nic->stats_mtx, 0);
259
260         ether_ifattach(nic->ifp, nic->hwaddr);
261
262         return (0);
263
264 err_free_ifnet:
265         if_free(nic->ifp);
266 err_release_intr:
267         nicvf_release_all_interrupts(nic);
268 err_free_res:
269         bus_release_resource(dev, SYS_RES_MEMORY, rman_get_rid(nic->reg_base),
270             nic->reg_base);
271
272         return (err);
273 }
274
275 static int
276 nicvf_detach(device_t dev)
277 {
278         struct nicvf *nic;
279
280         nic = device_get_softc(dev);
281
282         NICVF_CORE_LOCK(nic);
283         /* Shut down the port and release ring resources */
284         nicvf_stop_locked(nic);
285         /* Release stats lock */
286         mtx_destroy(&nic->stats_mtx);
287         /* Release interrupts */
288         nicvf_release_all_interrupts(nic);
289         /* Release memory resource */
290         if (nic->reg_base != NULL) {
291                 bus_release_resource(dev, SYS_RES_MEMORY,
292                     rman_get_rid(nic->reg_base), nic->reg_base);
293         }
294
295         /* Remove all ifmedia configurations */
296         ifmedia_removeall(&nic->if_media);
297         /* Free this ifnet */
298         if_free(nic->ifp);
299         NICVF_CORE_UNLOCK(nic);
300         /* Finally destroy the lock */
301         NICVF_CORE_LOCK_DESTROY(nic);
302
303         return (0);
304 }
305
306 static void
307 nicvf_hw_addr_random(uint8_t *hwaddr)
308 {
309         uint32_t rnd;
310         uint8_t addr[ETHER_ADDR_LEN];
311
312         /*
313          * Create randomized MAC address.
314          * Set 'bsd' + random 24 low-order bits.
315          */
316         rnd = arc4random() & 0x00ffffff;
317         addr[0] = 'b';
318         addr[1] = 's';
319         addr[2] = 'd';
320         addr[3] = rnd >> 16;
321         addr[4] = rnd >> 8;
322         addr[5] = rnd >> 0;
323
324         memcpy(hwaddr, addr, ETHER_ADDR_LEN);
325 }
326
327 static int
328 nicvf_setup_ifnet(struct nicvf *nic)
329 {
330         struct ifnet *ifp;
331
332         ifp = if_alloc(IFT_ETHER);
333         if (ifp == NULL) {
334                 device_printf(nic->dev, "Could not allocate ifnet structure\n");
335                 return (ENOMEM);
336         }
337
338         nic->ifp = ifp;
339
340         if_setsoftc(ifp, nic);
341         if_initname(ifp, device_get_name(nic->dev), device_get_unit(nic->dev));
342         if_setflags(ifp, IFF_BROADCAST | IFF_SIMPLEX);
343
344         if_settransmitfn(ifp, nicvf_if_transmit);
345         if_setqflushfn(ifp, nicvf_if_qflush);
346         if_setioctlfn(ifp, nicvf_if_ioctl);
347         if_setinitfn(ifp, nicvf_if_init);
348         if_setgetcounterfn(ifp, nicvf_if_getcounter);
349
350         /* Set send queue len to number to default maximum */
351         if_setsendqlen(ifp, IFQ_MAXLEN);
352         if_setsendqready(ifp);
353         if_setmtu(ifp, ETHERMTU);
354
355         if_setcapabilities(ifp, IFCAP_VLAN_MTU);
356 #ifdef DEVICE_POLLING
357 #error "DEVICE_POLLING not supported in VNIC driver yet"
358         if_setcapabilitiesbit(ifp, IFCAP_POLLING, 0);
359 #endif
360         if_setcapenable(ifp, if_getcapabilities(ifp));
361         if_setmtu(ifp, ETHERMTU);
362
363         return (0);
364 }
365
366 static int
367 nicvf_setup_ifmedia(struct nicvf *nic)
368 {
369
370         ifmedia_init(&nic->if_media, IFM_IMASK, nicvf_media_change,
371             nicvf_media_status);
372
373         /*
374          * Advertise availability of all possible connection types,
375          * even though not all are possible at the same time.
376          */
377
378         ifmedia_add(&nic->if_media, (IFM_ETHER | IFM_10_T | IFM_FDX),
379             0, NULL);
380         ifmedia_add(&nic->if_media, (IFM_ETHER | IFM_100_TX | IFM_FDX),
381             0, NULL);
382         ifmedia_add(&nic->if_media, (IFM_ETHER | IFM_1000_T | IFM_FDX),
383             0, NULL);
384         ifmedia_add(&nic->if_media, (IFM_ETHER | IFM_10G_SR | IFM_FDX),
385             0, NULL);
386         ifmedia_add(&nic->if_media, (IFM_ETHER | IFM_40G_CR4 | IFM_FDX),
387             0, NULL);
388         ifmedia_add(&nic->if_media, (IFM_ETHER | IFM_AUTO | IFM_FDX),
389             0, NULL);
390
391         ifmedia_set(&nic->if_media, (IFM_ETHER | IFM_AUTO | IFM_FDX));
392
393         return (0);
394 }
395
396 static int
397 nicvf_if_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
398 {
399         struct nicvf *nic;
400         struct ifreq *ifr;
401         uint32_t flags;
402         int mask, err;
403 #if defined(INET) || defined(INET6)
404         struct ifaddr *ifa;
405         boolean_t avoid_reset = FALSE;
406 #endif
407
408         nic = if_getsoftc(ifp);
409         ifr = (struct ifreq *)data;
410 #if defined(INET) || defined(INET6)
411         ifa = (struct ifaddr *)data;
412 #endif
413         err = 0;
414         switch (cmd) {
415         case SIOCSIFADDR:
416 #ifdef INET
417                 if (ifa->ifa_addr->sa_family == AF_INET)
418                         avoid_reset = TRUE;
419 #endif
420 #ifdef INET6
421                 if (ifa->ifa_addr->sa_family == AF_INET6)
422                         avoid_reset = TRUE;
423 #endif
424
425 #if defined(INET) || defined(INET6)
426                 /* Avoid reinitialization unless it's necessary */
427                 if (avoid_reset) {
428                         ifp->if_flags |= IFF_UP;
429                         if (!(if_getdrvflags(ifp) & IFF_DRV_RUNNING))
430                                 nicvf_if_init(nic);
431 #ifdef INET
432                         if (!(if_getflags(ifp) & IFF_NOARP))
433                                 arp_ifinit(ifp, ifa);
434 #endif
435
436                         return (0);
437                 }
438 #endif
439                 err = ether_ioctl(ifp, cmd, data);
440                 break;
441         case SIOCSIFMTU:
442                 /*
443                  * ARM64TODO: Needs to be implemented.
444                  * Currently ETHERMTU is set by default.
445                  */
446                 err = ether_ioctl(ifp, cmd, data);
447                 break;
448         case SIOCSIFFLAGS:
449                 NICVF_CORE_LOCK(nic);
450                 if (if_getflags(ifp) & IFF_UP) {
451                         if (if_getdrvflags(ifp) & IFF_DRV_RUNNING) {
452                                 flags = ifp->if_flags ^ nic->if_flags;
453                                 if ((nic->if_flags & ifp->if_flags) &
454                                     IFF_PROMISC) {
455                                         /* Change promiscous mode */
456 #if 0
457                                         /* ARM64TODO */
458                                         nicvf_set_promiscous(nic);
459 #endif
460                                 }
461
462                                 if ((nic->if_flags ^ ifp->if_flags) &
463                                     IFF_ALLMULTI) {
464                                         /* Change multicasting settings */
465 #if 0
466                                         /* ARM64TODO */
467                                         nicvf_set_multicast(nic);
468 #endif
469                                 }
470                         } else {
471                                 nicvf_if_init_locked(nic);
472                         }
473                 } else if (if_getdrvflags(ifp) & IFF_DRV_RUNNING)
474                         nicvf_stop_locked(nic);
475
476                 nic->if_flags = ifp->if_flags;
477                 NICVF_CORE_UNLOCK(nic);
478                 break;
479
480         case SIOCADDMULTI:
481         case SIOCDELMULTI:
482                 if (if_getdrvflags(ifp) & IFF_DRV_RUNNING) {
483 #if 0
484                         NICVF_CORE_LOCK(nic);
485                         /* ARM64TODO */
486                         nicvf_set_multicast(nic);
487                         NICVF_CORE_UNLOCK(nic);
488 #endif
489                 }
490                 break;
491
492         case SIOCSIFMEDIA:
493         case SIOCGIFMEDIA:
494                 err = ifmedia_ioctl(ifp, ifr, &nic->if_media, cmd);
495                 break;
496
497         case SIOCSIFCAP:
498                 mask = ifp->if_capenable ^ ifr->ifr_reqcap;
499                 if (mask & IFCAP_VLAN_MTU) {
500                         /* No work to do except acknowledge the change took. */
501                         ifp->if_capenable ^= IFCAP_VLAN_MTU;
502                 }
503                 break;
504
505         default:
506                 err = ether_ioctl(ifp, cmd, data);
507                 break;
508         }
509
510         return (err);
511 }
512
513 static void
514 nicvf_if_init_locked(struct nicvf *nic)
515 {
516         struct queue_set *qs = nic->qs;
517         struct ifnet *ifp;
518         int qidx;
519         int err;
520         caddr_t if_addr;
521
522         NICVF_CORE_LOCK_ASSERT(nic);
523         ifp = nic->ifp;
524
525         if ((if_getdrvflags(ifp) & IFF_DRV_RUNNING) != 0)
526                 nicvf_stop_locked(nic);
527
528         err = nicvf_enable_misc_interrupt(nic);
529         if (err != 0) {
530                 if_printf(ifp, "Could not reenable Mbox interrupt\n");
531                 return;
532         }
533
534         /* Get the latest MAC address */
535         if_addr = if_getlladdr(ifp);
536         /* Update MAC address if changed */
537         if (memcmp(nic->hwaddr, if_addr, ETHER_ADDR_LEN) != 0) {
538                 memcpy(nic->hwaddr, if_addr, ETHER_ADDR_LEN);
539                 nicvf_hw_set_mac_addr(nic, if_addr);
540         }
541
542         /* Initialize the queues */
543         err = nicvf_init_resources(nic);
544         if (err != 0)
545                 goto error;
546
547         /* Make sure queue initialization is written */
548         wmb();
549
550         nicvf_reg_write(nic, NIC_VF_INT, ~0UL);
551         /* Enable Qset err interrupt */
552         nicvf_enable_intr(nic, NICVF_INTR_QS_ERR, 0);
553
554         /* Enable completion queue interrupt */
555         for (qidx = 0; qidx < qs->cq_cnt; qidx++)
556                 nicvf_enable_intr(nic, NICVF_INTR_CQ, qidx);
557
558         /* Enable RBDR threshold interrupt */
559         for (qidx = 0; qidx < qs->rbdr_cnt; qidx++)
560                 nicvf_enable_intr(nic, NICVF_INTR_RBDR, qidx);
561
562         nic->drv_stats.txq_stop = 0;
563         nic->drv_stats.txq_wake = 0;
564
565         /* Activate network interface */
566         if_setdrvflagbits(ifp, IFF_DRV_RUNNING, IFF_DRV_OACTIVE);
567
568         /* Schedule callout to update stats */
569         callout_reset(&nic->stats_callout, hz, nicvf_tick_stats, nic);
570
571         return;
572
573 error:
574         /* Something went very wrong. Disable this ifnet for good */
575         if_setdrvflagbits(ifp, IFF_DRV_OACTIVE, IFF_DRV_RUNNING);
576 }
577
578 static void
579 nicvf_if_init(void *if_softc)
580 {
581         struct nicvf *nic = if_softc;
582
583         NICVF_CORE_LOCK(nic);
584         nicvf_if_init_locked(nic);
585         NICVF_CORE_UNLOCK(nic);
586 }
587
588 static int
589 nicvf_if_transmit(struct ifnet *ifp, struct mbuf *mbuf)
590 {
591         struct nicvf *nic = if_getsoftc(ifp);
592         struct queue_set *qs = nic->qs;
593         struct snd_queue *sq;
594         int qidx;
595         int err = 0;
596
597
598         if (__predict_false(qs == NULL)) {
599                 panic("%s: missing queue set for %s", __func__,
600                     device_get_nameunit(nic->dev));
601         }
602
603         /* Select queue */
604         if (M_HASHTYPE_GET(mbuf) != M_HASHTYPE_NONE)
605                 qidx = mbuf->m_pkthdr.flowid % qs->sq_cnt;
606         else
607                 qidx = curcpu % qs->sq_cnt;
608
609         sq = &qs->sq[qidx];
610
611         if ((if_getdrvflags(ifp) & (IFF_DRV_RUNNING | IFF_DRV_OACTIVE)) !=
612             IFF_DRV_RUNNING) {
613                 if (mbuf != NULL)
614                         err = drbr_enqueue(ifp, sq->br, mbuf);
615                 return (err);
616         }
617
618         if (mbuf != NULL) {
619                 err = drbr_enqueue(ifp, sq->br, mbuf);
620                 if (err != 0)
621                         return (err);
622         }
623
624         taskqueue_enqueue(sq->snd_taskq, &sq->snd_task);
625
626         return (0);
627 }
628
629 static void
630 nicvf_if_qflush(struct ifnet *ifp)
631 {
632         struct nicvf *nic;
633         struct queue_set *qs;
634         struct snd_queue *sq;
635         struct mbuf *mbuf;
636         size_t idx;
637
638         nic = if_getsoftc(ifp);
639         qs = nic->qs;
640
641         for (idx = 0; idx < qs->sq_cnt; idx++) {
642                 sq = &qs->sq[idx];
643                 NICVF_TX_LOCK(sq);
644                 while ((mbuf = buf_ring_dequeue_sc(sq->br)) != NULL)
645                         m_freem(mbuf);
646                 NICVF_TX_UNLOCK(sq);
647         }
648         if_qflush(ifp);
649 }
650
651 static uint64_t
652 nicvf_if_getcounter(struct ifnet *ifp, ift_counter cnt)
653 {
654         struct nicvf *nic;
655         struct nicvf_hw_stats *hw_stats;
656         struct nicvf_drv_stats *drv_stats;
657
658         nic = if_getsoftc(ifp);
659         hw_stats = &nic->hw_stats;
660         drv_stats = &nic->drv_stats;
661
662         switch (cnt) {
663         case IFCOUNTER_IPACKETS:
664                 return (drv_stats->rx_frames_ok);
665         case IFCOUNTER_OPACKETS:
666                 return (drv_stats->tx_frames_ok);
667         case IFCOUNTER_IBYTES:
668                 return (hw_stats->rx_bytes);
669         case IFCOUNTER_OBYTES:
670                 return (hw_stats->tx_bytes_ok);
671         case IFCOUNTER_IMCASTS:
672                 return (hw_stats->rx_mcast_frames);
673         case IFCOUNTER_COLLISIONS:
674                 return (0);
675         case IFCOUNTER_IQDROPS:
676                 return (drv_stats->rx_drops);
677         case IFCOUNTER_OQDROPS:
678                 return (drv_stats->tx_drops);
679         default:
680                 return (if_get_counter_default(ifp, cnt));
681         }
682
683 }
684
685 static void
686 nicvf_media_status(struct ifnet *ifp, struct ifmediareq *ifmr)
687 {
688         struct nicvf *nic = if_getsoftc(ifp);
689
690         NICVF_CORE_LOCK(nic);
691
692         ifmr->ifm_status = IFM_AVALID;
693         ifmr->ifm_active = IFM_ETHER;
694
695         if (nic->link_up) {
696                 /* Device attached to working network */
697                 ifmr->ifm_status |= IFM_ACTIVE;
698         }
699
700         switch (nic->speed) {
701         case SPEED_10:
702                 ifmr->ifm_active |= IFM_10_T;
703                 break;
704         case SPEED_100:
705                 ifmr->ifm_active |= IFM_100_TX;
706                 break;
707         case SPEED_1000:
708                 ifmr->ifm_active |= IFM_1000_T;
709                 break;
710         case SPEED_10000:
711                 ifmr->ifm_active |= IFM_10G_SR;
712                 break;
713         case SPEED_40000:
714                 ifmr->ifm_active |= IFM_40G_CR4;
715                 break;
716         default:
717                 ifmr->ifm_active |= IFM_AUTO;
718                 break;
719         }
720
721         if (nic->duplex)
722                 ifmr->ifm_active |= IFM_FDX;
723         else
724                 ifmr->ifm_active |= IFM_HDX;
725
726         NICVF_CORE_UNLOCK(nic);
727 }
728
729 static int
730 nicvf_media_change(struct ifnet *ifp __unused)
731 {
732
733         return (0);
734 }
735
736 /* Register read/write APIs */
737 void
738 nicvf_reg_write(struct nicvf *nic, bus_space_handle_t offset, uint64_t val)
739 {
740
741         bus_write_8(nic->reg_base, offset, val);
742 }
743
744 uint64_t
745 nicvf_reg_read(struct nicvf *nic, uint64_t offset)
746 {
747
748         return (bus_read_8(nic->reg_base, offset));
749 }
750
751 void
752 nicvf_queue_reg_write(struct nicvf *nic, bus_space_handle_t offset,
753     uint64_t qidx, uint64_t val)
754 {
755
756         bus_write_8(nic->reg_base, offset + (qidx << NIC_Q_NUM_SHIFT), val);
757 }
758
759 uint64_t
760 nicvf_queue_reg_read(struct nicvf *nic, bus_space_handle_t offset,
761     uint64_t qidx)
762 {
763
764         return (bus_read_8(nic->reg_base, offset + (qidx << NIC_Q_NUM_SHIFT)));
765 }
766
767 /* VF -> PF mailbox communication */
768 static void
769 nicvf_write_to_mbx(struct nicvf *nic, union nic_mbx *mbx)
770 {
771         uint64_t *msg = (uint64_t *)mbx;
772
773         nicvf_reg_write(nic, NIC_VF_PF_MAILBOX_0_1 + 0, msg[0]);
774         nicvf_reg_write(nic, NIC_VF_PF_MAILBOX_0_1 + 8, msg[1]);
775 }
776
777 int
778 nicvf_send_msg_to_pf(struct nicvf *nic, union nic_mbx *mbx)
779 {
780         int timeout = NIC_MBOX_MSG_TIMEOUT * 10;
781         int sleep = 2;
782
783         NICVF_CORE_LOCK_ASSERT(nic);
784
785         nic->pf_acked = FALSE;
786         nic->pf_nacked = FALSE;
787
788         nicvf_write_to_mbx(nic, mbx);
789
790         /* Wait for previous message to be acked, timeout 2sec */
791         while (!nic->pf_acked) {
792                 if (nic->pf_nacked)
793                         return (EINVAL);
794
795                 DELAY(sleep * 1000);
796
797                 if (nic->pf_acked)
798                         break;
799                 timeout -= sleep;
800                 if (!timeout) {
801                         device_printf(nic->dev,
802                                    "PF didn't ack to mbox msg %d from VF%d\n",
803                                    (mbx->msg.msg & 0xFF), nic->vf_id);
804
805                         return (EBUSY);
806                 }
807         }
808         return (0);
809 }
810
811 /*
812  * Checks if VF is able to comminicate with PF
813  * and also gets the VNIC number this VF is associated to.
814  */
815 static int
816 nicvf_check_pf_ready(struct nicvf *nic)
817 {
818         union nic_mbx mbx = {};
819
820         mbx.msg.msg = NIC_MBOX_MSG_READY;
821         if (nicvf_send_msg_to_pf(nic, &mbx)) {
822                 device_printf(nic->dev,
823                            "PF didn't respond to READY msg\n");
824                 return 0;
825         }
826
827         return 1;
828 }
829
830 static void
831 nicvf_read_bgx_stats(struct nicvf *nic, struct bgx_stats_msg *bgx)
832 {
833
834         if (bgx->rx)
835                 nic->bgx_stats.rx_stats[bgx->idx] = bgx->stats;
836         else
837                 nic->bgx_stats.tx_stats[bgx->idx] = bgx->stats;
838 }
839
840 static void
841 nicvf_handle_mbx_intr(struct nicvf *nic)
842 {
843         union nic_mbx mbx = {};
844         uint64_t *mbx_data;
845         uint64_t mbx_addr;
846         int i;
847
848         mbx_addr = NIC_VF_PF_MAILBOX_0_1;
849         mbx_data = (uint64_t *)&mbx;
850
851         for (i = 0; i < NIC_PF_VF_MAILBOX_SIZE; i++) {
852                 *mbx_data = nicvf_reg_read(nic, mbx_addr);
853                 mbx_data++;
854                 mbx_addr += sizeof(uint64_t);
855         }
856
857         switch (mbx.msg.msg) {
858         case NIC_MBOX_MSG_READY:
859                 nic->pf_acked = TRUE;
860                 nic->vf_id = mbx.nic_cfg.vf_id & 0x7F;
861                 nic->tns_mode = mbx.nic_cfg.tns_mode & 0x7F;
862                 nic->node = mbx.nic_cfg.node_id;
863                 memcpy(nic->hwaddr, mbx.nic_cfg.mac_addr, ETHER_ADDR_LEN);
864                 nic->loopback_supported = mbx.nic_cfg.loopback_supported;
865                 nic->link_up = FALSE;
866                 nic->duplex = 0;
867                 nic->speed = 0;
868                 break;
869         case NIC_MBOX_MSG_ACK:
870                 nic->pf_acked = TRUE;
871                 break;
872         case NIC_MBOX_MSG_NACK:
873                 nic->pf_nacked = TRUE;
874                 break;
875         case NIC_MBOX_MSG_BGX_STATS:
876                 nicvf_read_bgx_stats(nic, &mbx.bgx_stats);
877                 nic->pf_acked = TRUE;
878                 break;
879         case NIC_MBOX_MSG_BGX_LINK_CHANGE:
880                 nic->pf_acked = TRUE;
881                 nic->link_up = mbx.link_status.link_up;
882                 nic->duplex = mbx.link_status.duplex;
883                 nic->speed = mbx.link_status.speed;
884                 if (nic->link_up) {
885                         if_setbaudrate(nic->ifp, nic->speed * 1000000);
886                         if_link_state_change(nic->ifp, LINK_STATE_UP);
887                 } else {
888                         if_setbaudrate(nic->ifp, 0);
889                         if_link_state_change(nic->ifp, LINK_STATE_DOWN);
890                 }
891                 break;
892         default:
893                 device_printf(nic->dev,
894                            "Invalid message from PF, msg 0x%x\n", mbx.msg.msg);
895                 break;
896         }
897         nicvf_clear_intr(nic, NICVF_INTR_MBOX, 0);
898 }
899
900 static int
901 nicvf_hw_set_mac_addr(struct nicvf *nic, uint8_t *hwaddr)
902 {
903         union nic_mbx mbx = {};
904
905         mbx.mac.msg = NIC_MBOX_MSG_SET_MAC;
906         mbx.mac.vf_id = nic->vf_id;
907         memcpy(mbx.mac.mac_addr, hwaddr, ETHER_ADDR_LEN);
908
909         return (nicvf_send_msg_to_pf(nic, &mbx));
910 }
911
912 static void
913 nicvf_config_cpi(struct nicvf *nic)
914 {
915         union nic_mbx mbx = {};
916
917         mbx.cpi_cfg.msg = NIC_MBOX_MSG_CPI_CFG;
918         mbx.cpi_cfg.vf_id = nic->vf_id;
919         mbx.cpi_cfg.cpi_alg = nic->cpi_alg;
920         mbx.cpi_cfg.rq_cnt = nic->qs->rq_cnt;
921
922         nicvf_send_msg_to_pf(nic, &mbx);
923 }
924
925 static int
926 nicvf_init_resources(struct nicvf *nic)
927 {
928         int err;
929         union nic_mbx mbx = {};
930
931         mbx.msg.msg = NIC_MBOX_MSG_CFG_DONE;
932
933         /* Enable Qset */
934         nicvf_qset_config(nic, TRUE);
935
936         /* Initialize queues and HW for data transfer */
937         err = nicvf_config_data_transfer(nic, TRUE);
938         if (err) {
939                 device_printf(nic->dev,
940                     "Failed to alloc/config VF's QSet resources\n");
941                 return (err);
942         }
943
944         /* Send VF config done msg to PF */
945         nicvf_write_to_mbx(nic, &mbx);
946
947         return (0);
948 }
949
950 static void
951 nicvf_misc_intr_handler(void *arg)
952 {
953         struct nicvf *nic = (struct nicvf *)arg;
954         uint64_t intr;
955
956         intr = nicvf_reg_read(nic, NIC_VF_INT);
957         /* Check for spurious interrupt */
958         if (!(intr & NICVF_INTR_MBOX_MASK))
959                 return;
960
961         nicvf_handle_mbx_intr(nic);
962 }
963
964 static int
965 nicvf_intr_handler(void *arg)
966 {
967         struct nicvf *nic;
968         struct cmp_queue *cq;
969         int qidx;
970
971         cq = (struct cmp_queue *)arg;
972         nic = cq->nic;
973         qidx = cq->idx;
974
975         /* Disable interrupts */
976         nicvf_disable_intr(nic, NICVF_INTR_CQ, qidx);
977
978         taskqueue_enqueue(cq->cmp_taskq, &cq->cmp_task);
979
980         /* Clear interrupt */
981         nicvf_clear_intr(nic, NICVF_INTR_CQ, qidx);
982
983         return (FILTER_HANDLED);
984 }
985
986 static void
987 nicvf_rbdr_intr_handler(void *arg)
988 {
989         struct nicvf *nic;
990         struct queue_set *qs;
991         struct rbdr *rbdr;
992         int qidx;
993
994         nic = (struct nicvf *)arg;
995
996         /* Disable RBDR interrupt and schedule softirq */
997         for (qidx = 0; qidx < nic->qs->rbdr_cnt; qidx++) {
998                 if (!nicvf_is_intr_enabled(nic, NICVF_INTR_RBDR, qidx))
999                         continue;
1000                 nicvf_disable_intr(nic, NICVF_INTR_RBDR, qidx);
1001
1002                 qs = nic->qs;
1003                 rbdr = &qs->rbdr[qidx];
1004                 taskqueue_enqueue(rbdr->rbdr_taskq, &rbdr->rbdr_task_nowait);
1005                 /* Clear interrupt */
1006                 nicvf_clear_intr(nic, NICVF_INTR_RBDR, qidx);
1007         }
1008 }
1009
1010 static void
1011 nicvf_qs_err_intr_handler(void *arg)
1012 {
1013         struct nicvf *nic = (struct nicvf *)arg;
1014         struct queue_set *qs = nic->qs;
1015
1016         /* Disable Qset err interrupt and schedule softirq */
1017         nicvf_disable_intr(nic, NICVF_INTR_QS_ERR, 0);
1018         taskqueue_enqueue(qs->qs_err_taskq, &qs->qs_err_task);
1019         nicvf_clear_intr(nic, NICVF_INTR_QS_ERR, 0);
1020
1021 }
1022
1023 static int
1024 nicvf_enable_msix(struct nicvf *nic)
1025 {
1026         struct pci_devinfo *dinfo;
1027         int rid, count;
1028         int ret;
1029
1030         dinfo = device_get_ivars(nic->dev);
1031         rid = dinfo->cfg.msix.msix_table_bar;
1032         nic->msix_table_res =
1033             bus_alloc_resource_any(nic->dev, SYS_RES_MEMORY, &rid, RF_ACTIVE);
1034         if (nic->msix_table_res == NULL) {
1035                 device_printf(nic->dev,
1036                     "Could not allocate memory for MSI-X table\n");
1037                 return (ENXIO);
1038         }
1039
1040         count = nic->num_vec = NIC_VF_MSIX_VECTORS;
1041
1042         ret = pci_alloc_msix(nic->dev, &count);
1043         if ((ret != 0) || (count != nic->num_vec)) {
1044                 device_printf(nic->dev,
1045                     "Request for #%d msix vectors failed, error: %d\n",
1046                     nic->num_vec, ret);
1047                 return (ret);
1048         }
1049
1050         nic->msix_enabled = 1;
1051         return (0);
1052 }
1053
1054 static void
1055 nicvf_disable_msix(struct nicvf *nic)
1056 {
1057
1058         if (nic->msix_enabled) {
1059                 pci_release_msi(nic->dev);
1060                 nic->msix_enabled = 0;
1061                 nic->num_vec = 0;
1062         }
1063 }
1064
1065 static void
1066 nicvf_release_all_interrupts(struct nicvf *nic)
1067 {
1068         struct resource *res;
1069         int irq;
1070         int err;
1071
1072         /* Free registered interrupts */
1073         for (irq = 0; irq < nic->num_vec; irq++) {
1074                 res = nic->msix_entries[irq].irq_res;
1075                 if (res == NULL)
1076                         continue;
1077                 /* Teardown interrupt first */
1078                 if (nic->msix_entries[irq].handle != NULL) {
1079                         err = bus_teardown_intr(nic->dev,
1080                             nic->msix_entries[irq].irq_res,
1081                             nic->msix_entries[irq].handle);
1082                         KASSERT(err == 0,
1083                             ("ERROR: Unable to teardown interrupt %d", irq));
1084                         nic->msix_entries[irq].handle = NULL;
1085                 }
1086
1087                 bus_release_resource(nic->dev, SYS_RES_IRQ,
1088                             rman_get_rid(res), nic->msix_entries[irq].irq_res);
1089                 nic->msix_entries[irq].irq_res = NULL;
1090         }
1091         /* Disable MSI-X */
1092         nicvf_disable_msix(nic);
1093 }
1094
1095 /*
1096  * Initialize MSIX vectors and register MISC interrupt.
1097  * Send READY message to PF to check if its alive
1098  */
1099 static int
1100 nicvf_allocate_misc_interrupt(struct nicvf *nic)
1101 {
1102         struct resource *res;
1103         int irq, rid;
1104         int ret = 0;
1105
1106         /* Return if mailbox interrupt is already registered */
1107         if (nic->msix_enabled)
1108                 return (0);
1109
1110         /* Enable MSI-X */
1111         if (nicvf_enable_msix(nic) != 0)
1112                 return (ENXIO);
1113
1114         irq = NICVF_INTR_ID_MISC;
1115         rid = irq + 1;
1116         nic->msix_entries[irq].irq_res = bus_alloc_resource_any(nic->dev,
1117             SYS_RES_IRQ, &rid, (RF_SHAREABLE | RF_ACTIVE));
1118         if (nic->msix_entries[irq].irq_res == NULL) {
1119                 device_printf(nic->dev,
1120                     "Could not allocate Mbox interrupt for VF%d\n",
1121                     device_get_unit(nic->dev));
1122                 return (ENXIO);
1123         }
1124
1125         ret = bus_setup_intr(nic->dev, nic->msix_entries[irq].irq_res,
1126             (INTR_MPSAFE | INTR_TYPE_MISC), NULL, nicvf_misc_intr_handler, nic,
1127             &nic->msix_entries[irq].handle);
1128         if (ret != 0) {
1129                 res = nic->msix_entries[irq].irq_res;
1130                 bus_release_resource(nic->dev, SYS_RES_IRQ,
1131                             rman_get_rid(res), res);
1132                 nic->msix_entries[irq].irq_res = NULL;
1133                 return (ret);
1134         }
1135
1136         return (0);
1137 }
1138
1139 static int
1140 nicvf_enable_misc_interrupt(struct nicvf *nic)
1141 {
1142
1143         /* Enable mailbox interrupt */
1144         nicvf_enable_intr(nic, NICVF_INTR_MBOX, 0);
1145
1146         /* Check if VF is able to communicate with PF */
1147         if (!nicvf_check_pf_ready(nic)) {
1148                 nicvf_disable_intr(nic, NICVF_INTR_MBOX, 0);
1149                 return (ENXIO);
1150         }
1151
1152         return (0);
1153 }
1154
1155 static void
1156 nicvf_release_net_interrupts(struct nicvf *nic)
1157 {
1158         struct resource *res;
1159         int irq;
1160         int err;
1161
1162         for_each_cq_irq(irq) {
1163                 res = nic->msix_entries[irq].irq_res;
1164                 if (res == NULL)
1165                         continue;
1166                 /* Teardown active interrupts first */
1167                 if (nic->msix_entries[irq].handle != NULL) {
1168                         err = bus_teardown_intr(nic->dev,
1169                             nic->msix_entries[irq].irq_res,
1170                             nic->msix_entries[irq].handle);
1171                         KASSERT(err == 0,
1172                             ("ERROR: Unable to teardown CQ interrupt %d",
1173                             (irq - NICVF_INTR_ID_CQ)));
1174                         if (err != 0)
1175                                 continue;
1176                 }
1177
1178                 /* Release resource */
1179                 bus_release_resource(nic->dev, SYS_RES_IRQ, rman_get_rid(res),
1180                     res);
1181                 nic->msix_entries[irq].irq_res = NULL;
1182         }
1183
1184         for_each_rbdr_irq(irq) {
1185                 res = nic->msix_entries[irq].irq_res;
1186                 if (res == NULL)
1187                         continue;
1188                 /* Teardown active interrupts first */
1189                 if (nic->msix_entries[irq].handle != NULL) {
1190                         err = bus_teardown_intr(nic->dev,
1191                             nic->msix_entries[irq].irq_res,
1192                             nic->msix_entries[irq].handle);
1193                         KASSERT(err == 0,
1194                             ("ERROR: Unable to teardown RDBR interrupt %d",
1195                             (irq - NICVF_INTR_ID_RBDR)));
1196                         if (err != 0)
1197                                 continue;
1198                 }
1199
1200                 /* Release resource */
1201                 bus_release_resource(nic->dev, SYS_RES_IRQ, rman_get_rid(res),
1202                     res);
1203                 nic->msix_entries[irq].irq_res = NULL;
1204         }
1205
1206         irq = NICVF_INTR_ID_QS_ERR;
1207         res = nic->msix_entries[irq].irq_res;
1208         if (res != NULL) {
1209                 /* Teardown active interrupts first */
1210                 if (nic->msix_entries[irq].handle != NULL) {
1211                         err = bus_teardown_intr(nic->dev,
1212                             nic->msix_entries[irq].irq_res,
1213                             nic->msix_entries[irq].handle);
1214                         KASSERT(err == 0,
1215                             ("ERROR: Unable to teardown QS Error interrupt %d",
1216                             irq));
1217                         if (err != 0)
1218                                 return;
1219                 }
1220
1221                 /* Release resource */
1222                 bus_release_resource(nic->dev, SYS_RES_IRQ, rman_get_rid(res),
1223                     res);
1224                 nic->msix_entries[irq].irq_res = NULL;
1225         }
1226 }
1227
1228 static int
1229 nicvf_allocate_net_interrupts(struct nicvf *nic)
1230 {
1231         int irq, rid;
1232         int qidx;
1233         int ret = 0;
1234
1235         /* MSI-X must be configured by now */
1236         if (!nic->msix_enabled) {
1237                 device_printf(nic->dev, "Cannot alloacte queue interrups. "
1238                     "MSI-X interrupts disabled.\n");
1239                 return (ENXIO);
1240         }
1241
1242         /* Register CQ interrupts */
1243         for_each_cq_irq(irq) {
1244                 if (irq >= (NICVF_INTR_ID_CQ + nic->qs->cq_cnt))
1245                         break;
1246
1247                 qidx = irq - NICVF_INTR_ID_CQ;
1248                 rid = irq + 1;
1249                 nic->msix_entries[irq].irq_res = bus_alloc_resource_any(nic->dev,
1250                     SYS_RES_IRQ, &rid, (RF_SHAREABLE | RF_ACTIVE));
1251                 if (nic->msix_entries[irq].irq_res == NULL) {
1252                         device_printf(nic->dev,
1253                             "Could not allocate CQ interrupt %d for VF%d\n",
1254                             (irq - NICVF_INTR_ID_CQ), device_get_unit(nic->dev));
1255                         ret = ENXIO;
1256                         goto error;
1257                 }
1258                 ret = bus_setup_intr(nic->dev, nic->msix_entries[irq].irq_res,
1259                     (INTR_MPSAFE | INTR_TYPE_NET), nicvf_intr_handler,
1260                     NULL, &nic->qs->cq[qidx], &nic->msix_entries[irq].handle);
1261                 if (ret != 0) {
1262                         device_printf(nic->dev,
1263                             "Could not setup CQ interrupt %d for VF%d\n",
1264                             (irq - NICVF_INTR_ID_CQ), device_get_unit(nic->dev));
1265                         goto error;
1266                 }
1267         }
1268
1269         /* Register RBDR interrupt */
1270         for_each_rbdr_irq(irq) {
1271                 if (irq >= (NICVF_INTR_ID_RBDR + nic->qs->rbdr_cnt))
1272                         break;
1273
1274                 rid = irq + 1;
1275                 nic->msix_entries[irq].irq_res = bus_alloc_resource_any(nic->dev,
1276                     SYS_RES_IRQ, &rid, (RF_SHAREABLE | RF_ACTIVE));
1277                 if (nic->msix_entries[irq].irq_res == NULL) {
1278                         device_printf(nic->dev,
1279                             "Could not allocate RBDR interrupt %d for VF%d\n",
1280                             (irq - NICVF_INTR_ID_RBDR),
1281                             device_get_unit(nic->dev));
1282                         ret = ENXIO;
1283                         goto error;
1284                 }
1285                 ret = bus_setup_intr(nic->dev, nic->msix_entries[irq].irq_res,
1286                     (INTR_MPSAFE | INTR_TYPE_NET), NULL,
1287                     nicvf_rbdr_intr_handler, nic,
1288                     &nic->msix_entries[irq].handle);
1289                 if (ret != 0) {
1290                         device_printf(nic->dev,
1291                             "Could not setup RBDR interrupt %d for VF%d\n",
1292                             (irq - NICVF_INTR_ID_RBDR),
1293                             device_get_unit(nic->dev));
1294                         goto error;
1295                 }
1296         }
1297
1298         /* Register QS error interrupt */
1299         irq = NICVF_INTR_ID_QS_ERR;
1300         rid = irq + 1;
1301         nic->msix_entries[irq].irq_res = bus_alloc_resource_any(nic->dev,
1302             SYS_RES_IRQ, &rid, (RF_SHAREABLE | RF_ACTIVE));
1303         if (nic->msix_entries[irq].irq_res == NULL) {
1304                 device_printf(nic->dev,
1305                     "Could not allocate QS Error interrupt for VF%d\n",
1306                     device_get_unit(nic->dev));
1307                 ret = ENXIO;
1308                 goto error;
1309         }
1310         ret = bus_setup_intr(nic->dev, nic->msix_entries[irq].irq_res,
1311             (INTR_MPSAFE | INTR_TYPE_NET), NULL, nicvf_qs_err_intr_handler,
1312             nic, &nic->msix_entries[irq].handle);
1313         if (ret != 0) {
1314                 device_printf(nic->dev,
1315                     "Could not setup QS Error interrupt for VF%d\n",
1316                     device_get_unit(nic->dev));
1317                 goto error;
1318         }
1319
1320         return (0);
1321 error:
1322         nicvf_release_net_interrupts(nic);
1323         return (ret);
1324 }
1325
1326 static int
1327 nicvf_stop_locked(struct nicvf *nic)
1328 {
1329         struct ifnet *ifp;
1330         int qidx;
1331         struct queue_set *qs = nic->qs;
1332         union nic_mbx mbx = {};
1333
1334         NICVF_CORE_LOCK_ASSERT(nic);
1335         /* Stop callout. Can block here since holding SX lock */
1336         callout_drain(&nic->stats_callout);
1337
1338         ifp = nic->ifp;
1339
1340         mbx.msg.msg = NIC_MBOX_MSG_SHUTDOWN;
1341         nicvf_send_msg_to_pf(nic, &mbx);
1342
1343         /* Disable RBDR & QS error interrupts */
1344         for (qidx = 0; qidx < qs->rbdr_cnt; qidx++) {
1345                 nicvf_disable_intr(nic, NICVF_INTR_RBDR, qidx);
1346                 nicvf_clear_intr(nic, NICVF_INTR_RBDR, qidx);
1347         }
1348         nicvf_disable_intr(nic, NICVF_INTR_QS_ERR, 0);
1349         nicvf_clear_intr(nic, NICVF_INTR_QS_ERR, 0);
1350
1351         /* Deactivate network interface */
1352         if_setdrvflagbits(ifp, IFF_DRV_OACTIVE, IFF_DRV_RUNNING);
1353
1354         /* Free resources */
1355         nicvf_config_data_transfer(nic, FALSE);
1356
1357         /* Disable HW Qset */
1358         nicvf_qset_config(nic, FALSE);
1359
1360         /* disable mailbox interrupt */
1361         nicvf_disable_intr(nic, NICVF_INTR_MBOX, 0);
1362
1363         return (0);
1364 }
1365
1366 static void
1367 nicvf_update_stats(struct nicvf *nic)
1368 {
1369         int qidx;
1370         struct nicvf_hw_stats *stats = &nic->hw_stats;
1371         struct nicvf_drv_stats *drv_stats = &nic->drv_stats;
1372         struct queue_set *qs = nic->qs;
1373
1374 #define GET_RX_STATS(reg) \
1375     nicvf_reg_read(nic, NIC_VNIC_RX_STAT_0_13 | ((reg) << 3))
1376 #define GET_TX_STATS(reg) \
1377     nicvf_reg_read(nic, NIC_VNIC_TX_STAT_0_4 | ((reg) << 3))
1378
1379         stats->rx_bytes = GET_RX_STATS(RX_OCTS);
1380         stats->rx_ucast_frames = GET_RX_STATS(RX_UCAST);
1381         stats->rx_bcast_frames = GET_RX_STATS(RX_BCAST);
1382         stats->rx_mcast_frames = GET_RX_STATS(RX_MCAST);
1383         stats->rx_fcs_errors = GET_RX_STATS(RX_FCS);
1384         stats->rx_l2_errors = GET_RX_STATS(RX_L2ERR);
1385         stats->rx_drop_red = GET_RX_STATS(RX_RED);
1386         stats->rx_drop_red_bytes = GET_RX_STATS(RX_RED_OCTS);
1387         stats->rx_drop_overrun = GET_RX_STATS(RX_ORUN);
1388         stats->rx_drop_overrun_bytes = GET_RX_STATS(RX_ORUN_OCTS);
1389         stats->rx_drop_bcast = GET_RX_STATS(RX_DRP_BCAST);
1390         stats->rx_drop_mcast = GET_RX_STATS(RX_DRP_MCAST);
1391         stats->rx_drop_l3_bcast = GET_RX_STATS(RX_DRP_L3BCAST);
1392         stats->rx_drop_l3_mcast = GET_RX_STATS(RX_DRP_L3MCAST);
1393
1394         stats->tx_bytes_ok = GET_TX_STATS(TX_OCTS);
1395         stats->tx_ucast_frames_ok = GET_TX_STATS(TX_UCAST);
1396         stats->tx_bcast_frames_ok = GET_TX_STATS(TX_BCAST);
1397         stats->tx_mcast_frames_ok = GET_TX_STATS(TX_MCAST);
1398         stats->tx_drops = GET_TX_STATS(TX_DROP);
1399
1400         drv_stats->tx_frames_ok = stats->tx_ucast_frames_ok +
1401             stats->tx_bcast_frames_ok + stats->tx_mcast_frames_ok;
1402         drv_stats->rx_drops = stats->rx_drop_red + stats->rx_drop_overrun;
1403         drv_stats->tx_drops = stats->tx_drops;
1404
1405         /* Update RQ and SQ stats */
1406         for (qidx = 0; qidx < qs->rq_cnt; qidx++)
1407                 nicvf_update_rq_stats(nic, qidx);
1408         for (qidx = 0; qidx < qs->sq_cnt; qidx++)
1409                 nicvf_update_sq_stats(nic, qidx);
1410 }
1411
1412 static void
1413 nicvf_tick_stats(void *arg)
1414 {
1415         struct nicvf *nic;
1416
1417         nic = (struct nicvf *)arg;
1418
1419         /* Read the statistics */
1420         nicvf_update_stats(nic);
1421
1422         callout_reset(&nic->stats_callout, hz, nicvf_tick_stats, nic);
1423 }