xref: /freebsd/sys/dev/ixgbe/if_ixv.c (revision c58d34dd67a419866ee50f152044e49cecbae261)
1*c58d34ddSKevin Bowling /*****************************************************************************
2758cc3dcSJack F Vogel 
38eb6488eSEric Joyner   Copyright (c) 2001-2017, Intel Corporation
4758cc3dcSJack F Vogel   All rights reserved.
5758cc3dcSJack F Vogel 
6758cc3dcSJack F Vogel   Redistribution and use in source and binary forms, with or without
7758cc3dcSJack F Vogel   modification, are permitted provided that the following conditions are met:
8758cc3dcSJack F Vogel 
9758cc3dcSJack F Vogel    1. Redistributions of source code must retain the above copyright notice,
10758cc3dcSJack F Vogel       this list of conditions and the following disclaimer.
11758cc3dcSJack F Vogel 
12758cc3dcSJack F Vogel    2. Redistributions in binary form must reproduce the above copyright
13758cc3dcSJack F Vogel       notice, this list of conditions and the following disclaimer in the
14758cc3dcSJack F Vogel       documentation and/or other materials provided with the distribution.
15758cc3dcSJack F Vogel 
16758cc3dcSJack F Vogel    3. Neither the name of the Intel Corporation nor the names of its
17758cc3dcSJack F Vogel       contributors may be used to endorse or promote products derived from
18758cc3dcSJack F Vogel       this software without specific prior written permission.
19758cc3dcSJack F Vogel 
20758cc3dcSJack F Vogel   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21758cc3dcSJack F Vogel   AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22758cc3dcSJack F Vogel   IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23758cc3dcSJack F Vogel   ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
24758cc3dcSJack F Vogel   LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25758cc3dcSJack F Vogel   CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26758cc3dcSJack F Vogel   SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27758cc3dcSJack F Vogel   INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28758cc3dcSJack F Vogel   CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29758cc3dcSJack F Vogel   ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30758cc3dcSJack F Vogel   POSSIBILITY OF SUCH DAMAGE.
31758cc3dcSJack F Vogel 
32*c58d34ddSKevin Bowling *****************************************************************************/
33758cc3dcSJack F Vogel 
34758cc3dcSJack F Vogel 
35758cc3dcSJack F Vogel #include "opt_inet.h"
36758cc3dcSJack F Vogel #include "opt_inet6.h"
37236204eeSAndriy Gapon #include "opt_rss.h"
38758cc3dcSJack F Vogel 
39758cc3dcSJack F Vogel #include "ixgbe.h"
40c19c7afeSEric Joyner #include "ifdi_if.h"
41c19c7afeSEric Joyner 
42c19c7afeSEric Joyner #include <net/netmap.h>
43c19c7afeSEric Joyner #include <dev/netmap/netmap_kern.h>
44758cc3dcSJack F Vogel 
458eb6488eSEric Joyner /************************************************************************
46758cc3dcSJack F Vogel  * Driver version
478eb6488eSEric Joyner  ************************************************************************/
4851e23514SMarius Strobl static const char ixv_driver_version[] = "2.0.1-k";
49758cc3dcSJack F Vogel 
508eb6488eSEric Joyner /************************************************************************
51758cc3dcSJack F Vogel  * PCI Device ID Table
52758cc3dcSJack F Vogel  *
53758cc3dcSJack F Vogel  *   Used by probe to select devices to load on
54758cc3dcSJack F Vogel  *   Last field stores an index into ixv_strings
55758cc3dcSJack F Vogel  *   Last entry must be all 0s
56758cc3dcSJack F Vogel  *
57758cc3dcSJack F Vogel  *   { Vendor ID, Device ID, SubVendor ID, SubDevice ID, String Index }
588eb6488eSEric Joyner  ************************************************************************/
5951e23514SMarius Strobl static const pci_vendor_info_t ixv_vendor_info_array[] =
60758cc3dcSJack F Vogel {
61*c58d34ddSKevin Bowling 	PVID(IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82599_VF,
62*c58d34ddSKevin Bowling 	    "Intel(R) X520 82599 Virtual Function"),
63*c58d34ddSKevin Bowling 	PVID(IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X540_VF,
64*c58d34ddSKevin Bowling 	    "Intel(R) X540 Virtual Function"),
65*c58d34ddSKevin Bowling 	PVID(IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X550_VF,
66*c58d34ddSKevin Bowling 	    "Intel(R) X550 Virtual Function"),
67*c58d34ddSKevin Bowling 	PVID(IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X550EM_X_VF,
68*c58d34ddSKevin Bowling 	    "Intel(R) X552 Virtual Function"),
69*c58d34ddSKevin Bowling 	PVID(IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X550EM_A_VF,
70*c58d34ddSKevin Bowling 	    "Intel(R) X553 Virtual Function"),
71758cc3dcSJack F Vogel 	/* required last entry */
72c19c7afeSEric Joyner 	PVID_END
73758cc3dcSJack F Vogel };
74758cc3dcSJack F Vogel 
758eb6488eSEric Joyner /************************************************************************
76758cc3dcSJack F Vogel  * Function prototypes
778eb6488eSEric Joyner  ************************************************************************/
78b1d5caf3SKevin Bowling static void     *ixv_register(device_t);
79b1d5caf3SKevin Bowling static int      ixv_if_attach_pre(if_ctx_t);
80b1d5caf3SKevin Bowling static int      ixv_if_attach_post(if_ctx_t);
81b1d5caf3SKevin Bowling static int      ixv_if_detach(if_ctx_t);
82c19c7afeSEric Joyner 
83b1d5caf3SKevin Bowling static int      ixv_if_rx_queue_intr_enable(if_ctx_t, uint16_t);
84*c58d34ddSKevin Bowling static int      ixv_if_tx_queues_alloc(if_ctx_t, caddr_t *, uint64_t *, int,
85*c58d34ddSKevin Bowling     int);
86*c58d34ddSKevin Bowling static int      ixv_if_rx_queues_alloc(if_ctx_t, caddr_t *, uint64_t *, int,
87*c58d34ddSKevin Bowling     int);
88b1d5caf3SKevin Bowling static void     ixv_if_queues_free(if_ctx_t);
89b1d5caf3SKevin Bowling static void     ixv_identify_hardware(if_ctx_t);
90b1d5caf3SKevin Bowling static void     ixv_init_device_features(struct ixgbe_softc *);
91b1d5caf3SKevin Bowling static int      ixv_allocate_pci_resources(if_ctx_t);
92b1d5caf3SKevin Bowling static void     ixv_free_pci_resources(if_ctx_t);
93b1d5caf3SKevin Bowling static int      ixv_setup_interface(if_ctx_t);
94c19c7afeSEric Joyner static void     ixv_if_media_status(if_ctx_t, struct ifmediareq *);
95b1d5caf3SKevin Bowling static int      ixv_if_media_change(if_ctx_t);
96b1d5caf3SKevin Bowling static void     ixv_if_update_admin_status(if_ctx_t);
97b1d5caf3SKevin Bowling static int      ixv_if_msix_intr_assign(if_ctx_t, int);
98c19c7afeSEric Joyner 
99b1d5caf3SKevin Bowling static int      ixv_if_mtu_set(if_ctx_t, uint32_t);
100b1d5caf3SKevin Bowling static void     ixv_if_init(if_ctx_t);
101b1d5caf3SKevin Bowling static void     ixv_if_local_timer(if_ctx_t, uint16_t);
102b1d5caf3SKevin Bowling static void     ixv_if_stop(if_ctx_t);
103b1d5caf3SKevin Bowling static int      ixv_negotiate_api(struct ixgbe_softc *);
104758cc3dcSJack F Vogel 
105b1d5caf3SKevin Bowling static void     ixv_initialize_transmit_units(if_ctx_t);
106b1d5caf3SKevin Bowling static void     ixv_initialize_receive_units(if_ctx_t);
107b1d5caf3SKevin Bowling static void     ixv_initialize_rss_mapping(struct ixgbe_softc *);
108758cc3dcSJack F Vogel 
109b1d5caf3SKevin Bowling static void     ixv_setup_vlan_support(if_ctx_t);
110b1d5caf3SKevin Bowling static void     ixv_configure_ivars(struct ixgbe_softc *);
111b1d5caf3SKevin Bowling static void     ixv_if_enable_intr(if_ctx_t);
112b1d5caf3SKevin Bowling static void     ixv_if_disable_intr(if_ctx_t);
113b1d5caf3SKevin Bowling static void     ixv_if_multi_set(if_ctx_t);
114758cc3dcSJack F Vogel 
115c19c7afeSEric Joyner static void     ixv_if_register_vlan(if_ctx_t, u16);
116c19c7afeSEric Joyner static void     ixv_if_unregister_vlan(if_ctx_t, u16);
117c19c7afeSEric Joyner 
118c19c7afeSEric Joyner static uint64_t ixv_if_get_counter(if_ctx_t, ift_counter);
119cf150917SEric Joyner static bool	ixv_if_needs_restart(if_ctx_t, enum iflib_restart_event);
120758cc3dcSJack F Vogel 
121b1d5caf3SKevin Bowling static void     ixv_save_stats(struct ixgbe_softc *);
122b1d5caf3SKevin Bowling static void     ixv_init_stats(struct ixgbe_softc *);
123b1d5caf3SKevin Bowling static void     ixv_update_stats(struct ixgbe_softc *);
124b1d5caf3SKevin Bowling static void     ixv_add_stats_sysctls(struct ixgbe_softc *);
125c19c7afeSEric Joyner 
126c19c7afeSEric Joyner static int      ixv_sysctl_debug(SYSCTL_HANDLER_ARGS);
127b1d5caf3SKevin Bowling static void     ixv_set_ivar(struct ixgbe_softc *, u8, u8, s8);
128c19c7afeSEric Joyner 
129c19c7afeSEric Joyner static u8       *ixv_mc_array_itr(struct ixgbe_hw *, u8 **, u32 *);
130758cc3dcSJack F Vogel 
1318eb6488eSEric Joyner /* The MSI-X Interrupt handlers */
132c19c7afeSEric Joyner static int      ixv_msix_que(void *);
133c19c7afeSEric Joyner static int      ixv_msix_mbx(void *);
134758cc3dcSJack F Vogel 
1358eb6488eSEric Joyner /************************************************************************
136758cc3dcSJack F Vogel  * FreeBSD Device Interface Entry Points
1378eb6488eSEric Joyner  ************************************************************************/
138758cc3dcSJack F Vogel static device_method_t ixv_methods[] = {
139758cc3dcSJack F Vogel 	/* Device interface */
140c19c7afeSEric Joyner 	DEVMETHOD(device_register, ixv_register),
141c19c7afeSEric Joyner 	DEVMETHOD(device_probe, iflib_device_probe),
142c19c7afeSEric Joyner 	DEVMETHOD(device_attach, iflib_device_attach),
143c19c7afeSEric Joyner 	DEVMETHOD(device_detach, iflib_device_detach),
144c19c7afeSEric Joyner 	DEVMETHOD(device_shutdown, iflib_device_shutdown),
145758cc3dcSJack F Vogel 	DEVMETHOD_END
146758cc3dcSJack F Vogel };
147758cc3dcSJack F Vogel 
148758cc3dcSJack F Vogel static driver_t ixv_driver = {
149b1d5caf3SKevin Bowling 	"ixv", ixv_methods, sizeof(struct ixgbe_softc),
150758cc3dcSJack F Vogel };
151758cc3dcSJack F Vogel 
152964c2b3aSJohn Baldwin DRIVER_MODULE(ixv, pci, ixv_driver, 0, 0);
153937b0f25SYuri Pankov IFLIB_PNP_INFO(pci, ixv_driver, ixv_vendor_info_array);
154c75f49f7SKonstantin Belousov MODULE_DEPEND(ixv, iflib, 1, 1, 1);
155758cc3dcSJack F Vogel MODULE_DEPEND(ixv, pci, 1, 1, 1);
156758cc3dcSJack F Vogel MODULE_DEPEND(ixv, ether, 1, 1, 1);
157c19c7afeSEric Joyner 
158c19c7afeSEric Joyner static device_method_t ixv_if_methods[] = {
159c19c7afeSEric Joyner 	DEVMETHOD(ifdi_attach_pre, ixv_if_attach_pre),
160c19c7afeSEric Joyner 	DEVMETHOD(ifdi_attach_post, ixv_if_attach_post),
161c19c7afeSEric Joyner 	DEVMETHOD(ifdi_detach, ixv_if_detach),
162c19c7afeSEric Joyner 	DEVMETHOD(ifdi_init, ixv_if_init),
163c19c7afeSEric Joyner 	DEVMETHOD(ifdi_stop, ixv_if_stop),
164c19c7afeSEric Joyner 	DEVMETHOD(ifdi_msix_intr_assign, ixv_if_msix_intr_assign),
165c19c7afeSEric Joyner 	DEVMETHOD(ifdi_intr_enable, ixv_if_enable_intr),
166c19c7afeSEric Joyner 	DEVMETHOD(ifdi_intr_disable, ixv_if_disable_intr),
167c19c7afeSEric Joyner 	DEVMETHOD(ifdi_tx_queue_intr_enable, ixv_if_rx_queue_intr_enable),
168c19c7afeSEric Joyner 	DEVMETHOD(ifdi_rx_queue_intr_enable, ixv_if_rx_queue_intr_enable),
169c19c7afeSEric Joyner 	DEVMETHOD(ifdi_tx_queues_alloc, ixv_if_tx_queues_alloc),
170c19c7afeSEric Joyner 	DEVMETHOD(ifdi_rx_queues_alloc, ixv_if_rx_queues_alloc),
171c19c7afeSEric Joyner 	DEVMETHOD(ifdi_queues_free, ixv_if_queues_free),
172c19c7afeSEric Joyner 	DEVMETHOD(ifdi_update_admin_status, ixv_if_update_admin_status),
173c19c7afeSEric Joyner 	DEVMETHOD(ifdi_multi_set, ixv_if_multi_set),
174c19c7afeSEric Joyner 	DEVMETHOD(ifdi_mtu_set, ixv_if_mtu_set),
175c19c7afeSEric Joyner 	DEVMETHOD(ifdi_media_status, ixv_if_media_status),
176c19c7afeSEric Joyner 	DEVMETHOD(ifdi_media_change, ixv_if_media_change),
177c19c7afeSEric Joyner 	DEVMETHOD(ifdi_timer, ixv_if_local_timer),
178c19c7afeSEric Joyner 	DEVMETHOD(ifdi_vlan_register, ixv_if_register_vlan),
179c19c7afeSEric Joyner 	DEVMETHOD(ifdi_vlan_unregister, ixv_if_unregister_vlan),
180c19c7afeSEric Joyner 	DEVMETHOD(ifdi_get_counter, ixv_if_get_counter),
181cf150917SEric Joyner 	DEVMETHOD(ifdi_needs_restart, ixv_if_needs_restart),
182c19c7afeSEric Joyner 	DEVMETHOD_END
183c19c7afeSEric Joyner };
184c19c7afeSEric Joyner 
185c19c7afeSEric Joyner static driver_t ixv_if_driver = {
186b1d5caf3SKevin Bowling   "ixv_if", ixv_if_methods, sizeof(struct ixgbe_softc)
187c19c7afeSEric Joyner };
188758cc3dcSJack F Vogel 
189758cc3dcSJack F Vogel /*
1908eb6488eSEric Joyner  * TUNEABLE PARAMETERS:
191758cc3dcSJack F Vogel  */
192758cc3dcSJack F Vogel 
193758cc3dcSJack F Vogel /* Flow control setting, default to full */
194758cc3dcSJack F Vogel static int ixv_flow_control = ixgbe_fc_full;
195758cc3dcSJack F Vogel TUNABLE_INT("hw.ixv.flow_control", &ixv_flow_control);
196758cc3dcSJack F Vogel 
197758cc3dcSJack F Vogel /*
198758cc3dcSJack F Vogel  * Header split: this causes the hardware to DMA
199363089d8SPedro F. Giffuni  * the header into a separate mbuf from the payload,
200758cc3dcSJack F Vogel  * it can be a performance win in some workloads, but
201758cc3dcSJack F Vogel  * in others it actually hurts, its off by default.
202758cc3dcSJack F Vogel  */
20379b36ec9SKevin Bowling static int ixv_header_split = false;
204758cc3dcSJack F Vogel TUNABLE_INT("hw.ixv.hdr_split", &ixv_header_split);
205758cc3dcSJack F Vogel 
206c19c7afeSEric Joyner extern struct if_txrx ixgbe_txrx;
207758cc3dcSJack F Vogel 
208c19c7afeSEric Joyner static struct if_shared_ctx ixv_sctx_init = {
209c19c7afeSEric Joyner 	.isc_magic = IFLIB_MAGIC,
210c19c7afeSEric Joyner 	.isc_q_align = PAGE_SIZE,/* max(DBA_ALIGN, PAGE_SIZE) */
2117f87c040SMarius Strobl 	.isc_tx_maxsize = IXGBE_TSO_SIZE + sizeof(struct ether_vlan_header),
212c19c7afeSEric Joyner 	.isc_tx_maxsegsize = PAGE_SIZE,
2137f87c040SMarius Strobl 	.isc_tso_maxsize = IXGBE_TSO_SIZE + sizeof(struct ether_vlan_header),
2147f87c040SMarius Strobl 	.isc_tso_maxsegsize = PAGE_SIZE,
215c19c7afeSEric Joyner 	.isc_rx_maxsize = MJUM16BYTES,
216c19c7afeSEric Joyner 	.isc_rx_nsegments = 1,
217c19c7afeSEric Joyner 	.isc_rx_maxsegsize = MJUM16BYTES,
218c19c7afeSEric Joyner 	.isc_nfl = 1,
219c19c7afeSEric Joyner 	.isc_ntxqs = 1,
220c19c7afeSEric Joyner 	.isc_nrxqs = 1,
221c19c7afeSEric Joyner 	.isc_admin_intrcnt = 1,
222c19c7afeSEric Joyner 	.isc_vendor_info = ixv_vendor_info_array,
223c19c7afeSEric Joyner 	.isc_driver_version = ixv_driver_version,
224c19c7afeSEric Joyner 	.isc_driver = &ixv_if_driver,
225be6bdccfSEric Joyner 	.isc_flags = IFLIB_IS_VF | IFLIB_TSO_INIT_IP,
226c19c7afeSEric Joyner 
227c19c7afeSEric Joyner 	.isc_nrxd_min = {MIN_RXD},
228c19c7afeSEric Joyner 	.isc_ntxd_min = {MIN_TXD},
229c19c7afeSEric Joyner 	.isc_nrxd_max = {MAX_RXD},
230c19c7afeSEric Joyner 	.isc_ntxd_max = {MAX_TXD},
231c19c7afeSEric Joyner 	.isc_nrxd_default = {DEFAULT_RXD},
232c19c7afeSEric Joyner 	.isc_ntxd_default = {DEFAULT_TXD},
233c19c7afeSEric Joyner };
234c19c7afeSEric Joyner 
235c19c7afeSEric Joyner static void *
ixv_register(device_t dev)236c19c7afeSEric Joyner ixv_register(device_t dev)
237c19c7afeSEric Joyner {
238ffe3def9SMark Johnston 	return (&ixv_sctx_init);
239c19c7afeSEric Joyner }
2408eb6488eSEric Joyner 
2418eb6488eSEric Joyner /************************************************************************
242c19c7afeSEric Joyner  * ixv_if_tx_queues_alloc
2438eb6488eSEric Joyner  ************************************************************************/
244758cc3dcSJack F Vogel static int
ixv_if_tx_queues_alloc(if_ctx_t ctx,caddr_t * vaddrs,uint64_t * paddrs,int ntxqs,int ntxqsets)245c19c7afeSEric Joyner ixv_if_tx_queues_alloc(if_ctx_t ctx, caddr_t *vaddrs, uint64_t *paddrs,
246c19c7afeSEric Joyner     int ntxqs, int ntxqsets)
247758cc3dcSJack F Vogel {
248b1d5caf3SKevin Bowling 	struct ixgbe_softc *sc = iflib_get_softc(ctx);
249b1d5caf3SKevin Bowling 	if_softc_ctx_t scctx = sc->shared;
250c19c7afeSEric Joyner 	struct ix_tx_queue *que;
251c19c7afeSEric Joyner 	int i, j, error;
252758cc3dcSJack F Vogel 
253b1d5caf3SKevin Bowling 	MPASS(sc->num_tx_queues == ntxqsets);
254c19c7afeSEric Joyner 	MPASS(ntxqs == 1);
255758cc3dcSJack F Vogel 
256c19c7afeSEric Joyner 	/* Allocate queue structure memory */
257b1d5caf3SKevin Bowling 	sc->tx_queues =
258*c58d34ddSKevin Bowling 	    (struct ix_tx_queue *)malloc(sizeof(struct ix_tx_queue) *
259*c58d34ddSKevin Bowling 	    ntxqsets, M_DEVBUF, M_NOWAIT | M_ZERO);
260b1d5caf3SKevin Bowling 	if (!sc->tx_queues) {
261c19c7afeSEric Joyner 		device_printf(iflib_get_dev(ctx),
262c19c7afeSEric Joyner 		    "Unable to allocate TX ring memory\n");
263c19c7afeSEric Joyner 		return (ENOMEM);
264758cc3dcSJack F Vogel 	}
265758cc3dcSJack F Vogel 
266b1d5caf3SKevin Bowling 	for (i = 0, que = sc->tx_queues; i < ntxqsets; i++, que++) {
267c19c7afeSEric Joyner 		struct tx_ring *txr = &que->txr;
268c19c7afeSEric Joyner 
269c19c7afeSEric Joyner 		txr->me = i;
270b1d5caf3SKevin Bowling 		txr->sc =  que->sc = sc;
271c19c7afeSEric Joyner 
272c19c7afeSEric Joyner 		/* Allocate report status array */
273*c58d34ddSKevin Bowling 		if (!(txr->tx_rsq = (qidx_t *)malloc(sizeof(qidx_t) *
274*c58d34ddSKevin Bowling 		    scctx->isc_ntxd[0], M_DEVBUF, M_NOWAIT | M_ZERO))) {
275c19c7afeSEric Joyner 			error = ENOMEM;
276c19c7afeSEric Joyner 			goto fail;
277c19c7afeSEric Joyner 		}
278c19c7afeSEric Joyner 		for (j = 0; j < scctx->isc_ntxd[0]; j++)
279c19c7afeSEric Joyner 			txr->tx_rsq[j] = QIDX_INVALID;
280*c58d34ddSKevin Bowling 		/* get virtual and physical address of the hardware queues */
281c19c7afeSEric Joyner 		txr->tail = IXGBE_VFTDT(txr->me);
282c19c7afeSEric Joyner 		txr->tx_base = (union ixgbe_adv_tx_desc *)vaddrs[i*ntxqs];
283c19c7afeSEric Joyner 		txr->tx_paddr = paddrs[i*ntxqs];
284c19c7afeSEric Joyner 
285c19c7afeSEric Joyner 		txr->bytes = 0;
286c19c7afeSEric Joyner 		txr->total_packets = 0;
287c19c7afeSEric Joyner 
288c19c7afeSEric Joyner 	}
289c19c7afeSEric Joyner 
290c19c7afeSEric Joyner 	device_printf(iflib_get_dev(ctx), "allocated for %d queues\n",
291b1d5caf3SKevin Bowling 	    sc->num_tx_queues);
292c19c7afeSEric Joyner 
293c19c7afeSEric Joyner 	return (0);
294c19c7afeSEric Joyner 
295c19c7afeSEric Joyner  fail:
296c19c7afeSEric Joyner 	ixv_if_queues_free(ctx);
297c19c7afeSEric Joyner 
298c19c7afeSEric Joyner 	return (error);
299c19c7afeSEric Joyner } /* ixv_if_tx_queues_alloc */
3008eb6488eSEric Joyner 
3018eb6488eSEric Joyner /************************************************************************
302c19c7afeSEric Joyner  * ixv_if_rx_queues_alloc
303c19c7afeSEric Joyner  ************************************************************************/
304c19c7afeSEric Joyner static int
ixv_if_rx_queues_alloc(if_ctx_t ctx,caddr_t * vaddrs,uint64_t * paddrs,int nrxqs,int nrxqsets)305c19c7afeSEric Joyner ixv_if_rx_queues_alloc(if_ctx_t ctx, caddr_t *vaddrs, uint64_t *paddrs,
306c19c7afeSEric Joyner     int nrxqs, int nrxqsets)
307c19c7afeSEric Joyner {
308b1d5caf3SKevin Bowling 	struct ixgbe_softc *sc = iflib_get_softc(ctx);
309c19c7afeSEric Joyner 	struct ix_rx_queue *que;
310c19c7afeSEric Joyner 	int i, error;
311c19c7afeSEric Joyner 
312b1d5caf3SKevin Bowling 	MPASS(sc->num_rx_queues == nrxqsets);
313c19c7afeSEric Joyner 	MPASS(nrxqs == 1);
314c19c7afeSEric Joyner 
315c19c7afeSEric Joyner 	/* Allocate queue structure memory */
316b1d5caf3SKevin Bowling 	sc->rx_queues =
317*c58d34ddSKevin Bowling 	    (struct ix_rx_queue *)malloc(sizeof(struct ix_rx_queue) *
318*c58d34ddSKevin Bowling 	    nrxqsets, M_DEVBUF, M_NOWAIT | M_ZERO);
319b1d5caf3SKevin Bowling 	if (!sc->rx_queues) {
320c19c7afeSEric Joyner 		device_printf(iflib_get_dev(ctx),
321c19c7afeSEric Joyner 		    "Unable to allocate TX ring memory\n");
322c19c7afeSEric Joyner 		error = ENOMEM;
323c19c7afeSEric Joyner 		goto fail;
324c19c7afeSEric Joyner 	}
325c19c7afeSEric Joyner 
326b1d5caf3SKevin Bowling 	for (i = 0, que = sc->rx_queues; i < nrxqsets; i++, que++) {
327c19c7afeSEric Joyner 		struct rx_ring *rxr = &que->rxr;
328c19c7afeSEric Joyner 		rxr->me = i;
329b1d5caf3SKevin Bowling 		rxr->sc = que->sc = sc;
330c19c7afeSEric Joyner 
331c19c7afeSEric Joyner 
332c19c7afeSEric Joyner 		/* get the virtual and physical address of the hw queues */
333c19c7afeSEric Joyner 		rxr->tail = IXGBE_VFRDT(rxr->me);
334c19c7afeSEric Joyner 		rxr->rx_base = (union ixgbe_adv_rx_desc *)vaddrs[i];
335c19c7afeSEric Joyner 		rxr->rx_paddr = paddrs[i*nrxqs];
336c19c7afeSEric Joyner 		rxr->bytes = 0;
337c19c7afeSEric Joyner 		rxr->que = que;
338c19c7afeSEric Joyner 	}
339c19c7afeSEric Joyner 
340c19c7afeSEric Joyner 	device_printf(iflib_get_dev(ctx), "allocated for %d rx queues\n",
341b1d5caf3SKevin Bowling 	    sc->num_rx_queues);
342c19c7afeSEric Joyner 
343c19c7afeSEric Joyner 	return (0);
344c19c7afeSEric Joyner 
345c19c7afeSEric Joyner fail:
346c19c7afeSEric Joyner 	ixv_if_queues_free(ctx);
347c19c7afeSEric Joyner 
348c19c7afeSEric Joyner 	return (error);
349c19c7afeSEric Joyner } /* ixv_if_rx_queues_alloc */
350c19c7afeSEric Joyner 
351c19c7afeSEric Joyner /************************************************************************
352c19c7afeSEric Joyner  * ixv_if_queues_free
353c19c7afeSEric Joyner  ************************************************************************/
354c19c7afeSEric Joyner static void
ixv_if_queues_free(if_ctx_t ctx)355c19c7afeSEric Joyner ixv_if_queues_free(if_ctx_t ctx)
356c19c7afeSEric Joyner {
357b1d5caf3SKevin Bowling 	struct ixgbe_softc *sc = iflib_get_softc(ctx);
358b1d5caf3SKevin Bowling 	struct ix_tx_queue *que = sc->tx_queues;
359c19c7afeSEric Joyner 	int i;
360c19c7afeSEric Joyner 
361c19c7afeSEric Joyner 	if (que == NULL)
362c19c7afeSEric Joyner 		goto free;
363c19c7afeSEric Joyner 
364b1d5caf3SKevin Bowling 	for (i = 0; i < sc->num_tx_queues; i++, que++) {
365c19c7afeSEric Joyner 		struct tx_ring *txr = &que->txr;
366c19c7afeSEric Joyner 		if (txr->tx_rsq == NULL)
367c19c7afeSEric Joyner 			break;
368c19c7afeSEric Joyner 
369c19c7afeSEric Joyner 		free(txr->tx_rsq, M_DEVBUF);
370c19c7afeSEric Joyner 		txr->tx_rsq = NULL;
371c19c7afeSEric Joyner 	}
372b1d5caf3SKevin Bowling 	if (sc->tx_queues != NULL)
373b1d5caf3SKevin Bowling 		free(sc->tx_queues, M_DEVBUF);
374c19c7afeSEric Joyner free:
375b1d5caf3SKevin Bowling 	if (sc->rx_queues != NULL)
376b1d5caf3SKevin Bowling 		free(sc->rx_queues, M_DEVBUF);
377b1d5caf3SKevin Bowling 	sc->tx_queues = NULL;
378b1d5caf3SKevin Bowling 	sc->rx_queues = NULL;
379c19c7afeSEric Joyner } /* ixv_if_queues_free */
380c19c7afeSEric Joyner 
381c19c7afeSEric Joyner /************************************************************************
382c19c7afeSEric Joyner  * ixv_if_attach_pre - Device initialization routine
383758cc3dcSJack F Vogel  *
3848eb6488eSEric Joyner  *   Called when the driver is being loaded.
3858eb6488eSEric Joyner  *   Identifies the type of hardware, allocates all resources
386758cc3dcSJack F Vogel  *   and initializes the hardware.
387758cc3dcSJack F Vogel  *
388758cc3dcSJack F Vogel  *   return 0 on success, positive on failure
3898eb6488eSEric Joyner  ************************************************************************/
390758cc3dcSJack F Vogel static int
ixv_if_attach_pre(if_ctx_t ctx)391c19c7afeSEric Joyner ixv_if_attach_pre(if_ctx_t ctx)
392758cc3dcSJack F Vogel {
393b1d5caf3SKevin Bowling 	struct ixgbe_softc *sc;
394c19c7afeSEric Joyner 	device_t dev;
395c19c7afeSEric Joyner 	if_softc_ctx_t scctx;
396758cc3dcSJack F Vogel 	struct ixgbe_hw *hw;
397758cc3dcSJack F Vogel 	int error = 0;
398758cc3dcSJack F Vogel 
399758cc3dcSJack F Vogel 	INIT_DEBUGOUT("ixv_attach: begin");
400758cc3dcSJack F Vogel 
401b1d5caf3SKevin Bowling 	/* Allocate, clear, and link in our sc structure */
402c19c7afeSEric Joyner 	dev = iflib_get_dev(ctx);
403b1d5caf3SKevin Bowling 	sc = iflib_get_softc(ctx);
404b1d5caf3SKevin Bowling 	sc->dev = dev;
405b1d5caf3SKevin Bowling 	sc->ctx = ctx;
406b1d5caf3SKevin Bowling 	sc->hw.back = sc;
407b1d5caf3SKevin Bowling 	scctx = sc->shared = iflib_get_softc_ctx(ctx);
408b1d5caf3SKevin Bowling 	sc->media = iflib_get_media(ctx);
409b1d5caf3SKevin Bowling 	hw = &sc->hw;
410758cc3dcSJack F Vogel 
411758cc3dcSJack F Vogel 	/* Do base PCI setup - map BAR0 */
412c19c7afeSEric Joyner 	if (ixv_allocate_pci_resources(ctx)) {
413a9ca1c79SSean Bruno 		device_printf(dev, "ixv_allocate_pci_resources() failed!\n");
414758cc3dcSJack F Vogel 		error = ENXIO;
415758cc3dcSJack F Vogel 		goto err_out;
416758cc3dcSJack F Vogel 	}
417758cc3dcSJack F Vogel 
4188eb6488eSEric Joyner 	/* SYSCTL APIs */
4198eb6488eSEric Joyner 	SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev),
4208eb6488eSEric Joyner 	    SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO, "debug",
42120b91f0aSPawel Biernacki 	    CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_NEEDGIANT,
422b1d5caf3SKevin Bowling 	    sc, 0, ixv_sysctl_debug, "I", "Debug Info");
4238eb6488eSEric Joyner 
424c19c7afeSEric Joyner 	/* Determine hardware revision */
425c19c7afeSEric Joyner 	ixv_identify_hardware(ctx);
426b1d5caf3SKevin Bowling 	ixv_init_device_features(sc);
4278eb6488eSEric Joyner 
4288eb6488eSEric Joyner 	/* Initialize the shared code */
4298eb6488eSEric Joyner 	error = ixgbe_init_ops_vf(hw);
4308eb6488eSEric Joyner 	if (error) {
4318eb6488eSEric Joyner 		device_printf(dev, "ixgbe_init_ops_vf() failed!\n");
4328eb6488eSEric Joyner 		error = EIO;
4338eb6488eSEric Joyner 		goto err_out;
4348eb6488eSEric Joyner 	}
4358eb6488eSEric Joyner 
4368eb6488eSEric Joyner 	/* Setup the mailbox */
4378eb6488eSEric Joyner 	ixgbe_init_mbx_params_vf(hw);
4388eb6488eSEric Joyner 
4398eb6488eSEric Joyner 	error = hw->mac.ops.reset_hw(hw);
4408eb6488eSEric Joyner 	if (error == IXGBE_ERR_RESET_FAILED)
4418eb6488eSEric Joyner 		device_printf(dev, "...reset_hw() failure: Reset Failed!\n");
4428eb6488eSEric Joyner 	else if (error)
4438eb6488eSEric Joyner 		device_printf(dev, "...reset_hw() failed with error %d\n",
4448eb6488eSEric Joyner 		    error);
4458eb6488eSEric Joyner 	if (error) {
4468eb6488eSEric Joyner 		error = EIO;
4478eb6488eSEric Joyner 		goto err_out;
4488eb6488eSEric Joyner 	}
4498eb6488eSEric Joyner 
4508eb6488eSEric Joyner 	error = hw->mac.ops.init_hw(hw);
4518eb6488eSEric Joyner 	if (error) {
4528eb6488eSEric Joyner 		device_printf(dev, "...init_hw() failed with error %d\n",
4538eb6488eSEric Joyner 		    error);
4548eb6488eSEric Joyner 		error = EIO;
4558eb6488eSEric Joyner 		goto err_out;
4568eb6488eSEric Joyner 	}
4578eb6488eSEric Joyner 
4588eb6488eSEric Joyner 	/* Negotiate mailbox API version */
459b1d5caf3SKevin Bowling 	error = ixv_negotiate_api(sc);
4608eb6488eSEric Joyner 	if (error) {
461b82c9ba1SEric Joyner 		device_printf(dev,
462b82c9ba1SEric Joyner 		    "Mailbox API negotiation failed during attach!\n");
4638eb6488eSEric Joyner 		goto err_out;
4648eb6488eSEric Joyner 	}
4658eb6488eSEric Joyner 
466a3e719bbSPiotr Pietruszewski 	/* Check if VF was disabled by PF */
467a3e719bbSPiotr Pietruszewski 	error = hw->mac.ops.get_link_state(hw, &sc->link_enabled);
468a3e719bbSPiotr Pietruszewski 	if (error) {
469*c58d34ddSKevin Bowling 		/* PF is not capable of controlling VF state. Enable link. */
470a3e719bbSPiotr Pietruszewski 		sc->link_enabled = true;
471a3e719bbSPiotr Pietruszewski 	}
472a3e719bbSPiotr Pietruszewski 
4738eb6488eSEric Joyner 	/* If no mac address was assigned, make a random one */
4748eb6488eSEric Joyner 	if (!ixv_check_ether_addr(hw->mac.addr)) {
4750e5811a2SKevin Bowling 		ether_gen_addr(iflib_get_ifp(ctx),
4760e5811a2SKevin Bowling 		    (struct ether_addr *)hw->mac.addr);
4770e5811a2SKevin Bowling 		bcopy(hw->mac.addr, hw->mac.perm_addr,
4780e5811a2SKevin Bowling 		    sizeof(hw->mac.perm_addr));
4798eb6488eSEric Joyner 	}
4808eb6488eSEric Joyner 
481c19c7afeSEric Joyner 	/* Most of the iflib initialization... */
4828eb6488eSEric Joyner 
483c19c7afeSEric Joyner 	iflib_set_mac(ctx, hw->mac.addr);
484b1d5caf3SKevin Bowling 	switch (sc->hw.mac.type) {
485c19c7afeSEric Joyner 	case ixgbe_mac_X550_vf:
486c19c7afeSEric Joyner 	case ixgbe_mac_X550EM_x_vf:
487c19c7afeSEric Joyner 	case ixgbe_mac_X550EM_a_vf:
488c19c7afeSEric Joyner 		scctx->isc_ntxqsets_max = scctx->isc_nrxqsets_max = 2;
489c19c7afeSEric Joyner 		break;
490c19c7afeSEric Joyner 	default:
491c19c7afeSEric Joyner 		scctx->isc_ntxqsets_max = scctx->isc_nrxqsets_max = 1;
492758cc3dcSJack F Vogel 	}
493c19c7afeSEric Joyner 	scctx->isc_txqsizes[0] =
494c19c7afeSEric Joyner 	    roundup2(scctx->isc_ntxd[0] * sizeof(union ixgbe_adv_tx_desc) +
495c19c7afeSEric Joyner 	    sizeof(u32), DBA_ALIGN);
496c19c7afeSEric Joyner 	scctx->isc_rxqsizes[0] =
497c19c7afeSEric Joyner 	    roundup2(scctx->isc_nrxd[0] * sizeof(union ixgbe_adv_rx_desc),
498c19c7afeSEric Joyner 	    DBA_ALIGN);
499c19c7afeSEric Joyner 	/* XXX */
500c19c7afeSEric Joyner 	scctx->isc_tx_csum_flags = CSUM_IP | CSUM_TCP | CSUM_UDP | CSUM_TSO |
501c19c7afeSEric Joyner 	    CSUM_IP6_TCP | CSUM_IP6_UDP | CSUM_IP6_TSO;
502c19c7afeSEric Joyner 	scctx->isc_tx_nsegments = IXGBE_82599_SCATTER;
503749597dcSEric Joyner 	scctx->isc_msix_bar = pci_msix_table_bar(dev);
504c19c7afeSEric Joyner 	scctx->isc_tx_tso_segments_max = scctx->isc_tx_nsegments;
505c19c7afeSEric Joyner 	scctx->isc_tx_tso_size_max = IXGBE_TSO_SIZE;
506c19c7afeSEric Joyner 	scctx->isc_tx_tso_segsize_max = PAGE_SIZE;
507c19c7afeSEric Joyner 
508c19c7afeSEric Joyner 	scctx->isc_txrx = &ixgbe_txrx;
509c19c7afeSEric Joyner 
510c19c7afeSEric Joyner 	/*
511c19c7afeSEric Joyner 	 * Tell the upper layer(s) we support everything the PF
512c19c7afeSEric Joyner 	 * driver does except...
513c19c7afeSEric Joyner 	 *   Wake-on-LAN
514c19c7afeSEric Joyner 	 */
5157f87c040SMarius Strobl 	scctx->isc_capabilities = IXGBE_CAPS;
5167f87c040SMarius Strobl 	scctx->isc_capabilities ^= IFCAP_WOL;
5177f87c040SMarius Strobl 	scctx->isc_capenable = scctx->isc_capabilities;
518c19c7afeSEric Joyner 
519c19c7afeSEric Joyner 	INIT_DEBUGOUT("ixv_if_attach_pre: end");
520c19c7afeSEric Joyner 
521c19c7afeSEric Joyner 	return (0);
522c19c7afeSEric Joyner 
523c19c7afeSEric Joyner err_out:
524c19c7afeSEric Joyner 	ixv_free_pci_resources(ctx);
525c19c7afeSEric Joyner 
526c19c7afeSEric Joyner 	return (error);
527c19c7afeSEric Joyner } /* ixv_if_attach_pre */
528c19c7afeSEric Joyner 
529c19c7afeSEric Joyner static int
ixv_if_attach_post(if_ctx_t ctx)530c19c7afeSEric Joyner ixv_if_attach_post(if_ctx_t ctx)
531c19c7afeSEric Joyner {
532b1d5caf3SKevin Bowling 	struct ixgbe_softc *sc = iflib_get_softc(ctx);
533c19c7afeSEric Joyner 	device_t dev = iflib_get_dev(ctx);
534c19c7afeSEric Joyner 	int error = 0;
535758cc3dcSJack F Vogel 
5368eb6488eSEric Joyner 	/* Setup OS specific network interface */
537c19c7afeSEric Joyner 	error = ixv_setup_interface(ctx);
538a9ca1c79SSean Bruno 	if (error) {
539c19c7afeSEric Joyner 		device_printf(dev, "Interface setup failed: %d\n", error);
540c19c7afeSEric Joyner 		goto end;
541a9ca1c79SSean Bruno 	}
542758cc3dcSJack F Vogel 
543758cc3dcSJack F Vogel 	/* Do the stats setup */
544b1d5caf3SKevin Bowling 	ixv_save_stats(sc);
545b1d5caf3SKevin Bowling 	ixv_init_stats(sc);
546b1d5caf3SKevin Bowling 	ixv_add_stats_sysctls(sc);
547758cc3dcSJack F Vogel 
548c19c7afeSEric Joyner end:
549c19c7afeSEric Joyner 	return error;
550c19c7afeSEric Joyner } /* ixv_if_attach_post */
551758cc3dcSJack F Vogel 
5528eb6488eSEric Joyner /************************************************************************
5538eb6488eSEric Joyner  * ixv_detach - Device removal routine
554758cc3dcSJack F Vogel  *
5558eb6488eSEric Joyner  *   Called when the driver is being removed.
5568eb6488eSEric Joyner  *   Stops the adapter and deallocates all the resources
557758cc3dcSJack F Vogel  *   that were allocated for driver operation.
558758cc3dcSJack F Vogel  *
559758cc3dcSJack F Vogel  *   return 0 on success, positive on failure
5608eb6488eSEric Joyner  ************************************************************************/
561758cc3dcSJack F Vogel static int
ixv_if_detach(if_ctx_t ctx)562c19c7afeSEric Joyner ixv_if_detach(if_ctx_t ctx)
563758cc3dcSJack F Vogel {
564758cc3dcSJack F Vogel 	INIT_DEBUGOUT("ixv_detach: begin");
565758cc3dcSJack F Vogel 
566c19c7afeSEric Joyner 	ixv_free_pci_resources(ctx);
5678eb6488eSEric Joyner 
568758cc3dcSJack F Vogel 	return (0);
569c19c7afeSEric Joyner } /* ixv_if_detach */
5708eb6488eSEric Joyner 
5718eb6488eSEric Joyner /************************************************************************
572c19c7afeSEric Joyner  * ixv_if_mtu_set
573c19c7afeSEric Joyner  ************************************************************************/
574c19c7afeSEric Joyner static int
ixv_if_mtu_set(if_ctx_t ctx,uint32_t mtu)575c19c7afeSEric Joyner ixv_if_mtu_set(if_ctx_t ctx, uint32_t mtu)
576c19c7afeSEric Joyner {
577b1d5caf3SKevin Bowling 	struct ixgbe_softc *sc = iflib_get_softc(ctx);
578ff06a8dbSJustin Hibbits 	if_t ifp = iflib_get_ifp(ctx);
579c19c7afeSEric Joyner 	int error = 0;
580c19c7afeSEric Joyner 
581c19c7afeSEric Joyner 	IOCTL_DEBUGOUT("ioctl: SIOCSIFMTU (Set Interface MTU)");
582c19c7afeSEric Joyner 	if (mtu > IXGBE_MAX_FRAME_SIZE - IXGBE_MTU_HDR) {
583c19c7afeSEric Joyner 		error = EINVAL;
584c19c7afeSEric Joyner 	} else {
585ff06a8dbSJustin Hibbits 		if_setmtu(ifp, mtu);
586ff06a8dbSJustin Hibbits 		sc->max_frame_size = if_getmtu(ifp) + IXGBE_MTU_HDR;
587c19c7afeSEric Joyner 	}
588c19c7afeSEric Joyner 
589c19c7afeSEric Joyner 	return error;
590c19c7afeSEric Joyner } /* ixv_if_mtu_set */
591c19c7afeSEric Joyner 
592c19c7afeSEric Joyner /************************************************************************
593c19c7afeSEric Joyner  * ixv_if_init - Init entry point
5948eb6488eSEric Joyner  *
5958eb6488eSEric Joyner  *   Used in two ways: It is used by the stack as an init entry
5968eb6488eSEric Joyner  *   point in network interface structure. It is also used
5978eb6488eSEric Joyner  *   by the driver as a hw/sw initialization routine to get
5988eb6488eSEric Joyner  *   to a consistent state.
5998eb6488eSEric Joyner  *
6008eb6488eSEric Joyner  *   return 0 on success, positive on failure
6018eb6488eSEric Joyner  ************************************************************************/
602c19c7afeSEric Joyner static void
ixv_if_init(if_ctx_t ctx)603c19c7afeSEric Joyner ixv_if_init(if_ctx_t ctx)
6048eb6488eSEric Joyner {
605b1d5caf3SKevin Bowling 	struct ixgbe_softc  *sc = iflib_get_softc(ctx);
606ff06a8dbSJustin Hibbits 	if_t ifp = iflib_get_ifp(ctx);
607c19c7afeSEric Joyner 	device_t dev = iflib_get_dev(ctx);
608b1d5caf3SKevin Bowling 	struct ixgbe_hw *hw = &sc->hw;
6098eb6488eSEric Joyner 	int error = 0;
6108eb6488eSEric Joyner 
611c19c7afeSEric Joyner 	INIT_DEBUGOUT("ixv_if_init: begin");
61279b36ec9SKevin Bowling 	hw->adapter_stopped = false;
6138eb6488eSEric Joyner 	hw->mac.ops.stop_adapter(hw);
6148eb6488eSEric Joyner 
6158eb6488eSEric Joyner 	/* reprogram the RAR[0] in case user changed it. */
6168eb6488eSEric Joyner 	hw->mac.ops.set_rar(hw, 0, hw->mac.addr, 0, IXGBE_RAH_AV);
6178eb6488eSEric Joyner 
6188eb6488eSEric Joyner 	/* Get the latest mac address, User can use a LAA */
619ff06a8dbSJustin Hibbits 	bcopy(if_getlladdr(ifp), hw->mac.addr, IXGBE_ETH_LENGTH_OF_ADDRESS);
6208eb6488eSEric Joyner 	hw->mac.ops.set_rar(hw, 0, hw->mac.addr, 0, 1);
6218eb6488eSEric Joyner 
6228eb6488eSEric Joyner 	/* Reset VF and renegotiate mailbox API version */
6238eb6488eSEric Joyner 	hw->mac.ops.reset_hw(hw);
6247d48aa4cSEric Joyner 	hw->mac.ops.start_hw(hw);
625b1d5caf3SKevin Bowling 	error = ixv_negotiate_api(sc);
626b82c9ba1SEric Joyner 	if (error) {
627b82c9ba1SEric Joyner 		device_printf(dev,
628c19c7afeSEric Joyner 		    "Mailbox API negotiation failed in if_init!\n");
629b82c9ba1SEric Joyner 		return;
630b82c9ba1SEric Joyner 	}
6318eb6488eSEric Joyner 
632c19c7afeSEric Joyner 	ixv_initialize_transmit_units(ctx);
6338eb6488eSEric Joyner 
6348eb6488eSEric Joyner 	/* Setup Multicast table */
635c19c7afeSEric Joyner 	ixv_if_multi_set(ctx);
6368eb6488eSEric Joyner 
637b1d5caf3SKevin Bowling 	sc->rx_mbuf_sz = iflib_get_rx_mbuf_sz(ctx);
6388eb6488eSEric Joyner 
6398eb6488eSEric Joyner 	/* Configure RX settings */
640c19c7afeSEric Joyner 	ixv_initialize_receive_units(ctx);
6418eb6488eSEric Joyner 
6428eb6488eSEric Joyner 	/* Set up VLAN offload and filter */
643c19c7afeSEric Joyner 	ixv_setup_vlan_support(ctx);
6448eb6488eSEric Joyner 
6458eb6488eSEric Joyner 	/* Set up MSI-X routing */
646b1d5caf3SKevin Bowling 	ixv_configure_ivars(sc);
6478eb6488eSEric Joyner 
6488eb6488eSEric Joyner 	/* Set up auto-mask */
6498eb6488eSEric Joyner 	IXGBE_WRITE_REG(hw, IXGBE_VTEIAM, IXGBE_EICS_RTX_QUEUE);
6508eb6488eSEric Joyner 
6518eb6488eSEric Joyner 	/* Set moderation on the Link interrupt */
652b1d5caf3SKevin Bowling 	IXGBE_WRITE_REG(hw, IXGBE_VTEITR(sc->vector), IXGBE_LINK_ITR);
6538eb6488eSEric Joyner 
6548eb6488eSEric Joyner 	/* Stats init */
655b1d5caf3SKevin Bowling 	ixv_init_stats(sc);
6568eb6488eSEric Joyner 
6578eb6488eSEric Joyner 	/* Config/Enable Link */
658a3e719bbSPiotr Pietruszewski 	error = hw->mac.ops.get_link_state(hw, &sc->link_enabled);
659a3e719bbSPiotr Pietruszewski 	if (error) {
660a3e719bbSPiotr Pietruszewski 		/* PF is not capable of controlling VF state. Enable the link. */
661a3e719bbSPiotr Pietruszewski 		sc->link_enabled = true;
662a3e719bbSPiotr Pietruszewski 	} else if (sc->link_enabled == false)
663a3e719bbSPiotr Pietruszewski 		device_printf(dev, "VF is disabled by PF\n");
664a3e719bbSPiotr Pietruszewski 
665b1d5caf3SKevin Bowling 	hw->mac.ops.check_link(hw, &sc->link_speed, &sc->link_up,
66679b36ec9SKevin Bowling 	    false);
6678eb6488eSEric Joyner 
6688eb6488eSEric Joyner 	/* And now turn on interrupts */
669c19c7afeSEric Joyner 	ixv_if_enable_intr(ctx);
6708eb6488eSEric Joyner 
6718eb6488eSEric Joyner 	return;
672c19c7afeSEric Joyner } /* ixv_if_init */
6738eb6488eSEric Joyner 
674c19c7afeSEric Joyner /************************************************************************
675c19c7afeSEric Joyner  * ixv_enable_queue
676c19c7afeSEric Joyner  ************************************************************************/
6778eb6488eSEric Joyner static inline void
ixv_enable_queue(struct ixgbe_softc * sc,u32 vector)678b1d5caf3SKevin Bowling ixv_enable_queue(struct ixgbe_softc *sc, u32 vector)
6798eb6488eSEric Joyner {
680b1d5caf3SKevin Bowling 	struct ixgbe_hw *hw = &sc->hw;
6818eb6488eSEric Joyner 	u32 queue = 1 << vector;
6828eb6488eSEric Joyner 	u32 mask;
6838eb6488eSEric Joyner 
6848eb6488eSEric Joyner 	mask = (IXGBE_EIMS_RTX_QUEUE & queue);
6858eb6488eSEric Joyner 	IXGBE_WRITE_REG(hw, IXGBE_VTEIMS, mask);
6868eb6488eSEric Joyner } /* ixv_enable_queue */
6878eb6488eSEric Joyner 
688c19c7afeSEric Joyner /************************************************************************
689c19c7afeSEric Joyner  * ixv_disable_queue
690c19c7afeSEric Joyner  ************************************************************************/
6918eb6488eSEric Joyner static inline void
ixv_disable_queue(struct ixgbe_softc * sc,u32 vector)692b1d5caf3SKevin Bowling ixv_disable_queue(struct ixgbe_softc *sc, u32 vector)
6938eb6488eSEric Joyner {
694b1d5caf3SKevin Bowling 	struct ixgbe_hw *hw = &sc->hw;
6958eb6488eSEric Joyner 	u64 queue = (u64)(1 << vector);
6968eb6488eSEric Joyner 	u32 mask;
6978eb6488eSEric Joyner 
6988eb6488eSEric Joyner 	mask = (IXGBE_EIMS_RTX_QUEUE & queue);
6998eb6488eSEric Joyner 	IXGBE_WRITE_REG(hw, IXGBE_VTEIMC, mask);
7008eb6488eSEric Joyner } /* ixv_disable_queue */
7018eb6488eSEric Joyner 
7028eb6488eSEric Joyner 
7038eb6488eSEric Joyner /************************************************************************
704c19c7afeSEric Joyner  * ixv_msix_que - MSI-X Queue Interrupt Service routine
7058eb6488eSEric Joyner  ************************************************************************/
706c19c7afeSEric Joyner static int
ixv_msix_que(void * arg)7078eb6488eSEric Joyner ixv_msix_que(void *arg)
7088eb6488eSEric Joyner {
709c19c7afeSEric Joyner 	struct ix_rx_queue *que = arg;
710b1d5caf3SKevin Bowling 	struct ixgbe_softc *sc = que->sc;
7118eb6488eSEric Joyner 
712b1d5caf3SKevin Bowling 	ixv_disable_queue(sc, que->msix);
7138eb6488eSEric Joyner 	++que->irqs;
7148eb6488eSEric Joyner 
715c19c7afeSEric Joyner 	return (FILTER_SCHEDULE_THREAD);
7168eb6488eSEric Joyner } /* ixv_msix_que */
7178eb6488eSEric Joyner 
7188eb6488eSEric Joyner /************************************************************************
7198eb6488eSEric Joyner  * ixv_msix_mbx
7208eb6488eSEric Joyner  ************************************************************************/
721c19c7afeSEric Joyner static int
ixv_msix_mbx(void * arg)7228eb6488eSEric Joyner ixv_msix_mbx(void *arg)
7238eb6488eSEric Joyner {
724b1d5caf3SKevin Bowling 	struct ixgbe_softc *sc = arg;
725b1d5caf3SKevin Bowling 	struct ixgbe_hw *hw = &sc->hw;
7268eb6488eSEric Joyner 	u32 reg;
7278eb6488eSEric Joyner 
728b1d5caf3SKevin Bowling 	++sc->link_irq;
7298eb6488eSEric Joyner 
7308eb6488eSEric Joyner 	/* First get the cause */
7318eb6488eSEric Joyner 	reg = IXGBE_READ_REG(hw, IXGBE_VTEICS);
7328eb6488eSEric Joyner 	/* Clear interrupt with write */
7338eb6488eSEric Joyner 	IXGBE_WRITE_REG(hw, IXGBE_VTEICR, reg);
7348eb6488eSEric Joyner 
7358eb6488eSEric Joyner 	/* Link status change */
7368eb6488eSEric Joyner 	if (reg & IXGBE_EICR_LSC)
737b1d5caf3SKevin Bowling 		iflib_admin_intr_deferred(sc->ctx);
7388eb6488eSEric Joyner 
7398eb6488eSEric Joyner 	IXGBE_WRITE_REG(hw, IXGBE_VTEIMS, IXGBE_EIMS_OTHER);
7408eb6488eSEric Joyner 
741c19c7afeSEric Joyner 	return (FILTER_HANDLED);
7428eb6488eSEric Joyner } /* ixv_msix_mbx */
7438eb6488eSEric Joyner 
7448eb6488eSEric Joyner /************************************************************************
7458eb6488eSEric Joyner  * ixv_media_status - Media Ioctl callback
746758cc3dcSJack F Vogel  *
7478eb6488eSEric Joyner  *   Called whenever the user queries the status of
7488eb6488eSEric Joyner  *   the interface using ifconfig.
7498eb6488eSEric Joyner  ************************************************************************/
7508eb6488eSEric Joyner static void
ixv_if_media_status(if_ctx_t ctx,struct ifmediareq * ifmr)751c19c7afeSEric Joyner ixv_if_media_status(if_ctx_t ctx, struct ifmediareq * ifmr)
7528eb6488eSEric Joyner {
753b1d5caf3SKevin Bowling 	struct ixgbe_softc *sc = iflib_get_softc(ctx);
7548eb6488eSEric Joyner 
7558eb6488eSEric Joyner 	INIT_DEBUGOUT("ixv_media_status: begin");
756c19c7afeSEric Joyner 
757c19c7afeSEric Joyner 	iflib_admin_intr_deferred(ctx);
7588eb6488eSEric Joyner 
7598eb6488eSEric Joyner 	ifmr->ifm_status = IFM_AVALID;
7608eb6488eSEric Joyner 	ifmr->ifm_active = IFM_ETHER;
7618eb6488eSEric Joyner 
762b1d5caf3SKevin Bowling 	if (!sc->link_active)
7638eb6488eSEric Joyner 		return;
7648eb6488eSEric Joyner 
7658eb6488eSEric Joyner 	ifmr->ifm_status |= IFM_ACTIVE;
7668eb6488eSEric Joyner 
767b1d5caf3SKevin Bowling 	switch (sc->link_speed) {
7688eb6488eSEric Joyner 		case IXGBE_LINK_SPEED_1GB_FULL:
7698eb6488eSEric Joyner 			ifmr->ifm_active |= IFM_1000_T | IFM_FDX;
7708eb6488eSEric Joyner 			break;
7718eb6488eSEric Joyner 		case IXGBE_LINK_SPEED_10GB_FULL:
7728eb6488eSEric Joyner 			ifmr->ifm_active |= IFM_10G_T | IFM_FDX;
7738eb6488eSEric Joyner 			break;
7748eb6488eSEric Joyner 		case IXGBE_LINK_SPEED_100_FULL:
7758eb6488eSEric Joyner 			ifmr->ifm_active |= IFM_100_TX | IFM_FDX;
7768eb6488eSEric Joyner 			break;
7778eb6488eSEric Joyner 		case IXGBE_LINK_SPEED_10_FULL:
7788eb6488eSEric Joyner 			ifmr->ifm_active |= IFM_10_T | IFM_FDX;
7798eb6488eSEric Joyner 			break;
7808eb6488eSEric Joyner 	}
781c19c7afeSEric Joyner } /* ixv_if_media_status */
7828eb6488eSEric Joyner 
7838eb6488eSEric Joyner /************************************************************************
784c19c7afeSEric Joyner  * ixv_if_media_change - Media Ioctl callback
785758cc3dcSJack F Vogel  *
7868eb6488eSEric Joyner  *   Called when the user changes speed/duplex using
7878eb6488eSEric Joyner  *   media/mediopt option with ifconfig.
7888eb6488eSEric Joyner  ************************************************************************/
7898eb6488eSEric Joyner static int
ixv_if_media_change(if_ctx_t ctx)790c19c7afeSEric Joyner ixv_if_media_change(if_ctx_t ctx)
7918eb6488eSEric Joyner {
792b1d5caf3SKevin Bowling 	struct ixgbe_softc *sc = iflib_get_softc(ctx);
793c19c7afeSEric Joyner 	struct ifmedia *ifm = iflib_get_media(ctx);
7948eb6488eSEric Joyner 
7958eb6488eSEric Joyner 	INIT_DEBUGOUT("ixv_media_change: begin");
7968eb6488eSEric Joyner 
7978eb6488eSEric Joyner 	if (IFM_TYPE(ifm->ifm_media) != IFM_ETHER)
7988eb6488eSEric Joyner 		return (EINVAL);
7998eb6488eSEric Joyner 
8008eb6488eSEric Joyner 	switch (IFM_SUBTYPE(ifm->ifm_media)) {
8018eb6488eSEric Joyner 	case IFM_AUTO:
8028eb6488eSEric Joyner 		break;
8038eb6488eSEric Joyner 	default:
804b1d5caf3SKevin Bowling 		device_printf(sc->dev, "Only auto media type\n");
8058eb6488eSEric Joyner 		return (EINVAL);
8068eb6488eSEric Joyner 	}
8078eb6488eSEric Joyner 
8088eb6488eSEric Joyner 	return (0);
809c19c7afeSEric Joyner } /* ixv_if_media_change */
8108eb6488eSEric Joyner 
8118eb6488eSEric Joyner 
8128eb6488eSEric Joyner /************************************************************************
813b82c9ba1SEric Joyner  * ixv_negotiate_api
814b82c9ba1SEric Joyner  *
815b82c9ba1SEric Joyner  *   Negotiate the Mailbox API with the PF;
816b82c9ba1SEric Joyner  *   start with the most featured API first.
817b82c9ba1SEric Joyner  ************************************************************************/
818b82c9ba1SEric Joyner static int
ixv_negotiate_api(struct ixgbe_softc * sc)819b1d5caf3SKevin Bowling ixv_negotiate_api(struct ixgbe_softc *sc)
820b82c9ba1SEric Joyner {
821b1d5caf3SKevin Bowling 	struct ixgbe_hw *hw = &sc->hw;
822*c58d34ddSKevin Bowling 	int mbx_api[] = {
823*c58d34ddSKevin Bowling 		ixgbe_mbox_api_12,
824a3e719bbSPiotr Pietruszewski 		ixgbe_mbox_api_11,
825b82c9ba1SEric Joyner 		ixgbe_mbox_api_10,
826*c58d34ddSKevin Bowling 		ixgbe_mbox_api_unknown
827*c58d34ddSKevin Bowling 	};
828b82c9ba1SEric Joyner 	int i = 0;
829b82c9ba1SEric Joyner 
830b82c9ba1SEric Joyner 	while (mbx_api[i] != ixgbe_mbox_api_unknown) {
831b82c9ba1SEric Joyner 		if (ixgbevf_negotiate_api_version(hw, mbx_api[i]) == 0)
832b82c9ba1SEric Joyner 			return (0);
833b82c9ba1SEric Joyner 		i++;
834b82c9ba1SEric Joyner 	}
835b82c9ba1SEric Joyner 
836b82c9ba1SEric Joyner 	return (EINVAL);
837b82c9ba1SEric Joyner } /* ixv_negotiate_api */
838b82c9ba1SEric Joyner 
839b82c9ba1SEric Joyner 
840ff06a8dbSJustin Hibbits static u_int
ixv_if_multi_set_cb(void * cb_arg,struct sockaddr_dl * addr,u_int cnt)841ff06a8dbSJustin Hibbits ixv_if_multi_set_cb(void *cb_arg, struct sockaddr_dl *addr, u_int cnt)
842ff06a8dbSJustin Hibbits {
843*c58d34ddSKevin Bowling 	bcopy(LLADDR(addr),
844*c58d34ddSKevin Bowling 	    &((u8 *)cb_arg)[cnt * IXGBE_ETH_LENGTH_OF_ADDRESS],
845ff06a8dbSJustin Hibbits 	    IXGBE_ETH_LENGTH_OF_ADDRESS);
846ff06a8dbSJustin Hibbits 
847ff06a8dbSJustin Hibbits 	return (++cnt);
848ff06a8dbSJustin Hibbits }
849ff06a8dbSJustin Hibbits 
850b82c9ba1SEric Joyner /************************************************************************
851c19c7afeSEric Joyner  * ixv_if_multi_set - Multicast Update
8528eb6488eSEric Joyner  *
8538eb6488eSEric Joyner  *   Called whenever multicast address list is updated.
8548eb6488eSEric Joyner  ************************************************************************/
8558eb6488eSEric Joyner static void
ixv_if_multi_set(if_ctx_t ctx)856c19c7afeSEric Joyner ixv_if_multi_set(if_ctx_t ctx)
8578eb6488eSEric Joyner {
8588eb6488eSEric Joyner 	u8 mta[MAX_NUM_MULTICAST_ADDRESSES * IXGBE_ETH_LENGTH_OF_ADDRESS];
859b1d5caf3SKevin Bowling 	struct ixgbe_softc *sc = iflib_get_softc(ctx);
8608eb6488eSEric Joyner 	u8 *update_ptr;
861c19c7afeSEric Joyner 	if_t ifp = iflib_get_ifp(ctx);
8628eb6488eSEric Joyner 	int mcnt = 0;
8638eb6488eSEric Joyner 
864c19c7afeSEric Joyner 	IOCTL_DEBUGOUT("ixv_if_multi_set: begin");
8658eb6488eSEric Joyner 
866ff06a8dbSJustin Hibbits 	mcnt = if_foreach_llmaddr(ifp, ixv_if_multi_set_cb, mta);
8678eb6488eSEric Joyner 
8688eb6488eSEric Joyner 	update_ptr = mta;
8698eb6488eSEric Joyner 
870b1d5caf3SKevin Bowling 	sc->hw.mac.ops.update_mc_addr_list(&sc->hw, update_ptr, mcnt,
87179b36ec9SKevin Bowling 	    ixv_mc_array_itr, true);
872c19c7afeSEric Joyner } /* ixv_if_multi_set */
8738eb6488eSEric Joyner 
8748eb6488eSEric Joyner /************************************************************************
8758eb6488eSEric Joyner  * ixv_mc_array_itr
8768eb6488eSEric Joyner  *
8778eb6488eSEric Joyner  *   An iterator function needed by the multicast shared code.
8788eb6488eSEric Joyner  *   It feeds the shared code routine the addresses in the
8798eb6488eSEric Joyner  *   array of ixv_set_multi() one by one.
8808eb6488eSEric Joyner  ************************************************************************/
8818eb6488eSEric Joyner static u8 *
ixv_mc_array_itr(struct ixgbe_hw * hw,u8 ** update_ptr,u32 * vmdq)8828eb6488eSEric Joyner ixv_mc_array_itr(struct ixgbe_hw *hw, u8 **update_ptr, u32 *vmdq)
8838eb6488eSEric Joyner {
8848eb6488eSEric Joyner 	u8 *addr = *update_ptr;
8858eb6488eSEric Joyner 	u8 *newptr;
886c19c7afeSEric Joyner 
8878eb6488eSEric Joyner 	*vmdq = 0;
8888eb6488eSEric Joyner 
8898eb6488eSEric Joyner 	newptr = addr + IXGBE_ETH_LENGTH_OF_ADDRESS;
8908eb6488eSEric Joyner 	*update_ptr = newptr;
8918eb6488eSEric Joyner 
8928eb6488eSEric Joyner 	return addr;
8938eb6488eSEric Joyner } /* ixv_mc_array_itr */
8948eb6488eSEric Joyner 
8958eb6488eSEric Joyner /************************************************************************
896c19c7afeSEric Joyner  * ixv_if_local_timer - Timer routine
8978eb6488eSEric Joyner  *
8988eb6488eSEric Joyner  *   Checks for link status, updates statistics,
8998eb6488eSEric Joyner  *   and runs the watchdog check.
9008eb6488eSEric Joyner  ************************************************************************/
9018eb6488eSEric Joyner static void
ixv_if_local_timer(if_ctx_t ctx,uint16_t qid)902c19c7afeSEric Joyner ixv_if_local_timer(if_ctx_t ctx, uint16_t qid)
9038eb6488eSEric Joyner {
904c19c7afeSEric Joyner 	if (qid != 0)
9058eb6488eSEric Joyner 		return;
9068eb6488eSEric Joyner 
907c19c7afeSEric Joyner 	/* Fire off the adminq task */
908c19c7afeSEric Joyner 	iflib_admin_intr_deferred(ctx);
909c19c7afeSEric Joyner } /* ixv_if_local_timer */
9108eb6488eSEric Joyner 
9118eb6488eSEric Joyner /************************************************************************
912c19c7afeSEric Joyner  * ixv_if_update_admin_status - Update OS on link state
9138eb6488eSEric Joyner  *
9148eb6488eSEric Joyner  * Note: Only updates the OS on the cached link state.
9158eb6488eSEric Joyner  *       The real check of the hardware only happens with
9168eb6488eSEric Joyner  *       a link interrupt.
9178eb6488eSEric Joyner  ************************************************************************/
9188eb6488eSEric Joyner static void
ixv_if_update_admin_status(if_ctx_t ctx)919c19c7afeSEric Joyner ixv_if_update_admin_status(if_ctx_t ctx)
9208eb6488eSEric Joyner {
921b1d5caf3SKevin Bowling 	struct ixgbe_softc *sc = iflib_get_softc(ctx);
922c19c7afeSEric Joyner 	device_t dev = iflib_get_dev(ctx);
9237d48aa4cSEric Joyner 	s32 status;
924c19c7afeSEric Joyner 
925b1d5caf3SKevin Bowling 	sc->hw.mac.get_link_status = true;
9267d48aa4cSEric Joyner 
927b1d5caf3SKevin Bowling 	status = ixgbe_check_link(&sc->hw, &sc->link_speed,
928b1d5caf3SKevin Bowling 	    &sc->link_up, false);
9297d48aa4cSEric Joyner 
930b1d5caf3SKevin Bowling 	if (status != IXGBE_SUCCESS && sc->hw.adapter_stopped == false) {
9317d48aa4cSEric Joyner 		/* Mailbox's Clear To Send status is lost or timeout occurred.
9327d48aa4cSEric Joyner 		 * We need reinitialization. */
933ff06a8dbSJustin Hibbits 		if_init(iflib_get_ifp(ctx), ctx);
9347d48aa4cSEric Joyner 	}
9358eb6488eSEric Joyner 
936a3e719bbSPiotr Pietruszewski 	if (sc->link_up && sc->link_enabled) {
937b1d5caf3SKevin Bowling 		if (sc->link_active == false) {
9388eb6488eSEric Joyner 			if (bootverbose)
9398eb6488eSEric Joyner 				device_printf(dev, "Link is up %d Gbps %s \n",
940b1d5caf3SKevin Bowling 				    ((sc->link_speed == 128) ? 10 : 1),
9418eb6488eSEric Joyner 				    "Full Duplex");
942b1d5caf3SKevin Bowling 			sc->link_active = true;
943c19c7afeSEric Joyner 			iflib_link_state_change(ctx, LINK_STATE_UP,
9445ddb1aa3SPiotr Kubaj 			    ixgbe_link_speed_to_baudrate(sc->link_speed));
9458eb6488eSEric Joyner 		}
9468eb6488eSEric Joyner 	} else { /* Link down */
947b1d5caf3SKevin Bowling 		if (sc->link_active == true) {
9488eb6488eSEric Joyner 			if (bootverbose)
9498eb6488eSEric Joyner 				device_printf(dev, "Link is Down\n");
950c19c7afeSEric Joyner 			iflib_link_state_change(ctx, LINK_STATE_DOWN,  0);
951b1d5caf3SKevin Bowling 			sc->link_active = false;
9528eb6488eSEric Joyner 		}
9538eb6488eSEric Joyner 	}
9548eb6488eSEric Joyner 
955c19c7afeSEric Joyner 	/* Stats Update */
956b1d5caf3SKevin Bowling 	ixv_update_stats(sc);
957c19c7afeSEric Joyner } /* ixv_if_update_admin_status */
9588eb6488eSEric Joyner 
9598eb6488eSEric Joyner 
9608eb6488eSEric Joyner /************************************************************************
961c19c7afeSEric Joyner  * ixv_if_stop - Stop the hardware
9628eb6488eSEric Joyner  *
9638eb6488eSEric Joyner  *   Disables all traffic on the adapter by issuing a
9648eb6488eSEric Joyner  *   global reset on the MAC and deallocates TX/RX buffers.
9658eb6488eSEric Joyner  ************************************************************************/
9668eb6488eSEric Joyner static void
ixv_if_stop(if_ctx_t ctx)967c19c7afeSEric Joyner ixv_if_stop(if_ctx_t ctx)
9688eb6488eSEric Joyner {
969b1d5caf3SKevin Bowling 	struct ixgbe_softc *sc = iflib_get_softc(ctx);
970b1d5caf3SKevin Bowling 	struct ixgbe_hw *hw = &sc->hw;
9718eb6488eSEric Joyner 
9728eb6488eSEric Joyner 	INIT_DEBUGOUT("ixv_stop: begin\n");
9738eb6488eSEric Joyner 
974c19c7afeSEric Joyner 	ixv_if_disable_intr(ctx);
9758eb6488eSEric Joyner 
9768eb6488eSEric Joyner 	hw->mac.ops.reset_hw(hw);
977b1d5caf3SKevin Bowling 	sc->hw.adapter_stopped = false;
9788eb6488eSEric Joyner 	hw->mac.ops.stop_adapter(hw);
979c19c7afeSEric Joyner 
980c19c7afeSEric Joyner 	/* Update the stack */
981b1d5caf3SKevin Bowling 	sc->link_up = false;
982c19c7afeSEric Joyner 	ixv_if_update_admin_status(ctx);
9838eb6488eSEric Joyner 
9848eb6488eSEric Joyner 	/* reprogram the RAR[0] in case user changed it. */
9858eb6488eSEric Joyner 	hw->mac.ops.set_rar(hw, 0, hw->mac.addr, 0, IXGBE_RAH_AV);
986c19c7afeSEric Joyner } /* ixv_if_stop */
9878eb6488eSEric Joyner 
9888eb6488eSEric Joyner 
989c19c7afeSEric Joyner /************************************************************************
990c19c7afeSEric Joyner  * ixv_identify_hardware - Determine hardware revision.
991c19c7afeSEric Joyner  ************************************************************************/
992c19c7afeSEric Joyner static void
ixv_identify_hardware(if_ctx_t ctx)993c19c7afeSEric Joyner ixv_identify_hardware(if_ctx_t ctx)
994c19c7afeSEric Joyner {
995b1d5caf3SKevin Bowling 	struct ixgbe_softc *sc = iflib_get_softc(ctx);
996c19c7afeSEric Joyner 	device_t dev = iflib_get_dev(ctx);
997b1d5caf3SKevin Bowling 	struct ixgbe_hw *hw = &sc->hw;
998c19c7afeSEric Joyner 
999c19c7afeSEric Joyner 	/* Save off the information about this board */
1000c19c7afeSEric Joyner 	hw->vendor_id = pci_get_vendor(dev);
1001c19c7afeSEric Joyner 	hw->device_id = pci_get_device(dev);
1002c19c7afeSEric Joyner 	hw->revision_id = pci_get_revid(dev);
1003c19c7afeSEric Joyner 	hw->subsystem_vendor_id = pci_get_subvendor(dev);
1004c19c7afeSEric Joyner 	hw->subsystem_device_id = pci_get_subdevice(dev);
1005c19c7afeSEric Joyner 
1006c19c7afeSEric Joyner 	/* A subset of set_mac_type */
1007c19c7afeSEric Joyner 	switch (hw->device_id) {
1008c19c7afeSEric Joyner 	case IXGBE_DEV_ID_82599_VF:
1009c19c7afeSEric Joyner 		hw->mac.type = ixgbe_mac_82599_vf;
1010c19c7afeSEric Joyner 		break;
1011c19c7afeSEric Joyner 	case IXGBE_DEV_ID_X540_VF:
1012c19c7afeSEric Joyner 		hw->mac.type = ixgbe_mac_X540_vf;
1013c19c7afeSEric Joyner 		break;
1014c19c7afeSEric Joyner 	case IXGBE_DEV_ID_X550_VF:
1015c19c7afeSEric Joyner 		hw->mac.type = ixgbe_mac_X550_vf;
1016c19c7afeSEric Joyner 		break;
1017c19c7afeSEric Joyner 	case IXGBE_DEV_ID_X550EM_X_VF:
1018c19c7afeSEric Joyner 		hw->mac.type = ixgbe_mac_X550EM_x_vf;
1019c19c7afeSEric Joyner 		break;
1020c19c7afeSEric Joyner 	case IXGBE_DEV_ID_X550EM_A_VF:
1021c19c7afeSEric Joyner 		hw->mac.type = ixgbe_mac_X550EM_a_vf;
1022c19c7afeSEric Joyner 		break;
1023c19c7afeSEric Joyner 	default:
1024c19c7afeSEric Joyner 		device_printf(dev, "unknown mac type\n");
1025c19c7afeSEric Joyner 		hw->mac.type = ixgbe_mac_unknown;
1026c19c7afeSEric Joyner 		break;
1027c19c7afeSEric Joyner 	}
1028c19c7afeSEric Joyner } /* ixv_identify_hardware */
1029c19c7afeSEric Joyner 
1030c19c7afeSEric Joyner /************************************************************************
1031c19c7afeSEric Joyner  * ixv_if_msix_intr_assign - Setup MSI-X Interrupt resources and handlers
1032c19c7afeSEric Joyner  ************************************************************************/
1033c19c7afeSEric Joyner static int
ixv_if_msix_intr_assign(if_ctx_t ctx,int msix)1034c19c7afeSEric Joyner ixv_if_msix_intr_assign(if_ctx_t ctx, int msix)
1035c19c7afeSEric Joyner {
1036b1d5caf3SKevin Bowling 	struct ixgbe_softc *sc = iflib_get_softc(ctx);
1037c19c7afeSEric Joyner 	device_t dev = iflib_get_dev(ctx);
1038b1d5caf3SKevin Bowling 	struct ix_rx_queue *rx_que = sc->rx_queues;
1039c19c7afeSEric Joyner 	struct ix_tx_queue *tx_que;
1040c19c7afeSEric Joyner 	int error, rid, vector = 0;
1041c19c7afeSEric Joyner 	char buf[16];
1042c19c7afeSEric Joyner 
1043b1d5caf3SKevin Bowling 	for (int i = 0; i < sc->num_rx_queues; i++, vector++, rx_que++) {
1044c19c7afeSEric Joyner 		rid = vector + 1;
1045c19c7afeSEric Joyner 
1046c19c7afeSEric Joyner 		snprintf(buf, sizeof(buf), "rxq%d", i);
1047c19c7afeSEric Joyner 		error = iflib_irq_alloc_generic(ctx, &rx_que->que_irq, rid,
1048*c58d34ddSKevin Bowling 		    IFLIB_INTR_RXTX, ixv_msix_que, rx_que, rx_que->rxr.me,
1049*c58d34ddSKevin Bowling 		    buf);
1050c19c7afeSEric Joyner 
1051c19c7afeSEric Joyner 		if (error) {
1052c19c7afeSEric Joyner 			device_printf(iflib_get_dev(ctx),
1053*c58d34ddSKevin Bowling 			    "Failed to allocate que int %d err: %d",
1054*c58d34ddSKevin Bowling 			    i, error);
1055b1d5caf3SKevin Bowling 			sc->num_rx_queues = i + 1;
1056c19c7afeSEric Joyner 			goto fail;
1057c19c7afeSEric Joyner 		}
1058c19c7afeSEric Joyner 
1059c19c7afeSEric Joyner 		rx_que->msix = vector;
1060c19c7afeSEric Joyner 	}
1061c19c7afeSEric Joyner 
1062b1d5caf3SKevin Bowling 	for (int i = 0; i < sc->num_tx_queues; i++) {
1063c19c7afeSEric Joyner 		snprintf(buf, sizeof(buf), "txq%d", i);
1064b1d5caf3SKevin Bowling 		tx_que = &sc->tx_queues[i];
1065b1d5caf3SKevin Bowling 		tx_que->msix = i % sc->num_rx_queues;
1066c19c7afeSEric Joyner 		iflib_softirq_alloc_generic(ctx,
1067b1d5caf3SKevin Bowling 		    &sc->rx_queues[tx_que->msix].que_irq,
1068c19c7afeSEric Joyner 		    IFLIB_INTR_TX, tx_que, tx_que->txr.me, buf);
1069c19c7afeSEric Joyner 	}
1070c19c7afeSEric Joyner 	rid = vector + 1;
1071b1d5caf3SKevin Bowling 	error = iflib_irq_alloc_generic(ctx, &sc->irq, rid,
1072b1d5caf3SKevin Bowling 	    IFLIB_INTR_ADMIN, ixv_msix_mbx, sc, 0, "aq");
1073c19c7afeSEric Joyner 	if (error) {
1074c19c7afeSEric Joyner 		device_printf(iflib_get_dev(ctx),
1075c19c7afeSEric Joyner 		    "Failed to register admin handler");
1076c19c7afeSEric Joyner 		return (error);
1077c19c7afeSEric Joyner 	}
1078c19c7afeSEric Joyner 
1079b1d5caf3SKevin Bowling 	sc->vector = vector;
1080c19c7afeSEric Joyner 	/*
1081c19c7afeSEric Joyner 	 * Due to a broken design QEMU will fail to properly
1082c19c7afeSEric Joyner 	 * enable the guest for MSIX unless the vectors in
1083c19c7afeSEric Joyner 	 * the table are all set up, so we must rewrite the
1084c19c7afeSEric Joyner 	 * ENABLE in the MSIX control register again at this
1085c19c7afeSEric Joyner 	 * point to cause it to successfully initialize us.
1086c19c7afeSEric Joyner 	 */
1087b1d5caf3SKevin Bowling 	if (sc->hw.mac.type == ixgbe_mac_82599_vf) {
1088c19c7afeSEric Joyner 		int msix_ctrl;
1089b87b3696SJeremiah Lott 		if (pci_find_cap(dev, PCIY_MSIX, &rid)) {
1090*c58d34ddSKevin Bowling 			device_printf(dev,
1091*c58d34ddSKevin Bowling 			    "Finding MSIX capability failed\n");
1092b87b3696SJeremiah Lott 		} else {
1093c19c7afeSEric Joyner 			rid += PCIR_MSIX_CTRL;
1094c19c7afeSEric Joyner 			msix_ctrl = pci_read_config(dev, rid, 2);
1095c19c7afeSEric Joyner 			msix_ctrl |= PCIM_MSIXCTRL_MSIX_ENABLE;
1096c19c7afeSEric Joyner 			pci_write_config(dev, rid, msix_ctrl, 2);
1097c19c7afeSEric Joyner 		}
1098b87b3696SJeremiah Lott 	}
1099c19c7afeSEric Joyner 
1100c19c7afeSEric Joyner 	return (0);
1101c19c7afeSEric Joyner 
1102c19c7afeSEric Joyner fail:
1103b1d5caf3SKevin Bowling 	iflib_irq_free(ctx, &sc->irq);
1104b1d5caf3SKevin Bowling 	rx_que = sc->rx_queues;
1105b1d5caf3SKevin Bowling 	for (int i = 0; i < sc->num_rx_queues; i++, rx_que++)
1106c19c7afeSEric Joyner 		iflib_irq_free(ctx, &rx_que->que_irq);
1107c19c7afeSEric Joyner 
1108c19c7afeSEric Joyner 	return (error);
1109c19c7afeSEric Joyner } /* ixv_if_msix_intr_assign */
11108eb6488eSEric Joyner 
11118eb6488eSEric Joyner /************************************************************************
11128eb6488eSEric Joyner  * ixv_allocate_pci_resources
11138eb6488eSEric Joyner  ************************************************************************/
11148eb6488eSEric Joyner static int
ixv_allocate_pci_resources(if_ctx_t ctx)1115c19c7afeSEric Joyner ixv_allocate_pci_resources(if_ctx_t ctx)
11168eb6488eSEric Joyner {
1117b1d5caf3SKevin Bowling 	struct ixgbe_softc *sc = iflib_get_softc(ctx);
1118c19c7afeSEric Joyner 	device_t dev = iflib_get_dev(ctx);
11198eb6488eSEric Joyner 	int rid;
11208eb6488eSEric Joyner 
11218eb6488eSEric Joyner 	rid = PCIR_BAR(0);
1122b1d5caf3SKevin Bowling 	sc->pci_mem = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
11238eb6488eSEric Joyner 	    RF_ACTIVE);
11248eb6488eSEric Joyner 
1125b1d5caf3SKevin Bowling 	if (!(sc->pci_mem)) {
1126*c58d34ddSKevin Bowling 		device_printf(dev,
1127*c58d34ddSKevin Bowling 		    "Unable to allocate bus resource: memory\n");
11288eb6488eSEric Joyner 		return (ENXIO);
11298eb6488eSEric Joyner 	}
11308eb6488eSEric Joyner 
1131b1d5caf3SKevin Bowling 	sc->osdep.mem_bus_space_tag = rman_get_bustag(sc->pci_mem);
1132*c58d34ddSKevin Bowling 	sc->osdep.mem_bus_space_handle = rman_get_bushandle(sc->pci_mem);
1133b1d5caf3SKevin Bowling 	sc->hw.hw_addr = (u8 *)&sc->osdep.mem_bus_space_handle;
11348eb6488eSEric Joyner 
11358eb6488eSEric Joyner 	return (0);
11368eb6488eSEric Joyner } /* ixv_allocate_pci_resources */
11378eb6488eSEric Joyner 
11388eb6488eSEric Joyner /************************************************************************
11398eb6488eSEric Joyner  * ixv_free_pci_resources
11408eb6488eSEric Joyner  ************************************************************************/
11418eb6488eSEric Joyner static void
ixv_free_pci_resources(if_ctx_t ctx)1142c19c7afeSEric Joyner ixv_free_pci_resources(if_ctx_t ctx)
11438eb6488eSEric Joyner {
1144b1d5caf3SKevin Bowling 	struct ixgbe_softc *sc = iflib_get_softc(ctx);
1145b1d5caf3SKevin Bowling 	struct ix_rx_queue *que = sc->rx_queues;
1146c19c7afeSEric Joyner 	device_t dev = iflib_get_dev(ctx);
11478eb6488eSEric Joyner 
1148b97de13aSMarius Strobl 	/* Release all MSI-X queue resources */
1149b1d5caf3SKevin Bowling 	if (sc->intr_type == IFLIB_INTR_MSIX)
1150b1d5caf3SKevin Bowling 		iflib_irq_free(ctx, &sc->irq);
11518eb6488eSEric Joyner 
1152c19c7afeSEric Joyner 	if (que != NULL) {
1153b1d5caf3SKevin Bowling 		for (int i = 0; i < sc->num_rx_queues; i++, que++) {
1154c19c7afeSEric Joyner 			iflib_irq_free(ctx, &que->que_irq);
11558eb6488eSEric Joyner 		}
11568eb6488eSEric Joyner 	}
11578eb6488eSEric Joyner 
1158b1d5caf3SKevin Bowling 	if (sc->pci_mem != NULL)
1159c19c7afeSEric Joyner 		bus_release_resource(dev, SYS_RES_MEMORY,
1160b1d5caf3SKevin Bowling 		    rman_get_rid(sc->pci_mem), sc->pci_mem);
11618eb6488eSEric Joyner } /* ixv_free_pci_resources */
11628eb6488eSEric Joyner 
11638eb6488eSEric Joyner /************************************************************************
11648eb6488eSEric Joyner  * ixv_setup_interface
11658eb6488eSEric Joyner  *
11668eb6488eSEric Joyner  *   Setup networking device structure and register an interface.
11678eb6488eSEric Joyner  ************************************************************************/
1168c19c7afeSEric Joyner static int
ixv_setup_interface(if_ctx_t ctx)1169c19c7afeSEric Joyner ixv_setup_interface(if_ctx_t ctx)
11708eb6488eSEric Joyner {
1171b1d5caf3SKevin Bowling 	struct ixgbe_softc *sc = iflib_get_softc(ctx);
1172b1d5caf3SKevin Bowling 	if_softc_ctx_t scctx = sc->shared;
1173ff06a8dbSJustin Hibbits 	if_t ifp = iflib_get_ifp(ctx);
11748eb6488eSEric Joyner 
11758eb6488eSEric Joyner 	INIT_DEBUGOUT("ixv_setup_interface: begin");
11768eb6488eSEric Joyner 
1177c19c7afeSEric Joyner 	if_setbaudrate(ifp, IF_Gbps(10));
1178ff06a8dbSJustin Hibbits 	if_setsendqlen(ifp, scctx->isc_ntxd[0] - 2);
11798eb6488eSEric Joyner 
11808eb6488eSEric Joyner 
1181ff06a8dbSJustin Hibbits 	sc->max_frame_size = if_getmtu(ifp) + IXGBE_MTU_HDR;
1182b1d5caf3SKevin Bowling 	ifmedia_add(sc->media, IFM_ETHER | IFM_AUTO, 0, NULL);
1183b1d5caf3SKevin Bowling 	ifmedia_set(sc->media, IFM_ETHER | IFM_AUTO);
11848eb6488eSEric Joyner 
1185c19c7afeSEric Joyner 	return 0;
11868eb6488eSEric Joyner } /* ixv_setup_interface */
11878eb6488eSEric Joyner 
1188c19c7afeSEric Joyner /************************************************************************
1189c19c7afeSEric Joyner  * ixv_if_get_counter
1190c19c7afeSEric Joyner  ************************************************************************/
1191c19c7afeSEric Joyner static uint64_t
ixv_if_get_counter(if_ctx_t ctx,ift_counter cnt)1192c19c7afeSEric Joyner ixv_if_get_counter(if_ctx_t ctx, ift_counter cnt)
1193c19c7afeSEric Joyner {
1194b1d5caf3SKevin Bowling 	struct ixgbe_softc *sc = iflib_get_softc(ctx);
1195c19c7afeSEric Joyner 	if_t ifp = iflib_get_ifp(ctx);
1196c19c7afeSEric Joyner 
1197c19c7afeSEric Joyner 	switch (cnt) {
1198c19c7afeSEric Joyner 	case IFCOUNTER_IPACKETS:
1199b1d5caf3SKevin Bowling 		return (sc->ipackets);
1200c19c7afeSEric Joyner 	case IFCOUNTER_OPACKETS:
1201b1d5caf3SKevin Bowling 		return (sc->opackets);
1202c19c7afeSEric Joyner 	case IFCOUNTER_IBYTES:
1203b1d5caf3SKevin Bowling 		return (sc->ibytes);
1204c19c7afeSEric Joyner 	case IFCOUNTER_OBYTES:
1205b1d5caf3SKevin Bowling 		return (sc->obytes);
1206c19c7afeSEric Joyner 	case IFCOUNTER_IMCASTS:
1207b1d5caf3SKevin Bowling 		return (sc->imcasts);
1208c19c7afeSEric Joyner 	default:
1209c19c7afeSEric Joyner 		return (if_get_counter_default(ifp, cnt));
1210c19c7afeSEric Joyner 	}
1211c19c7afeSEric Joyner } /* ixv_if_get_counter */
12128eb6488eSEric Joyner 
1213cf150917SEric Joyner /* ixv_if_needs_restart - Tell iflib when the driver needs to be reinitialized
1214cf150917SEric Joyner  * @ctx: iflib context
1215cf150917SEric Joyner  * @event: event code to check
1216cf150917SEric Joyner  *
1217cf150917SEric Joyner  * Defaults to returning true for every event.
1218cf150917SEric Joyner  *
1219cf150917SEric Joyner  * @returns true if iflib needs to reinit the interface
1220cf150917SEric Joyner  */
1221cf150917SEric Joyner static bool
ixv_if_needs_restart(if_ctx_t ctx __unused,enum iflib_restart_event event)1222cf150917SEric Joyner ixv_if_needs_restart(if_ctx_t ctx __unused, enum iflib_restart_event event)
1223cf150917SEric Joyner {
1224cf150917SEric Joyner 	switch (event) {
1225cf150917SEric Joyner 	case IFLIB_RESTART_VLAN_CONFIG:
1226cf150917SEric Joyner 		/* XXX: This may not need to return true */
1227cf150917SEric Joyner 	default:
1228cf150917SEric Joyner 		return (true);
1229cf150917SEric Joyner 	}
1230cf150917SEric Joyner }
1231cf150917SEric Joyner 
12328eb6488eSEric Joyner /************************************************************************
12338eb6488eSEric Joyner  * ixv_initialize_transmit_units - Enable transmit unit.
12348eb6488eSEric Joyner  ************************************************************************/
12358eb6488eSEric Joyner static void
ixv_initialize_transmit_units(if_ctx_t ctx)1236c19c7afeSEric Joyner ixv_initialize_transmit_units(if_ctx_t ctx)
12378eb6488eSEric Joyner {
1238b1d5caf3SKevin Bowling 	struct ixgbe_softc *sc = iflib_get_softc(ctx);
1239b1d5caf3SKevin Bowling 	struct ixgbe_hw *hw = &sc->hw;
1240b1d5caf3SKevin Bowling 	if_softc_ctx_t scctx = sc->shared;
1241b1d5caf3SKevin Bowling 	struct ix_tx_queue *que = sc->tx_queues;
1242c19c7afeSEric Joyner 	int i;
12438eb6488eSEric Joyner 
1244b1d5caf3SKevin Bowling 	for (i = 0; i < sc->num_tx_queues; i++, que++) {
1245c19c7afeSEric Joyner 		struct tx_ring *txr = &que->txr;
1246c19c7afeSEric Joyner 		u64 tdba = txr->tx_paddr;
12478eb6488eSEric Joyner 		u32 txctrl, txdctl;
1248c19c7afeSEric Joyner 		int j = txr->me;
12498eb6488eSEric Joyner 
12508eb6488eSEric Joyner 		/* Set WTHRESH to 8, burst writeback */
1251c19c7afeSEric Joyner 		txdctl = IXGBE_READ_REG(hw, IXGBE_VFTXDCTL(j));
12528eb6488eSEric Joyner 		txdctl |= (8 << 16);
1253c19c7afeSEric Joyner 		IXGBE_WRITE_REG(hw, IXGBE_VFTXDCTL(j), txdctl);
12548eb6488eSEric Joyner 
12558eb6488eSEric Joyner 		/* Set the HW Tx Head and Tail indices */
1256b1d5caf3SKevin Bowling 		IXGBE_WRITE_REG(&sc->hw, IXGBE_VFTDH(j), 0);
1257b1d5caf3SKevin Bowling 		IXGBE_WRITE_REG(&sc->hw, IXGBE_VFTDT(j), 0);
12588eb6488eSEric Joyner 
12598eb6488eSEric Joyner 		/* Set Tx Tail register */
1260c19c7afeSEric Joyner 		txr->tail = IXGBE_VFTDT(j);
1261c19c7afeSEric Joyner 
1262088a0b27SEric Joyner 		txr->tx_rs_cidx = txr->tx_rs_pidx;
1263088a0b27SEric Joyner 		/* Initialize the last processed descriptor to be the end of
1264088a0b27SEric Joyner 		 * the ring, rather than the start, so that we avoid an
1265088a0b27SEric Joyner 		 * off-by-one error when calculating how many descriptors are
1266088a0b27SEric Joyner 		 * done in the credits_update function.
1267088a0b27SEric Joyner 		 */
1268088a0b27SEric Joyner 		txr->tx_cidx_processed = scctx->isc_ntxd[0] - 1;
1269c19c7afeSEric Joyner 		for (int k = 0; k < scctx->isc_ntxd[0]; k++)
1270c19c7afeSEric Joyner 			txr->tx_rsq[k] = QIDX_INVALID;
12718eb6488eSEric Joyner 
12728eb6488eSEric Joyner 		/* Set Ring parameters */
1273c19c7afeSEric Joyner 		IXGBE_WRITE_REG(hw, IXGBE_VFTDBAL(j),
12748eb6488eSEric Joyner 		    (tdba & 0x00000000ffffffffULL));
1275c19c7afeSEric Joyner 		IXGBE_WRITE_REG(hw, IXGBE_VFTDBAH(j), (tdba >> 32));
1276c19c7afeSEric Joyner 		IXGBE_WRITE_REG(hw, IXGBE_VFTDLEN(j),
1277c19c7afeSEric Joyner 		    scctx->isc_ntxd[0] * sizeof(struct ixgbe_legacy_tx_desc));
1278c19c7afeSEric Joyner 		txctrl = IXGBE_READ_REG(hw, IXGBE_VFDCA_TXCTRL(j));
12798eb6488eSEric Joyner 		txctrl &= ~IXGBE_DCA_TXCTRL_DESC_WRO_EN;
1280c19c7afeSEric Joyner 		IXGBE_WRITE_REG(hw, IXGBE_VFDCA_TXCTRL(j), txctrl);
12818eb6488eSEric Joyner 
12828eb6488eSEric Joyner 		/* Now enable */
1283c19c7afeSEric Joyner 		txdctl = IXGBE_READ_REG(hw, IXGBE_VFTXDCTL(j));
12848eb6488eSEric Joyner 		txdctl |= IXGBE_TXDCTL_ENABLE;
1285c19c7afeSEric Joyner 		IXGBE_WRITE_REG(hw, IXGBE_VFTXDCTL(j), txdctl);
12868eb6488eSEric Joyner 	}
12878eb6488eSEric Joyner 
12888eb6488eSEric Joyner 	return;
12898eb6488eSEric Joyner } /* ixv_initialize_transmit_units */
12908eb6488eSEric Joyner 
12918eb6488eSEric Joyner /************************************************************************
12928eb6488eSEric Joyner  * ixv_initialize_rss_mapping
12938eb6488eSEric Joyner  ************************************************************************/
12948eb6488eSEric Joyner static void
ixv_initialize_rss_mapping(struct ixgbe_softc * sc)1295b1d5caf3SKevin Bowling ixv_initialize_rss_mapping(struct ixgbe_softc *sc)
12968eb6488eSEric Joyner {
1297b1d5caf3SKevin Bowling 	struct ixgbe_hw *hw = &sc->hw;
12988eb6488eSEric Joyner 	u32 reta = 0, mrqc, rss_key[10];
12998eb6488eSEric Joyner 	int queue_id;
13008eb6488eSEric Joyner 	int i, j;
13018eb6488eSEric Joyner 	u32 rss_hash_config;
13028eb6488eSEric Joyner 
1303b1d5caf3SKevin Bowling 	if (sc->feat_en & IXGBE_FEATURE_RSS) {
13048eb6488eSEric Joyner 		/* Fetch the configured RSS key */
13058eb6488eSEric Joyner 		rss_getkey((uint8_t *)&rss_key);
13068eb6488eSEric Joyner 	} else {
13078eb6488eSEric Joyner 		/* set up random bits */
13088eb6488eSEric Joyner 		arc4rand(&rss_key, sizeof(rss_key), 0);
13098eb6488eSEric Joyner 	}
13108eb6488eSEric Joyner 
13118eb6488eSEric Joyner 	/* Now fill out hash function seeds */
13128eb6488eSEric Joyner 	for (i = 0; i < 10; i++)
13138eb6488eSEric Joyner 		IXGBE_WRITE_REG(hw, IXGBE_VFRSSRK(i), rss_key[i]);
13148eb6488eSEric Joyner 
13158eb6488eSEric Joyner 	/* Set up the redirection table */
13168eb6488eSEric Joyner 	for (i = 0, j = 0; i < 64; i++, j++) {
1317b1d5caf3SKevin Bowling 		if (j == sc->num_rx_queues)
13188eb6488eSEric Joyner 			j = 0;
13198eb6488eSEric Joyner 
1320b1d5caf3SKevin Bowling 		if (sc->feat_en & IXGBE_FEATURE_RSS) {
13218eb6488eSEric Joyner 			/*
13228eb6488eSEric Joyner 			 * Fetch the RSS bucket id for the given indirection
13238eb6488eSEric Joyner 			 * entry. Cap it at the number of configured buckets
1324c19c7afeSEric Joyner 			 * (which is num_rx_queues.)
13258eb6488eSEric Joyner 			 */
13268eb6488eSEric Joyner 			queue_id = rss_get_indirection_to_bucket(i);
1327b1d5caf3SKevin Bowling 			queue_id = queue_id % sc->num_rx_queues;
13288eb6488eSEric Joyner 		} else
13298eb6488eSEric Joyner 			queue_id = j;
13308eb6488eSEric Joyner 
13318eb6488eSEric Joyner 		/*
13328eb6488eSEric Joyner 		 * The low 8 bits are for hash value (n+0);
13338eb6488eSEric Joyner 		 * The next 8 bits are for hash value (n+1), etc.
13348eb6488eSEric Joyner 		 */
13358eb6488eSEric Joyner 		reta >>= 8;
13368eb6488eSEric Joyner 		reta |= ((uint32_t)queue_id) << 24;
13378eb6488eSEric Joyner 		if ((i & 3) == 3) {
13388eb6488eSEric Joyner 			IXGBE_WRITE_REG(hw, IXGBE_VFRETA(i >> 2), reta);
13398eb6488eSEric Joyner 			reta = 0;
13408eb6488eSEric Joyner 		}
13418eb6488eSEric Joyner 	}
13428eb6488eSEric Joyner 
13438eb6488eSEric Joyner 	/* Perform hash on these packet types */
1344b1d5caf3SKevin Bowling 	if (sc->feat_en & IXGBE_FEATURE_RSS)
13458eb6488eSEric Joyner 		rss_hash_config = rss_gethashconfig();
13468eb6488eSEric Joyner 	else {
13478eb6488eSEric Joyner 		/*
13488eb6488eSEric Joyner 		 * Disable UDP - IP fragments aren't currently being handled
13498eb6488eSEric Joyner 		 * and so we end up with a mix of 2-tuple and 4-tuple
13508eb6488eSEric Joyner 		 * traffic.
13518eb6488eSEric Joyner 		 */
13528eb6488eSEric Joyner 		rss_hash_config = RSS_HASHTYPE_RSS_IPV4
13538eb6488eSEric Joyner 		                | RSS_HASHTYPE_RSS_TCP_IPV4
13548eb6488eSEric Joyner 		                | RSS_HASHTYPE_RSS_IPV6
13558eb6488eSEric Joyner 		                | RSS_HASHTYPE_RSS_TCP_IPV6;
13568eb6488eSEric Joyner 	}
13578eb6488eSEric Joyner 
13588eb6488eSEric Joyner 	mrqc = IXGBE_MRQC_RSSEN;
13598eb6488eSEric Joyner 	if (rss_hash_config & RSS_HASHTYPE_RSS_IPV4)
13608eb6488eSEric Joyner 		mrqc |= IXGBE_MRQC_RSS_FIELD_IPV4;
13618eb6488eSEric Joyner 	if (rss_hash_config & RSS_HASHTYPE_RSS_TCP_IPV4)
13628eb6488eSEric Joyner 		mrqc |= IXGBE_MRQC_RSS_FIELD_IPV4_TCP;
13638eb6488eSEric Joyner 	if (rss_hash_config & RSS_HASHTYPE_RSS_IPV6)
13648eb6488eSEric Joyner 		mrqc |= IXGBE_MRQC_RSS_FIELD_IPV6;
13658eb6488eSEric Joyner 	if (rss_hash_config & RSS_HASHTYPE_RSS_TCP_IPV6)
13668eb6488eSEric Joyner 		mrqc |= IXGBE_MRQC_RSS_FIELD_IPV6_TCP;
13678eb6488eSEric Joyner 	if (rss_hash_config & RSS_HASHTYPE_RSS_IPV6_EX)
1368*c58d34ddSKevin Bowling 		device_printf(sc->dev,
1369*c58d34ddSKevin Bowling 		    "%s: RSS_HASHTYPE_RSS_IPV6_EX defined,"
1370*c58d34ddSKevin Bowling 		    " but not supported\n", __func__);
13718eb6488eSEric Joyner 	if (rss_hash_config & RSS_HASHTYPE_RSS_TCP_IPV6_EX)
1372*c58d34ddSKevin Bowling 		device_printf(sc->dev,
1373*c58d34ddSKevin Bowling 		    "%s: RSS_HASHTYPE_RSS_TCP_IPV6_EX defined,"
1374*c58d34ddSKevin Bowling 		    " but not supported\n", __func__);
13758eb6488eSEric Joyner 	if (rss_hash_config & RSS_HASHTYPE_RSS_UDP_IPV4)
13768eb6488eSEric Joyner 		mrqc |= IXGBE_MRQC_RSS_FIELD_IPV4_UDP;
13778eb6488eSEric Joyner 	if (rss_hash_config & RSS_HASHTYPE_RSS_UDP_IPV6)
13788eb6488eSEric Joyner 		mrqc |= IXGBE_MRQC_RSS_FIELD_IPV6_UDP;
13798eb6488eSEric Joyner 	if (rss_hash_config & RSS_HASHTYPE_RSS_UDP_IPV6_EX)
1380*c58d34ddSKevin Bowling 		device_printf(sc->dev,
1381*c58d34ddSKevin Bowling 		    "%s: RSS_HASHTYPE_RSS_UDP_IPV6_EX defined,"
1382*c58d34ddSKevin Bowling 		    " but not supported\n", __func__);
13838eb6488eSEric Joyner 	IXGBE_WRITE_REG(hw, IXGBE_VFMRQC, mrqc);
13848eb6488eSEric Joyner } /* ixv_initialize_rss_mapping */
13858eb6488eSEric Joyner 
1386cdbe3de5SKevin Bowling #define BSIZEPKT_ROUNDUP ((1<<IXGBE_SRRCTL_BSIZEPKT_SHIFT)-1)
13878eb6488eSEric Joyner /************************************************************************
13888eb6488eSEric Joyner  * ixv_initialize_receive_units - Setup receive registers and features.
13898eb6488eSEric Joyner  ************************************************************************/
13908eb6488eSEric Joyner static void
ixv_initialize_receive_units(if_ctx_t ctx)1391c19c7afeSEric Joyner ixv_initialize_receive_units(if_ctx_t ctx)
13928eb6488eSEric Joyner {
1393b1d5caf3SKevin Bowling 	struct ixgbe_softc *sc = iflib_get_softc(ctx);
1394c19c7afeSEric Joyner 	if_softc_ctx_t scctx;
1395b1d5caf3SKevin Bowling 	struct ixgbe_hw *hw = &sc->hw;
1396b0993e3bSKonstantin Belousov #ifdef DEV_NETMAP
1397ff06a8dbSJustin Hibbits 	if_t ifp = iflib_get_ifp(ctx);
1398b0993e3bSKonstantin Belousov #endif
1399b1d5caf3SKevin Bowling 	struct ix_rx_queue *que = sc->rx_queues;
1400c19c7afeSEric Joyner 	u32 bufsz, psrtype;
14018eb6488eSEric Joyner 
1402cdbe3de5SKevin Bowling 	bufsz = (sc->rx_mbuf_sz + BSIZEPKT_ROUNDUP) >>
1403cdbe3de5SKevin Bowling 	    IXGBE_SRRCTL_BSIZEPKT_SHIFT;
14048eb6488eSEric Joyner 
1405*c58d34ddSKevin Bowling 	psrtype = IXGBE_PSRTYPE_TCPHDR |
1406*c58d34ddSKevin Bowling 	    IXGBE_PSRTYPE_UDPHDR |
1407*c58d34ddSKevin Bowling 	    IXGBE_PSRTYPE_IPV4HDR |
1408*c58d34ddSKevin Bowling 	    IXGBE_PSRTYPE_IPV6HDR |
1409*c58d34ddSKevin Bowling 	    IXGBE_PSRTYPE_L2HDR;
14108eb6488eSEric Joyner 
1411b1d5caf3SKevin Bowling 	if (sc->num_rx_queues > 1)
14128eb6488eSEric Joyner 		psrtype |= 1 << 29;
14138eb6488eSEric Joyner 
14148eb6488eSEric Joyner 	IXGBE_WRITE_REG(hw, IXGBE_VFPSRTYPE, psrtype);
14158eb6488eSEric Joyner 
14168eb6488eSEric Joyner 	/* Tell PF our max_frame size */
1417b1d5caf3SKevin Bowling 	if (ixgbevf_rlpml_set_vf(hw, sc->max_frame_size) != 0) {
1418*c58d34ddSKevin Bowling 		device_printf(sc->dev,
1419*c58d34ddSKevin Bowling 		    "There is a problem with the PF setup.  It is likely the"
1420*c58d34ddSKevin Bowling 		    " receive unit for this VF will not function correctly."
1421*c58d34ddSKevin Bowling 		    "\n");
14228eb6488eSEric Joyner 	}
1423b1d5caf3SKevin Bowling 	scctx = sc->shared;
14248eb6488eSEric Joyner 
1425b1d5caf3SKevin Bowling 	for (int i = 0; i < sc->num_rx_queues; i++, que++) {
1426c19c7afeSEric Joyner 		struct rx_ring *rxr = &que->rxr;
1427c19c7afeSEric Joyner 		u64 rdba = rxr->rx_paddr;
14288eb6488eSEric Joyner 		u32 reg, rxdctl;
1429c19c7afeSEric Joyner 		int j = rxr->me;
14308eb6488eSEric Joyner 
14318eb6488eSEric Joyner 		/* Disable the queue */
1432c19c7afeSEric Joyner 		rxdctl = IXGBE_READ_REG(hw, IXGBE_VFRXDCTL(j));
14338eb6488eSEric Joyner 		rxdctl &= ~IXGBE_RXDCTL_ENABLE;
1434c19c7afeSEric Joyner 		IXGBE_WRITE_REG(hw, IXGBE_VFRXDCTL(j), rxdctl);
1435c19c7afeSEric Joyner 		for (int k = 0; k < 10; k++) {
1436c19c7afeSEric Joyner 			if (IXGBE_READ_REG(hw, IXGBE_VFRXDCTL(j)) &
14378eb6488eSEric Joyner 			    IXGBE_RXDCTL_ENABLE)
14388eb6488eSEric Joyner 				msec_delay(1);
14398eb6488eSEric Joyner 			else
14408eb6488eSEric Joyner 				break;
14418eb6488eSEric Joyner 		}
14428eb6488eSEric Joyner 		wmb();
14438eb6488eSEric Joyner 		/* Setup the Base and Length of the Rx Descriptor Ring */
1444c19c7afeSEric Joyner 		IXGBE_WRITE_REG(hw, IXGBE_VFRDBAL(j),
14458eb6488eSEric Joyner 		    (rdba & 0x00000000ffffffffULL));
1446c19c7afeSEric Joyner 		IXGBE_WRITE_REG(hw, IXGBE_VFRDBAH(j), (rdba >> 32));
1447c19c7afeSEric Joyner 		IXGBE_WRITE_REG(hw, IXGBE_VFRDLEN(j),
1448c19c7afeSEric Joyner 		    scctx->isc_nrxd[0] * sizeof(union ixgbe_adv_rx_desc));
14498eb6488eSEric Joyner 
14508eb6488eSEric Joyner 		/* Reset the ring indices */
14518eb6488eSEric Joyner 		IXGBE_WRITE_REG(hw, IXGBE_VFRDH(rxr->me), 0);
14528eb6488eSEric Joyner 		IXGBE_WRITE_REG(hw, IXGBE_VFRDT(rxr->me), 0);
14538eb6488eSEric Joyner 
14548eb6488eSEric Joyner 		/* Set up the SRRCTL register */
1455c19c7afeSEric Joyner 		reg = IXGBE_READ_REG(hw, IXGBE_VFSRRCTL(j));
14568eb6488eSEric Joyner 		reg &= ~IXGBE_SRRCTL_BSIZEHDR_MASK;
14578eb6488eSEric Joyner 		reg &= ~IXGBE_SRRCTL_BSIZEPKT_MASK;
14588eb6488eSEric Joyner 		reg |= bufsz;
14598eb6488eSEric Joyner 		reg |= IXGBE_SRRCTL_DESCTYPE_ADV_ONEBUF;
1460c19c7afeSEric Joyner 		IXGBE_WRITE_REG(hw, IXGBE_VFSRRCTL(j), reg);
14618eb6488eSEric Joyner 
14628eb6488eSEric Joyner 		/* Capture Rx Tail index */
14638eb6488eSEric Joyner 		rxr->tail = IXGBE_VFRDT(rxr->me);
14648eb6488eSEric Joyner 
14658eb6488eSEric Joyner 		/* Do the queue enabling last */
14668eb6488eSEric Joyner 		rxdctl |= IXGBE_RXDCTL_ENABLE | IXGBE_RXDCTL_VME;
1467c19c7afeSEric Joyner 		IXGBE_WRITE_REG(hw, IXGBE_VFRXDCTL(j), rxdctl);
1468c19c7afeSEric Joyner 		for (int l = 0; l < 10; l++) {
1469c19c7afeSEric Joyner 			if (IXGBE_READ_REG(hw, IXGBE_VFRXDCTL(j)) &
14708eb6488eSEric Joyner 			    IXGBE_RXDCTL_ENABLE)
14718eb6488eSEric Joyner 				break;
14728eb6488eSEric Joyner 			msec_delay(1);
14738eb6488eSEric Joyner 		}
14748eb6488eSEric Joyner 		wmb();
14758eb6488eSEric Joyner 
14768eb6488eSEric Joyner 		/* Set the Tail Pointer */
1477c19c7afeSEric Joyner #ifdef DEV_NETMAP
14788eb6488eSEric Joyner 		/*
14798eb6488eSEric Joyner 		 * In netmap mode, we must preserve the buffers made
14808eb6488eSEric Joyner 		 * available to userspace before the if_init()
14818eb6488eSEric Joyner 		 * (this is true by default on the TX side, because
14828eb6488eSEric Joyner 		 * init makes all buffers available to userspace).
14838eb6488eSEric Joyner 		 *
14848eb6488eSEric Joyner 		 * netmap_reset() and the device specific routines
14858eb6488eSEric Joyner 		 * (e.g. ixgbe_setup_receive_rings()) map these
14868eb6488eSEric Joyner 		 * buffers at the end of the NIC ring, so here we
14878eb6488eSEric Joyner 		 * must set the RDT (tail) register to make sure
14888eb6488eSEric Joyner 		 * they are not overwritten.
14898eb6488eSEric Joyner 		 *
14908eb6488eSEric Joyner 		 * In this driver the NIC ring starts at RDH = 0,
14918eb6488eSEric Joyner 		 * RDT points to the last slot available for reception (?),
14928eb6488eSEric Joyner 		 * so RDT = num_rx_desc - 1 means the whole ring is available.
14938eb6488eSEric Joyner 		 */
1494ff06a8dbSJustin Hibbits 		if (if_getcapenable(ifp) & IFCAP_NETMAP) {
1495c19c7afeSEric Joyner 			struct netmap_adapter *na = NA(ifp);
14962ff91c17SVincenzo Maffione 			struct netmap_kring *kring = na->rx_rings[j];
14978eb6488eSEric Joyner 			int t = na->num_rx_desc - 1 - nm_kr_rxspace(kring);
14988eb6488eSEric Joyner 
14998eb6488eSEric Joyner 			IXGBE_WRITE_REG(hw, IXGBE_VFRDT(rxr->me), t);
15008eb6488eSEric Joyner 		} else
15018eb6488eSEric Joyner #endif /* DEV_NETMAP */
15028eb6488eSEric Joyner 			IXGBE_WRITE_REG(hw, IXGBE_VFRDT(rxr->me),
1503c19c7afeSEric Joyner 			    scctx->isc_nrxd[0] - 1);
15048eb6488eSEric Joyner 	}
15058eb6488eSEric Joyner 
1506236204eeSAndriy Gapon 	/*
1507236204eeSAndriy Gapon 	 * Do not touch RSS and RETA settings for older hardware
1508236204eeSAndriy Gapon 	 * as those are shared among PF and all VF.
1509236204eeSAndriy Gapon 	 */
1510b1d5caf3SKevin Bowling 	if (sc->hw.mac.type >= ixgbe_mac_X550_vf)
1511b1d5caf3SKevin Bowling 		ixv_initialize_rss_mapping(sc);
15128eb6488eSEric Joyner } /* ixv_initialize_receive_units */
15138eb6488eSEric Joyner 
15148eb6488eSEric Joyner /************************************************************************
15158eb6488eSEric Joyner  * ixv_setup_vlan_support
15168eb6488eSEric Joyner  ************************************************************************/
15178eb6488eSEric Joyner static void
ixv_setup_vlan_support(if_ctx_t ctx)1518c19c7afeSEric Joyner ixv_setup_vlan_support(if_ctx_t ctx)
15198eb6488eSEric Joyner {
1520ff06a8dbSJustin Hibbits 	if_t ifp = iflib_get_ifp(ctx);
1521b1d5caf3SKevin Bowling 	struct ixgbe_softc *sc = iflib_get_softc(ctx);
1522b1d5caf3SKevin Bowling 	struct ixgbe_hw *hw = &sc->hw;
15238eb6488eSEric Joyner 	u32 ctrl, vid, vfta, retry;
15248eb6488eSEric Joyner 
15258eb6488eSEric Joyner 	/*
1526c19c7afeSEric Joyner 	 * We get here thru if_init, meaning
15278eb6488eSEric Joyner 	 * a soft reset, this has already cleared
15288eb6488eSEric Joyner 	 * the VFTA and other state, so if there
15298eb6488eSEric Joyner 	 * have been no vlan's registered do nothing.
15308eb6488eSEric Joyner 	 */
1531b1d5caf3SKevin Bowling 	if (sc->num_vlans == 0)
15328eb6488eSEric Joyner 		return;
15338eb6488eSEric Joyner 
1534ff06a8dbSJustin Hibbits 	if (if_getcapenable(ifp) & IFCAP_VLAN_HWTAGGING) {
15358eb6488eSEric Joyner 		/* Enable the queues */
1536b1d5caf3SKevin Bowling 		for (int i = 0; i < sc->num_rx_queues; i++) {
15378eb6488eSEric Joyner 			ctrl = IXGBE_READ_REG(hw, IXGBE_VFRXDCTL(i));
15388eb6488eSEric Joyner 			ctrl |= IXGBE_RXDCTL_VME;
15398eb6488eSEric Joyner 			IXGBE_WRITE_REG(hw, IXGBE_VFRXDCTL(i), ctrl);
15408eb6488eSEric Joyner 			/*
15418eb6488eSEric Joyner 			 * Let Rx path know that it needs to store VLAN tag
15428eb6488eSEric Joyner 			 * as part of extra mbuf info.
15438eb6488eSEric Joyner 			 */
1544b1d5caf3SKevin Bowling 			sc->rx_queues[i].rxr.vtag_strip = true;
15458eb6488eSEric Joyner 		}
1546de35521aSEric Joyner 	}
1547de35521aSEric Joyner 
1548de35521aSEric Joyner 	/*
1549de35521aSEric Joyner 	 * If filtering VLAN tags is disabled,
1550de35521aSEric Joyner 	 * there is no need to fill VLAN Filter Table Array (VFTA).
1551de35521aSEric Joyner 	 */
1552ff06a8dbSJustin Hibbits 	if ((if_getcapenable(ifp) & IFCAP_VLAN_HWFILTER) == 0)
1553de35521aSEric Joyner 		return;
15548eb6488eSEric Joyner 
15558eb6488eSEric Joyner 	/*
15568eb6488eSEric Joyner 	 * A soft reset zero's out the VFTA, so
15578eb6488eSEric Joyner 	 * we need to repopulate it now.
15588eb6488eSEric Joyner 	 */
15598eb6488eSEric Joyner 	for (int i = 0; i < IXGBE_VFTA_SIZE; i++) {
156061a8231dSYuichiro Naito 		if (sc->shadow_vfta[i] == 0)
15618eb6488eSEric Joyner 			continue;
156261a8231dSYuichiro Naito 		vfta = sc->shadow_vfta[i];
15638eb6488eSEric Joyner 		/*
15648eb6488eSEric Joyner 		 * Reconstruct the vlan id's
15658eb6488eSEric Joyner 		 * based on the bits set in each
15668eb6488eSEric Joyner 		 * of the array ints.
15678eb6488eSEric Joyner 		 */
15688eb6488eSEric Joyner 		for (int j = 0; j < 32; j++) {
15698eb6488eSEric Joyner 			retry = 0;
15708eb6488eSEric Joyner 			if ((vfta & (1 << j)) == 0)
15718eb6488eSEric Joyner 				continue;
15728eb6488eSEric Joyner 			vid = (i * 32) + j;
15738eb6488eSEric Joyner 			/* Call the shared code mailbox routine */
157479b36ec9SKevin Bowling 			while (hw->mac.ops.set_vfta(hw, vid, 0, true, false)) {
15758eb6488eSEric Joyner 				if (++retry > 5)
15768eb6488eSEric Joyner 					break;
15778eb6488eSEric Joyner 			}
15788eb6488eSEric Joyner 		}
15798eb6488eSEric Joyner 	}
15808eb6488eSEric Joyner } /* ixv_setup_vlan_support */
15818eb6488eSEric Joyner 
15828eb6488eSEric Joyner /************************************************************************
1583c19c7afeSEric Joyner  * ixv_if_register_vlan
15848eb6488eSEric Joyner  *
15858eb6488eSEric Joyner  *   Run via a vlan config EVENT, it enables us to use the
15868eb6488eSEric Joyner  *   HW Filter table since we can get the vlan id. This just
15878eb6488eSEric Joyner  *   creates the entry in the soft version of the VFTA, init
15888eb6488eSEric Joyner  *   will repopulate the real table.
15898eb6488eSEric Joyner  ************************************************************************/
15908eb6488eSEric Joyner static void
ixv_if_register_vlan(if_ctx_t ctx,u16 vtag)1591c19c7afeSEric Joyner ixv_if_register_vlan(if_ctx_t ctx, u16 vtag)
15928eb6488eSEric Joyner {
1593b1d5caf3SKevin Bowling 	struct ixgbe_softc *sc = iflib_get_softc(ctx);
15948eb6488eSEric Joyner 	u16 index, bit;
15958eb6488eSEric Joyner 
15968eb6488eSEric Joyner 	index = (vtag >> 5) & 0x7F;
15978eb6488eSEric Joyner 	bit = vtag & 0x1F;
159861a8231dSYuichiro Naito 	sc->shadow_vfta[index] |= (1 << bit);
1599b1d5caf3SKevin Bowling 	++sc->num_vlans;
1600c19c7afeSEric Joyner } /* ixv_if_register_vlan */
16018eb6488eSEric Joyner 
16028eb6488eSEric Joyner /************************************************************************
1603c19c7afeSEric Joyner  * ixv_if_unregister_vlan
16048eb6488eSEric Joyner  *
16058eb6488eSEric Joyner  *   Run via a vlan unconfig EVENT, remove our entry
16068eb6488eSEric Joyner  *   in the soft vfta.
16078eb6488eSEric Joyner  ************************************************************************/
16088eb6488eSEric Joyner static void
ixv_if_unregister_vlan(if_ctx_t ctx,u16 vtag)1609c19c7afeSEric Joyner ixv_if_unregister_vlan(if_ctx_t ctx, u16 vtag)
16108eb6488eSEric Joyner {
1611b1d5caf3SKevin Bowling 	struct ixgbe_softc *sc = iflib_get_softc(ctx);
16128eb6488eSEric Joyner 	u16 index, bit;
16138eb6488eSEric Joyner 
16148eb6488eSEric Joyner 	index = (vtag >> 5) & 0x7F;
16158eb6488eSEric Joyner 	bit = vtag & 0x1F;
161661a8231dSYuichiro Naito 	sc->shadow_vfta[index] &= ~(1 << bit);
1617b1d5caf3SKevin Bowling 	--sc->num_vlans;
1618c19c7afeSEric Joyner } /* ixv_if_unregister_vlan */
16198eb6488eSEric Joyner 
16208eb6488eSEric Joyner /************************************************************************
1621c19c7afeSEric Joyner  * ixv_if_enable_intr
16228eb6488eSEric Joyner  ************************************************************************/
16238eb6488eSEric Joyner static void
ixv_if_enable_intr(if_ctx_t ctx)1624c19c7afeSEric Joyner ixv_if_enable_intr(if_ctx_t ctx)
16258eb6488eSEric Joyner {
1626b1d5caf3SKevin Bowling 	struct ixgbe_softc *sc = iflib_get_softc(ctx);
1627b1d5caf3SKevin Bowling 	struct ixgbe_hw *hw = &sc->hw;
1628b1d5caf3SKevin Bowling 	struct ix_rx_queue *que = sc->rx_queues;
16298eb6488eSEric Joyner 	u32 mask = (IXGBE_EIMS_ENABLE_MASK & ~IXGBE_EIMS_RTX_QUEUE);
16308eb6488eSEric Joyner 
16318eb6488eSEric Joyner 	IXGBE_WRITE_REG(hw, IXGBE_VTEIMS, mask);
16328eb6488eSEric Joyner 
16338eb6488eSEric Joyner 	mask = IXGBE_EIMS_ENABLE_MASK;
16348eb6488eSEric Joyner 	mask &= ~(IXGBE_EIMS_OTHER | IXGBE_EIMS_LSC);
16358eb6488eSEric Joyner 	IXGBE_WRITE_REG(hw, IXGBE_VTEIAC, mask);
16368eb6488eSEric Joyner 
1637b1d5caf3SKevin Bowling 	for (int i = 0; i < sc->num_rx_queues; i++, que++)
1638b1d5caf3SKevin Bowling 		ixv_enable_queue(sc, que->msix);
16398eb6488eSEric Joyner 
16408eb6488eSEric Joyner 	IXGBE_WRITE_FLUSH(hw);
1641c19c7afeSEric Joyner } /* ixv_if_enable_intr */
16428eb6488eSEric Joyner 
16438eb6488eSEric Joyner /************************************************************************
1644c19c7afeSEric Joyner  * ixv_if_disable_intr
16458eb6488eSEric Joyner  ************************************************************************/
16468eb6488eSEric Joyner static void
ixv_if_disable_intr(if_ctx_t ctx)1647c19c7afeSEric Joyner ixv_if_disable_intr(if_ctx_t ctx)
16488eb6488eSEric Joyner {
1649b1d5caf3SKevin Bowling 	struct ixgbe_softc *sc = iflib_get_softc(ctx);
1650b1d5caf3SKevin Bowling 	IXGBE_WRITE_REG(&sc->hw, IXGBE_VTEIAC, 0);
1651b1d5caf3SKevin Bowling 	IXGBE_WRITE_REG(&sc->hw, IXGBE_VTEIMC, ~0);
1652b1d5caf3SKevin Bowling 	IXGBE_WRITE_FLUSH(&sc->hw);
1653c19c7afeSEric Joyner } /* ixv_if_disable_intr */
16548eb6488eSEric Joyner 
1655c19c7afeSEric Joyner /************************************************************************
1656c19c7afeSEric Joyner  * ixv_if_rx_queue_intr_enable
1657c19c7afeSEric Joyner  ************************************************************************/
1658c19c7afeSEric Joyner static int
ixv_if_rx_queue_intr_enable(if_ctx_t ctx,uint16_t rxqid)1659c19c7afeSEric Joyner ixv_if_rx_queue_intr_enable(if_ctx_t ctx, uint16_t rxqid)
1660c19c7afeSEric Joyner {
1661b1d5caf3SKevin Bowling 	struct ixgbe_softc *sc = iflib_get_softc(ctx);
1662b1d5caf3SKevin Bowling 	struct ix_rx_queue *que = &sc->rx_queues[rxqid];
1663c19c7afeSEric Joyner 
1664b1d5caf3SKevin Bowling 	ixv_enable_queue(sc, que->rxr.me);
1665c19c7afeSEric Joyner 
1666c19c7afeSEric Joyner 	return (0);
1667c19c7afeSEric Joyner } /* ixv_if_rx_queue_intr_enable */
16688eb6488eSEric Joyner 
16698eb6488eSEric Joyner /************************************************************************
16708eb6488eSEric Joyner  * ixv_set_ivar
16718eb6488eSEric Joyner  *
16728eb6488eSEric Joyner  *   Setup the correct IVAR register for a particular MSI-X interrupt
16738eb6488eSEric Joyner  *    - entry is the register array entry
16748eb6488eSEric Joyner  *    - vector is the MSI-X vector for this queue
16758eb6488eSEric Joyner  *    - type is RX/TX/MISC
16768eb6488eSEric Joyner  ************************************************************************/
16778eb6488eSEric Joyner static void
ixv_set_ivar(struct ixgbe_softc * sc,u8 entry,u8 vector,s8 type)1678b1d5caf3SKevin Bowling ixv_set_ivar(struct ixgbe_softc *sc, u8 entry, u8 vector, s8 type)
16798eb6488eSEric Joyner {
1680b1d5caf3SKevin Bowling 	struct ixgbe_hw *hw = &sc->hw;
16818eb6488eSEric Joyner 	u32 ivar, index;
16828eb6488eSEric Joyner 
16838eb6488eSEric Joyner 	vector |= IXGBE_IVAR_ALLOC_VAL;
16848eb6488eSEric Joyner 
16858eb6488eSEric Joyner 	if (type == -1) { /* MISC IVAR */
16868eb6488eSEric Joyner 		ivar = IXGBE_READ_REG(hw, IXGBE_VTIVAR_MISC);
16878eb6488eSEric Joyner 		ivar &= ~0xFF;
16888eb6488eSEric Joyner 		ivar |= vector;
16898eb6488eSEric Joyner 		IXGBE_WRITE_REG(hw, IXGBE_VTIVAR_MISC, ivar);
16908eb6488eSEric Joyner 	} else {          /* RX/TX IVARS */
16918eb6488eSEric Joyner 		index = (16 * (entry & 1)) + (8 * type);
16928eb6488eSEric Joyner 		ivar = IXGBE_READ_REG(hw, IXGBE_VTIVAR(entry >> 1));
16938eb6488eSEric Joyner 		ivar &= ~(0xFF << index);
16948eb6488eSEric Joyner 		ivar |= (vector << index);
16958eb6488eSEric Joyner 		IXGBE_WRITE_REG(hw, IXGBE_VTIVAR(entry >> 1), ivar);
16968eb6488eSEric Joyner 	}
16978eb6488eSEric Joyner } /* ixv_set_ivar */
16988eb6488eSEric Joyner 
16998eb6488eSEric Joyner /************************************************************************
17008eb6488eSEric Joyner  * ixv_configure_ivars
17018eb6488eSEric Joyner  ************************************************************************/
17028eb6488eSEric Joyner static void
ixv_configure_ivars(struct ixgbe_softc * sc)1703b1d5caf3SKevin Bowling ixv_configure_ivars(struct ixgbe_softc *sc)
17048eb6488eSEric Joyner {
1705b1d5caf3SKevin Bowling 	struct ix_rx_queue *que = sc->rx_queues;
17068eb6488eSEric Joyner 
1707b1d5caf3SKevin Bowling 	MPASS(sc->num_rx_queues == sc->num_tx_queues);
1708c19c7afeSEric Joyner 
1709b1d5caf3SKevin Bowling 	for (int i = 0; i < sc->num_rx_queues; i++, que++) {
17108eb6488eSEric Joyner 		/* First the RX queue entry */
1711b1d5caf3SKevin Bowling 		ixv_set_ivar(sc, i, que->msix, 0);
17128eb6488eSEric Joyner 		/* ... and the TX */
1713b1d5caf3SKevin Bowling 		ixv_set_ivar(sc, i, que->msix, 1);
17148eb6488eSEric Joyner 		/* Set an initial value in EITR */
1715b1d5caf3SKevin Bowling 		IXGBE_WRITE_REG(&sc->hw, IXGBE_VTEITR(que->msix),
17168eb6488eSEric Joyner 		    IXGBE_EITR_DEFAULT);
17178eb6488eSEric Joyner 	}
17188eb6488eSEric Joyner 
17198eb6488eSEric Joyner 	/* For the mailbox interrupt */
1720b1d5caf3SKevin Bowling 	ixv_set_ivar(sc, 1, sc->vector, -1);
17218eb6488eSEric Joyner } /* ixv_configure_ivars */
17228eb6488eSEric Joyner 
17238eb6488eSEric Joyner /************************************************************************
17248eb6488eSEric Joyner  * ixv_save_stats
17258eb6488eSEric Joyner  *
17268eb6488eSEric Joyner  *   The VF stats registers never have a truly virgin
17278eb6488eSEric Joyner  *   starting point, so this routine tries to make an
17288eb6488eSEric Joyner  *   artificial one, marking ground zero on attach as
17298eb6488eSEric Joyner  *   it were.
17308eb6488eSEric Joyner  ************************************************************************/
17318eb6488eSEric Joyner static void
ixv_save_stats(struct ixgbe_softc * sc)1732b1d5caf3SKevin Bowling ixv_save_stats(struct ixgbe_softc *sc)
17338eb6488eSEric Joyner {
1734b1d5caf3SKevin Bowling 	if (sc->stats.vf.vfgprc || sc->stats.vf.vfgptc) {
1735b1d5caf3SKevin Bowling 		sc->stats.vf.saved_reset_vfgprc +=
1736b1d5caf3SKevin Bowling 		    sc->stats.vf.vfgprc - sc->stats.vf.base_vfgprc;
1737b1d5caf3SKevin Bowling 		sc->stats.vf.saved_reset_vfgptc +=
1738b1d5caf3SKevin Bowling 		    sc->stats.vf.vfgptc - sc->stats.vf.base_vfgptc;
1739b1d5caf3SKevin Bowling 		sc->stats.vf.saved_reset_vfgorc +=
1740b1d5caf3SKevin Bowling 		    sc->stats.vf.vfgorc - sc->stats.vf.base_vfgorc;
1741b1d5caf3SKevin Bowling 		sc->stats.vf.saved_reset_vfgotc +=
1742b1d5caf3SKevin Bowling 		    sc->stats.vf.vfgotc - sc->stats.vf.base_vfgotc;
1743b1d5caf3SKevin Bowling 		sc->stats.vf.saved_reset_vfmprc +=
1744b1d5caf3SKevin Bowling 		    sc->stats.vf.vfmprc - sc->stats.vf.base_vfmprc;
17458eb6488eSEric Joyner 	}
17468eb6488eSEric Joyner } /* ixv_save_stats */
17478eb6488eSEric Joyner 
17488eb6488eSEric Joyner /************************************************************************
17498eb6488eSEric Joyner  * ixv_init_stats
17508eb6488eSEric Joyner  ************************************************************************/
17518eb6488eSEric Joyner static void
ixv_init_stats(struct ixgbe_softc * sc)1752b1d5caf3SKevin Bowling ixv_init_stats(struct ixgbe_softc *sc)
17538eb6488eSEric Joyner {
1754b1d5caf3SKevin Bowling 	struct ixgbe_hw *hw = &sc->hw;
17558eb6488eSEric Joyner 
1756b1d5caf3SKevin Bowling 	sc->stats.vf.last_vfgprc = IXGBE_READ_REG(hw, IXGBE_VFGPRC);
1757b1d5caf3SKevin Bowling 	sc->stats.vf.last_vfgorc = IXGBE_READ_REG(hw, IXGBE_VFGORC_LSB);
1758b1d5caf3SKevin Bowling 	sc->stats.vf.last_vfgorc |=
17598eb6488eSEric Joyner 	    (((u64)(IXGBE_READ_REG(hw, IXGBE_VFGORC_MSB))) << 32);
17608eb6488eSEric Joyner 
1761b1d5caf3SKevin Bowling 	sc->stats.vf.last_vfgptc = IXGBE_READ_REG(hw, IXGBE_VFGPTC);
1762b1d5caf3SKevin Bowling 	sc->stats.vf.last_vfgotc = IXGBE_READ_REG(hw, IXGBE_VFGOTC_LSB);
1763b1d5caf3SKevin Bowling 	sc->stats.vf.last_vfgotc |=
17648eb6488eSEric Joyner 	    (((u64)(IXGBE_READ_REG(hw, IXGBE_VFGOTC_MSB))) << 32);
17658eb6488eSEric Joyner 
1766b1d5caf3SKevin Bowling 	sc->stats.vf.last_vfmprc = IXGBE_READ_REG(hw, IXGBE_VFMPRC);
17678eb6488eSEric Joyner 
1768b1d5caf3SKevin Bowling 	sc->stats.vf.base_vfgprc = sc->stats.vf.last_vfgprc;
1769b1d5caf3SKevin Bowling 	sc->stats.vf.base_vfgorc = sc->stats.vf.last_vfgorc;
1770b1d5caf3SKevin Bowling 	sc->stats.vf.base_vfgptc = sc->stats.vf.last_vfgptc;
1771b1d5caf3SKevin Bowling 	sc->stats.vf.base_vfgotc = sc->stats.vf.last_vfgotc;
1772b1d5caf3SKevin Bowling 	sc->stats.vf.base_vfmprc = sc->stats.vf.last_vfmprc;
17738eb6488eSEric Joyner } /* ixv_init_stats */
17748eb6488eSEric Joyner 
17758eb6488eSEric Joyner #define UPDATE_STAT_32(reg, last, count)                \
17768eb6488eSEric Joyner {                                                       \
17778eb6488eSEric Joyner 	u32 current = IXGBE_READ_REG(hw, reg);          \
17788eb6488eSEric Joyner 	if (current < last)                             \
17798eb6488eSEric Joyner 		count += 0x100000000LL;                 \
17808eb6488eSEric Joyner 	last = current;                                 \
17818eb6488eSEric Joyner 	count &= 0xFFFFFFFF00000000LL;                  \
17828eb6488eSEric Joyner 	count |= current;                               \
17838eb6488eSEric Joyner }
17848eb6488eSEric Joyner 
17858eb6488eSEric Joyner #define UPDATE_STAT_36(lsb, msb, last, count)           \
17868eb6488eSEric Joyner {                                                       \
17878eb6488eSEric Joyner 	u64 cur_lsb = IXGBE_READ_REG(hw, lsb);          \
17888eb6488eSEric Joyner 	u64 cur_msb = IXGBE_READ_REG(hw, msb);          \
17898eb6488eSEric Joyner 	u64 current = ((cur_msb << 32) | cur_lsb);      \
17908eb6488eSEric Joyner 	if (current < last)                             \
17918eb6488eSEric Joyner 		count += 0x1000000000LL;                \
17928eb6488eSEric Joyner 	last = current;                                 \
17938eb6488eSEric Joyner 	count &= 0xFFFFFFF000000000LL;                  \
17948eb6488eSEric Joyner 	count |= current;                               \
17958eb6488eSEric Joyner }
17968eb6488eSEric Joyner 
17978eb6488eSEric Joyner /************************************************************************
17988eb6488eSEric Joyner  * ixv_update_stats - Update the board statistics counters.
17998eb6488eSEric Joyner  ************************************************************************/
18008eb6488eSEric Joyner void
ixv_update_stats(struct ixgbe_softc * sc)1801b1d5caf3SKevin Bowling ixv_update_stats(struct ixgbe_softc *sc)
18028eb6488eSEric Joyner {
1803b1d5caf3SKevin Bowling 	struct ixgbe_hw *hw = &sc->hw;
1804b1d5caf3SKevin Bowling 	struct ixgbevf_hw_stats *stats = &sc->stats.vf;
18058eb6488eSEric Joyner 
1806b1d5caf3SKevin Bowling 	UPDATE_STAT_32(IXGBE_VFGPRC, sc->stats.vf.last_vfgprc,
1807b1d5caf3SKevin Bowling 	    sc->stats.vf.vfgprc);
1808b1d5caf3SKevin Bowling 	UPDATE_STAT_32(IXGBE_VFGPTC, sc->stats.vf.last_vfgptc,
1809b1d5caf3SKevin Bowling 	    sc->stats.vf.vfgptc);
18108eb6488eSEric Joyner 	UPDATE_STAT_36(IXGBE_VFGORC_LSB, IXGBE_VFGORC_MSB,
1811b1d5caf3SKevin Bowling 	    sc->stats.vf.last_vfgorc, sc->stats.vf.vfgorc);
18128eb6488eSEric Joyner 	UPDATE_STAT_36(IXGBE_VFGOTC_LSB, IXGBE_VFGOTC_MSB,
1813b1d5caf3SKevin Bowling 	    sc->stats.vf.last_vfgotc, sc->stats.vf.vfgotc);
1814b1d5caf3SKevin Bowling 	UPDATE_STAT_32(IXGBE_VFMPRC, sc->stats.vf.last_vfmprc,
1815b1d5caf3SKevin Bowling 	    sc->stats.vf.vfmprc);
18168eb6488eSEric Joyner 
18178eb6488eSEric Joyner 	/* Fill out the OS statistics structure */
1818b1d5caf3SKevin Bowling 	IXGBE_SET_IPACKETS(sc, stats->vfgprc);
1819b1d5caf3SKevin Bowling 	IXGBE_SET_OPACKETS(sc, stats->vfgptc);
1820b1d5caf3SKevin Bowling 	IXGBE_SET_IBYTES(sc, stats->vfgorc);
1821b1d5caf3SKevin Bowling 	IXGBE_SET_OBYTES(sc, stats->vfgotc);
1822b1d5caf3SKevin Bowling 	IXGBE_SET_IMCASTS(sc, stats->vfmprc);
18238eb6488eSEric Joyner } /* ixv_update_stats */
18248eb6488eSEric Joyner 
18258eb6488eSEric Joyner /************************************************************************
18268eb6488eSEric Joyner  * ixv_add_stats_sysctls - Add statistic sysctls for the VF.
18278eb6488eSEric Joyner  ************************************************************************/
18288eb6488eSEric Joyner static void
ixv_add_stats_sysctls(struct ixgbe_softc * sc)1829b1d5caf3SKevin Bowling ixv_add_stats_sysctls(struct ixgbe_softc *sc)
18308eb6488eSEric Joyner {
1831b1d5caf3SKevin Bowling 	device_t dev = sc->dev;
1832b1d5caf3SKevin Bowling 	struct ix_tx_queue *tx_que = sc->tx_queues;
1833b1d5caf3SKevin Bowling 	struct ix_rx_queue *rx_que = sc->rx_queues;
18348eb6488eSEric Joyner 	struct sysctl_ctx_list *ctx = device_get_sysctl_ctx(dev);
18358eb6488eSEric Joyner 	struct sysctl_oid *tree = device_get_sysctl_tree(dev);
18368eb6488eSEric Joyner 	struct sysctl_oid_list *child = SYSCTL_CHILDREN(tree);
1837b1d5caf3SKevin Bowling 	struct ixgbevf_hw_stats *stats = &sc->stats.vf;
18388eb6488eSEric Joyner 	struct sysctl_oid *stat_node, *queue_node;
18398eb6488eSEric Joyner 	struct sysctl_oid_list *stat_list, *queue_list;
18408eb6488eSEric Joyner 
18418eb6488eSEric Joyner #define QUEUE_NAME_LEN 32
18428eb6488eSEric Joyner 	char namebuf[QUEUE_NAME_LEN];
18438eb6488eSEric Joyner 
18448eb6488eSEric Joyner 	/* Driver Statistics */
18458eb6488eSEric Joyner 	SYSCTL_ADD_ULONG(ctx, child, OID_AUTO, "watchdog_events",
1846b1d5caf3SKevin Bowling 	    CTLFLAG_RD, &sc->watchdog_events, "Watchdog timeouts");
18478eb6488eSEric Joyner 	SYSCTL_ADD_ULONG(ctx, child, OID_AUTO, "link_irq",
1848b1d5caf3SKevin Bowling 	    CTLFLAG_RD, &sc->link_irq, "Link MSI-X IRQ Handled");
18498eb6488eSEric Joyner 
1850b1d5caf3SKevin Bowling 	for (int i = 0; i < sc->num_tx_queues; i++, tx_que++) {
1851c19c7afeSEric Joyner 		struct tx_ring *txr = &tx_que->txr;
1852c19c7afeSEric Joyner 		snprintf(namebuf, QUEUE_NAME_LEN, "queue%d", i);
1853c19c7afeSEric Joyner 		queue_node = SYSCTL_ADD_NODE(ctx, child, OID_AUTO, namebuf,
185420b91f0aSPawel Biernacki 		    CTLFLAG_RD | CTLFLAG_MPSAFE, NULL, "Queue Name");
1855c19c7afeSEric Joyner 		queue_list = SYSCTL_CHILDREN(queue_node);
1856c19c7afeSEric Joyner 
1857788a1230SEric Joyner 		SYSCTL_ADD_UQUAD(ctx, queue_list, OID_AUTO, "tso_tx",
1858c19c7afeSEric Joyner 		    CTLFLAG_RD, &(txr->tso_tx), "TSO Packets");
1859c19c7afeSEric Joyner 		SYSCTL_ADD_UQUAD(ctx, queue_list, OID_AUTO, "tx_packets",
1860c19c7afeSEric Joyner 		    CTLFLAG_RD, &(txr->total_packets), "TX Packets");
1861c19c7afeSEric Joyner 	}
1862c19c7afeSEric Joyner 
1863b1d5caf3SKevin Bowling 	for (int i = 0; i < sc->num_rx_queues; i++, rx_que++) {
1864c19c7afeSEric Joyner 		struct rx_ring *rxr = &rx_que->rxr;
18658eb6488eSEric Joyner 		snprintf(namebuf, QUEUE_NAME_LEN, "queue%d", i);
18668eb6488eSEric Joyner 		queue_node = SYSCTL_ADD_NODE(ctx, child, OID_AUTO, namebuf,
186720b91f0aSPawel Biernacki 		    CTLFLAG_RD | CTLFLAG_MPSAFE, NULL, "Queue Name");
18688eb6488eSEric Joyner 		queue_list = SYSCTL_CHILDREN(queue_node);
18698eb6488eSEric Joyner 
18708eb6488eSEric Joyner 		SYSCTL_ADD_UQUAD(ctx, queue_list, OID_AUTO, "irqs",
1871c19c7afeSEric Joyner 		    CTLFLAG_RD, &(rx_que->irqs), "IRQs on queue");
18728eb6488eSEric Joyner 		SYSCTL_ADD_UQUAD(ctx, queue_list, OID_AUTO, "rx_packets",
18738eb6488eSEric Joyner 		    CTLFLAG_RD, &(rxr->rx_packets), "RX packets");
18748eb6488eSEric Joyner 		SYSCTL_ADD_UQUAD(ctx, queue_list, OID_AUTO, "rx_bytes",
18758eb6488eSEric Joyner 		    CTLFLAG_RD, &(rxr->rx_bytes), "RX bytes");
18768eb6488eSEric Joyner 		SYSCTL_ADD_UQUAD(ctx, queue_list, OID_AUTO, "rx_discarded",
18778eb6488eSEric Joyner 		    CTLFLAG_RD, &(rxr->rx_discarded), "Discarded RX packets");
18788eb6488eSEric Joyner 	}
18798eb6488eSEric Joyner 
18808eb6488eSEric Joyner 	stat_node = SYSCTL_ADD_NODE(ctx, child, OID_AUTO, "mac",
188120b91f0aSPawel Biernacki 	    CTLFLAG_RD | CTLFLAG_MPSAFE, NULL,
188220b91f0aSPawel Biernacki 	    "VF Statistics (read from HW registers)");
18838eb6488eSEric Joyner 	stat_list = SYSCTL_CHILDREN(stat_node);
18848eb6488eSEric Joyner 
18858eb6488eSEric Joyner 	SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "good_pkts_rcvd",
18868eb6488eSEric Joyner 	    CTLFLAG_RD, &stats->vfgprc, "Good Packets Received");
18878eb6488eSEric Joyner 	SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "good_octets_rcvd",
18888eb6488eSEric Joyner 	    CTLFLAG_RD, &stats->vfgorc, "Good Octets Received");
18898eb6488eSEric Joyner 	SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "mcast_pkts_rcvd",
18908eb6488eSEric Joyner 	    CTLFLAG_RD, &stats->vfmprc, "Multicast Packets Received");
18918eb6488eSEric Joyner 	SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "good_pkts_txd",
18928eb6488eSEric Joyner 	    CTLFLAG_RD, &stats->vfgptc, "Good Packets Transmitted");
18938eb6488eSEric Joyner 	SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "good_octets_txd",
18948eb6488eSEric Joyner 	    CTLFLAG_RD, &stats->vfgotc, "Good Octets Transmitted");
18958eb6488eSEric Joyner } /* ixv_add_stats_sysctls */
18968eb6488eSEric Joyner 
18978eb6488eSEric Joyner /************************************************************************
18988eb6488eSEric Joyner  * ixv_print_debug_info
18998eb6488eSEric Joyner  *
19008eb6488eSEric Joyner  *   Called only when em_display_debug_stats is enabled.
19018eb6488eSEric Joyner  *   Provides a way to take a look at important statistics
19028eb6488eSEric Joyner  *   maintained by the driver and hardware.
19038eb6488eSEric Joyner  ************************************************************************/
19048eb6488eSEric Joyner static void
ixv_print_debug_info(struct ixgbe_softc * sc)1905b1d5caf3SKevin Bowling ixv_print_debug_info(struct ixgbe_softc *sc)
19068eb6488eSEric Joyner {
1907b1d5caf3SKevin Bowling 	device_t dev = sc->dev;
1908b1d5caf3SKevin Bowling 	struct ixgbe_hw *hw = &sc->hw;
19098eb6488eSEric Joyner 
19108eb6488eSEric Joyner 	device_printf(dev, "Error Byte Count = %u \n",
19118eb6488eSEric Joyner 	    IXGBE_READ_REG(hw, IXGBE_ERRBC));
19128eb6488eSEric Joyner 
1913b1d5caf3SKevin Bowling 	device_printf(dev, "MBX IRQ Handled: %lu\n", (long)sc->link_irq);
19148eb6488eSEric Joyner } /* ixv_print_debug_info */
19158eb6488eSEric Joyner 
19168eb6488eSEric Joyner /************************************************************************
19178eb6488eSEric Joyner  * ixv_sysctl_debug
19188eb6488eSEric Joyner  ************************************************************************/
19198eb6488eSEric Joyner static int
ixv_sysctl_debug(SYSCTL_HANDLER_ARGS)19208eb6488eSEric Joyner ixv_sysctl_debug(SYSCTL_HANDLER_ARGS)
19218eb6488eSEric Joyner {
1922b1d5caf3SKevin Bowling 	struct ixgbe_softc *sc;
19238eb6488eSEric Joyner 	int error, result;
19248eb6488eSEric Joyner 
19258eb6488eSEric Joyner 	result = -1;
19268eb6488eSEric Joyner 	error = sysctl_handle_int(oidp, &result, 0, req);
19278eb6488eSEric Joyner 
19288eb6488eSEric Joyner 	if (error || !req->newptr)
19298eb6488eSEric Joyner 		return (error);
19308eb6488eSEric Joyner 
19318eb6488eSEric Joyner 	if (result == 1) {
1932b1d5caf3SKevin Bowling 		sc = (struct ixgbe_softc *)arg1;
1933b1d5caf3SKevin Bowling 		ixv_print_debug_info(sc);
19348eb6488eSEric Joyner 	}
19358eb6488eSEric Joyner 
19368eb6488eSEric Joyner 	return error;
19378eb6488eSEric Joyner } /* ixv_sysctl_debug */
19388eb6488eSEric Joyner 
19398eb6488eSEric Joyner /************************************************************************
19408eb6488eSEric Joyner  * ixv_init_device_features
19418eb6488eSEric Joyner  ************************************************************************/
19428eb6488eSEric Joyner static void
ixv_init_device_features(struct ixgbe_softc * sc)1943b1d5caf3SKevin Bowling ixv_init_device_features(struct ixgbe_softc *sc)
19448eb6488eSEric Joyner {
1945*c58d34ddSKevin Bowling 	sc->feat_cap = IXGBE_FEATURE_NETMAP |
1946*c58d34ddSKevin Bowling 	    IXGBE_FEATURE_VF |
1947*c58d34ddSKevin Bowling 	    IXGBE_FEATURE_LEGACY_TX;
19488eb6488eSEric Joyner 
19498eb6488eSEric Joyner 	/* A tad short on feature flags for VFs, atm. */
1950b1d5caf3SKevin Bowling 	switch (sc->hw.mac.type) {
19518eb6488eSEric Joyner 	case ixgbe_mac_82599_vf:
19528eb6488eSEric Joyner 		break;
19538eb6488eSEric Joyner 	case ixgbe_mac_X540_vf:
19548eb6488eSEric Joyner 		break;
19558eb6488eSEric Joyner 	case ixgbe_mac_X550_vf:
19568eb6488eSEric Joyner 	case ixgbe_mac_X550EM_x_vf:
19578eb6488eSEric Joyner 	case ixgbe_mac_X550EM_a_vf:
1958b1d5caf3SKevin Bowling 		sc->feat_cap |= IXGBE_FEATURE_NEEDS_CTXD;
1959b1d5caf3SKevin Bowling 		sc->feat_cap |= IXGBE_FEATURE_RSS;
19608eb6488eSEric Joyner 		break;
19618eb6488eSEric Joyner 	default:
19628eb6488eSEric Joyner 		break;
19638eb6488eSEric Joyner 	}
19648eb6488eSEric Joyner 
19658eb6488eSEric Joyner 	/* Enabled by default... */
19668eb6488eSEric Joyner 	/* Is a virtual function (VF) */
1967b1d5caf3SKevin Bowling 	if (sc->feat_cap & IXGBE_FEATURE_VF)
1968b1d5caf3SKevin Bowling 		sc->feat_en |= IXGBE_FEATURE_VF;
19698eb6488eSEric Joyner 	/* Netmap */
1970b1d5caf3SKevin Bowling 	if (sc->feat_cap & IXGBE_FEATURE_NETMAP)
1971b1d5caf3SKevin Bowling 		sc->feat_en |= IXGBE_FEATURE_NETMAP;
19728eb6488eSEric Joyner 	/* Receive-Side Scaling (RSS) */
1973b1d5caf3SKevin Bowling 	if (sc->feat_cap & IXGBE_FEATURE_RSS)
1974b1d5caf3SKevin Bowling 		sc->feat_en |= IXGBE_FEATURE_RSS;
19758eb6488eSEric Joyner 	/* Needs advanced context descriptor regardless of offloads req'd */
1976b1d5caf3SKevin Bowling 	if (sc->feat_cap & IXGBE_FEATURE_NEEDS_CTXD)
1977b1d5caf3SKevin Bowling 		sc->feat_en |= IXGBE_FEATURE_NEEDS_CTXD;
19788eb6488eSEric Joyner } /* ixv_init_device_features */
19798eb6488eSEric Joyner 
1980