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