if_ixl.c revision 266423
1266423Sjfv/******************************************************************************
2266423Sjfv
3266423Sjfv  Copyright (c) 2013-2014, Intel Corporation
4266423Sjfv  All rights reserved.
5266423Sjfv
6266423Sjfv  Redistribution and use in source and binary forms, with or without
7266423Sjfv  modification, are permitted provided that the following conditions are met:
8266423Sjfv
9266423Sjfv   1. Redistributions of source code must retain the above copyright notice,
10266423Sjfv      this list of conditions and the following disclaimer.
11266423Sjfv
12266423Sjfv   2. Redistributions in binary form must reproduce the above copyright
13266423Sjfv      notice, this list of conditions and the following disclaimer in the
14266423Sjfv      documentation and/or other materials provided with the distribution.
15266423Sjfv
16266423Sjfv   3. Neither the name of the Intel Corporation nor the names of its
17266423Sjfv      contributors may be used to endorse or promote products derived from
18266423Sjfv      this software without specific prior written permission.
19266423Sjfv
20266423Sjfv  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21266423Sjfv  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22266423Sjfv  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23266423Sjfv  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
24266423Sjfv  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25266423Sjfv  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26266423Sjfv  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27266423Sjfv  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28266423Sjfv  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29266423Sjfv  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30266423Sjfv  POSSIBILITY OF SUCH DAMAGE.
31266423Sjfv
32266423Sjfv******************************************************************************/
33266423Sjfv/*$FreeBSD: head/sys/dev/i40e/if_i40e.c 266423 2014-05-19 01:21:02Z jfv $*/
34266423Sjfv
35266423Sjfv#include "opt_inet.h"
36266423Sjfv#include "opt_inet6.h"
37266423Sjfv#include "i40e.h"
38266423Sjfv#include "i40e_pf.h"
39266423Sjfv
40266423Sjfv/*********************************************************************
41266423Sjfv *  Driver version
42266423Sjfv *********************************************************************/
43266423Sjfvchar i40e_driver_version[] = "0.6.9 - Beta Release";
44266423Sjfv
45266423Sjfv/*********************************************************************
46266423Sjfv *  PCI Device ID Table
47266423Sjfv *
48266423Sjfv *  Used by probe to select devices to load on
49266423Sjfv *  Last field stores an index into i40e_strings
50266423Sjfv *  Last entry must be all 0s
51266423Sjfv *
52266423Sjfv *  { Vendor ID, Device ID, SubVendor ID, SubDevice ID, String Index }
53266423Sjfv *********************************************************************/
54266423Sjfv
55266423Sjfvstatic i40e_vendor_info_t i40e_vendor_info_array[] =
56266423Sjfv{
57266423Sjfv	{I40E_INTEL_VENDOR_ID, I40E_DEV_ID_SFP_XL710, 0, 0, 0},
58266423Sjfv	{I40E_INTEL_VENDOR_ID, I40E_DEV_ID_KX_A, 0, 0, 0},
59266423Sjfv	{I40E_INTEL_VENDOR_ID, I40E_DEV_ID_KX_B, 0, 0, 0},
60266423Sjfv	{I40E_INTEL_VENDOR_ID, I40E_DEV_ID_KX_C, 0, 0, 0},
61266423Sjfv	{I40E_INTEL_VENDOR_ID, I40E_DEV_ID_QSFP_A, 0, 0, 0},
62266423Sjfv	{I40E_INTEL_VENDOR_ID, I40E_DEV_ID_QSFP_B, 0, 0, 0},
63266423Sjfv	{I40E_INTEL_VENDOR_ID, I40E_DEV_ID_QSFP_C, 0, 0, 0},
64266423Sjfv	/* required last entry */
65266423Sjfv	{0, 0, 0, 0, 0}
66266423Sjfv};
67266423Sjfv
68266423Sjfv/*********************************************************************
69266423Sjfv *  Table of branding strings
70266423Sjfv *********************************************************************/
71266423Sjfv
72266423Sjfvstatic char    *i40e_strings[] = {
73266423Sjfv	"Intel(R) Ethernet Connection XL710 Driver"
74266423Sjfv};
75266423Sjfv
76266423Sjfv
77266423Sjfv/*********************************************************************
78266423Sjfv *  Function prototypes
79266423Sjfv *********************************************************************/
80266423Sjfvstatic int      i40e_probe(device_t);
81266423Sjfvstatic int      i40e_attach(device_t);
82266423Sjfvstatic int      i40e_detach(device_t);
83266423Sjfvstatic int      i40e_shutdown(device_t);
84266423Sjfvstatic int	i40e_get_hw_capabilities(struct i40e_pf *);
85266423Sjfvstatic void	i40e_cap_txcsum_tso(struct i40e_vsi *, struct ifnet *, int);
86266423Sjfvstatic int      i40e_ioctl(struct ifnet *, u_long, caddr_t);
87266423Sjfvstatic void	i40e_init(void *);
88266423Sjfvstatic void	i40e_init_locked(struct i40e_pf *);
89266423Sjfvstatic void     i40e_stop(struct i40e_pf *);
90266423Sjfvstatic void     i40e_media_status(struct ifnet *, struct ifmediareq *);
91266423Sjfvstatic int      i40e_media_change(struct ifnet *);
92266423Sjfvstatic void     i40e_update_link_status(struct i40e_pf *);
93266423Sjfvstatic int      i40e_allocate_pci_resources(struct i40e_pf *);
94266423Sjfvstatic u16	i40e_get_bus_info(struct i40e_hw *, device_t);
95266423Sjfvstatic int	i40e_setup_stations(struct i40e_pf *);
96266423Sjfvstatic int	i40e_setup_vsi(struct i40e_vsi *);
97266423Sjfvstatic int	i40e_initialize_vsi(struct i40e_vsi *);
98266423Sjfvstatic int	i40e_assign_vsi_msix(struct i40e_pf *);
99266423Sjfvstatic int	i40e_assign_vsi_legacy(struct i40e_pf *);
100266423Sjfvstatic int	i40e_init_msix(struct i40e_pf *);
101266423Sjfvstatic void	i40e_configure_msix(struct i40e_pf *);
102266423Sjfvstatic void	i40e_configure_itr(struct i40e_pf *);
103266423Sjfvstatic void	i40e_configure_legacy(struct i40e_pf *);
104266423Sjfvstatic void	i40e_free_pci_resources(struct i40e_pf *);
105266423Sjfvstatic void	i40e_local_timer(void *);
106266423Sjfvstatic int	i40e_setup_interface(device_t, struct i40e_vsi *);
107266423Sjfvstatic bool	i40e_config_link(struct i40e_hw *);
108266423Sjfvstatic void	i40e_config_rss(struct i40e_vsi *);
109266423Sjfvstatic void	i40e_set_queue_rx_itr(struct i40e_queue *);
110266423Sjfvstatic void	i40e_set_queue_tx_itr(struct i40e_queue *);
111266423Sjfv
112266423Sjfvstatic void	i40e_enable_rings(struct i40e_vsi *);
113266423Sjfvstatic void	i40e_disable_rings(struct i40e_vsi *);
114266423Sjfvstatic void     i40e_enable_intr(struct i40e_vsi *);
115266423Sjfvstatic void     i40e_disable_intr(struct i40e_vsi *);
116266423Sjfv
117266423Sjfvstatic void     i40e_enable_adminq(struct i40e_hw *);
118266423Sjfvstatic void     i40e_disable_adminq(struct i40e_hw *);
119266423Sjfvstatic void     i40e_enable_queue(struct i40e_hw *, int);
120266423Sjfvstatic void     i40e_disable_queue(struct i40e_hw *, int);
121266423Sjfvstatic void     i40e_enable_legacy(struct i40e_hw *);
122266423Sjfvstatic void     i40e_disable_legacy(struct i40e_hw *);
123266423Sjfv
124266423Sjfvstatic void     i40e_set_promisc(struct i40e_vsi *);
125266423Sjfvstatic void     i40e_add_multi(struct i40e_vsi *);
126266423Sjfvstatic void     i40e_del_multi(struct i40e_vsi *);
127266423Sjfvstatic void	i40e_register_vlan(void *, struct ifnet *, u16);
128266423Sjfvstatic void	i40e_unregister_vlan(void *, struct ifnet *, u16);
129266423Sjfvstatic void	i40e_setup_vlan_filters(struct i40e_vsi *);
130266423Sjfv
131266423Sjfvstatic void	i40e_init_filters(struct i40e_vsi *);
132266423Sjfvstatic void	i40e_add_filter(struct i40e_vsi *, u8 *, s16 vlan);
133266423Sjfvstatic void	i40e_del_filter(struct i40e_vsi *, u8 *, s16 vlan);
134266423Sjfvstatic void	i40e_add_hw_filters(struct i40e_vsi *, int, int);
135266423Sjfvstatic void	i40e_del_hw_filters(struct i40e_vsi *, int);
136266423Sjfvstatic struct i40e_mac_filter *
137266423Sjfv		i40e_find_filter(struct i40e_vsi *, u8 *, s16);
138266423Sjfvstatic void	i40e_add_mc_filter(struct i40e_vsi *, u8 *);
139266423Sjfv
140266423Sjfv/* Sysctl debug interface */
141266423Sjfvstatic int	i40e_debug_info(SYSCTL_HANDLER_ARGS);
142266423Sjfvstatic void	i40e_print_debug_info(struct i40e_pf *);
143266423Sjfv
144266423Sjfv/* The MSI/X Interrupt handlers */
145266423Sjfvstatic void	i40e_intr(void *);
146266423Sjfvstatic void	i40e_msix_que(void *);
147266423Sjfvstatic void	i40e_msix_adminq(void *);
148266423Sjfv
149266423Sjfv/* Deferred interrupt tasklets */
150266423Sjfvstatic void	i40e_do_adminq(void *, int);
151266423Sjfv
152266423Sjfv/* Sysctl handlers */
153266423Sjfvstatic int	i40e_set_flowcntl(SYSCTL_HANDLER_ARGS);
154266423Sjfv
155266423Sjfv/* Statistics */
156266423Sjfvstatic void     i40e_add_hw_stats(struct i40e_pf *);
157266423Sjfvstatic void	i40e_add_sysctls_mac_stats(struct sysctl_ctx_list *,
158266423Sjfv		    struct sysctl_oid_list *, struct i40e_hw_port_stats *);
159266423Sjfvstatic void	i40e_add_sysctls_eth_stats(struct sysctl_ctx_list *,
160266423Sjfv		    struct sysctl_oid_list *,
161266423Sjfv		    struct i40e_eth_stats *);
162266423Sjfvstatic void	i40e_update_stats_counters(struct i40e_pf *);
163266423Sjfvstatic void	i40e_update_eth_stats(struct i40e_vsi *);
164266423Sjfvstatic void	i40e_pf_reset_stats(struct i40e_pf *);
165266423Sjfvstatic void	i40e_vsi_reset_stats(struct i40e_vsi *);
166266423Sjfvstatic void	i40e_stat_update48(struct i40e_hw *, u32, u32, bool,
167266423Sjfv		    u64 *, u64 *);
168266423Sjfvstatic void	i40e_stat_update32(struct i40e_hw *, u32, bool,
169266423Sjfv		    u64 *, u64 *);
170266423Sjfv
171266423Sjfv#ifdef I40E_DEBUG
172266423Sjfvstatic int 	i40e_sysctl_link_status(SYSCTL_HANDLER_ARGS);
173266423Sjfvstatic int	i40e_sysctl_phy_abilities(SYSCTL_HANDLER_ARGS);
174266423Sjfvstatic int	i40e_sysctl_sw_filter_list(SYSCTL_HANDLER_ARGS);
175266423Sjfv#endif
176266423Sjfv
177266423Sjfv/*********************************************************************
178266423Sjfv *  FreeBSD Device Interface Entry Points
179266423Sjfv *********************************************************************/
180266423Sjfv
181266423Sjfvstatic device_method_t i40e_methods[] = {
182266423Sjfv	/* Device interface */
183266423Sjfv	DEVMETHOD(device_probe, i40e_probe),
184266423Sjfv	DEVMETHOD(device_attach, i40e_attach),
185266423Sjfv	DEVMETHOD(device_detach, i40e_detach),
186266423Sjfv	DEVMETHOD(device_shutdown, i40e_shutdown),
187266423Sjfv	{0, 0}
188266423Sjfv};
189266423Sjfv
190266423Sjfvstatic driver_t i40e_driver = {
191266423Sjfv	"i40e", i40e_methods, sizeof(struct i40e_pf),
192266423Sjfv};
193266423Sjfv
194266423Sjfvdevclass_t i40e_devclass;
195266423SjfvDRIVER_MODULE(i40e, pci, i40e_driver, i40e_devclass, 0, 0);
196266423Sjfv
197266423SjfvMODULE_DEPEND(i40e, pci, 1, 1, 1);
198266423SjfvMODULE_DEPEND(i40e, ether, 1, 1, 1);
199266423Sjfv
200266423Sjfv/*
201266423Sjfv * MSIX should be the default for best performance,
202266423Sjfv * but this allows it to be forced off for testing.
203266423Sjfv */
204266423Sjfvstatic int i40e_enable_msix = 1;
205266423SjfvTUNABLE_INT("hw.i40e.enable_msix", &i40e_enable_msix);
206266423Sjfv
207266423Sjfv/*
208266423Sjfv** Number of descriptors per ring:
209266423Sjfv**   - TX and RX are the same size
210266423Sjfv*/
211266423Sjfvstatic int i40e_ringsz = DEFAULT_RING;
212266423SjfvTUNABLE_INT("hw.i40e.ringsz", &i40e_ringsz);
213266423Sjfv
214266423Sjfv/*
215266423Sjfv** This can be set manually, if left as 0 the
216266423Sjfv** number of queues will be calculated based
217266423Sjfv** on cpus and msix vectors available.
218266423Sjfv*/
219266423Sjfvint i40e_max_queues = 0;
220266423SjfvTUNABLE_INT("hw.i40e.max_queues", &i40e_max_queues);
221266423Sjfv
222266423Sjfv/*
223266423Sjfv** Controls for Interrupt Throttling
224266423Sjfv**	- true/false for dynamic adjustment
225266423Sjfv** 	- default values for static ITR
226266423Sjfv*/
227266423Sjfvint i40e_dynamic_rx_itr = 0;
228266423SjfvTUNABLE_INT("hw.i40e.dynamic_rx_itr", &i40e_dynamic_rx_itr);
229266423Sjfvint i40e_dynamic_tx_itr = 0;
230266423SjfvTUNABLE_INT("hw.i40e.dynamic_tx_itr", &i40e_dynamic_tx_itr);
231266423Sjfv
232266423Sjfvint i40e_rx_itr = I40E_ITR_8K;
233266423SjfvTUNABLE_INT("hw.i40e.rx_itr", &i40e_rx_itr);
234266423Sjfvint i40e_tx_itr = I40E_ITR_4K;
235266423SjfvTUNABLE_INT("hw.i40e.tx_itr", &i40e_tx_itr);
236266423Sjfv
237266423Sjfv#ifdef I40E_FDIR
238266423Sjfvstatic int i40e_enable_fdir = 1;
239266423SjfvTUNABLE_INT("hw.i40e.enable_fdir", &i40e_enable_fdir);
240266423Sjfv/* Rate at which we sample */
241266423Sjfvint i40e_atr_rate = 20;
242266423SjfvTUNABLE_INT("hw.i40e.atr_rate", &i40e_atr_rate);
243266423Sjfv#endif
244266423Sjfv
245266423Sjfv
246266423Sjfvstatic char *i40e_fc_string[6] = {
247266423Sjfv	"None",
248266423Sjfv	"Rx",
249266423Sjfv	"Tx",
250266423Sjfv	"Full",
251266423Sjfv	"Priority",
252266423Sjfv	"Default"
253266423Sjfv};
254266423Sjfv
255266423Sjfv/*********************************************************************
256266423Sjfv *  Device identification routine
257266423Sjfv *
258266423Sjfv *  i40e_probe determines if the driver should be loaded on
259266423Sjfv *  the hardware based on PCI vendor/device id of the device.
260266423Sjfv *
261266423Sjfv *  return BUS_PROBE_DEFAULT on success, positive on failure
262266423Sjfv *********************************************************************/
263266423Sjfv
264266423Sjfvstatic int
265266423Sjfvi40e_probe(device_t dev)
266266423Sjfv{
267266423Sjfv	i40e_vendor_info_t *ent;
268266423Sjfv
269266423Sjfv	u16	pci_vendor_id, pci_device_id;
270266423Sjfv	u16	pci_subvendor_id, pci_subdevice_id;
271266423Sjfv	char	device_name[256];
272266423Sjfv
273266423Sjfv	INIT_DEBUGOUT("i40e_probe: begin");
274266423Sjfv
275266423Sjfv	pci_vendor_id = pci_get_vendor(dev);
276266423Sjfv	if (pci_vendor_id != I40E_INTEL_VENDOR_ID)
277266423Sjfv		return (ENXIO);
278266423Sjfv
279266423Sjfv	pci_device_id = pci_get_device(dev);
280266423Sjfv	pci_subvendor_id = pci_get_subvendor(dev);
281266423Sjfv	pci_subdevice_id = pci_get_subdevice(dev);
282266423Sjfv
283266423Sjfv	ent = i40e_vendor_info_array;
284266423Sjfv	while (ent->vendor_id != 0) {
285266423Sjfv		if ((pci_vendor_id == ent->vendor_id) &&
286266423Sjfv		    (pci_device_id == ent->device_id) &&
287266423Sjfv
288266423Sjfv		    ((pci_subvendor_id == ent->subvendor_id) ||
289266423Sjfv		     (ent->subvendor_id == 0)) &&
290266423Sjfv
291266423Sjfv		    ((pci_subdevice_id == ent->subdevice_id) ||
292266423Sjfv		     (ent->subdevice_id == 0))) {
293266423Sjfv			sprintf(device_name, "%s, Version - %s",
294266423Sjfv				i40e_strings[ent->index],
295266423Sjfv				i40e_driver_version);
296266423Sjfv			device_set_desc_copy(dev, device_name);
297266423Sjfv			return (BUS_PROBE_DEFAULT);
298266423Sjfv		}
299266423Sjfv		ent++;
300266423Sjfv	}
301266423Sjfv	return (ENXIO);
302266423Sjfv}
303266423Sjfv
304266423Sjfv/*********************************************************************
305266423Sjfv *  Device initialization routine
306266423Sjfv *
307266423Sjfv *  The attach entry point is called when the driver is being loaded.
308266423Sjfv *  This routine identifies the type of hardware, allocates all resources
309266423Sjfv *  and initializes the hardware.
310266423Sjfv *
311266423Sjfv *  return 0 on success, positive on failure
312266423Sjfv *********************************************************************/
313266423Sjfv
314266423Sjfvstatic int
315266423Sjfvi40e_attach(device_t dev)
316266423Sjfv{
317266423Sjfv	struct i40e_pf	*pf;
318266423Sjfv	struct i40e_hw	*hw;
319266423Sjfv	struct i40e_vsi *vsi;
320266423Sjfv	u16		bus;
321266423Sjfv	u32		reg;
322266423Sjfv	int             error = 0;
323266423Sjfv
324266423Sjfv	INIT_DEBUGOUT("i40e_attach: begin");
325266423Sjfv
326266423Sjfv	/* Allocate, clear, and link in our primary soft structure */
327266423Sjfv	pf = device_get_softc(dev);
328266423Sjfv	pf->dev = pf->osdep.dev = dev;
329266423Sjfv	hw = &pf->hw;
330266423Sjfv
331266423Sjfv	/*
332266423Sjfv	** Note this assumes we have a single embedded VSI,
333266423Sjfv	** this could be enhanced later to allocate multiple
334266423Sjfv	*/
335266423Sjfv	vsi = &pf->vsi;
336266423Sjfv	vsi->dev = pf->dev;
337266423Sjfv
338266423Sjfv	/* Core Lock Init*/
339266423Sjfv	I40E_PF_LOCK_INIT(pf, device_get_nameunit(dev));
340266423Sjfv
341266423Sjfv	/* Set up the timer callout */
342266423Sjfv	callout_init_mtx(&pf->timer, &pf->pf_mtx, 0);
343266423Sjfv
344266423Sjfv	/* Set up sysctls */
345266423Sjfv	SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev),
346266423Sjfv	    SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
347266423Sjfv	    OID_AUTO, "fc", CTLTYPE_INT | CTLFLAG_RW,
348266423Sjfv	    pf, 0, i40e_set_flowcntl, "I", "Flow Control");
349266423Sjfv
350266423Sjfv	SYSCTL_ADD_INT(device_get_sysctl_ctx(dev),
351266423Sjfv	    SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
352266423Sjfv	    OID_AUTO, "rx_itr", CTLTYPE_INT | CTLFLAG_RW,
353266423Sjfv	    &i40e_rx_itr, I40E_ITR_8K, "RX ITR");
354266423Sjfv
355266423Sjfv	SYSCTL_ADD_INT(device_get_sysctl_ctx(dev),
356266423Sjfv	    SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
357266423Sjfv	    OID_AUTO, "dynamic_rx_itr", CTLTYPE_INT | CTLFLAG_RW,
358266423Sjfv	    &i40e_dynamic_rx_itr, 0, "Dynamic RX ITR");
359266423Sjfv
360266423Sjfv	SYSCTL_ADD_INT(device_get_sysctl_ctx(dev),
361266423Sjfv	    SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
362266423Sjfv	    OID_AUTO, "tx_itr", CTLTYPE_INT | CTLFLAG_RW,
363266423Sjfv	    &i40e_tx_itr, I40E_ITR_4K, "TX ITR");
364266423Sjfv
365266423Sjfv	SYSCTL_ADD_INT(device_get_sysctl_ctx(dev),
366266423Sjfv	    SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
367266423Sjfv	    OID_AUTO, "dynamic_tx_itr", CTLTYPE_INT | CTLFLAG_RW,
368266423Sjfv	    &i40e_dynamic_tx_itr, 0, "Dynamic TX ITR");
369266423Sjfv
370266423Sjfv#ifdef I40E_DEBUG
371266423Sjfv	SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev),
372266423Sjfv	    SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
373266423Sjfv	    OID_AUTO, "link_status", CTLTYPE_STRING | CTLFLAG_RD,
374266423Sjfv	    pf, 0, i40e_sysctl_link_status, "A", "Current Link Status");
375266423Sjfv
376266423Sjfv	SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev),
377266423Sjfv	    SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
378266423Sjfv	    OID_AUTO, "phy_abilities", CTLTYPE_STRING | CTLFLAG_RD,
379266423Sjfv	    pf, 0, i40e_sysctl_phy_abilities, "A", "PHY Abilities");
380266423Sjfv
381266423Sjfv	SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev),
382266423Sjfv	    SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
383266423Sjfv	    OID_AUTO, "filter_list", CTLTYPE_STRING | CTLFLAG_RD,
384266423Sjfv	    pf, 0, i40e_sysctl_sw_filter_list, "A", "SW Filter List");
385266423Sjfv#endif
386266423Sjfv
387266423Sjfv	/* Save off the information about this board */
388266423Sjfv	hw->vendor_id = pci_get_vendor(dev);
389266423Sjfv	hw->device_id = pci_get_device(dev);
390266423Sjfv	hw->revision_id = pci_read_config(dev, PCIR_REVID, 1);
391266423Sjfv	hw->subsystem_vendor_id =
392266423Sjfv	    pci_read_config(dev, PCIR_SUBVEND_0, 2);
393266423Sjfv	hw->subsystem_device_id =
394266423Sjfv	    pci_read_config(dev, PCIR_SUBDEV_0, 2);
395266423Sjfv
396266423Sjfv	hw->bus.device = pci_get_device(dev);
397266423Sjfv	hw->bus.func = pci_get_function(dev);
398266423Sjfv
399266423Sjfv	/* Do PCI setup - map BAR0, etc */
400266423Sjfv	if (i40e_allocate_pci_resources(pf)) {
401266423Sjfv		device_printf(dev, "Allocation of PCI resources failed\n");
402266423Sjfv		error = ENXIO;
403266423Sjfv		goto err_out;
404266423Sjfv	}
405266423Sjfv
406266423Sjfv	/* Create for initial debugging use */
407266423Sjfv	SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev),
408266423Sjfv	    SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
409266423Sjfv	    OID_AUTO, "debug", CTLTYPE_INT|CTLFLAG_RW, pf, 0,
410266423Sjfv	    i40e_debug_info, "I", "Debug Information");
411266423Sjfv
412266423Sjfv	/* Workaround to keep ARI detection off */
413266423Sjfv	reg = rd32(hw, I40E_GLPCI_CAPSUP);
414266423Sjfv	reg &= ~I40E_GLPCI_CAPSUP_ARI_EN_MASK;
415266423Sjfv	wr32(hw, I40E_GLPCI_CAPSUP, reg);
416266423Sjfv
417266423Sjfv	/* Establish a clean starting point */
418266423Sjfv	error = i40e_pf_reset(hw);
419266423Sjfv	if (error) {
420266423Sjfv		// TODO: Remove EMPR reset
421266423Sjfv		/* Use the heavy hammer, force a firmware reset */
422266423Sjfv		reg = rd32(&pf->hw, I40E_GLGEN_RSTENA_EMP);
423266423Sjfv		reg |= I40E_GLGEN_RSTENA_EMP_EMP_RST_ENA_MASK;
424266423Sjfv		wr32(&pf->hw, I40E_GLGEN_RSTENA_EMP, reg);
425266423Sjfv		/* force the reset */
426266423Sjfv		reg = rd32(&pf->hw, I40E_GLGEN_RTRIG);
427266423Sjfv		reg |= I40E_GLGEN_RTRIG_EMPFWR_MASK;
428266423Sjfv		wr32(&pf->hw, I40E_GLGEN_RTRIG, reg);
429266423Sjfv		i40e_flush(hw);
430266423Sjfv
431266423Sjfv		error = i40e_pf_reset(hw);
432266423Sjfv		if (error) {
433266423Sjfv			device_printf(dev,"PF reset failure %x\n", error);
434266423Sjfv			error = EIO;
435266423Sjfv			goto err_out;
436266423Sjfv		}
437266423Sjfv	}
438266423Sjfv
439266423Sjfv	/* Set admin queue parameters */
440266423Sjfv	hw->aq.num_arq_entries = I40E_AQ_LEN;
441266423Sjfv	hw->aq.num_asq_entries = I40E_AQ_LEN;
442266423Sjfv	hw->aq.arq_buf_size = I40E_AQ_BUFSZ;
443266423Sjfv	hw->aq.asq_buf_size = I40E_AQ_BUFSZ;
444266423Sjfv
445266423Sjfv	/* Initialize the shared code */
446266423Sjfv	error = i40e_init_shared_code(hw);
447266423Sjfv	if (error) {
448266423Sjfv		device_printf(dev,"Unable to initialize the shared code\n");
449266423Sjfv		error = EIO;
450266423Sjfv		goto err_out;
451266423Sjfv	}
452266423Sjfv
453266423Sjfv	/* Set up the admin queue */
454266423Sjfv	error = i40e_init_adminq(hw);
455266423Sjfv	if (error) {
456266423Sjfv		device_printf(dev, "Admin Queue setup failure!\n");
457266423Sjfv		goto err_out;
458266423Sjfv	}
459266423Sjfv
460266423Sjfv#ifdef I40E_DEBUG
461266423Sjfv	device_printf(dev,"Firmware version: %d.%d "
462266423Sjfv	    "API version %d.%d NVM track %x version %x\n",
463266423Sjfv	    hw->aq.fw_maj_ver, hw->aq.fw_min_ver,
464266423Sjfv	    hw->aq.api_maj_ver, hw->aq.api_min_ver,
465266423Sjfv	    hw->nvm.eetrack, hw->nvm.version);
466266423Sjfv#endif
467266423Sjfv
468266423Sjfv	/* Clear PXE mode */
469266423Sjfv	i40e_clear_pxe_mode(hw);
470266423Sjfv
471266423Sjfv	/* Get capabilities from the device */
472266423Sjfv	error = i40e_get_hw_capabilities(pf);
473266423Sjfv	if (error) {
474266423Sjfv		device_printf(dev, "HW capabilities failure!\n");
475266423Sjfv		goto err_get_cap;
476266423Sjfv	}
477266423Sjfv
478266423Sjfv	/* Set up host memory cache */
479266423Sjfv	error = i40e_init_lan_hmc(hw, vsi->num_queues, vsi->num_queues, 0, 0);
480266423Sjfv	if (error) {
481266423Sjfv		device_printf(dev, "init_lan_hmc failed: %d\n", error);
482266423Sjfv		goto err_get_cap;
483266423Sjfv	}
484266423Sjfv
485266423Sjfv	error = i40e_configure_lan_hmc(hw, I40E_HMC_MODEL_DIRECT_ONLY);
486266423Sjfv	if (error) {
487266423Sjfv		device_printf(dev, "configure_lan_hmc failed: %d\n", error);
488266423Sjfv		goto err_mac_hmc;
489266423Sjfv	}
490266423Sjfv
491266423Sjfv	i40e_get_mac_addr(hw, hw->mac.addr);
492266423Sjfv	error = i40e_validate_mac_addr(hw->mac.addr);
493266423Sjfv	if (error) {
494266423Sjfv		device_printf(dev, "validate_mac_addr failed: %d\n", error);
495266423Sjfv		goto err_mac_hmc;
496266423Sjfv	}
497266423Sjfv	bcopy(hw->mac.addr, hw->mac.perm_addr, ETHER_ADDR_LEN);
498266423Sjfv	i40e_get_port_mac_addr(hw, hw->mac.port_addr);
499266423Sjfv
500266423Sjfv	if (i40e_setup_stations(pf) != 0) {
501266423Sjfv		device_printf(dev, "setup stations failed!\n");
502266423Sjfv		error = ENOMEM;
503266423Sjfv		goto err_mac_hmc;
504266423Sjfv	}
505266423Sjfv
506266423Sjfv	/* Initialize mac filter list for VSI */
507266423Sjfv	SLIST_INIT(&vsi->ftl);
508266423Sjfv
509266423Sjfv	/* Set up interrupt routing here */
510266423Sjfv	if (pf->msix > 1)
511266423Sjfv		error = i40e_assign_vsi_msix(pf);
512266423Sjfv	else
513266423Sjfv		error = i40e_assign_vsi_legacy(pf);
514266423Sjfv	if (error)
515266423Sjfv		goto err_late;
516266423Sjfv
517266423Sjfv	/* Determine link state */
518266423Sjfv	vsi->link_up = i40e_config_link(hw);
519266423Sjfv
520266423Sjfv	/* Setup OS specific network interface */
521266423Sjfv	if (i40e_setup_interface(dev, vsi) != 0)
522266423Sjfv		goto err_late;
523266423Sjfv
524266423Sjfv	/* Get the bus configuration and set the shared code */
525266423Sjfv	bus = i40e_get_bus_info(hw, dev);
526266423Sjfv	i40e_set_pci_config_data(hw, bus);
527266423Sjfv
528266423Sjfv	/* Initialize statistics */
529266423Sjfv	i40e_pf_reset_stats(pf);
530266423Sjfv	i40e_update_stats_counters(pf);
531266423Sjfv	i40e_add_hw_stats(pf);
532266423Sjfv
533266423Sjfv	/* Register for VLAN events */
534266423Sjfv	vsi->vlan_attach = EVENTHANDLER_REGISTER(vlan_config,
535266423Sjfv	    i40e_register_vlan, vsi, EVENTHANDLER_PRI_FIRST);
536266423Sjfv	vsi->vlan_detach = EVENTHANDLER_REGISTER(vlan_unconfig,
537266423Sjfv	    i40e_unregister_vlan, vsi, EVENTHANDLER_PRI_FIRST);
538266423Sjfv
539266423Sjfv	INIT_DEBUGOUT("i40e_attach: end");
540266423Sjfv	return (0);
541266423Sjfv
542266423Sjfverr_late:
543266423Sjfv	i40e_free_vsi(vsi);
544266423Sjfverr_mac_hmc:
545266423Sjfv	i40e_shutdown_lan_hmc(hw);
546266423Sjfverr_get_cap:
547266423Sjfv	i40e_shutdown_adminq(hw);
548266423Sjfverr_out:
549266423Sjfv	if (vsi->ifp != NULL)
550266423Sjfv		if_free(vsi->ifp);
551266423Sjfv	i40e_free_pci_resources(pf);
552266423Sjfv	I40E_PF_LOCK_DESTROY(pf);
553266423Sjfv	return (error);
554266423Sjfv}
555266423Sjfv
556266423Sjfv/*********************************************************************
557266423Sjfv *  Device removal routine
558266423Sjfv *
559266423Sjfv *  The detach entry point is called when the driver is being removed.
560266423Sjfv *  This routine stops the adapter and deallocates all the resources
561266423Sjfv *  that were allocated for driver operation.
562266423Sjfv *
563266423Sjfv *  return 0 on success, positive on failure
564266423Sjfv *********************************************************************/
565266423Sjfv
566266423Sjfvstatic int
567266423Sjfvi40e_detach(device_t dev)
568266423Sjfv{
569266423Sjfv	struct i40e_pf		*pf = device_get_softc(dev);
570266423Sjfv	struct i40e_hw		*hw = &pf->hw;
571266423Sjfv	struct i40e_vsi		*vsi = &pf->vsi;
572266423Sjfv	struct i40e_queue	*que = vsi->queues;
573266423Sjfv	i40e_status		status;
574266423Sjfv	u32			reg;
575266423Sjfv
576266423Sjfv	INIT_DEBUGOUT("i40e_detach: begin");
577266423Sjfv
578266423Sjfv	/* Make sure VLANS are not using driver */
579266423Sjfv	if (vsi->ifp->if_vlantrunk != NULL) {
580266423Sjfv		device_printf(dev,"Vlan in use, detach first\n");
581266423Sjfv		return (EBUSY);
582266423Sjfv	}
583266423Sjfv
584266423Sjfv	I40E_PF_LOCK(pf);
585266423Sjfv	i40e_stop(pf);
586266423Sjfv	I40E_PF_UNLOCK(pf);
587266423Sjfv
588266423Sjfv	for (int i = 0; i < vsi->num_queues; i++, que++) {
589266423Sjfv		if (que->tq) {
590266423Sjfv			taskqueue_drain(que->tq, &que->task);
591266423Sjfv			taskqueue_drain(que->tq, &que->tx_task);
592266423Sjfv			taskqueue_free(que->tq);
593266423Sjfv		}
594266423Sjfv	}
595266423Sjfv
596266423Sjfv	/* Drain other tasks here */
597266423Sjfv
598266423Sjfv	/* Shutdown LAN HMC */
599266423Sjfv	status = i40e_shutdown_lan_hmc(hw);
600266423Sjfv	if (status)
601266423Sjfv		device_printf(dev,
602266423Sjfv		    "Shutdown LAN HMC failed with code %d\n", status);
603266423Sjfv
604266423Sjfv	/* Shutdown admin queue */
605266423Sjfv	status = i40e_shutdown_adminq(hw);
606266423Sjfv	if (status)
607266423Sjfv		device_printf(dev,
608266423Sjfv		    "Shutdown Admin queue failed with code %d\n", status);
609266423Sjfv
610266423Sjfv	/* Now force a pf reset */
611266423Sjfv	reg = rd32(hw, I40E_PFGEN_CTRL);
612266423Sjfv	reg |= I40E_PFGEN_CTRL_PFSWR_MASK;
613266423Sjfv	wr32(hw, I40E_PFGEN_CTRL, reg);
614266423Sjfv	//i40e_pf_reset(hw);
615266423Sjfv	i40e_flush(hw);
616266423Sjfv
617266423Sjfv	/* Unregister VLAN events */
618266423Sjfv	if (vsi->vlan_attach != NULL)
619266423Sjfv		EVENTHANDLER_DEREGISTER(vlan_config, vsi->vlan_attach);
620266423Sjfv	if (vsi->vlan_detach != NULL)
621266423Sjfv		EVENTHANDLER_DEREGISTER(vlan_unconfig, vsi->vlan_detach);
622266423Sjfv
623266423Sjfv	ether_ifdetach(vsi->ifp);
624266423Sjfv	callout_drain(&pf->timer);
625266423Sjfv
626266423Sjfv
627266423Sjfv	i40e_free_pci_resources(pf);
628266423Sjfv	bus_generic_detach(dev);
629266423Sjfv	if_free(vsi->ifp);
630266423Sjfv	i40e_free_vsi(vsi);
631266423Sjfv	I40E_PF_LOCK_DESTROY(pf);
632266423Sjfv	return (0);
633266423Sjfv}
634266423Sjfv
635266423Sjfv/*********************************************************************
636266423Sjfv *
637266423Sjfv *  Shutdown entry point
638266423Sjfv *
639266423Sjfv **********************************************************************/
640266423Sjfv
641266423Sjfvstatic int
642266423Sjfvi40e_shutdown(device_t dev)
643266423Sjfv{
644266423Sjfv	struct i40e_pf *pf = device_get_softc(dev);
645266423Sjfv	I40E_PF_LOCK(pf);
646266423Sjfv	i40e_stop(pf);
647266423Sjfv	I40E_PF_UNLOCK(pf);
648266423Sjfv	return (0);
649266423Sjfv}
650266423Sjfv
651266423Sjfv
652266423Sjfv/*********************************************************************
653266423Sjfv *
654266423Sjfv *  Get the hardware capabilities
655266423Sjfv *
656266423Sjfv **********************************************************************/
657266423Sjfv
658266423Sjfvstatic int
659266423Sjfvi40e_get_hw_capabilities(struct i40e_pf *pf)
660266423Sjfv{
661266423Sjfv	struct i40e_aqc_list_capabilities_element_resp *buf;
662266423Sjfv	struct i40e_hw	*hw = &pf->hw;
663266423Sjfv	device_t 	dev = pf->dev;
664266423Sjfv	int             error, len;
665266423Sjfv	u16		needed;
666266423Sjfv	bool		again = TRUE;
667266423Sjfv
668266423Sjfv	len = 40 * sizeof(struct i40e_aqc_list_capabilities_element_resp);
669266423Sjfvretry:
670266423Sjfv	if (!(buf = (struct i40e_aqc_list_capabilities_element_resp *)
671266423Sjfv	    malloc(len, M_DEVBUF, M_NOWAIT | M_ZERO))) {
672266423Sjfv		device_printf(dev, "Unable to allocate cap memory\n");
673266423Sjfv                return (ENOMEM);
674266423Sjfv	}
675266423Sjfv
676266423Sjfv	/* This populates the hw struct */
677266423Sjfv        error = i40e_aq_discover_capabilities(hw, buf, len,
678266423Sjfv	    &needed, i40e_aqc_opc_list_func_capabilities, NULL);
679266423Sjfv	free(buf, M_DEVBUF);
680266423Sjfv	if ((pf->hw.aq.asq_last_status == I40E_AQ_RC_ENOMEM) &&
681266423Sjfv	    (again == TRUE)) {
682266423Sjfv		/* retry once with a larger buffer */
683266423Sjfv		again = FALSE;
684266423Sjfv		len = needed;
685266423Sjfv		goto retry;
686266423Sjfv	} else if (pf->hw.aq.asq_last_status != I40E_AQ_RC_OK) {
687266423Sjfv		device_printf(dev, "capability discovery failed: %d\n",
688266423Sjfv		    pf->hw.aq.asq_last_status);
689266423Sjfv		return (ENODEV);
690266423Sjfv	}
691266423Sjfv
692266423Sjfv	/* Capture this PF's starting queue pair */
693266423Sjfv	pf->qbase = hw->func_caps.base_queue;
694266423Sjfv
695266423Sjfv#ifdef I40E_DEBUG
696266423Sjfv	device_printf(dev,"pf_id=%d, num_vfs=%d, msix_pf=%d, "
697266423Sjfv	    "msix_vf=%d, fd_g=%d, fd_b=%d, tx_qp=%d rx_qp=%d qbase=%d\n",
698266423Sjfv	    hw->pf_id, hw->func_caps.num_vfs,
699266423Sjfv	    hw->func_caps.num_msix_vectors,
700266423Sjfv	    hw->func_caps.num_msix_vectors_vf,
701266423Sjfv	    hw->func_caps.fd_filters_guaranteed,
702266423Sjfv	    hw->func_caps.fd_filters_best_effort,
703266423Sjfv	    hw->func_caps.num_tx_qp,
704266423Sjfv	    hw->func_caps.num_rx_qp,
705266423Sjfv	    hw->func_caps.base_queue);
706266423Sjfv#endif
707266423Sjfv	return (error);
708266423Sjfv}
709266423Sjfv
710266423Sjfvstatic void
711266423Sjfvi40e_cap_txcsum_tso(struct i40e_vsi *vsi, struct ifnet *ifp, int mask)
712266423Sjfv{
713266423Sjfv	device_t 	dev = vsi->dev;
714266423Sjfv
715266423Sjfv	/* Enable/disable TXCSUM/TSO4 */
716266423Sjfv	if (!(ifp->if_capenable & IFCAP_TXCSUM)
717266423Sjfv	    && !(ifp->if_capenable & IFCAP_TSO4)) {
718266423Sjfv		if (mask & IFCAP_TXCSUM) {
719266423Sjfv			ifp->if_capenable |= IFCAP_TXCSUM;
720266423Sjfv			/* enable TXCSUM, restore TSO if previously enabled */
721266423Sjfv			if (vsi->flags & I40E_FLAGS_KEEP_TSO4) {
722266423Sjfv				vsi->flags &= ~I40E_FLAGS_KEEP_TSO4;
723266423Sjfv				ifp->if_capenable |= IFCAP_TSO4;
724266423Sjfv			}
725266423Sjfv		}
726266423Sjfv		else if (mask & IFCAP_TSO4) {
727266423Sjfv			ifp->if_capenable |= (IFCAP_TXCSUM | IFCAP_TSO4);
728266423Sjfv			vsi->flags &= ~I40E_FLAGS_KEEP_TSO4;
729266423Sjfv			device_printf(dev,
730266423Sjfv			    "TSO4 requires txcsum, enabling both...\n");
731266423Sjfv		}
732266423Sjfv	} else if((ifp->if_capenable & IFCAP_TXCSUM)
733266423Sjfv	    && !(ifp->if_capenable & IFCAP_TSO4)) {
734266423Sjfv		if (mask & IFCAP_TXCSUM)
735266423Sjfv			ifp->if_capenable &= ~IFCAP_TXCSUM;
736266423Sjfv		else if (mask & IFCAP_TSO4)
737266423Sjfv			ifp->if_capenable |= IFCAP_TSO4;
738266423Sjfv	} else if((ifp->if_capenable & IFCAP_TXCSUM)
739266423Sjfv	    && (ifp->if_capenable & IFCAP_TSO4)) {
740266423Sjfv		if (mask & IFCAP_TXCSUM) {
741266423Sjfv			vsi->flags |= I40E_FLAGS_KEEP_TSO4;
742266423Sjfv			ifp->if_capenable &= ~(IFCAP_TXCSUM | IFCAP_TSO4);
743266423Sjfv			device_printf(dev,
744266423Sjfv			    "TSO4 requires txcsum, disabling both...\n");
745266423Sjfv		} else if (mask & IFCAP_TSO4)
746266423Sjfv			ifp->if_capenable &= ~IFCAP_TSO4;
747266423Sjfv	}
748266423Sjfv
749266423Sjfv	/* Enable/disable TXCSUM_IPV6/TSO6 */
750266423Sjfv	if (!(ifp->if_capenable & IFCAP_TXCSUM_IPV6)
751266423Sjfv	    && !(ifp->if_capenable & IFCAP_TSO6)) {
752266423Sjfv		if (mask & IFCAP_TXCSUM_IPV6) {
753266423Sjfv			ifp->if_capenable |= IFCAP_TXCSUM_IPV6;
754266423Sjfv			if (vsi->flags & I40E_FLAGS_KEEP_TSO6) {
755266423Sjfv				vsi->flags &= ~I40E_FLAGS_KEEP_TSO6;
756266423Sjfv				ifp->if_capenable |= IFCAP_TSO6;
757266423Sjfv			}
758266423Sjfv		} else if (mask & IFCAP_TSO6) {
759266423Sjfv			ifp->if_capenable |= (IFCAP_TXCSUM_IPV6 | IFCAP_TSO6);
760266423Sjfv			vsi->flags &= ~I40E_FLAGS_KEEP_TSO6;
761266423Sjfv			device_printf(dev,
762266423Sjfv			    "TSO6 requires txcsum6, enabling both...\n");
763266423Sjfv		}
764266423Sjfv	} else if((ifp->if_capenable & IFCAP_TXCSUM_IPV6)
765266423Sjfv	    && !(ifp->if_capenable & IFCAP_TSO6)) {
766266423Sjfv		if (mask & IFCAP_TXCSUM_IPV6)
767266423Sjfv			ifp->if_capenable &= ~IFCAP_TXCSUM_IPV6;
768266423Sjfv		else if (mask & IFCAP_TSO6)
769266423Sjfv			ifp->if_capenable |= IFCAP_TSO6;
770266423Sjfv	} else if ((ifp->if_capenable & IFCAP_TXCSUM_IPV6)
771266423Sjfv	    && (ifp->if_capenable & IFCAP_TSO6)) {
772266423Sjfv		if (mask & IFCAP_TXCSUM_IPV6) {
773266423Sjfv			vsi->flags |= I40E_FLAGS_KEEP_TSO6;
774266423Sjfv			ifp->if_capenable &= ~(IFCAP_TXCSUM_IPV6 | IFCAP_TSO6);
775266423Sjfv			device_printf(dev,
776266423Sjfv			    "TSO6 requires txcsum6, disabling both...\n");
777266423Sjfv		} else if (mask & IFCAP_TSO6)
778266423Sjfv			ifp->if_capenable &= ~IFCAP_TSO6;
779266423Sjfv	}
780266423Sjfv}
781266423Sjfv
782266423Sjfv/*********************************************************************
783266423Sjfv *  Ioctl entry point
784266423Sjfv *
785266423Sjfv *  i40e_ioctl is called when the user wants to configure the
786266423Sjfv *  interface.
787266423Sjfv *
788266423Sjfv *  return 0 on success, positive on failure
789266423Sjfv **********************************************************************/
790266423Sjfv
791266423Sjfvstatic int
792266423Sjfvi40e_ioctl(struct ifnet * ifp, u_long command, caddr_t data)
793266423Sjfv{
794266423Sjfv	struct i40e_vsi	*vsi = ifp->if_softc;
795266423Sjfv	struct i40e_pf	*pf = (struct i40e_pf *)vsi->back;
796266423Sjfv	struct ifreq	*ifr = (struct ifreq *) data;
797266423Sjfv#if defined(INET) || defined(INET6)
798266423Sjfv	struct ifaddr *ifa = (struct ifaddr *)data;
799266423Sjfv	bool		avoid_reset = FALSE;
800266423Sjfv#endif
801266423Sjfv	int             error = 0;
802266423Sjfv
803266423Sjfv	switch (command) {
804266423Sjfv
805266423Sjfv        case SIOCSIFADDR:
806266423Sjfv#ifdef INET
807266423Sjfv		if (ifa->ifa_addr->sa_family == AF_INET)
808266423Sjfv			avoid_reset = TRUE;
809266423Sjfv#endif
810266423Sjfv#ifdef INET6
811266423Sjfv		if (ifa->ifa_addr->sa_family == AF_INET6)
812266423Sjfv			avoid_reset = TRUE;
813266423Sjfv#endif
814266423Sjfv#if defined(INET) || defined(INET6)
815266423Sjfv		/*
816266423Sjfv		** Calling init results in link renegotiation,
817266423Sjfv		** so we avoid doing it when possible.
818266423Sjfv		*/
819266423Sjfv		if (avoid_reset) {
820266423Sjfv			ifp->if_flags |= IFF_UP;
821266423Sjfv			if (!(ifp->if_drv_flags & IFF_DRV_RUNNING))
822266423Sjfv				i40e_init(pf);
823266423Sjfv			if (!(ifp->if_flags & IFF_NOARP))
824266423Sjfv				arp_ifinit(ifp, ifa);
825266423Sjfv		} else
826266423Sjfv			error = ether_ioctl(ifp, command, data);
827266423Sjfv		break;
828266423Sjfv#endif
829266423Sjfv	case SIOCSIFMTU:
830266423Sjfv		IOCTL_DEBUGOUT("ioctl: SIOCSIFMTU (Set Interface MTU)");
831266423Sjfv		if (ifr->ifr_mtu > I40E_MAX_FRAME -
832266423Sjfv		   ETHER_HDR_LEN - ETHER_CRC_LEN - ETHER_VLAN_ENCAP_LEN) {
833266423Sjfv			error = EINVAL;
834266423Sjfv		} else {
835266423Sjfv			I40E_PF_LOCK(pf);
836266423Sjfv			ifp->if_mtu = ifr->ifr_mtu;
837266423Sjfv			vsi->max_frame_size =
838266423Sjfv				ifp->if_mtu + ETHER_HDR_LEN + ETHER_CRC_LEN
839266423Sjfv			    + ETHER_VLAN_ENCAP_LEN;
840266423Sjfv			i40e_init_locked(pf);
841266423Sjfv			I40E_PF_UNLOCK(pf);
842266423Sjfv		}
843266423Sjfv		break;
844266423Sjfv	case SIOCSIFFLAGS:
845266423Sjfv		IOCTL_DEBUGOUT("ioctl: SIOCSIFFLAGS (Set Interface Flags)");
846266423Sjfv		I40E_PF_LOCK(pf);
847266423Sjfv		if (ifp->if_flags & IFF_UP) {
848266423Sjfv			if ((ifp->if_drv_flags & IFF_DRV_RUNNING)) {
849266423Sjfv				if ((ifp->if_flags ^ pf->if_flags) &
850266423Sjfv				    (IFF_PROMISC | IFF_ALLMULTI)) {
851266423Sjfv					i40e_set_promisc(vsi);
852266423Sjfv				}
853266423Sjfv			} else
854266423Sjfv				i40e_init_locked(pf);
855266423Sjfv		} else
856266423Sjfv			if (ifp->if_drv_flags & IFF_DRV_RUNNING)
857266423Sjfv				i40e_stop(pf);
858266423Sjfv		pf->if_flags = ifp->if_flags;
859266423Sjfv		I40E_PF_UNLOCK(pf);
860266423Sjfv		break;
861266423Sjfv	case SIOCADDMULTI:
862266423Sjfv		IOCTL_DEBUGOUT("ioctl: SIOCADDMULTI");
863266423Sjfv		if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
864266423Sjfv			I40E_PF_LOCK(pf);
865266423Sjfv			i40e_disable_intr(vsi);
866266423Sjfv			i40e_add_multi(vsi);
867266423Sjfv			i40e_enable_intr(vsi);
868266423Sjfv			I40E_PF_UNLOCK(pf);
869266423Sjfv		}
870266423Sjfv		break;
871266423Sjfv	case SIOCDELMULTI:
872266423Sjfv		IOCTL_DEBUGOUT("ioctl: SIOCDELMULTI");
873266423Sjfv		if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
874266423Sjfv			I40E_PF_LOCK(pf);
875266423Sjfv			i40e_disable_intr(vsi);
876266423Sjfv			i40e_del_multi(vsi);
877266423Sjfv			i40e_enable_intr(vsi);
878266423Sjfv			I40E_PF_UNLOCK(pf);
879266423Sjfv		}
880266423Sjfv		break;
881266423Sjfv	case SIOCSIFMEDIA:
882266423Sjfv	case SIOCGIFMEDIA:
883266423Sjfv		IOCTL_DEBUGOUT("ioctl: SIOCxIFMEDIA (Get/Set Interface Media)");
884266423Sjfv		error = ifmedia_ioctl(ifp, ifr, &vsi->media, command);
885266423Sjfv		break;
886266423Sjfv	case SIOCSIFCAP:
887266423Sjfv	{
888266423Sjfv		int mask = ifr->ifr_reqcap ^ ifp->if_capenable;
889266423Sjfv		IOCTL_DEBUGOUT("ioctl: SIOCSIFCAP (Set Capabilities)");
890266423Sjfv
891266423Sjfv		i40e_cap_txcsum_tso(vsi, ifp, mask);
892266423Sjfv
893266423Sjfv		if (mask & IFCAP_RXCSUM)
894266423Sjfv			ifp->if_capenable ^= IFCAP_RXCSUM;
895266423Sjfv		if (mask & IFCAP_RXCSUM_IPV6)
896266423Sjfv			ifp->if_capenable ^= IFCAP_RXCSUM_IPV6;
897266423Sjfv		if (mask & IFCAP_LRO)
898266423Sjfv			ifp->if_capenable ^= IFCAP_LRO;
899266423Sjfv		if (mask & IFCAP_VLAN_HWTAGGING)
900266423Sjfv			ifp->if_capenable ^= IFCAP_VLAN_HWTAGGING;
901266423Sjfv		if (mask & IFCAP_VLAN_HWFILTER)
902266423Sjfv			ifp->if_capenable ^= IFCAP_VLAN_HWFILTER;
903266423Sjfv		if (mask & IFCAP_VLAN_HWTSO)
904266423Sjfv			ifp->if_capenable ^= IFCAP_VLAN_HWTSO;
905266423Sjfv		if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
906266423Sjfv			I40E_PF_LOCK(pf);
907266423Sjfv			i40e_init_locked(pf);
908266423Sjfv			I40E_PF_UNLOCK(pf);
909266423Sjfv		}
910266423Sjfv		VLAN_CAPABILITIES(ifp);
911266423Sjfv
912266423Sjfv		break;
913266423Sjfv	}
914266423Sjfv
915266423Sjfv	default:
916266423Sjfv		IOCTL_DEBUGOUT1("ioctl: UNKNOWN (0x%X)\n", (int)command);
917266423Sjfv		error = ether_ioctl(ifp, command, data);
918266423Sjfv		break;
919266423Sjfv	}
920266423Sjfv
921266423Sjfv	return (error);
922266423Sjfv}
923266423Sjfv
924266423Sjfv
925266423Sjfv/*********************************************************************
926266423Sjfv *  Init entry point
927266423Sjfv *
928266423Sjfv *  This routine is used in two ways. It is used by the stack as
929266423Sjfv *  init entry point in network interface structure. It is also used
930266423Sjfv *  by the driver as a hw/sw initialization routine to get to a
931266423Sjfv *  consistent state.
932266423Sjfv *
933266423Sjfv *  return 0 on success, positive on failure
934266423Sjfv **********************************************************************/
935266423Sjfv
936266423Sjfvstatic void
937266423Sjfvi40e_init_locked(struct i40e_pf *pf)
938266423Sjfv{
939266423Sjfv	struct i40e_hw	*hw = &pf->hw;
940266423Sjfv	struct i40e_vsi	*vsi = &pf->vsi;
941266423Sjfv	struct ifnet	*ifp = vsi->ifp;
942266423Sjfv	device_t 	dev = pf->dev;
943266423Sjfv	struct i40e_filter_control_settings	filter;
944266423Sjfv	u8		tmpaddr[ETHER_ADDR_LEN];
945266423Sjfv	int		ret;
946266423Sjfv
947266423Sjfv	mtx_assert(&pf->pf_mtx, MA_OWNED);
948266423Sjfv	INIT_DEBUGOUT("i40e_init: begin");
949266423Sjfv	i40e_stop(pf);
950266423Sjfv
951266423Sjfv	/* Get the latest mac address... User might use a LAA */
952266423Sjfv	bcopy(IF_LLADDR(vsi->ifp), tmpaddr,
953266423Sjfv	      I40E_ETH_LENGTH_OF_ADDRESS);
954266423Sjfv	if (!cmp_etheraddr(hw->mac.addr, tmpaddr) &&
955266423Sjfv	    i40e_validate_mac_addr(tmpaddr)) {
956266423Sjfv		bcopy(tmpaddr, hw->mac.addr,
957266423Sjfv		    I40E_ETH_LENGTH_OF_ADDRESS);
958266423Sjfv		ret = i40e_aq_mac_address_write(hw,
959266423Sjfv		    I40E_AQC_WRITE_TYPE_LAA_ONLY,
960266423Sjfv		    hw->mac.addr, NULL);
961266423Sjfv		if (ret) {
962266423Sjfv			device_printf(dev, "LLA address"
963266423Sjfv			 "change failed!!\n");
964266423Sjfv			return;
965266423Sjfv		}
966266423Sjfv	}
967266423Sjfv
968266423Sjfv	/* Set the various hardware offload abilities */
969266423Sjfv	ifp->if_hwassist = 0;
970266423Sjfv	if (ifp->if_capenable & IFCAP_TSO)
971266423Sjfv		ifp->if_hwassist |= CSUM_TSO;
972266423Sjfv	if (ifp->if_capenable & IFCAP_TXCSUM)
973266423Sjfv		ifp->if_hwassist |= (CSUM_TCP | CSUM_UDP);
974266423Sjfv	if (ifp->if_capenable & IFCAP_TXCSUM_IPV6)
975266423Sjfv		ifp->if_hwassist |= (CSUM_TCP_IPV6 | CSUM_UDP_IPV6);
976266423Sjfv
977266423Sjfv	/* Set up the device filtering */
978266423Sjfv	bzero(&filter, sizeof(filter));
979266423Sjfv	filter.enable_ethtype = TRUE;
980266423Sjfv	filter.enable_macvlan = TRUE;
981266423Sjfv#ifdef I40E_FDIR
982266423Sjfv	filter.enable_fdir = TRUE;
983266423Sjfv#endif
984266423Sjfv	if (i40e_set_filter_control(hw, &filter))
985266423Sjfv		device_printf(dev, "set_filter_control() failed\n");
986266423Sjfv
987266423Sjfv	/* Set up RSS */
988266423Sjfv	i40e_config_rss(vsi);
989266423Sjfv
990266423Sjfv	/* Setup the VSI */
991266423Sjfv	i40e_setup_vsi(vsi);
992266423Sjfv
993266423Sjfv	/*
994266423Sjfv	** Prepare the rings, hmc contexts, etc...
995266423Sjfv	*/
996266423Sjfv	if (i40e_initialize_vsi(vsi)) {
997266423Sjfv		device_printf(dev,"initialize vsi failed!!\n");
998266423Sjfv		return;
999266423Sjfv	}
1000266423Sjfv
1001266423Sjfv	/* Add protocol filters to list */
1002266423Sjfv	i40e_init_filters(vsi);
1003266423Sjfv
1004266423Sjfv	/* Setup vlan's if needed */
1005266423Sjfv	i40e_setup_vlan_filters(vsi);
1006266423Sjfv
1007266423Sjfv	/* Start the local timer */
1008266423Sjfv	callout_reset(&pf->timer, hz, i40e_local_timer, pf);
1009266423Sjfv
1010266423Sjfv	/* Set up MSI/X routing and the ITR settings */
1011266423Sjfv	if (i40e_enable_msix) {
1012266423Sjfv		i40e_configure_msix(pf);
1013266423Sjfv		i40e_configure_itr(pf);
1014266423Sjfv	} else
1015266423Sjfv		i40e_configure_legacy(pf);
1016266423Sjfv
1017266423Sjfv	/*
1018266423Sjfv	** Only a temporary workaround for RX hangs
1019266423Sjfv	*/
1020266423Sjfv	if (rd32(hw, I40E_PRTRPB_SLW) != 0x30000)
1021266423Sjfv		wr32(hw, I40E_PRTRPB_SLW, 0x30000);
1022266423Sjfv
1023266423Sjfv	i40e_enable_rings(vsi);
1024266423Sjfv
1025266423Sjfv	i40e_aq_set_default_vsi(hw, vsi->seid, NULL);
1026266423Sjfv
1027266423Sjfv	/* Flow control setup */
1028266423Sjfv	/* NOTE: flow control currently doesn't work correctly */
1029266423Sjfv	// i40e_set_fc_mode(pf, I40E_FC_FULL);
1030266423Sjfv
1031266423Sjfv	/* Set MTU in hardware*/
1032266423Sjfv	if (ifp->if_mtu > ETHERMTU) {
1033266423Sjfv		int aq_error =
1034266423Sjfv			i40e_aq_set_mac_config(hw, vsi->max_frame_size,
1035266423Sjfv				TRUE, 0, NULL);
1036266423Sjfv		if (aq_error)
1037266423Sjfv			device_printf(vsi->dev,
1038266423Sjfv				"aq_set_mac_config in init error, code %d\n",
1039266423Sjfv			    aq_error);
1040266423Sjfv	}
1041266423Sjfv
1042266423Sjfv	/* And now turn on interrupts */
1043266423Sjfv	i40e_enable_intr(vsi);
1044266423Sjfv
1045266423Sjfv	/* Now inform the stack we're ready */
1046266423Sjfv	ifp->if_drv_flags |= IFF_DRV_RUNNING;
1047266423Sjfv	ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
1048266423Sjfv
1049266423Sjfv	return;
1050266423Sjfv}
1051266423Sjfv
1052266423Sjfvstatic void
1053266423Sjfvi40e_init(void *arg)
1054266423Sjfv{
1055266423Sjfv	struct i40e_pf *pf = arg;
1056266423Sjfv
1057266423Sjfv	I40E_PF_LOCK(pf);
1058266423Sjfv	i40e_init_locked(pf);
1059266423Sjfv	I40E_PF_UNLOCK(pf);
1060266423Sjfv	return;
1061266423Sjfv}
1062266423Sjfv
1063266423Sjfv/*
1064266423Sjfv**
1065266423Sjfv** MSIX Interrupt Handlers and Tasklets
1066266423Sjfv**
1067266423Sjfv*/
1068266423Sjfvstatic void
1069266423Sjfvi40e_handle_que(void *context, int pending)
1070266423Sjfv{
1071266423Sjfv	struct i40e_queue *que = context;
1072266423Sjfv	struct i40e_vsi *vsi = que->vsi;
1073266423Sjfv	struct i40e_hw  *hw = vsi->hw;
1074266423Sjfv	struct tx_ring  *txr = &que->txr;
1075266423Sjfv	struct ifnet    *ifp = vsi->ifp;
1076266423Sjfv	bool		more;
1077266423Sjfv
1078266423Sjfv	if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
1079266423Sjfv		more = i40e_rxeof(que, I40E_RX_LIMIT);
1080266423Sjfv		I40E_TX_LOCK(txr);
1081266423Sjfv		i40e_txeof(que);
1082266423Sjfv		if (!drbr_empty(ifp, txr->br))
1083266423Sjfv			i40e_mq_start_locked(ifp, txr);
1084266423Sjfv		I40E_TX_UNLOCK(txr);
1085266423Sjfv		if (more) {
1086266423Sjfv			taskqueue_enqueue(que->tq, &que->task);
1087266423Sjfv			return;
1088266423Sjfv		}
1089266423Sjfv	}
1090266423Sjfv
1091266423Sjfv	/* Reenable this interrupt - hmmm */
1092266423Sjfv	i40e_enable_queue(hw, que->me);
1093266423Sjfv	return;
1094266423Sjfv}
1095266423Sjfv
1096266423Sjfv
1097266423Sjfv/*********************************************************************
1098266423Sjfv *
1099266423Sjfv *  Legacy Interrupt Service routine
1100266423Sjfv *
1101266423Sjfv **********************************************************************/
1102266423Sjfvvoid
1103266423Sjfvi40e_intr(void *arg)
1104266423Sjfv{
1105266423Sjfv	struct i40e_pf		*pf = arg;
1106266423Sjfv	struct i40e_hw		*hw =  &pf->hw;
1107266423Sjfv	struct i40e_vsi		*vsi = &pf->vsi;
1108266423Sjfv	struct i40e_queue	*que = vsi->queues;
1109266423Sjfv	struct ifnet		*ifp = vsi->ifp;
1110266423Sjfv	struct tx_ring		*txr = &que->txr;
1111266423Sjfv        u32			reg, icr0, mask;
1112266423Sjfv	bool			more_tx, more_rx;
1113266423Sjfv
1114266423Sjfv	++que->irqs;
1115266423Sjfv
1116266423Sjfv	/* Protect against spurious interrupts */
1117266423Sjfv	if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0)
1118266423Sjfv		return;
1119266423Sjfv
1120266423Sjfv	icr0 = rd32(hw, I40E_PFINT_ICR0);
1121266423Sjfv
1122266423Sjfv	reg = rd32(hw, I40E_PFINT_DYN_CTL0);
1123266423Sjfv	reg = reg | I40E_PFINT_DYN_CTL0_CLEARPBA_MASK;
1124266423Sjfv	wr32(hw, I40E_PFINT_DYN_CTL0, reg);
1125266423Sjfv
1126266423Sjfv        mask = rd32(hw, I40E_PFINT_ICR0_ENA);
1127266423Sjfv
1128266423Sjfv	if (icr0 & I40E_PFINT_ICR0_ADMINQ_MASK) {
1129266423Sjfv		taskqueue_enqueue(pf->tq, &pf->adminq);
1130266423Sjfv		return;
1131266423Sjfv	}
1132266423Sjfv
1133266423Sjfv	more_rx = i40e_rxeof(que, I40E_RX_LIMIT);
1134266423Sjfv
1135266423Sjfv	I40E_TX_LOCK(txr);
1136266423Sjfv	more_tx = i40e_txeof(que);
1137266423Sjfv	if (!drbr_empty(vsi->ifp, txr->br))
1138266423Sjfv		more_tx = 1;
1139266423Sjfv	I40E_TX_UNLOCK(txr);
1140266423Sjfv
1141266423Sjfv	/* re-enable other interrupt causes */
1142266423Sjfv	wr32(hw, I40E_PFINT_ICR0_ENA, mask);
1143266423Sjfv
1144266423Sjfv	/* And now the queues */
1145266423Sjfv	reg = rd32(hw, I40E_QINT_RQCTL(0));
1146266423Sjfv	reg |= I40E_QINT_RQCTL_CAUSE_ENA_MASK;
1147266423Sjfv	wr32(hw, I40E_QINT_RQCTL(0), reg);
1148266423Sjfv
1149266423Sjfv	reg = rd32(hw, I40E_QINT_TQCTL(0));
1150266423Sjfv	reg |= I40E_QINT_TQCTL_CAUSE_ENA_MASK;
1151266423Sjfv	reg &= ~I40E_PFINT_ICR0_INTEVENT_MASK;
1152266423Sjfv	wr32(hw, I40E_QINT_TQCTL(0), reg);
1153266423Sjfv
1154266423Sjfv	i40e_enable_legacy(hw);
1155266423Sjfv
1156266423Sjfv	return;
1157266423Sjfv}
1158266423Sjfv
1159266423Sjfv
1160266423Sjfv/*********************************************************************
1161266423Sjfv *
1162266423Sjfv *  MSIX VSI Interrupt Service routine
1163266423Sjfv *
1164266423Sjfv **********************************************************************/
1165266423Sjfvvoid
1166266423Sjfvi40e_msix_que(void *arg)
1167266423Sjfv{
1168266423Sjfv	struct i40e_queue	*que = arg;
1169266423Sjfv	struct i40e_vsi	*vsi = que->vsi;
1170266423Sjfv	struct i40e_hw	*hw = vsi->hw;
1171266423Sjfv	struct tx_ring	*txr = &que->txr;
1172266423Sjfv	bool		more_tx, more_rx;
1173266423Sjfv
1174266423Sjfv	++que->irqs;
1175266423Sjfv
1176266423Sjfv	more_rx = i40e_rxeof(que, I40E_RX_LIMIT);
1177266423Sjfv
1178266423Sjfv	I40E_TX_LOCK(txr);
1179266423Sjfv	more_tx = i40e_txeof(que);
1180266423Sjfv	/*
1181266423Sjfv	** Make certain that if the stack
1182266423Sjfv	** has anything queued the task gets
1183266423Sjfv	** scheduled to handle it.
1184266423Sjfv	*/
1185266423Sjfv	if (!drbr_empty(vsi->ifp, txr->br))
1186266423Sjfv		more_tx = 1;
1187266423Sjfv	I40E_TX_UNLOCK(txr);
1188266423Sjfv
1189266423Sjfv	i40e_set_queue_rx_itr(que);
1190266423Sjfv	i40e_set_queue_tx_itr(que);
1191266423Sjfv
1192266423Sjfv	if (more_tx || more_rx)
1193266423Sjfv		taskqueue_enqueue(que->tq, &que->task);
1194266423Sjfv	else
1195266423Sjfv		i40e_enable_queue(hw, que->me);
1196266423Sjfv
1197266423Sjfv	return;
1198266423Sjfv}
1199266423Sjfv
1200266423Sjfv
1201266423Sjfv/*********************************************************************
1202266423Sjfv *
1203266423Sjfv *  MSIX Admin Queue Interrupt Service routine
1204266423Sjfv *
1205266423Sjfv **********************************************************************/
1206266423Sjfvstatic void
1207266423Sjfvi40e_msix_adminq(void *arg)
1208266423Sjfv{
1209266423Sjfv	struct i40e_pf	*pf = arg;
1210266423Sjfv	struct i40e_hw	*hw = &pf->hw;
1211266423Sjfv	u32		reg, mask;
1212266423Sjfv
1213266423Sjfv	++pf->admin_irq;
1214266423Sjfv
1215266423Sjfv	reg = rd32(hw, I40E_PFINT_ICR0);
1216266423Sjfv	mask = rd32(hw, I40E_PFINT_ICR0_ENA);
1217266423Sjfv
1218266423Sjfv	/* Check on the cause */
1219266423Sjfv	if (reg & I40E_PFINT_ICR0_ADMINQ_MASK)
1220266423Sjfv		mask &= ~I40E_PFINT_ICR0_ENA_ADMINQ_MASK;
1221266423Sjfv
1222266423Sjfv	if (reg & I40E_PFINT_ICR0_MAL_DETECT_MASK)
1223266423Sjfv		mask &= ~I40E_PFINT_ICR0_ENA_MAL_DETECT_MASK;
1224266423Sjfv
1225266423Sjfv	if (reg & I40E_PFINT_ICR0_VFLR_MASK)
1226266423Sjfv		mask &= ~I40E_PFINT_ICR0_ENA_VFLR_MASK;
1227266423Sjfv
1228266423Sjfv	reg = rd32(hw, I40E_PFINT_DYN_CTL0);
1229266423Sjfv	reg = reg | I40E_PFINT_DYN_CTL0_CLEARPBA_MASK;
1230266423Sjfv	wr32(hw, I40E_PFINT_DYN_CTL0, reg);
1231266423Sjfv
1232266423Sjfv	taskqueue_enqueue(pf->tq, &pf->adminq);
1233266423Sjfv	return;
1234266423Sjfv}
1235266423Sjfv
1236266423Sjfv/*********************************************************************
1237266423Sjfv *
1238266423Sjfv *  Media Ioctl callback
1239266423Sjfv *
1240266423Sjfv *  This routine is called whenever the user queries the status of
1241266423Sjfv *  the interface using ifconfig.
1242266423Sjfv *
1243266423Sjfv **********************************************************************/
1244266423Sjfvstatic void
1245266423Sjfvi40e_media_status(struct ifnet * ifp, struct ifmediareq * ifmr)
1246266423Sjfv{
1247266423Sjfv	struct i40e_vsi	*vsi = ifp->if_softc;
1248266423Sjfv	struct i40e_pf	*pf = (struct i40e_pf *)vsi->back;
1249266423Sjfv	struct i40e_hw  *hw = &pf->hw;
1250266423Sjfv
1251266423Sjfv	INIT_DEBUGOUT("i40e_media_status: begin");
1252266423Sjfv	I40E_PF_LOCK(pf);
1253266423Sjfv
1254266423Sjfv	i40e_update_link_status(pf);
1255266423Sjfv
1256266423Sjfv	ifmr->ifm_status = IFM_AVALID;
1257266423Sjfv	ifmr->ifm_active = IFM_ETHER;
1258266423Sjfv
1259266423Sjfv	if (!vsi->link_up) {
1260266423Sjfv		I40E_PF_UNLOCK(pf);
1261266423Sjfv		return;
1262266423Sjfv	}
1263266423Sjfv
1264266423Sjfv	ifmr->ifm_status |= IFM_ACTIVE;
1265266423Sjfv	/* Hardware is always full-duplex */
1266266423Sjfv	ifmr->ifm_active |= IFM_FDX;
1267266423Sjfv
1268266423Sjfv	switch (hw->phy.link_info.phy_type) {
1269266423Sjfv		/* 100 M */
1270266423Sjfv		case I40E_PHY_TYPE_100BASE_TX:
1271266423Sjfv			ifmr->ifm_active |= IFM_100_TX;
1272266423Sjfv			break;
1273266423Sjfv		/* 1 G */
1274266423Sjfv		case I40E_PHY_TYPE_1000BASE_T:
1275266423Sjfv			ifmr->ifm_active |= IFM_1000_T;
1276266423Sjfv			break;
1277266423Sjfv		/* 10 G */
1278266423Sjfv		case I40E_PHY_TYPE_10GBASE_CR1_CU:
1279266423Sjfv		case I40E_PHY_TYPE_10GBASE_SFPP_CU:
1280266423Sjfv			ifmr->ifm_active |= IFM_10G_TWINAX;
1281266423Sjfv			break;
1282266423Sjfv		case I40E_PHY_TYPE_10GBASE_SR:
1283266423Sjfv			ifmr->ifm_active |= IFM_10G_SR;
1284266423Sjfv			break;
1285266423Sjfv		case I40E_PHY_TYPE_10GBASE_LR:
1286266423Sjfv			ifmr->ifm_active |= IFM_10G_LR;
1287266423Sjfv			break;
1288266423Sjfv		/* 40 G */
1289266423Sjfv		case I40E_PHY_TYPE_40GBASE_CR4:
1290266423Sjfv		case I40E_PHY_TYPE_40GBASE_CR4_CU:
1291266423Sjfv			ifmr->ifm_active |= IFM_40G_CR4;
1292266423Sjfv			break;
1293266423Sjfv		case I40E_PHY_TYPE_40GBASE_SR4:
1294266423Sjfv			ifmr->ifm_active |= IFM_40G_SR4;
1295266423Sjfv			break;
1296266423Sjfv		case I40E_PHY_TYPE_40GBASE_LR4:
1297266423Sjfv			ifmr->ifm_active |= IFM_40G_LR4;
1298266423Sjfv			break;
1299266423Sjfv		/*
1300266423Sjfv		 * FreeBSD doesn't know about the other phy
1301266423Sjfv		 * types this hardware supports.
1302266423Sjfv		 */
1303266423Sjfv		default:
1304266423Sjfv			ifmr->ifm_active |= IFM_UNKNOWN;
1305266423Sjfv			break;
1306266423Sjfv	}
1307266423Sjfv	/* Report flow control status as well */
1308266423Sjfv	/* TODO: Something special if PFC is enabled instead */
1309266423Sjfv	if (hw->phy.link_info.an_info & I40E_AQ_LINK_PAUSE_TX)
1310266423Sjfv		ifmr->ifm_active |= IFM_ETH_TXPAUSE;
1311266423Sjfv	if (hw->phy.link_info.an_info & I40E_AQ_LINK_PAUSE_RX)
1312266423Sjfv		ifmr->ifm_active |= IFM_ETH_RXPAUSE;
1313266423Sjfv
1314266423Sjfv	I40E_PF_UNLOCK(pf);
1315266423Sjfv
1316266423Sjfv	return;
1317266423Sjfv}
1318266423Sjfv
1319266423Sjfv/*********************************************************************
1320266423Sjfv *
1321266423Sjfv *  Media Ioctl callback
1322266423Sjfv *
1323266423Sjfv *  This routine is called when the user changes speed/duplex using
1324266423Sjfv *  media/mediopt option with ifconfig.
1325266423Sjfv *
1326266423Sjfv **********************************************************************/
1327266423Sjfvstatic int
1328266423Sjfvi40e_media_change(struct ifnet * ifp)
1329266423Sjfv{
1330266423Sjfv	struct i40e_vsi *vsi = ifp->if_softc;
1331266423Sjfv	struct ifmedia *ifm = &vsi->media;
1332266423Sjfv
1333266423Sjfv	INIT_DEBUGOUT("i40e_media_change: begin");
1334266423Sjfv
1335266423Sjfv	if (IFM_TYPE(ifm->ifm_media) != IFM_ETHER)
1336266423Sjfv		return (EINVAL);
1337266423Sjfv
1338266423Sjfv	return (0);
1339266423Sjfv}
1340266423Sjfv
1341266423Sjfv
1342266423Sjfv#ifdef I40E_FDIR
1343266423Sjfv/*
1344266423Sjfv** ATR: Application Targetted Receive - creates a filter
1345266423Sjfv**	based on TX flow info that will keep the receive
1346266423Sjfv**	portion of the flow on the same queue. Based on the
1347266423Sjfv**	implementation this is only available for TCP connections
1348266423Sjfv*/
1349266423Sjfvvoid
1350266423Sjfvi40e_atr(struct i40e_queue *que, struct tcphdr *th, int etype)
1351266423Sjfv{
1352266423Sjfv	struct i40e_vsi			*vsi = que->vsi;
1353266423Sjfv	struct tx_ring			*txr = &que->txr;
1354266423Sjfv	struct i40e_filter_program_desc	*FDIR;
1355266423Sjfv	u32				ptype, dtype;
1356266423Sjfv	int				idx;
1357266423Sjfv
1358266423Sjfv	/* check if ATR is enabled and sample rate */
1359266423Sjfv	if ((!i40e_enable_fdir) || (!txr->atr_rate))
1360266423Sjfv		return;
1361266423Sjfv	/*
1362266423Sjfv	** We sample all TCP SYN/FIN packets,
1363266423Sjfv	** or at the selected sample rate
1364266423Sjfv	*/
1365266423Sjfv	txr->atr_count++;
1366266423Sjfv	if (((th->th_flags & (TH_FIN | TH_SYN)) == 0) &&
1367266423Sjfv	    (txr->atr_count < txr->atr_rate))
1368266423Sjfv                return;
1369266423Sjfv	txr->atr_count = 0;
1370266423Sjfv
1371266423Sjfv	/* Get a descriptor to use */
1372266423Sjfv	idx = txr->next_avail;
1373266423Sjfv	FDIR = (struct i40e_filter_program_desc *) &txr->base[idx];
1374266423Sjfv	if (++idx == que->num_desc)
1375266423Sjfv		idx = 0;
1376266423Sjfv	txr->avail--;
1377266423Sjfv	txr->next_avail = idx;
1378266423Sjfv
1379266423Sjfv	ptype = (que->me << I40E_TXD_FLTR_QW0_QINDEX_SHIFT) &
1380266423Sjfv	    I40E_TXD_FLTR_QW0_QINDEX_MASK;
1381266423Sjfv
1382266423Sjfv	ptype |= (etype == ETHERTYPE_IP) ?
1383266423Sjfv	    (I40E_FILTER_PCTYPE_NONF_IPV4_TCP <<
1384266423Sjfv	    I40E_TXD_FLTR_QW0_PCTYPE_SHIFT) :
1385266423Sjfv	    (I40E_FILTER_PCTYPE_NONF_IPV6_TCP <<
1386266423Sjfv	    I40E_TXD_FLTR_QW0_PCTYPE_SHIFT);
1387266423Sjfv
1388266423Sjfv	ptype |= vsi->id << I40E_TXD_FLTR_QW0_DEST_VSI_SHIFT;
1389266423Sjfv
1390266423Sjfv	dtype = I40E_TX_DESC_DTYPE_FILTER_PROG;
1391266423Sjfv
1392266423Sjfv	/*
1393266423Sjfv	** We use the TCP TH_FIN as a trigger to remove
1394266423Sjfv	** the filter, otherwise its an update.
1395266423Sjfv	*/
1396266423Sjfv	dtype |= (th->th_flags & TH_FIN) ?
1397266423Sjfv	    (I40E_FILTER_PROGRAM_DESC_PCMD_REMOVE <<
1398266423Sjfv	    I40E_TXD_FLTR_QW1_PCMD_SHIFT) :
1399266423Sjfv	    (I40E_FILTER_PROGRAM_DESC_PCMD_ADD_UPDATE <<
1400266423Sjfv	    I40E_TXD_FLTR_QW1_PCMD_SHIFT);
1401266423Sjfv
1402266423Sjfv	dtype |= I40E_FILTER_PROGRAM_DESC_DEST_DIRECT_PACKET_QINDEX <<
1403266423Sjfv	    I40E_TXD_FLTR_QW1_DEST_SHIFT;
1404266423Sjfv
1405266423Sjfv	dtype |= I40E_FILTER_PROGRAM_DESC_FD_STATUS_FD_ID <<
1406266423Sjfv	    I40E_TXD_FLTR_QW1_FD_STATUS_SHIFT;
1407266423Sjfv
1408266423Sjfv	FDIR->qindex_flex_ptype_vsi = htole32(ptype);
1409266423Sjfv	FDIR->dtype_cmd_cntindex = htole32(dtype);
1410266423Sjfv	return;
1411266423Sjfv}
1412266423Sjfv#endif
1413266423Sjfv
1414266423Sjfv
1415266423Sjfvstatic void
1416266423Sjfvi40e_set_promisc(struct i40e_vsi *vsi)
1417266423Sjfv{
1418266423Sjfv	struct ifnet	*ifp = vsi->ifp;
1419266423Sjfv	struct i40e_hw	*hw = vsi->hw;
1420266423Sjfv	int		err, mcnt = 0;
1421266423Sjfv	bool		uni = FALSE, multi = FALSE;
1422266423Sjfv
1423266423Sjfv	if (ifp->if_flags & IFF_ALLMULTI)
1424266423Sjfv                multi = TRUE;
1425266423Sjfv	else { /* Need to count the multicast addresses */
1426266423Sjfv		struct  ifmultiaddr *ifma;
1427266423Sjfv		if_maddr_rlock(ifp);
1428266423Sjfv		TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
1429266423Sjfv                        if (ifma->ifma_addr->sa_family != AF_LINK)
1430266423Sjfv                                continue;
1431266423Sjfv                        if (mcnt == MAX_MULTICAST_ADDR)
1432266423Sjfv                                break;
1433266423Sjfv                        mcnt++;
1434266423Sjfv		}
1435266423Sjfv		if_maddr_runlock(ifp);
1436266423Sjfv	}
1437266423Sjfv
1438266423Sjfv	if (mcnt >= MAX_MULTICAST_ADDR)
1439266423Sjfv                multi = TRUE;
1440266423Sjfv        if (ifp->if_flags & IFF_PROMISC)
1441266423Sjfv		uni = TRUE;
1442266423Sjfv
1443266423Sjfv	err = i40e_aq_set_vsi_unicast_promiscuous(hw,
1444266423Sjfv	    vsi->seid, uni, NULL);
1445266423Sjfv	err = i40e_aq_set_vsi_multicast_promiscuous(hw,
1446266423Sjfv	    vsi->seid, multi, NULL);
1447266423Sjfv	return;
1448266423Sjfv}
1449266423Sjfv
1450266423Sjfv/*********************************************************************
1451266423Sjfv * 	Filter Routines
1452266423Sjfv *
1453266423Sjfv *	Routines for multicast and vlan filter management.
1454266423Sjfv *
1455266423Sjfv *********************************************************************/
1456266423Sjfvstatic void
1457266423Sjfvi40e_add_multi(struct i40e_vsi *vsi)
1458266423Sjfv{
1459266423Sjfv	struct	ifmultiaddr	*ifma;
1460266423Sjfv	struct ifnet		*ifp = vsi->ifp;
1461266423Sjfv	struct i40e_hw		*hw = vsi->hw;
1462266423Sjfv	int			mcnt = 0, flags;
1463266423Sjfv
1464266423Sjfv	IOCTL_DEBUGOUT("i40e_add_multi: begin");
1465266423Sjfv
1466266423Sjfv	if_maddr_rlock(ifp);
1467266423Sjfv	/*
1468266423Sjfv	** First just get a count, to decide if we
1469266423Sjfv	** we simply use multicast promiscuous.
1470266423Sjfv	*/
1471266423Sjfv	TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
1472266423Sjfv		if (ifma->ifma_addr->sa_family != AF_LINK)
1473266423Sjfv			continue;
1474266423Sjfv		mcnt++;
1475266423Sjfv	}
1476266423Sjfv	if_maddr_runlock(ifp);
1477266423Sjfv
1478266423Sjfv	if (__predict_false(mcnt >= MAX_MULTICAST_ADDR)) {
1479266423Sjfv		/* delete existing MC filters */
1480266423Sjfv		i40e_del_hw_filters(vsi, mcnt);
1481266423Sjfv		i40e_aq_set_vsi_multicast_promiscuous(hw,
1482266423Sjfv		    vsi->seid, TRUE, NULL);
1483266423Sjfv		return;
1484266423Sjfv	}
1485266423Sjfv
1486266423Sjfv	mcnt = 0;
1487266423Sjfv	if_maddr_rlock(ifp);
1488266423Sjfv	TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
1489266423Sjfv		if (ifma->ifma_addr->sa_family != AF_LINK)
1490266423Sjfv			continue;
1491266423Sjfv		i40e_add_mc_filter(vsi,
1492266423Sjfv		    (u8*)LLADDR((struct sockaddr_dl *) ifma->ifma_addr));
1493266423Sjfv		mcnt++;
1494266423Sjfv	}
1495266423Sjfv	if_maddr_runlock(ifp);
1496266423Sjfv	if (mcnt > 0) {
1497266423Sjfv		flags = (I40E_FILTER_ADD | I40E_FILTER_USED | I40E_FILTER_MC);
1498266423Sjfv		i40e_add_hw_filters(vsi, flags, mcnt);
1499266423Sjfv	}
1500266423Sjfv
1501266423Sjfv	IOCTL_DEBUGOUT("i40e_add_multi: end");
1502266423Sjfv	return;
1503266423Sjfv}
1504266423Sjfv
1505266423Sjfvstatic void
1506266423Sjfvi40e_del_multi(struct i40e_vsi *vsi)
1507266423Sjfv{
1508266423Sjfv	struct ifnet		*ifp = vsi->ifp;
1509266423Sjfv	struct ifmultiaddr	*ifma;
1510266423Sjfv	struct i40e_mac_filter	*f;
1511266423Sjfv	int			mcnt = 0;
1512266423Sjfv	bool		match = FALSE;
1513266423Sjfv
1514266423Sjfv	IOCTL_DEBUGOUT("i40e_del_multi: begin");
1515266423Sjfv
1516266423Sjfv	/* Search for removed multicast addresses */
1517266423Sjfv	if_maddr_rlock(ifp);
1518266423Sjfv	SLIST_FOREACH(f, &vsi->ftl, next) {
1519266423Sjfv		if ((f->flags & I40E_FILTER_USED) && (f->flags & I40E_FILTER_MC)) {
1520266423Sjfv			match = FALSE;
1521266423Sjfv			TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
1522266423Sjfv				if (ifma->ifma_addr->sa_family != AF_LINK)
1523266423Sjfv					continue;
1524266423Sjfv				u8 *mc_addr = (u8 *)LLADDR((struct sockaddr_dl *)ifma->ifma_addr);
1525266423Sjfv				if (cmp_etheraddr(f->macaddr, mc_addr)) {
1526266423Sjfv					match = TRUE;
1527266423Sjfv					break;
1528266423Sjfv				}
1529266423Sjfv			}
1530266423Sjfv			if (match == FALSE) {
1531266423Sjfv				f->flags |= I40E_FILTER_DEL;
1532266423Sjfv				mcnt++;
1533266423Sjfv			}
1534266423Sjfv		}
1535266423Sjfv	}
1536266423Sjfv	if_maddr_runlock(ifp);
1537266423Sjfv
1538266423Sjfv	if (mcnt > 0)
1539266423Sjfv		i40e_del_hw_filters(vsi, mcnt);
1540266423Sjfv}
1541266423Sjfv
1542266423Sjfv
1543266423Sjfv/*********************************************************************
1544266423Sjfv *  Timer routine
1545266423Sjfv *
1546266423Sjfv *  This routine checks for link status,updates statistics,
1547266423Sjfv *  and runs the watchdog check.
1548266423Sjfv *
1549266423Sjfv **********************************************************************/
1550266423Sjfv
1551266423Sjfvstatic void
1552266423Sjfvi40e_local_timer(void *arg)
1553266423Sjfv{
1554266423Sjfv	struct i40e_pf		*pf = arg;
1555266423Sjfv	struct i40e_hw		*hw = &pf->hw;
1556266423Sjfv	struct i40e_vsi		*vsi = &pf->vsi;
1557266423Sjfv	struct i40e_queue	*que = vsi->queues;
1558266423Sjfv	device_t		dev = pf->dev;
1559266423Sjfv	int			hung = 0;
1560266423Sjfv	u32			mask;
1561266423Sjfv
1562266423Sjfv	mtx_assert(&pf->pf_mtx, MA_OWNED);
1563266423Sjfv
1564266423Sjfv	/* Fire off the adminq task */
1565266423Sjfv	taskqueue_enqueue(pf->tq, &pf->adminq);
1566266423Sjfv
1567266423Sjfv	/* Update stats */
1568266423Sjfv	i40e_update_stats_counters(pf);
1569266423Sjfv
1570266423Sjfv	/*
1571266423Sjfv	** Check status on the queues for a hang
1572266423Sjfv	*/
1573266423Sjfv	mask = (I40E_PFINT_DYN_CTLN_INTENA_MASK |
1574266423Sjfv		I40E_PFINT_DYN_CTLN_SWINT_TRIG_MASK);
1575266423Sjfv
1576266423Sjfv	for (int i = 0; i < vsi->num_queues; i++,que++) {
1577266423Sjfv		/* Any queues with outstanding work get a sw irq */
1578266423Sjfv		if (que->busy)
1579266423Sjfv			wr32(hw, I40E_PFINT_DYN_CTLN(que->me), mask);
1580266423Sjfv		/*
1581266423Sjfv		** Each time txeof runs without cleaning, but there
1582266423Sjfv		** are uncleaned descriptors it increments busy. If
1583266423Sjfv		** we get to 5 we declare it hung.
1584266423Sjfv		*/
1585266423Sjfv		if (que->busy >= I40E_MAX_TX_BUSY) {
1586266423Sjfv			device_printf(dev,"Warning queue %d "
1587266423Sjfv			    "appears to be hung!", i);
1588266423Sjfv			++hung;
1589266423Sjfv		}
1590266423Sjfv	}
1591266423Sjfv	/* Only reinit if all queues show hung */
1592266423Sjfv	if (hung == vsi->num_queues)
1593266423Sjfv		goto hung;
1594266423Sjfv
1595266423Sjfv	callout_reset(&pf->timer, hz, i40e_local_timer, pf);
1596266423Sjfv	return;
1597266423Sjfv
1598266423Sjfvhung:
1599266423Sjfv	device_printf(dev, "Local Timer: HANG DETECT - Resetting!!\n");
1600266423Sjfv	i40e_init_locked(pf);
1601266423Sjfv}
1602266423Sjfv
1603266423Sjfv/*
1604266423Sjfv** Note: this routine updates the OS on the link state
1605266423Sjfv**	the real check of the hardware only happens with
1606266423Sjfv**	a link interrupt.
1607266423Sjfv*/
1608266423Sjfvstatic void
1609266423Sjfvi40e_update_link_status(struct i40e_pf *pf)
1610266423Sjfv{
1611266423Sjfv	struct i40e_vsi		*vsi = &pf->vsi;
1612266423Sjfv	struct i40e_hw		*hw = &pf->hw;
1613266423Sjfv	struct ifnet		*ifp = vsi->ifp;
1614266423Sjfv	device_t		dev = pf->dev;
1615266423Sjfv	enum i40e_fc_mode 	fc;
1616266423Sjfv
1617266423Sjfv
1618266423Sjfv	if (vsi->link_up){
1619266423Sjfv		if (vsi->link_active == FALSE) {
1620266423Sjfv			i40e_aq_get_link_info(hw, TRUE, NULL, NULL);
1621266423Sjfv			if (bootverbose) {
1622266423Sjfv				fc = hw->fc.current_mode;
1623266423Sjfv				device_printf(dev,"Link is up %d Gbps %s,"
1624266423Sjfv				    " Flow Control: %s\n",
1625266423Sjfv				    ((vsi->link_speed == I40E_LINK_SPEED_40GB)? 40:10),
1626266423Sjfv				    "Full Duplex", i40e_fc_string[fc]);
1627266423Sjfv			}
1628266423Sjfv			vsi->link_active = TRUE;
1629266423Sjfv			if_link_state_change(ifp, LINK_STATE_UP);
1630266423Sjfv		}
1631266423Sjfv	} else { /* Link down */
1632266423Sjfv		if (vsi->link_active == TRUE) {
1633266423Sjfv			if (bootverbose)
1634266423Sjfv				device_printf(dev,"Link is Down\n");
1635266423Sjfv			if_link_state_change(ifp, LINK_STATE_DOWN);
1636266423Sjfv			vsi->link_active = FALSE;
1637266423Sjfv		}
1638266423Sjfv	}
1639266423Sjfv
1640266423Sjfv	return;
1641266423Sjfv}
1642266423Sjfv
1643266423Sjfv/*********************************************************************
1644266423Sjfv *
1645266423Sjfv *  This routine disables all traffic on the adapter by issuing a
1646266423Sjfv *  global reset on the MAC and deallocates TX/RX buffers.
1647266423Sjfv *
1648266423Sjfv **********************************************************************/
1649266423Sjfv
1650266423Sjfvstatic void
1651266423Sjfvi40e_stop(struct i40e_pf *pf)
1652266423Sjfv{
1653266423Sjfv	struct i40e_vsi	*vsi = &pf->vsi;
1654266423Sjfv	struct ifnet	*ifp = vsi->ifp;
1655266423Sjfv
1656266423Sjfv	mtx_assert(&pf->pf_mtx, MA_OWNED);
1657266423Sjfv
1658266423Sjfv	INIT_DEBUGOUT("i40e_stop: begin\n");
1659266423Sjfv	i40e_disable_intr(vsi);
1660266423Sjfv	i40e_disable_rings(vsi);
1661266423Sjfv
1662266423Sjfv	/* Tell the stack that the interface is no longer active */
1663266423Sjfv	ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
1664266423Sjfv
1665266423Sjfv	/* Stop the local timer */
1666266423Sjfv	callout_stop(&pf->timer);
1667266423Sjfv
1668266423Sjfv	return;
1669266423Sjfv}
1670266423Sjfv
1671266423Sjfv
1672266423Sjfv/*********************************************************************
1673266423Sjfv *
1674266423Sjfv *  Setup MSIX Interrupt resources and handlers for the VSI
1675266423Sjfv *
1676266423Sjfv **********************************************************************/
1677266423Sjfvstatic int
1678266423Sjfvi40e_assign_vsi_legacy(struct i40e_pf *pf)
1679266423Sjfv{
1680266423Sjfv	device_t        dev = pf->dev;
1681266423Sjfv	struct 		i40e_vsi *vsi = &pf->vsi;
1682266423Sjfv	struct		i40e_queue *que = vsi->queues;
1683266423Sjfv	int 		error, rid = 0;
1684266423Sjfv
1685266423Sjfv	if (pf->msix == 1)
1686266423Sjfv		rid = 1;
1687266423Sjfv	pf->res = bus_alloc_resource_any(dev, SYS_RES_IRQ,
1688266423Sjfv	    &rid, RF_SHAREABLE | RF_ACTIVE);
1689266423Sjfv	if (pf->res == NULL) {
1690266423Sjfv		device_printf(dev,"Unable to allocate"
1691266423Sjfv		    " bus resource: vsi legacy/msi interrupt\n");
1692266423Sjfv		return (ENXIO);
1693266423Sjfv	}
1694266423Sjfv
1695266423Sjfv	/* Set the handler function */
1696266423Sjfv	error = bus_setup_intr(dev, pf->res,
1697266423Sjfv	    INTR_TYPE_NET | INTR_MPSAFE, NULL,
1698266423Sjfv	    i40e_intr, pf, &pf->tag);
1699266423Sjfv	if (error) {
1700266423Sjfv		pf->res = NULL;
1701266423Sjfv		device_printf(dev, "Failed to register legacy/msi handler");
1702266423Sjfv		return (error);
1703266423Sjfv	}
1704266423Sjfv	bus_describe_intr(dev, pf->res, pf->tag, "irq0");
1705266423Sjfv	TASK_INIT(&que->tx_task, 0, i40e_deferred_mq_start, que);
1706266423Sjfv	TASK_INIT(&que->task, 0, i40e_handle_que, que);
1707266423Sjfv	que->tq = taskqueue_create_fast("i40e_que", M_NOWAIT,
1708266423Sjfv	    taskqueue_thread_enqueue, &que->tq);
1709266423Sjfv	taskqueue_start_threads(&que->tq, 1, PI_NET, "%s que",
1710266423Sjfv	    device_get_nameunit(dev));
1711266423Sjfv	TASK_INIT(&pf->adminq, 0, i40e_do_adminq, pf);
1712266423Sjfv	pf->tq = taskqueue_create_fast("i40e_adm", M_NOWAIT,
1713266423Sjfv	    taskqueue_thread_enqueue, &pf->tq);
1714266423Sjfv	taskqueue_start_threads(&pf->tq, 1, PI_NET, "%s adminq",
1715266423Sjfv	    device_get_nameunit(dev));
1716266423Sjfv
1717266423Sjfv	return (0);
1718266423Sjfv}
1719266423Sjfv
1720266423Sjfv
1721266423Sjfv/*********************************************************************
1722266423Sjfv *
1723266423Sjfv *  Setup MSIX Interrupt resources and handlers for the VSI
1724266423Sjfv *
1725266423Sjfv **********************************************************************/
1726266423Sjfvstatic int
1727266423Sjfvi40e_assign_vsi_msix(struct i40e_pf *pf)
1728266423Sjfv{
1729266423Sjfv	device_t	dev = pf->dev;
1730266423Sjfv	struct 		i40e_vsi *vsi = &pf->vsi;
1731266423Sjfv	struct 		i40e_queue *que = vsi->queues;
1732266423Sjfv	struct		tx_ring	 *txr;
1733266423Sjfv	int 		error, rid, vector = 0;
1734266423Sjfv
1735266423Sjfv	/* Admin Que is vector 0*/
1736266423Sjfv	rid = vector + 1;
1737266423Sjfv	pf->res = bus_alloc_resource_any(dev,
1738266423Sjfv    	    SYS_RES_IRQ, &rid, RF_SHAREABLE | RF_ACTIVE);
1739266423Sjfv	if (!pf->res) {
1740266423Sjfv		device_printf(dev,"Unable to allocate"
1741266423Sjfv    	    " bus resource: Adminq interrupt [%d]\n", rid);
1742266423Sjfv		return (ENXIO);
1743266423Sjfv	}
1744266423Sjfv	/* Set the adminq vector and handler */
1745266423Sjfv	error = bus_setup_intr(dev, pf->res,
1746266423Sjfv	    INTR_TYPE_NET | INTR_MPSAFE, NULL,
1747266423Sjfv	    i40e_msix_adminq, pf, &pf->tag);
1748266423Sjfv	if (error) {
1749266423Sjfv		pf->res = NULL;
1750266423Sjfv		device_printf(dev, "Failed to register Admin que handler");
1751266423Sjfv		return (error);
1752266423Sjfv	}
1753266423Sjfv	bus_describe_intr(dev, pf->res, pf->tag, "aq");
1754266423Sjfv	pf->admvec = vector;
1755266423Sjfv	/* Tasklet for Admin Queue */
1756266423Sjfv	TASK_INIT(&pf->adminq, 0, i40e_do_adminq, pf);
1757266423Sjfv	pf->tq = taskqueue_create_fast("i40e_adm", M_NOWAIT,
1758266423Sjfv	    taskqueue_thread_enqueue, &pf->tq);
1759266423Sjfv	taskqueue_start_threads(&pf->tq, 1, PI_NET, "%s adminq",
1760266423Sjfv	    device_get_nameunit(pf->dev));
1761266423Sjfv	++vector;
1762266423Sjfv
1763266423Sjfv	/* Now set up the stations */
1764266423Sjfv	for (int i = 0; i < vsi->num_queues; i++, vector++, que++) {
1765266423Sjfv		rid = vector + 1;
1766266423Sjfv		txr = &que->txr;
1767266423Sjfv		que->res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid,
1768266423Sjfv		    RF_SHAREABLE | RF_ACTIVE);
1769266423Sjfv		if (que->res == NULL) {
1770266423Sjfv			device_printf(dev,"Unable to allocate"
1771266423Sjfv		    	    " bus resource: que interrupt [%d]\n", vector);
1772266423Sjfv			return (ENXIO);
1773266423Sjfv		}
1774266423Sjfv		/* Set the handler function */
1775266423Sjfv		error = bus_setup_intr(dev, que->res,
1776266423Sjfv		    INTR_TYPE_NET | INTR_MPSAFE, NULL,
1777266423Sjfv		    i40e_msix_que, que, &que->tag);
1778266423Sjfv		if (error) {
1779266423Sjfv			que->res = NULL;
1780266423Sjfv			device_printf(dev, "Failed to register que handler");
1781266423Sjfv			return (error);
1782266423Sjfv		}
1783266423Sjfv		bus_describe_intr(dev, que->res, que->tag, "q%d", i);
1784266423Sjfv		/* Bind the vector to a CPU */
1785266423Sjfv		bus_bind_intr(dev, que->res, i);
1786266423Sjfv		que->msix = vector;
1787266423Sjfv		TASK_INIT(&que->tx_task, 0, i40e_deferred_mq_start, que);
1788266423Sjfv		TASK_INIT(&que->task, 0, i40e_handle_que, que);
1789266423Sjfv		que->tq = taskqueue_create_fast("i40e_que", M_NOWAIT,
1790266423Sjfv		    taskqueue_thread_enqueue, &que->tq);
1791266423Sjfv		taskqueue_start_threads(&que->tq, 1, PI_NET, "%s que",
1792266423Sjfv		    device_get_nameunit(pf->dev));
1793266423Sjfv	}
1794266423Sjfv
1795266423Sjfv	return (0);
1796266423Sjfv}
1797266423Sjfv
1798266423Sjfv
1799266423Sjfv/*
1800266423Sjfv * Allocate MSI/X vectors
1801266423Sjfv */
1802266423Sjfvstatic int
1803266423Sjfvi40e_init_msix(struct i40e_pf *pf)
1804266423Sjfv{
1805266423Sjfv	device_t dev = pf->dev;
1806266423Sjfv	int rid, want, vectors, queues, available;
1807266423Sjfv
1808266423Sjfv	/* Override by tuneable */
1809266423Sjfv	if (i40e_enable_msix == 0)
1810266423Sjfv		goto msi;
1811266423Sjfv
1812266423Sjfv	/* First try MSI/X */
1813266423Sjfv	rid = PCIR_BAR(I40E_BAR);
1814266423Sjfv	pf->msix_mem = bus_alloc_resource_any(dev,
1815266423Sjfv	    SYS_RES_MEMORY, &rid, RF_ACTIVE);
1816266423Sjfv       	if (!pf->msix_mem) {
1817266423Sjfv		/* May not be enabled */
1818266423Sjfv		device_printf(pf->dev,
1819266423Sjfv		    "Unable to map MSIX table \n");
1820266423Sjfv		goto msi;
1821266423Sjfv	}
1822266423Sjfv
1823266423Sjfv	available = pci_msix_count(dev);
1824266423Sjfv	if (available == 0) { /* system has msix disabled */
1825266423Sjfv		bus_release_resource(dev, SYS_RES_MEMORY,
1826266423Sjfv		    rid, pf->msix_mem);
1827266423Sjfv		pf->msix_mem = NULL;
1828266423Sjfv		goto msi;
1829266423Sjfv	}
1830266423Sjfv
1831266423Sjfv	/* Figure out a reasonable auto config value */
1832266423Sjfv	queues = (mp_ncpus > (available - 1)) ? (available - 1) : mp_ncpus;
1833266423Sjfv
1834266423Sjfv	/* Override with hardcoded value if sane */
1835266423Sjfv	if ((i40e_max_queues != 0) && (i40e_max_queues <= queues))
1836266423Sjfv		queues = i40e_max_queues;
1837266423Sjfv
1838266423Sjfv	/*
1839266423Sjfv	** Want one vector (RX/TX pair) per queue
1840266423Sjfv	** plus an additional for the admin queue.
1841266423Sjfv	*/
1842266423Sjfv	want = queues + 1;
1843266423Sjfv	if (want <= available)	/* Have enough */
1844266423Sjfv		vectors = want;
1845266423Sjfv	else {
1846266423Sjfv               	device_printf(pf->dev,
1847266423Sjfv		    "MSIX Configuration Problem, "
1848266423Sjfv		    "%d vectors available but %d wanted!\n",
1849266423Sjfv		    available, want);
1850266423Sjfv		return (0); /* Will go to Legacy setup */
1851266423Sjfv	}
1852266423Sjfv
1853266423Sjfv	// NOTE this is all simplified based on ONE VSI
1854266423Sjfv	if (pci_alloc_msix(dev, &vectors) == 0) {
1855266423Sjfv               	device_printf(pf->dev,
1856266423Sjfv		    "Using MSIX interrupts with %d vectors\n", vectors);
1857266423Sjfv		pf->msix = vectors;
1858266423Sjfv		pf->vsi.num_queues = queues;
1859266423Sjfv		return (vectors);
1860266423Sjfv	}
1861266423Sjfvmsi:
1862266423Sjfv       	vectors = pci_msi_count(dev);
1863266423Sjfv	pf->vsi.num_queues = 1;
1864266423Sjfv	pf->msix = 1;
1865266423Sjfv	i40e_max_queues = 1;
1866266423Sjfv	i40e_enable_msix = 0;
1867266423Sjfv       	if (vectors == 1 && pci_alloc_msi(dev, &vectors) == 0)
1868266423Sjfv               	device_printf(pf->dev,"Using an MSI interrupt\n");
1869266423Sjfv	else {
1870266423Sjfv		pf->msix = 0;
1871266423Sjfv               	device_printf(pf->dev,"Using a Legacy interrupt\n");
1872266423Sjfv	}
1873266423Sjfv	return (vectors);
1874266423Sjfv}
1875266423Sjfv
1876266423Sjfv
1877266423Sjfv/*
1878266423Sjfv * Plumb MSI/X vectors
1879266423Sjfv */
1880266423Sjfvstatic void
1881266423Sjfvi40e_configure_msix(struct i40e_pf *pf)
1882266423Sjfv{
1883266423Sjfv	struct i40e_hw	*hw = &pf->hw;
1884266423Sjfv	struct i40e_vsi *vsi = &pf->vsi;
1885266423Sjfv	u32		reg;
1886266423Sjfv	u16		vector = 1;
1887266423Sjfv
1888266423Sjfv	/* First set up the adminq - vector 0 */
1889266423Sjfv	wr32(hw, I40E_PFINT_ICR0_ENA, 0);  /* disable all */
1890266423Sjfv	rd32(hw, I40E_PFINT_ICR0);         /* read to clear */
1891266423Sjfv
1892266423Sjfv	reg = I40E_PFINT_ICR0_ENA_ECC_ERR_MASK |
1893266423Sjfv	    I40E_PFINT_ICR0_ENA_GRST_MASK |
1894266423Sjfv	    I40E_PFINT_ICR0_HMC_ERR_MASK |
1895266423Sjfv	    I40E_PFINT_ICR0_ENA_ADMINQ_MASK |
1896266423Sjfv	    I40E_PFINT_ICR0_ENA_MAL_DETECT_MASK |
1897266423Sjfv	    I40E_PFINT_ICR0_ENA_VFLR_MASK |
1898266423Sjfv	    I40E_PFINT_ICR0_ENA_PCI_EXCEPTION_MASK;
1899266423Sjfv	wr32(hw, I40E_PFINT_ICR0_ENA, reg);
1900266423Sjfv
1901266423Sjfv	wr32(hw, I40E_PFINT_LNKLST0, 0x7FF);
1902266423Sjfv	wr32(hw, I40E_PFINT_ITR0(I40E_RX_ITR), 0x003E);
1903266423Sjfv
1904266423Sjfv	wr32(hw, I40E_PFINT_DYN_CTL0,
1905266423Sjfv	    I40E_PFINT_DYN_CTL0_SW_ITR_INDX_MASK |
1906266423Sjfv	    I40E_PFINT_DYN_CTL0_INTENA_MSK_MASK);
1907266423Sjfv
1908266423Sjfv	wr32(hw, I40E_PFINT_STAT_CTL0, 0);
1909266423Sjfv
1910266423Sjfv	/* Next configure the queues */
1911266423Sjfv	for (int i = 0; i < vsi->num_queues; i++, vector++) {
1912266423Sjfv		wr32(hw, I40E_PFINT_DYN_CTLN(i), i);
1913266423Sjfv		wr32(hw, I40E_PFINT_LNKLSTN(i), i);
1914266423Sjfv
1915266423Sjfv		reg = I40E_QINT_RQCTL_CAUSE_ENA_MASK |
1916266423Sjfv		(I40E_RX_ITR << I40E_QINT_RQCTL_ITR_INDX_SHIFT) |
1917266423Sjfv		(vector << I40E_QINT_RQCTL_MSIX_INDX_SHIFT) |
1918266423Sjfv		(i << I40E_QINT_RQCTL_NEXTQ_INDX_SHIFT) |
1919266423Sjfv		(I40E_QUEUE_TYPE_TX << I40E_QINT_RQCTL_NEXTQ_TYPE_SHIFT);
1920266423Sjfv		wr32(hw, I40E_QINT_RQCTL(i), reg);
1921266423Sjfv
1922266423Sjfv		reg = I40E_QINT_TQCTL_CAUSE_ENA_MASK |
1923266423Sjfv		(I40E_TX_ITR << I40E_QINT_TQCTL_ITR_INDX_SHIFT) |
1924266423Sjfv		(vector << I40E_QINT_TQCTL_MSIX_INDX_SHIFT) |
1925266423Sjfv		((i+1) << I40E_QINT_TQCTL_NEXTQ_INDX_SHIFT) |
1926266423Sjfv		(I40E_QUEUE_TYPE_RX << I40E_QINT_TQCTL_NEXTQ_TYPE_SHIFT);
1927266423Sjfv		if (i == (vsi->num_queues - 1))
1928266423Sjfv			reg |= (I40E_QUEUE_EOL
1929266423Sjfv			    << I40E_QINT_TQCTL_NEXTQ_INDX_SHIFT);
1930266423Sjfv		wr32(hw, I40E_QINT_TQCTL(i), reg);
1931266423Sjfv	}
1932266423Sjfv}
1933266423Sjfv
1934266423Sjfv/*
1935266423Sjfv * Configure for MSI single vector operation
1936266423Sjfv */
1937266423Sjfvstatic void
1938266423Sjfvi40e_configure_legacy(struct i40e_pf *pf)
1939266423Sjfv{
1940266423Sjfv	struct i40e_hw	*hw = &pf->hw;
1941266423Sjfv	u32		reg;
1942266423Sjfv
1943266423Sjfv
1944266423Sjfv	wr32(hw, I40E_PFINT_ITR0(0), 0);
1945266423Sjfv	wr32(hw, I40E_PFINT_ITR0(1), 0);
1946266423Sjfv
1947266423Sjfv
1948266423Sjfv	/* Setup "other" causes */
1949266423Sjfv	reg = I40E_PFINT_ICR0_ENA_ECC_ERR_MASK
1950266423Sjfv	    | I40E_PFINT_ICR0_ENA_MAL_DETECT_MASK
1951266423Sjfv	    | I40E_PFINT_ICR0_ENA_GRST_MASK
1952266423Sjfv	    | I40E_PFINT_ICR0_ENA_PCI_EXCEPTION_MASK
1953266423Sjfv	    | I40E_PFINT_ICR0_ENA_GPIO_MASK
1954266423Sjfv	    | I40E_PFINT_ICR0_ENA_LINK_STAT_CHANGE_MASK
1955266423Sjfv	    | I40E_PFINT_ICR0_ENA_HMC_ERR_MASK
1956266423Sjfv	    | I40E_PFINT_ICR0_ENA_PE_CRITERR_MASK
1957266423Sjfv	    | I40E_PFINT_ICR0_ENA_VFLR_MASK
1958266423Sjfv	    | I40E_PFINT_ICR0_ENA_ADMINQ_MASK
1959266423Sjfv	    ;
1960266423Sjfv	wr32(hw, I40E_PFINT_ICR0_ENA, reg);
1961266423Sjfv
1962266423Sjfv	/* SW_ITR_IDX = 0, but don't change INTENA */
1963266423Sjfv	wr32(hw, I40E_PFINT_DYN_CTL0,
1964266423Sjfv	    I40E_PFINT_DYN_CTLN_SW_ITR_INDX_MASK |
1965266423Sjfv	    I40E_PFINT_DYN_CTLN_INTENA_MSK_MASK);
1966266423Sjfv	/* SW_ITR_IDX = 0, OTHER_ITR_IDX = 0 */
1967266423Sjfv	wr32(hw, I40E_PFINT_STAT_CTL0, 0);
1968266423Sjfv
1969266423Sjfv	/* FIRSTQ_INDX = 0, FIRSTQ_TYPE = 0 (rx) */
1970266423Sjfv	wr32(hw, I40E_PFINT_LNKLST0, 0);
1971266423Sjfv
1972266423Sjfv	/* Associate the queue pair to the vector and enable the q int */
1973266423Sjfv	reg = I40E_QINT_RQCTL_CAUSE_ENA_MASK
1974266423Sjfv	    | (I40E_RX_ITR << I40E_QINT_RQCTL_ITR_INDX_SHIFT)
1975266423Sjfv	    | (I40E_QUEUE_TYPE_TX << I40E_QINT_TQCTL_NEXTQ_TYPE_SHIFT);
1976266423Sjfv	wr32(hw, I40E_QINT_RQCTL(0), reg);
1977266423Sjfv
1978266423Sjfv	reg = I40E_QINT_TQCTL_CAUSE_ENA_MASK
1979266423Sjfv	    | (I40E_TX_ITR << I40E_QINT_TQCTL_ITR_INDX_SHIFT)
1980266423Sjfv	    | (I40E_QUEUE_EOL << I40E_QINT_TQCTL_NEXTQ_INDX_SHIFT);
1981266423Sjfv	wr32(hw, I40E_QINT_TQCTL(0), reg);
1982266423Sjfv
1983266423Sjfv	/* Next enable the queue pair */
1984266423Sjfv	reg = rd32(hw, I40E_QTX_ENA(0));
1985266423Sjfv	reg |= I40E_QTX_ENA_QENA_REQ_MASK;
1986266423Sjfv	wr32(hw, I40E_QTX_ENA(0), reg);
1987266423Sjfv
1988266423Sjfv	reg = rd32(hw, I40E_QRX_ENA(0));
1989266423Sjfv	reg |= I40E_QRX_ENA_QENA_REQ_MASK;
1990266423Sjfv	wr32(hw, I40E_QRX_ENA(0), reg);
1991266423Sjfv}
1992266423Sjfv
1993266423Sjfv
1994266423Sjfv/*
1995266423Sjfv * Set the Initial ITR state
1996266423Sjfv */
1997266423Sjfvstatic void
1998266423Sjfvi40e_configure_itr(struct i40e_pf *pf)
1999266423Sjfv{
2000266423Sjfv	struct i40e_hw		*hw = &pf->hw;
2001266423Sjfv	struct i40e_vsi		*vsi = &pf->vsi;
2002266423Sjfv	struct i40e_queue	*que = vsi->queues;
2003266423Sjfv
2004266423Sjfv	vsi->rx_itr_setting = i40e_rx_itr;
2005266423Sjfv	if (i40e_dynamic_rx_itr)
2006266423Sjfv		vsi->rx_itr_setting |= I40E_ITR_DYNAMIC;
2007266423Sjfv	vsi->tx_itr_setting = i40e_tx_itr;
2008266423Sjfv	if (i40e_dynamic_tx_itr)
2009266423Sjfv		vsi->tx_itr_setting |= I40E_ITR_DYNAMIC;
2010266423Sjfv
2011266423Sjfv	for (int i = 0; i < vsi->num_queues; i++, que++) {
2012266423Sjfv		struct tx_ring	*txr = &que->txr;
2013266423Sjfv		struct rx_ring 	*rxr = &que->rxr;
2014266423Sjfv
2015266423Sjfv		wr32(hw, I40E_PFINT_ITRN(I40E_RX_ITR, i),
2016266423Sjfv		    vsi->rx_itr_setting);
2017266423Sjfv		rxr->itr = vsi->rx_itr_setting;
2018266423Sjfv		rxr->latency = I40E_AVE_LATENCY;
2019266423Sjfv		wr32(hw, I40E_PFINT_ITRN(I40E_TX_ITR, i),
2020266423Sjfv		    vsi->tx_itr_setting);
2021266423Sjfv		txr->itr = vsi->tx_itr_setting;
2022266423Sjfv		txr->latency = I40E_AVE_LATENCY;
2023266423Sjfv	}
2024266423Sjfv}
2025266423Sjfv
2026266423Sjfv
2027266423Sjfvstatic int
2028266423Sjfvi40e_allocate_pci_resources(struct i40e_pf *pf)
2029266423Sjfv{
2030266423Sjfv	int             rid;
2031266423Sjfv	device_t        dev = pf->dev;
2032266423Sjfv
2033266423Sjfv	rid = PCIR_BAR(0);
2034266423Sjfv	pf->pci_mem = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
2035266423Sjfv	    &rid, RF_ACTIVE);
2036266423Sjfv
2037266423Sjfv	if (!(pf->pci_mem)) {
2038266423Sjfv		device_printf(dev,"Unable to allocate bus resource: memory\n");
2039266423Sjfv		return (ENXIO);
2040266423Sjfv	}
2041266423Sjfv
2042266423Sjfv	pf->osdep.mem_bus_space_tag =
2043266423Sjfv		rman_get_bustag(pf->pci_mem);
2044266423Sjfv	pf->osdep.mem_bus_space_handle =
2045266423Sjfv		rman_get_bushandle(pf->pci_mem);
2046266423Sjfv	pf->hw.hw_addr = (u8 *) &pf->osdep.mem_bus_space_handle;
2047266423Sjfv
2048266423Sjfv	pf->hw.back = &pf->osdep;
2049266423Sjfv
2050266423Sjfv	/*
2051266423Sjfv	** Now setup MSI or MSI/X, should
2052266423Sjfv	** return us the number of supported
2053266423Sjfv	** vectors. (Will be 1 for MSI)
2054266423Sjfv	*/
2055266423Sjfv	pf->msix = i40e_init_msix(pf);
2056266423Sjfv	return (0);
2057266423Sjfv}
2058266423Sjfv
2059266423Sjfvstatic void
2060266423Sjfvi40e_free_pci_resources(struct i40e_pf * pf)
2061266423Sjfv{
2062266423Sjfv	struct i40e_vsi		*vsi = &pf->vsi;
2063266423Sjfv	struct i40e_queue	*que = vsi->queues;
2064266423Sjfv	device_t		dev = pf->dev;
2065266423Sjfv	int			rid, memrid;
2066266423Sjfv
2067266423Sjfv	memrid = PCIR_BAR(I40E_BAR);
2068266423Sjfv
2069266423Sjfv	/* We may get here before stations are setup */
2070266423Sjfv	if ((!i40e_enable_msix) || (que == NULL))
2071266423Sjfv		goto early;
2072266423Sjfv
2073266423Sjfv	/*
2074266423Sjfv	**  Release all msix VSI resources:
2075266423Sjfv	*/
2076266423Sjfv	for (int i = 0; i < vsi->num_queues; i++, que++) {
2077266423Sjfv		rid = que->msix + 1;
2078266423Sjfv		if (que->tag != NULL) {
2079266423Sjfv			bus_teardown_intr(dev, que->res, que->tag);
2080266423Sjfv			que->tag = NULL;
2081266423Sjfv		}
2082266423Sjfv		if (que->res != NULL)
2083266423Sjfv			bus_release_resource(dev, SYS_RES_IRQ, rid, que->res);
2084266423Sjfv	}
2085266423Sjfv
2086266423Sjfvearly:
2087266423Sjfv	/* Clean the AdminQ interrupt last */
2088266423Sjfv	if (pf->admvec) /* we are doing MSIX */
2089266423Sjfv		rid = pf->admvec + 1;
2090266423Sjfv	else
2091266423Sjfv		(pf->msix != 0) ? (rid = 1):(rid = 0);
2092266423Sjfv
2093266423Sjfv	if (pf->tag != NULL) {
2094266423Sjfv		bus_teardown_intr(dev, pf->res, pf->tag);
2095266423Sjfv		pf->tag = NULL;
2096266423Sjfv	}
2097266423Sjfv	if (pf->res != NULL)
2098266423Sjfv		bus_release_resource(dev, SYS_RES_IRQ, rid, pf->res);
2099266423Sjfv
2100266423Sjfv	if (pf->msix)
2101266423Sjfv		pci_release_msi(dev);
2102266423Sjfv
2103266423Sjfv	if (pf->msix_mem != NULL)
2104266423Sjfv		bus_release_resource(dev, SYS_RES_MEMORY,
2105266423Sjfv		    memrid, pf->msix_mem);
2106266423Sjfv
2107266423Sjfv	if (pf->pci_mem != NULL)
2108266423Sjfv		bus_release_resource(dev, SYS_RES_MEMORY,
2109266423Sjfv		    PCIR_BAR(0), pf->pci_mem);
2110266423Sjfv
2111266423Sjfv	return;
2112266423Sjfv}
2113266423Sjfv
2114266423Sjfv
2115266423Sjfv/*********************************************************************
2116266423Sjfv *
2117266423Sjfv *  Setup networking device structure and register an interface.
2118266423Sjfv *
2119266423Sjfv **********************************************************************/
2120266423Sjfvstatic int
2121266423Sjfvi40e_setup_interface(device_t dev, struct i40e_vsi *vsi)
2122266423Sjfv{
2123266423Sjfv	struct ifnet		*ifp;
2124266423Sjfv	struct i40e_hw		*hw = vsi->hw;
2125266423Sjfv	struct i40e_queue	*que = vsi->queues;
2126266423Sjfv	struct i40e_aq_get_phy_abilities_resp abilities_resp;
2127266423Sjfv	enum i40e_status_code aq_error = 0;
2128266423Sjfv
2129266423Sjfv	INIT_DEBUGOUT("i40e_setup_interface: begin");
2130266423Sjfv
2131266423Sjfv	ifp = vsi->ifp = if_alloc(IFT_ETHER);
2132266423Sjfv	if (ifp == NULL) {
2133266423Sjfv		device_printf(dev, "can not allocate ifnet structure\n");
2134266423Sjfv		return (-1);
2135266423Sjfv	}
2136266423Sjfv	if_initname(ifp, device_get_name(dev), device_get_unit(dev));
2137266423Sjfv	ifp->if_mtu = ETHERMTU;
2138266423Sjfv	ifp->if_baudrate = 4000000000;  // ??
2139266423Sjfv	ifp->if_init = i40e_init;
2140266423Sjfv	ifp->if_softc = vsi;
2141266423Sjfv	ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
2142266423Sjfv	ifp->if_ioctl = i40e_ioctl;
2143266423Sjfv
2144266423Sjfv	ifp->if_transmit = i40e_mq_start;
2145266423Sjfv
2146266423Sjfv	ifp->if_qflush = i40e_qflush;
2147266423Sjfv
2148266423Sjfv	ifp->if_snd.ifq_maxlen = que->num_desc - 2;
2149266423Sjfv
2150266423Sjfv	ether_ifattach(ifp, hw->mac.addr);
2151266423Sjfv
2152266423Sjfv	vsi->max_frame_size =
2153266423Sjfv	    ifp->if_mtu + ETHER_HDR_LEN + ETHER_CRC_LEN
2154266423Sjfv	    + ETHER_VLAN_ENCAP_LEN;
2155266423Sjfv
2156266423Sjfv	/*
2157266423Sjfv	 * Tell the upper layer(s) we support long frames.
2158266423Sjfv	 */
2159266423Sjfv	ifp->if_data.ifi_hdrlen = sizeof(struct ether_vlan_header);
2160266423Sjfv
2161266423Sjfv	ifp->if_capabilities |= IFCAP_HWCSUM;
2162266423Sjfv	ifp->if_capabilities |= IFCAP_HWCSUM_IPV6;
2163266423Sjfv	ifp->if_capabilities |= IFCAP_TSO;
2164266423Sjfv	ifp->if_capabilities |= IFCAP_JUMBO_MTU;
2165266423Sjfv	ifp->if_capabilities |= IFCAP_LRO;
2166266423Sjfv
2167266423Sjfv	/* VLAN capabilties */
2168266423Sjfv	ifp->if_capabilities |= IFCAP_VLAN_HWTAGGING
2169266423Sjfv			     |  IFCAP_VLAN_HWTSO
2170266423Sjfv			     |  IFCAP_VLAN_MTU
2171266423Sjfv			     |  IFCAP_VLAN_HWCSUM;
2172266423Sjfv	ifp->if_capenable = ifp->if_capabilities;
2173266423Sjfv
2174266423Sjfv	/*
2175266423Sjfv	** Don't turn this on by default, if vlans are
2176266423Sjfv	** created on another pseudo device (eg. lagg)
2177266423Sjfv	** then vlan events are not passed thru, breaking
2178266423Sjfv	** operation, but with HW FILTER off it works. If
2179266423Sjfv	** using vlans directly on the i40e driver you can
2180266423Sjfv	** enable this and get full hardware tag filtering.
2181266423Sjfv	*/
2182266423Sjfv	ifp->if_capabilities |= IFCAP_VLAN_HWFILTER;
2183266423Sjfv
2184266423Sjfv	/*
2185266423Sjfv	 * Specify the media types supported by this adapter and register
2186266423Sjfv	 * callbacks to update media and link information
2187266423Sjfv	 */
2188266423Sjfv	ifmedia_init(&vsi->media, IFM_IMASK, i40e_media_change,
2189266423Sjfv		     i40e_media_status);
2190266423Sjfv
2191266423Sjfv	aq_error = i40e_aq_get_phy_capabilities(hw, FALSE, TRUE, &abilities_resp, NULL);
2192266423Sjfv	if (aq_error) {
2193266423Sjfv		printf("Error getting supported media types, AQ error %d\n", aq_error);
2194266423Sjfv		return (EPERM);
2195266423Sjfv	}
2196266423Sjfv
2197266423Sjfv	/* Display PHY's supported media types */
2198266423Sjfv	if (abilities_resp.phy_type & (1 << I40E_PHY_TYPE_100BASE_TX))
2199266423Sjfv		ifmedia_add(&vsi->media, IFM_ETHER | IFM_100_TX, 0, NULL);
2200266423Sjfv
2201266423Sjfv	if (abilities_resp.phy_type & (1 << I40E_PHY_TYPE_1000BASE_T))
2202266423Sjfv		ifmedia_add(&vsi->media, IFM_ETHER | IFM_1000_T, 0, NULL);
2203266423Sjfv
2204266423Sjfv	if (abilities_resp.phy_type & (1 << I40E_PHY_TYPE_10GBASE_CR1_CU) ||
2205266423Sjfv	    abilities_resp.phy_type & (1 << I40E_PHY_TYPE_10GBASE_SFPP_CU))
2206266423Sjfv		ifmedia_add(&vsi->media, IFM_ETHER | IFM_10G_TWINAX, 0, NULL);
2207266423Sjfv	if (abilities_resp.phy_type & (1 << I40E_PHY_TYPE_10GBASE_SR))
2208266423Sjfv		ifmedia_add(&vsi->media, IFM_ETHER | IFM_10G_SR, 0, NULL);
2209266423Sjfv	if (abilities_resp.phy_type & (1 << I40E_PHY_TYPE_10GBASE_LR))
2210266423Sjfv		ifmedia_add(&vsi->media, IFM_ETHER | IFM_10G_LR, 0, NULL);
2211266423Sjfv
2212266423Sjfv	if (abilities_resp.phy_type & (1 << I40E_PHY_TYPE_40GBASE_CR4_CU) ||
2213266423Sjfv	    abilities_resp.phy_type & (1 << I40E_PHY_TYPE_40GBASE_CR4))
2214266423Sjfv		ifmedia_add(&vsi->media, IFM_ETHER | IFM_40G_CR4, 0, NULL);
2215266423Sjfv	if (abilities_resp.phy_type & (1 << I40E_PHY_TYPE_40GBASE_SR4))
2216266423Sjfv		ifmedia_add(&vsi->media, IFM_ETHER | IFM_40G_SR4, 0, NULL);
2217266423Sjfv	if (abilities_resp.phy_type & (1 << I40E_PHY_TYPE_40GBASE_LR4))
2218266423Sjfv		ifmedia_add(&vsi->media, IFM_ETHER | IFM_40G_LR4, 0, NULL);
2219266423Sjfv
2220266423Sjfv	/* Use autoselect media by default */
2221266423Sjfv	ifmedia_add(&vsi->media, IFM_ETHER | IFM_AUTO, 0, NULL);
2222266423Sjfv	ifmedia_set(&vsi->media, IFM_ETHER | IFM_AUTO);
2223266423Sjfv
2224266423Sjfv	return (0);
2225266423Sjfv}
2226266423Sjfv
2227266423Sjfvstatic bool
2228266423Sjfvi40e_config_link(struct i40e_hw *hw)
2229266423Sjfv{
2230266423Sjfv	bool check;
2231266423Sjfv
2232266423Sjfv	i40e_aq_get_link_info(hw, TRUE, NULL, NULL);
2233266423Sjfv	check = i40e_get_link_status(hw);
2234266423Sjfv#ifdef I40E_DEBUG
2235266423Sjfv	printf("Link is %s\n", check ? "up":"down");
2236266423Sjfv#endif
2237266423Sjfv	return (check);
2238266423Sjfv}
2239266423Sjfv
2240266423Sjfv/*********************************************************************
2241266423Sjfv *
2242266423Sjfv *  Initialize this VSI
2243266423Sjfv *
2244266423Sjfv **********************************************************************/
2245266423Sjfvstatic int
2246266423Sjfvi40e_setup_vsi(struct i40e_vsi *vsi)
2247266423Sjfv{
2248266423Sjfv	struct i40e_hw	*hw = vsi->hw;
2249266423Sjfv	device_t 	dev = vsi->dev;
2250266423Sjfv	struct i40e_aqc_get_switch_config_resp *sw_config;
2251266423Sjfv	struct i40e_vsi_context	ctxt;
2252266423Sjfv	u8	aq_buf[I40E_AQ_LARGE_BUF];
2253266423Sjfv	int	ret = I40E_SUCCESS;
2254266423Sjfv	u16	next = 0;
2255266423Sjfv
2256266423Sjfv	sw_config = (struct i40e_aqc_get_switch_config_resp *)aq_buf;
2257266423Sjfv	ret = i40e_aq_get_switch_config(hw, sw_config,
2258266423Sjfv	    sizeof(aq_buf), &next, NULL);
2259266423Sjfv	if (ret) {
2260266423Sjfv		device_printf(dev,"aq_get_switch_config failed!!\n");
2261266423Sjfv		return (ret);
2262266423Sjfv	}
2263266423Sjfv#ifdef I40E_DEBUG
2264266423Sjfv	printf("Switch config: header reported: %d in structure, %d total\n",
2265266423Sjfv    	    sw_config->header.num_reported, sw_config->header.num_total);
2266266423Sjfv	printf("type=%d seid=%d uplink=%d downlink=%d\n",
2267266423Sjfv	    sw_config->element[0].element_type,
2268266423Sjfv	    sw_config->element[0].seid,
2269266423Sjfv	    sw_config->element[0].uplink_seid,
2270266423Sjfv	    sw_config->element[0].downlink_seid);
2271266423Sjfv#endif
2272266423Sjfv	/* Save off this important value */
2273266423Sjfv	vsi->seid = sw_config->element[0].seid;
2274266423Sjfv
2275266423Sjfv	memset(&ctxt, 0, sizeof(ctxt));
2276266423Sjfv	ctxt.seid = vsi->seid;
2277266423Sjfv	ctxt.pf_num = hw->pf_id;
2278266423Sjfv	ret = i40e_aq_get_vsi_params(hw, &ctxt, NULL);
2279266423Sjfv	if (ret) {
2280266423Sjfv		device_printf(dev,"get vsi params failed %x!!\n", ret);
2281266423Sjfv		return (ret);
2282266423Sjfv	}
2283266423Sjfv#ifdef I40E_DEBUG
2284266423Sjfv	printf("get_vsi_params: seid: %d, uplinkseid: %d, vsi_number: %d, "
2285266423Sjfv	    "vsis_allocated: %d, vsis_unallocated: %d, flags: 0x%x, "
2286266423Sjfv	    "pfnum: %d, vfnum: %d, stat idx: %d, enabled: %d\n", ctxt.seid,
2287266423Sjfv	    ctxt.uplink_seid, ctxt.vsi_number,
2288266423Sjfv	    ctxt.vsis_allocated, ctxt.vsis_unallocated,
2289266423Sjfv	    ctxt.flags, ctxt.pf_num, ctxt.vf_num,
2290266423Sjfv	    ctxt.info.stat_counter_idx, ctxt.info.up_enable_bits);
2291266423Sjfv#endif
2292266423Sjfv	/*
2293266423Sjfv	** Set the queue and traffic class bits
2294266423Sjfv	**  - when multiple traffic classes are supported
2295266423Sjfv	**    this will need to be more robust.
2296266423Sjfv	*/
2297266423Sjfv	ctxt.info.valid_sections = I40E_AQ_VSI_PROP_QUEUE_MAP_VALID;
2298266423Sjfv	ctxt.info.mapping_flags |= I40E_AQ_VSI_QUE_MAP_CONTIG;
2299266423Sjfv	ctxt.info.queue_mapping[0] = 0;
2300266423Sjfv	ctxt.info.tc_mapping[0] = 0x0800;
2301266423Sjfv
2302266423Sjfv	/* Set VLAN receive stripping mode */
2303266423Sjfv	ctxt.info.valid_sections |= I40E_AQ_VSI_PROP_VLAN_VALID;
2304266423Sjfv	ctxt.info.port_vlan_flags = I40E_AQ_VSI_PVLAN_MODE_ALL;
2305266423Sjfv	if (vsi->ifp->if_capenable & IFCAP_VLAN_HWTAGGING)
2306266423Sjfv	    ctxt.info.port_vlan_flags |= I40E_AQ_VSI_PVLAN_EMOD_STR_BOTH;
2307266423Sjfv	else
2308266423Sjfv	    ctxt.info.port_vlan_flags |= I40E_AQ_VSI_PVLAN_EMOD_NOTHING;
2309266423Sjfv
2310266423Sjfv	/* Keep copy of VSI info in VSI for statistic counters */
2311266423Sjfv	memcpy(&vsi->info, &ctxt.info, sizeof(ctxt.info));
2312266423Sjfv
2313266423Sjfv	/* Reset VSI statistics */
2314266423Sjfv	i40e_vsi_reset_stats(vsi);
2315266423Sjfv	vsi->hw_filters_add = 0;
2316266423Sjfv	vsi->hw_filters_del = 0;
2317266423Sjfv
2318266423Sjfv	ret = i40e_aq_update_vsi_params(hw, &ctxt, NULL);
2319266423Sjfv	if (ret)
2320266423Sjfv		device_printf(dev,"update vsi params failed %x!!\n",
2321266423Sjfv		   hw->aq.asq_last_status);
2322266423Sjfv	return (ret);
2323266423Sjfv}
2324266423Sjfv
2325266423Sjfv
2326266423Sjfv/*********************************************************************
2327266423Sjfv *
2328266423Sjfv *  Initialize the VSI:  this handles contexts, which means things
2329266423Sjfv *  			 like the number of descriptors, buffer size,
2330266423Sjfv *			 plus we init the rings thru this function.
2331266423Sjfv *
2332266423Sjfv **********************************************************************/
2333266423Sjfvstatic int
2334266423Sjfvi40e_initialize_vsi(struct i40e_vsi *vsi)
2335266423Sjfv{
2336266423Sjfv	struct i40e_queue	*que = vsi->queues;
2337266423Sjfv	device_t		dev = vsi->dev;
2338266423Sjfv	struct i40e_hw		*hw = vsi->hw;
2339266423Sjfv	int			err = 0;
2340266423Sjfv
2341266423Sjfv
2342266423Sjfv	for (int i = 0; i < vsi->num_queues; i++, que++) {
2343266423Sjfv		struct tx_ring		*txr = &que->txr;
2344266423Sjfv		struct rx_ring 		*rxr = &que->rxr;
2345266423Sjfv		struct i40e_hmc_obj_txq tctx;
2346266423Sjfv		struct i40e_hmc_obj_rxq rctx;
2347266423Sjfv		u32			txctl;
2348266423Sjfv		u16			size;
2349266423Sjfv
2350266423Sjfv
2351266423Sjfv		/* Setup the HMC TX Context  */
2352266423Sjfv		size = que->num_desc * sizeof(struct i40e_tx_desc);
2353266423Sjfv		memset(&tctx, 0, sizeof(struct i40e_hmc_obj_txq));
2354266423Sjfv		tctx.new_context = 1;
2355266423Sjfv		tctx.base = (txr->dma.pa/128);
2356266423Sjfv		tctx.qlen = que->num_desc;
2357266423Sjfv		tctx.fc_ena = 0;
2358266423Sjfv		tctx.rdylist = vsi->info.qs_handle[0];
2359266423Sjfv		tctx.rdylist_act = 0;
2360266423Sjfv		err = i40e_clear_lan_tx_queue_context(hw, i);
2361266423Sjfv		if (err) {
2362266423Sjfv			device_printf(dev, "Unable to clear TX context\n");
2363266423Sjfv			break;
2364266423Sjfv		}
2365266423Sjfv		err = i40e_set_lan_tx_queue_context(hw, i, &tctx);
2366266423Sjfv		if (err) {
2367266423Sjfv			device_printf(dev, "Unable to set TX context\n");
2368266423Sjfv			break;
2369266423Sjfv		}
2370266423Sjfv		/* Associate the ring with this PF */
2371266423Sjfv		txctl = I40E_QTX_CTL_PF_QUEUE;
2372266423Sjfv		txctl |= ((hw->pf_id << I40E_QTX_CTL_PF_INDX_SHIFT) &
2373266423Sjfv		    I40E_QTX_CTL_PF_INDX_MASK);
2374266423Sjfv		wr32(hw, I40E_QTX_CTL(i), txctl);
2375266423Sjfv		i40e_flush(hw);
2376266423Sjfv
2377266423Sjfv		/* Do ring (re)init */
2378266423Sjfv		i40e_init_tx_ring(que);
2379266423Sjfv
2380266423Sjfv		/* Next setup the HMC RX Context  */
2381266423Sjfv		if (vsi->max_frame_size <= 2048)
2382266423Sjfv			rxr->mbuf_sz = MCLBYTES;
2383266423Sjfv		else
2384266423Sjfv			rxr->mbuf_sz = MJUMPAGESIZE;
2385266423Sjfv
2386266423Sjfv		u16 max_rxmax = rxr->mbuf_sz * hw->func_caps.rx_buf_chain_len;
2387266423Sjfv
2388266423Sjfv		/* Set up an RX context for the HMC */
2389266423Sjfv		memset(&rctx, 0, sizeof(struct i40e_hmc_obj_rxq));
2390266423Sjfv		rctx.dbuff = rxr->mbuf_sz >> I40E_RXQ_CTX_DBUFF_SHIFT;
2391266423Sjfv		/* ignore header split for now */
2392266423Sjfv		rctx.hbuff = 0 >> I40E_RXQ_CTX_HBUFF_SHIFT;
2393266423Sjfv		rctx.rxmax = (vsi->max_frame_size < max_rxmax) ?
2394266423Sjfv		    vsi->max_frame_size : max_rxmax;
2395266423Sjfv		rctx.dtype = 0;
2396266423Sjfv		rctx.dsize = 1;	/* do 32byte descriptors */
2397266423Sjfv		rctx.hsplit_0 = 0;  /* no HDR split initially */
2398266423Sjfv		rctx.base = (rxr->dma.pa/128);
2399266423Sjfv		rctx.qlen = que->num_desc;
2400266423Sjfv		rctx.tphrdesc_ena = 1;
2401266423Sjfv		rctx.tphwdesc_ena = 1;
2402266423Sjfv		rctx.tphdata_ena = 0;
2403266423Sjfv		rctx.tphhead_ena = 0;
2404266423Sjfv#ifdef FORTVILLE_A0_SUPPORT
2405266423Sjfv		rctx.lrxqthresh = 0;
2406266423Sjfv#else
2407266423Sjfv		rctx.lrxqthresh = 2;
2408266423Sjfv#endif
2409266423Sjfv		rctx.crcstrip = 1;
2410266423Sjfv		rctx.l2tsel = 1;
2411266423Sjfv		rctx.showiv = 1;
2412266423Sjfv		rctx.fc_ena = 0;
2413266423Sjfv		rctx.prefena = 1;
2414266423Sjfv
2415266423Sjfv		err = i40e_clear_lan_rx_queue_context(hw, i);
2416266423Sjfv		if (err) {
2417266423Sjfv			device_printf(dev,
2418266423Sjfv			    "Unable to clear RX context %d\n", i);
2419266423Sjfv			break;
2420266423Sjfv		}
2421266423Sjfv		err = i40e_set_lan_rx_queue_context(hw, i, &rctx);
2422266423Sjfv		if (err) {
2423266423Sjfv			device_printf(dev, "Unable to set RX context %d\n", i);
2424266423Sjfv			break;
2425266423Sjfv		}
2426266423Sjfv		err = i40e_init_rx_ring(que);
2427266423Sjfv		if (err) {
2428266423Sjfv			device_printf(dev, "Fail in init_rx_ring %d\n", i);
2429266423Sjfv			break;
2430266423Sjfv		}
2431266423Sjfv		wr32(vsi->hw, I40E_QRX_TAIL(que->me), 0);
2432266423Sjfv		wr32(vsi->hw, I40E_QRX_TAIL(que->me), que->num_desc - 1);
2433266423Sjfv	}
2434266423Sjfv	return (err);
2435266423Sjfv}
2436266423Sjfv
2437266423Sjfv
2438266423Sjfv/*********************************************************************
2439266423Sjfv *
2440266423Sjfv *  Free all VSI structs.
2441266423Sjfv *
2442266423Sjfv **********************************************************************/
2443266423Sjfvvoid
2444266423Sjfvi40e_free_vsi(struct i40e_vsi *vsi)
2445266423Sjfv{
2446266423Sjfv	struct i40e_pf		*pf = (struct i40e_pf *)vsi->back;
2447266423Sjfv	struct i40e_queue	*que = vsi->queues;
2448266423Sjfv	struct i40e_mac_filter *f;
2449266423Sjfv
2450266423Sjfv	/* Free station queues */
2451266423Sjfv	for (int i = 0; i < vsi->num_queues; i++, que++) {
2452266423Sjfv		struct tx_ring *txr = &que->txr;
2453266423Sjfv		struct rx_ring *rxr = &que->rxr;
2454266423Sjfv
2455266423Sjfv		if (!mtx_initialized(&txr->mtx)) /* uninitialized */
2456266423Sjfv			continue;
2457266423Sjfv		I40E_TX_LOCK(txr);
2458266423Sjfv		i40e_free_que_tx(que);
2459266423Sjfv		if (txr->base)
2460266423Sjfv			i40e_free_dma(&pf->hw, &txr->dma);
2461266423Sjfv		I40E_TX_UNLOCK(txr);
2462266423Sjfv		I40E_TX_LOCK_DESTROY(txr);
2463266423Sjfv
2464266423Sjfv		if (!mtx_initialized(&rxr->mtx)) /* uninitialized */
2465266423Sjfv			continue;
2466266423Sjfv		I40E_RX_LOCK(rxr);
2467266423Sjfv		i40e_free_que_rx(que);
2468266423Sjfv		if (rxr->base)
2469266423Sjfv			i40e_free_dma(&pf->hw, &rxr->dma);
2470266423Sjfv		I40E_RX_UNLOCK(rxr);
2471266423Sjfv		I40E_RX_LOCK_DESTROY(rxr);
2472266423Sjfv
2473266423Sjfv	}
2474266423Sjfv	free(vsi->queues, M_DEVBUF);
2475266423Sjfv
2476266423Sjfv	/* Free VSI filter list */
2477266423Sjfv	while (!SLIST_EMPTY(&vsi->ftl)) {
2478266423Sjfv		f = SLIST_FIRST(&vsi->ftl);
2479266423Sjfv		SLIST_REMOVE_HEAD(&vsi->ftl, next);
2480266423Sjfv		free(f, M_DEVBUF);
2481266423Sjfv	}
2482266423Sjfv}
2483266423Sjfv
2484266423Sjfv
2485266423Sjfv/*********************************************************************
2486266423Sjfv *
2487266423Sjfv *  Allocate memory for the VSI (virtual station interface) and their
2488266423Sjfv *  associated queues, rings and the descriptors associated with each,
2489266423Sjfv *  called only once at attach.
2490266423Sjfv *
2491266423Sjfv **********************************************************************/
2492266423Sjfvstatic int
2493266423Sjfvi40e_setup_stations(struct i40e_pf *pf)
2494266423Sjfv{
2495266423Sjfv	device_t		dev = pf->dev;
2496266423Sjfv	struct i40e_vsi		*vsi;
2497266423Sjfv	struct i40e_queue	*que;
2498266423Sjfv	struct tx_ring		*txr;
2499266423Sjfv	struct rx_ring		*rxr;
2500266423Sjfv	int 			rsize, tsize;
2501266423Sjfv	int			error = I40E_SUCCESS;
2502266423Sjfv
2503266423Sjfv	vsi = &pf->vsi;
2504266423Sjfv	vsi->back = (void *)pf;
2505266423Sjfv	vsi->hw = &pf->hw;
2506266423Sjfv	vsi->id = 0;
2507266423Sjfv	vsi->num_vlans = 0;
2508266423Sjfv
2509266423Sjfv	/* Get memory for the station queues */
2510266423Sjfv        if (!(vsi->queues =
2511266423Sjfv            (struct i40e_queue *) malloc(sizeof(struct i40e_queue) *
2512266423Sjfv            vsi->num_queues, M_DEVBUF, M_NOWAIT | M_ZERO))) {
2513266423Sjfv                device_printf(dev, "Unable to allocate queue memory\n");
2514266423Sjfv                error = ENOMEM;
2515266423Sjfv                goto early;
2516266423Sjfv        }
2517266423Sjfv
2518266423Sjfv	for (int i = 0; i < vsi->num_queues; i++) {
2519266423Sjfv		que = &vsi->queues[i];
2520266423Sjfv		que->num_desc = i40e_ringsz;
2521266423Sjfv		que->me = i;
2522266423Sjfv		que->vsi = vsi;
2523266423Sjfv		txr = &que->txr;
2524266423Sjfv		txr->que = que;
2525266423Sjfv
2526266423Sjfv		/* Initialize the TX lock */
2527266423Sjfv		snprintf(txr->mtx_name, sizeof(txr->mtx_name), "%s:tx(%d)",
2528266423Sjfv		    device_get_nameunit(dev), que->me);
2529266423Sjfv		mtx_init(&txr->mtx, txr->mtx_name, NULL, MTX_DEF);
2530266423Sjfv		/* Create the TX descriptor ring */
2531266423Sjfv		tsize = roundup2(que->num_desc *
2532266423Sjfv		    sizeof(struct i40e_tx_desc), DBA_ALIGN);
2533266423Sjfv		if (i40e_allocate_dma(&pf->hw,
2534266423Sjfv		    &txr->dma, tsize, DBA_ALIGN)) {
2535266423Sjfv			device_printf(dev,
2536266423Sjfv			    "Unable to allocate TX Descriptor memory\n");
2537266423Sjfv			error = ENOMEM;
2538266423Sjfv			goto fail;
2539266423Sjfv		}
2540266423Sjfv		txr->base = (struct i40e_tx_desc *)txr->dma.va;
2541266423Sjfv		bzero((void *)txr->base, tsize);
2542266423Sjfv       		/* Now allocate transmit soft structs for the ring */
2543266423Sjfv       		if (i40e_allocate_tx_data(que)) {
2544266423Sjfv			device_printf(dev,
2545266423Sjfv			    "Critical Failure setting up TX structures\n");
2546266423Sjfv			error = ENOMEM;
2547266423Sjfv			goto fail;
2548266423Sjfv       		}
2549266423Sjfv		/* Allocate a buf ring */
2550266423Sjfv		txr->br = buf_ring_alloc(4096, M_DEVBUF,
2551266423Sjfv		    M_WAITOK, &txr->mtx);
2552266423Sjfv		if (txr->br == NULL) {
2553266423Sjfv			device_printf(dev,
2554266423Sjfv			    "Critical Failure setting up TX buf ring\n");
2555266423Sjfv			error = ENOMEM;
2556266423Sjfv			goto fail;
2557266423Sjfv       		}
2558266423Sjfv
2559266423Sjfv		/*
2560266423Sjfv		 * Next the RX queues...
2561266423Sjfv		 */
2562266423Sjfv		rsize = roundup2(que->num_desc *
2563266423Sjfv		    sizeof(union i40e_rx_desc), DBA_ALIGN);
2564266423Sjfv		rxr = &que->rxr;
2565266423Sjfv		rxr->que = que;
2566266423Sjfv
2567266423Sjfv		/* Initialize the RX side lock */
2568266423Sjfv		snprintf(rxr->mtx_name, sizeof(rxr->mtx_name), "%s:rx(%d)",
2569266423Sjfv		    device_get_nameunit(dev), que->me);
2570266423Sjfv		mtx_init(&rxr->mtx, rxr->mtx_name, NULL, MTX_DEF);
2571266423Sjfv
2572266423Sjfv		if (i40e_allocate_dma(&pf->hw,
2573266423Sjfv		    &rxr->dma, rsize, 4096)) {
2574266423Sjfv			device_printf(dev,
2575266423Sjfv			    "Unable to allocate RX Descriptor memory\n");
2576266423Sjfv			error = ENOMEM;
2577266423Sjfv			goto fail;
2578266423Sjfv		}
2579266423Sjfv		rxr->base = (union i40e_rx_desc *)rxr->dma.va;
2580266423Sjfv		bzero((void *)rxr->base, rsize);
2581266423Sjfv
2582266423Sjfv        	/* Allocate receive soft structs for the ring*/
2583266423Sjfv		if (i40e_allocate_rx_data(que)) {
2584266423Sjfv			device_printf(dev,
2585266423Sjfv			    "Critical Failure setting up receive structs\n");
2586266423Sjfv			error = ENOMEM;
2587266423Sjfv			goto fail;
2588266423Sjfv		}
2589266423Sjfv	}
2590266423Sjfv
2591266423Sjfv	return (0);
2592266423Sjfv
2593266423Sjfvfail:
2594266423Sjfv	for (int i = 0; i < vsi->num_queues; i++) {
2595266423Sjfv		que = &vsi->queues[i];
2596266423Sjfv		rxr = &que->rxr;
2597266423Sjfv		txr = &que->txr;
2598266423Sjfv		if (rxr->base)
2599266423Sjfv			i40e_free_dma(&pf->hw, &rxr->dma);
2600266423Sjfv		if (txr->base)
2601266423Sjfv			i40e_free_dma(&pf->hw, &txr->dma);
2602266423Sjfv	}
2603266423Sjfv
2604266423Sjfvearly:
2605266423Sjfv	return (error);
2606266423Sjfv}
2607266423Sjfv
2608266423Sjfv/*
2609266423Sjfv** Provide a update to the queue RX
2610266423Sjfv** interrupt moderation value.
2611266423Sjfv*/
2612266423Sjfvstatic void
2613266423Sjfvi40e_set_queue_rx_itr(struct i40e_queue *que)
2614266423Sjfv{
2615266423Sjfv	struct i40e_vsi	*vsi = que->vsi;
2616266423Sjfv	struct i40e_hw	*hw = vsi->hw;
2617266423Sjfv	struct rx_ring	*rxr = &que->rxr;
2618266423Sjfv	u16		rx_itr;
2619266423Sjfv	u16		rx_latency = 0;
2620266423Sjfv	int		rx_bytes;
2621266423Sjfv
2622266423Sjfv
2623266423Sjfv	/* Idle, do nothing */
2624266423Sjfv	if (rxr->bytes == 0)
2625266423Sjfv		return;
2626266423Sjfv
2627266423Sjfv	if (i40e_dynamic_rx_itr) {
2628266423Sjfv		rx_bytes = rxr->bytes/rxr->itr;
2629266423Sjfv		rx_itr = rxr->itr;
2630266423Sjfv
2631266423Sjfv		/* Adjust latency range */
2632266423Sjfv		switch (rxr->latency) {
2633266423Sjfv		case I40E_LOW_LATENCY:
2634266423Sjfv			if (rx_bytes > 10) {
2635266423Sjfv				rx_latency = I40E_AVE_LATENCY;
2636266423Sjfv				rx_itr = I40E_ITR_20K;
2637266423Sjfv			}
2638266423Sjfv			break;
2639266423Sjfv		case I40E_AVE_LATENCY:
2640266423Sjfv			if (rx_bytes > 20) {
2641266423Sjfv				rx_latency = I40E_BULK_LATENCY;
2642266423Sjfv				rx_itr = I40E_ITR_8K;
2643266423Sjfv			} else if (rx_bytes <= 10) {
2644266423Sjfv				rx_latency = I40E_LOW_LATENCY;
2645266423Sjfv				rx_itr = I40E_ITR_100K;
2646266423Sjfv			}
2647266423Sjfv			break;
2648266423Sjfv		case I40E_BULK_LATENCY:
2649266423Sjfv			if (rx_bytes <= 20) {
2650266423Sjfv				rx_latency = I40E_AVE_LATENCY;
2651266423Sjfv				rx_itr = I40E_ITR_20K;
2652266423Sjfv			}
2653266423Sjfv			break;
2654266423Sjfv       		 }
2655266423Sjfv
2656266423Sjfv		rxr->latency = rx_latency;
2657266423Sjfv
2658266423Sjfv		if (rx_itr != rxr->itr) {
2659266423Sjfv			/* do an exponential smoothing */
2660266423Sjfv			rx_itr = (10 * rx_itr * rxr->itr) /
2661266423Sjfv			    ((9 * rx_itr) + rxr->itr);
2662266423Sjfv			rxr->itr = rx_itr & I40E_MAX_ITR;
2663266423Sjfv			wr32(hw, I40E_PFINT_ITRN(I40E_RX_ITR,
2664266423Sjfv			    que->me), rxr->itr);
2665266423Sjfv		}
2666266423Sjfv	} else { /* We may have have toggled to non-dynamic */
2667266423Sjfv		if (vsi->rx_itr_setting & I40E_ITR_DYNAMIC)
2668266423Sjfv			vsi->rx_itr_setting = i40e_rx_itr;
2669266423Sjfv		/* Update the hardware if needed */
2670266423Sjfv		if (rxr->itr != vsi->rx_itr_setting) {
2671266423Sjfv			rxr->itr = vsi->rx_itr_setting;
2672266423Sjfv			wr32(hw, I40E_PFINT_ITRN(I40E_RX_ITR,
2673266423Sjfv			    que->me), rxr->itr);
2674266423Sjfv		}
2675266423Sjfv	}
2676266423Sjfv	rxr->bytes = 0;
2677266423Sjfv	rxr->packets = 0;
2678266423Sjfv	return;
2679266423Sjfv}
2680266423Sjfv
2681266423Sjfv
2682266423Sjfv/*
2683266423Sjfv** Provide a update to the queue TX
2684266423Sjfv** interrupt moderation value.
2685266423Sjfv*/
2686266423Sjfvstatic void
2687266423Sjfvi40e_set_queue_tx_itr(struct i40e_queue *que)
2688266423Sjfv{
2689266423Sjfv	struct i40e_vsi	*vsi = que->vsi;
2690266423Sjfv	struct i40e_hw	*hw = vsi->hw;
2691266423Sjfv	struct tx_ring	*txr = &que->txr;
2692266423Sjfv	u16		tx_itr;
2693266423Sjfv	u16		tx_latency = 0;
2694266423Sjfv	int		tx_bytes;
2695266423Sjfv
2696266423Sjfv
2697266423Sjfv	/* Idle, do nothing */
2698266423Sjfv	if (txr->bytes == 0)
2699266423Sjfv		return;
2700266423Sjfv
2701266423Sjfv	if (i40e_dynamic_rx_itr) {
2702266423Sjfv		tx_bytes = txr->bytes/txr->itr;
2703266423Sjfv		tx_itr = txr->itr;
2704266423Sjfv
2705266423Sjfv		switch (txr->latency) {
2706266423Sjfv		case I40E_LOW_LATENCY:
2707266423Sjfv			if (tx_bytes > 10) {
2708266423Sjfv				tx_latency = I40E_AVE_LATENCY;
2709266423Sjfv				tx_itr = I40E_ITR_20K;
2710266423Sjfv			}
2711266423Sjfv			break;
2712266423Sjfv		case I40E_AVE_LATENCY:
2713266423Sjfv			if (tx_bytes > 20) {
2714266423Sjfv				tx_latency = I40E_BULK_LATENCY;
2715266423Sjfv				tx_itr = I40E_ITR_8K;
2716266423Sjfv			} else if (tx_bytes <= 10) {
2717266423Sjfv				tx_latency = I40E_LOW_LATENCY;
2718266423Sjfv				tx_itr = I40E_ITR_100K;
2719266423Sjfv			}
2720266423Sjfv			break;
2721266423Sjfv		case I40E_BULK_LATENCY:
2722266423Sjfv			if (tx_bytes <= 20) {
2723266423Sjfv				tx_latency = I40E_AVE_LATENCY;
2724266423Sjfv				tx_itr = I40E_ITR_20K;
2725266423Sjfv			}
2726266423Sjfv			break;
2727266423Sjfv		}
2728266423Sjfv
2729266423Sjfv		txr->latency = tx_latency;
2730266423Sjfv
2731266423Sjfv		if (tx_itr != txr->itr) {
2732266423Sjfv       	         /* do an exponential smoothing */
2733266423Sjfv			tx_itr = (10 * tx_itr * txr->itr) /
2734266423Sjfv			    ((9 * tx_itr) + txr->itr);
2735266423Sjfv			txr->itr = tx_itr & I40E_MAX_ITR;
2736266423Sjfv			wr32(hw, I40E_PFINT_ITRN(I40E_TX_ITR,
2737266423Sjfv			    que->me), txr->itr);
2738266423Sjfv		}
2739266423Sjfv
2740266423Sjfv	} else { /* We may have have toggled to non-dynamic */
2741266423Sjfv		if (vsi->tx_itr_setting & I40E_ITR_DYNAMIC)
2742266423Sjfv			vsi->tx_itr_setting = i40e_tx_itr;
2743266423Sjfv		/* Update the hardware if needed */
2744266423Sjfv		if (txr->itr != vsi->tx_itr_setting) {
2745266423Sjfv			txr->itr = vsi->tx_itr_setting;
2746266423Sjfv			wr32(hw, I40E_PFINT_ITRN(I40E_TX_ITR,
2747266423Sjfv			    que->me), txr->itr);
2748266423Sjfv		}
2749266423Sjfv	}
2750266423Sjfv	txr->bytes = 0;
2751266423Sjfv	txr->packets = 0;
2752266423Sjfv	return;
2753266423Sjfv}
2754266423Sjfv
2755266423Sjfv
2756266423Sjfvstatic void
2757266423Sjfvi40e_add_hw_stats(struct i40e_pf *pf)
2758266423Sjfv{
2759266423Sjfv	device_t dev = pf->dev;
2760266423Sjfv
2761266423Sjfv	struct sysctl_ctx_list *ctx = device_get_sysctl_ctx(dev);
2762266423Sjfv	struct sysctl_oid *tree = device_get_sysctl_tree(dev);
2763266423Sjfv	struct sysctl_oid_list *child = SYSCTL_CHILDREN(tree);
2764266423Sjfv
2765266423Sjfv	struct sysctl_oid *vsi_node, *queue_node;
2766266423Sjfv	struct sysctl_oid_list *vsi_list, *queue_list;
2767266423Sjfv
2768266423Sjfv	struct i40e_vsi *vsi = &pf->vsi;
2769266423Sjfv	struct i40e_eth_stats *vsi_stats = &vsi->eth_stats;
2770266423Sjfv	struct i40e_hw_port_stats *pf_stats = &pf->stats;
2771266423Sjfv
2772266423Sjfv	/* Driver statistics */
2773266423Sjfv	SYSCTL_ADD_ULONG(ctx, child, OID_AUTO, "watchdog_events",
2774266423Sjfv			CTLFLAG_RD, &pf->watchdog_events,
2775266423Sjfv			"Watchdog timeouts");
2776266423Sjfv	SYSCTL_ADD_ULONG(ctx, child, OID_AUTO, "admin_irq",
2777266423Sjfv			CTLFLAG_RD, &pf->admin_irq,
2778266423Sjfv			"Admin Queue IRQ Handled");
2779266423Sjfv
2780266423Sjfv	/* VSI statistics */
2781266423Sjfv#define QUEUE_NAME_LEN 32
2782266423Sjfv	char vsi_namebuf[QUEUE_NAME_LEN];
2783266423Sjfv	char queue_namebuf[QUEUE_NAME_LEN];
2784266423Sjfv
2785266423Sjfv	snprintf(vsi_namebuf, QUEUE_NAME_LEN, "vsi%d", vsi->info.stat_counter_idx);
2786266423Sjfv	vsi_node = SYSCTL_ADD_NODE(ctx, child, OID_AUTO, vsi_namebuf,
2787266423Sjfv				   CTLFLAG_RD, NULL, "VSI Number");
2788266423Sjfv	vsi_list = SYSCTL_CHILDREN(vsi_node);
2789266423Sjfv
2790266423Sjfv	i40e_add_sysctls_eth_stats(ctx, vsi_list, vsi_stats);
2791266423Sjfv
2792266423Sjfv	/* Queue statistics */
2793266423Sjfv	struct i40e_queue *queues = vsi->queues;
2794266423Sjfv	struct tx_ring *txr;
2795266423Sjfv	struct rx_ring *rxr;
2796266423Sjfv	for (int q = 0; q < vsi->num_queues; q++) {
2797266423Sjfv		snprintf(queue_namebuf, QUEUE_NAME_LEN, "queue%d", q);
2798266423Sjfv		queue_node = SYSCTL_ADD_NODE(ctx, vsi_list, OID_AUTO, queue_namebuf,
2799266423Sjfv					     CTLFLAG_RD, NULL, "Queue Name");
2800266423Sjfv		queue_list = SYSCTL_CHILDREN(queue_node);
2801266423Sjfv
2802266423Sjfv		SYSCTL_ADD_ULONG(ctx, queue_list, OID_AUTO, "mbuf_defrag_failed",
2803266423Sjfv				CTLFLAG_RD, &(queues[q].mbuf_defrag_failed),
2804266423Sjfv				"m_defrag() failed");
2805266423Sjfv		SYSCTL_ADD_ULONG(ctx, queue_list, OID_AUTO, "dropped",
2806266423Sjfv				CTLFLAG_RD, &(queues[q].dropped_pkts),
2807266423Sjfv				"Driver dropped packets");
2808266423Sjfv
2809266423Sjfv		txr = &(queues[q].txr);
2810266423Sjfv		/* ERJ - Need:
2811266423Sjfv		 * i40e_sysctl_interrupt_rate_handler
2812266423Sjfv		 * i40e_sysctl_tdh_handler
2813266423Sjfv		 * i40e_sysctl_tdt_handler
2814266423Sjfv		 *
2815266423Sjfv		 * i40e_sysctl_rdh_handler
2816266423Sjfv		 * i40e_sysctl_rdt_handler
2817266423Sjfv		 * rx_copies
2818266423Sjfv		 * LRO stats
2819266423Sjfv		 */
2820266423Sjfv		SYSCTL_ADD_UQUAD(ctx, queue_list, OID_AUTO, "irqs",
2821266423Sjfv				CTLFLAG_RD, &(queues[q].irqs),
2822266423Sjfv				"irqs on this queue");
2823266423Sjfv		SYSCTL_ADD_ULONG(ctx, queue_list, OID_AUTO, "tso_tx",
2824266423Sjfv				CTLFLAG_RD, &(queues[q].tso),
2825266423Sjfv				"TSO");
2826266423Sjfv		SYSCTL_ADD_ULONG(ctx, queue_list, OID_AUTO, "tx_dma_setup",
2827266423Sjfv				CTLFLAG_RD, &(queues[q].tx_dma_setup),
2828266423Sjfv				"Driver tx dma failure in xmit");
2829266423Sjfv		SYSCTL_ADD_UQUAD(ctx, queue_list, OID_AUTO, "no_desc_avail",
2830266423Sjfv				CTLFLAG_RD, &(txr->no_desc),
2831266423Sjfv				"Queue No Descriptor Available");
2832266423Sjfv		SYSCTL_ADD_UQUAD(ctx, queue_list, OID_AUTO, "tx_packets",
2833266423Sjfv				CTLFLAG_RD, &(txr->total_packets),
2834266423Sjfv				"Queue Packets Transmitted");
2835266423Sjfv		SYSCTL_ADD_UQUAD(ctx, queue_list, OID_AUTO, "tx_bytes",
2836266423Sjfv				CTLFLAG_RD, &(txr->bytes),
2837266423Sjfv				"Queue Bytes Transmitted");
2838266423Sjfv
2839266423Sjfv		rxr = &(queues[q].rxr);
2840266423Sjfv		SYSCTL_ADD_UQUAD(ctx, queue_list, OID_AUTO, "rx_packets",
2841266423Sjfv				CTLFLAG_RD, &(rxr->rx_packets),
2842266423Sjfv				"Queue Packets Received");
2843266423Sjfv		SYSCTL_ADD_UQUAD(ctx, queue_list, OID_AUTO, "rx_bytes",
2844266423Sjfv				CTLFLAG_RD, &(rxr->rx_bytes),
2845266423Sjfv				"Queue Bytes Received");
2846266423Sjfv	}
2847266423Sjfv
2848266423Sjfv	/* MAC stats */
2849266423Sjfv	i40e_add_sysctls_mac_stats(ctx, child, pf_stats);
2850266423Sjfv}
2851266423Sjfv
2852266423Sjfvstatic void
2853266423Sjfvi40e_add_sysctls_eth_stats(struct sysctl_ctx_list *ctx,
2854266423Sjfv	struct sysctl_oid_list *child,
2855266423Sjfv	struct i40e_eth_stats *eth_stats)
2856266423Sjfv{
2857266423Sjfv	struct i40e_sysctl_info ctls[] =
2858266423Sjfv	{
2859266423Sjfv		{&eth_stats->rx_bytes, "good_octets_rcvd", "Good Octets Received"},
2860266423Sjfv		{&eth_stats->rx_unicast, "ucast_pkts_rcvd",
2861266423Sjfv			"Unicast Packets Received"},
2862266423Sjfv		{&eth_stats->rx_multicast, "mcast_pkts_rcvd",
2863266423Sjfv			"Multicast Packets Received"},
2864266423Sjfv		{&eth_stats->rx_broadcast, "bcast_pkts_rcvd",
2865266423Sjfv			"Broadcast Packets Received"},
2866266423Sjfv		// Add description
2867266423Sjfv		{&eth_stats->rx_discards, "rx_discards", "?"},
2868266423Sjfv		{&eth_stats->tx_bytes, "good_octets_txd", "Good Octets Transmitted"},
2869266423Sjfv		{&eth_stats->tx_unicast, "ucast_pkts_txd", "Unicast Packets Transmitted"},
2870266423Sjfv		{&eth_stats->tx_multicast, "mcast_pkts_txd",
2871266423Sjfv			"Multicast Packets Transmitted"},
2872266423Sjfv		{&eth_stats->tx_broadcast, "bcast_pkts_txd",
2873266423Sjfv			"Broadcast Packets Transmitted"},
2874266423Sjfv		// Add description
2875266423Sjfv		{&eth_stats->tx_discards, "tx_discards", "?"},
2876266423Sjfv		// end
2877266423Sjfv		{0,0,0}
2878266423Sjfv	};
2879266423Sjfv
2880266423Sjfv	struct i40e_sysctl_info *entry = ctls;
2881266423Sjfv	while (entry->stat != 0)
2882266423Sjfv	{
2883266423Sjfv		SYSCTL_ADD_UQUAD(ctx, child, OID_AUTO, entry->name,
2884266423Sjfv				CTLFLAG_RD, entry->stat,
2885266423Sjfv				entry->description);
2886266423Sjfv		entry++;
2887266423Sjfv	}
2888266423Sjfv}
2889266423Sjfv
2890266423Sjfvstatic void
2891266423Sjfvi40e_add_sysctls_mac_stats(struct sysctl_ctx_list *ctx,
2892266423Sjfv	struct sysctl_oid_list *child,
2893266423Sjfv	struct i40e_hw_port_stats *stats)
2894266423Sjfv{
2895266423Sjfv	struct sysctl_oid *stat_node = SYSCTL_ADD_NODE(ctx, child, OID_AUTO, "mac_stats",
2896266423Sjfv				    CTLFLAG_RD, NULL, "Mac Statistics");
2897266423Sjfv	struct sysctl_oid_list *stat_list = SYSCTL_CHILDREN(stat_node);
2898266423Sjfv
2899266423Sjfv	struct i40e_eth_stats *eth_stats = &stats->eth;
2900266423Sjfv	i40e_add_sysctls_eth_stats(ctx, stat_list, eth_stats);
2901266423Sjfv
2902266423Sjfv	struct i40e_sysctl_info ctls[] =
2903266423Sjfv	{
2904266423Sjfv		{&stats->crc_errors, "crc_errors", "CRC Errors"},
2905266423Sjfv		{&stats->illegal_bytes, "illegal_bytes", "Illegal Byte Errors"},
2906266423Sjfv		{&stats->mac_local_faults, "local_faults", "MAC Local Faults"},
2907266423Sjfv		{&stats->mac_remote_faults, "remote_faults", "MAC Remote Faults"},
2908266423Sjfv		{&stats->rx_length_errors, "rx_length_errors", "Receive Length Errors"},
2909266423Sjfv		/* Packet Reception Stats */
2910266423Sjfv		{&stats->rx_size_64, "rx_frames_64", "64 byte frames received"},
2911266423Sjfv		{&stats->rx_size_127, "rx_frames_65_127", "65-127 byte frames received"},
2912266423Sjfv		{&stats->rx_size_255, "rx_frames_128_255", "128-255 byte frames received"},
2913266423Sjfv		{&stats->rx_size_511, "rx_frames_256_511", "256-511 byte frames received"},
2914266423Sjfv		{&stats->rx_size_1023, "rx_frames_512_1023", "512-1023 byte frames received"},
2915266423Sjfv		{&stats->rx_size_1522, "rx_frames_1024_1522", "1024-1522 byte frames received"},
2916266423Sjfv		{&stats->rx_size_big, "rx_frames_big", "1523-9522 byte frames received"},
2917266423Sjfv		{&stats->rx_undersize, "rx_undersize", "Undersized packets received"},
2918266423Sjfv		{&stats->rx_fragments, "rx_fragmented", "Fragmented packets received"},
2919266423Sjfv		{&stats->rx_oversize, "rx_oversized", "Oversized packets received"},
2920266423Sjfv		{&stats->rx_jabber, "rx_jabber", "Received Jabber"},
2921266423Sjfv		{&stats->checksum_error, "checksum_errors", "Checksum Errors"},
2922266423Sjfv		/* Packet Transmission Stats */
2923266423Sjfv		{&stats->tx_size_64, "tx_frames_64", "64 byte frames transmitted"},
2924266423Sjfv		{&stats->tx_size_127, "tx_frames_65_127", "65-127 byte frames transmitted"},
2925266423Sjfv		{&stats->tx_size_255, "tx_frames_128_255", "128-255 byte frames transmitted"},
2926266423Sjfv		{&stats->tx_size_511, "tx_frames_256_511", "256-511 byte frames transmitted"},
2927266423Sjfv		{&stats->tx_size_1023, "tx_frames_512_1023", "512-1023 byte frames transmitted"},
2928266423Sjfv		{&stats->tx_size_1522, "tx_frames_1024_1522", "1024-1522 byte frames transmitted"},
2929266423Sjfv		{&stats->tx_size_big, "tx_frames_big", "1523-9522 byte frames transmitted"},
2930266423Sjfv		/* Flow control */
2931266423Sjfv		{&stats->link_xon_tx, "xon_txd", "Link XON transmitted"},
2932266423Sjfv		{&stats->link_xon_rx, "xon_recvd", "Link XON received"},
2933266423Sjfv		{&stats->link_xoff_tx, "xoff_txd", "Link XOFF transmitted"},
2934266423Sjfv		{&stats->link_xoff_rx, "xoff_recvd", "Link XOFF received"},
2935266423Sjfv		/* End */
2936266423Sjfv		{0,0,0}
2937266423Sjfv	};
2938266423Sjfv
2939266423Sjfv	struct i40e_sysctl_info *entry = ctls;
2940266423Sjfv	while (entry->stat != 0)
2941266423Sjfv	{
2942266423Sjfv		SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, entry->name,
2943266423Sjfv				CTLFLAG_RD, entry->stat,
2944266423Sjfv				entry->description);
2945266423Sjfv		entry++;
2946266423Sjfv	}
2947266423Sjfv}
2948266423Sjfv
2949266423Sjfv/*
2950266423Sjfv** i40e_config_rss - setup RSS
2951266423Sjfv**  - note this is done for the single vsi
2952266423Sjfv*/
2953266423Sjfvstatic void i40e_config_rss(struct i40e_vsi *vsi)
2954266423Sjfv{
2955266423Sjfv	struct i40e_pf	*pf = (struct i40e_pf *)vsi->back;
2956266423Sjfv	struct i40e_hw	*hw = vsi->hw;
2957266423Sjfv	u32		lut = 0;
2958266423Sjfv	u64		set_hena, hena;
2959266423Sjfv	int		i, j;
2960266423Sjfv
2961266423Sjfv	static const u32 seed[I40E_PFQF_HKEY_MAX_INDEX + 1] = {0x41b01687,
2962266423Sjfv	    0x183cfd8c, 0xce880440, 0x580cbc3c, 0x35897377,
2963266423Sjfv	    0x328b25e1, 0x4fa98922, 0xb7d90c14, 0xd5bad70d,
2964266423Sjfv	    0xcd15a2c1, 0xe8580225, 0x4a1e9d11, 0xfe5731be};
2965266423Sjfv
2966266423Sjfv	/* Fill out hash function seed */
2967266423Sjfv	for (i = 0; i <= I40E_PFQF_HKEY_MAX_INDEX; i++)
2968266423Sjfv                wr32(hw, I40E_PFQF_HKEY(i), seed[i]);
2969266423Sjfv
2970266423Sjfv	/* Enable PCTYPES for RSS: */
2971266423Sjfv	set_hena =
2972266423Sjfv		((u64)1 << I40E_FILTER_PCTYPE_NONF_IPV4_UDP) |
2973266423Sjfv		((u64)1 << I40E_FILTER_PCTYPE_NONF_IPV4_TCP) |
2974266423Sjfv		((u64)1 << I40E_FILTER_PCTYPE_NONF_IPV4_SCTP) |
2975266423Sjfv		((u64)1 << I40E_FILTER_PCTYPE_NONF_IPV4_OTHER) |
2976266423Sjfv		((u64)1 << I40E_FILTER_PCTYPE_FRAG_IPV4) |
2977266423Sjfv		((u64)1 << I40E_FILTER_PCTYPE_NONF_IPV6_UDP) |
2978266423Sjfv		((u64)1 << I40E_FILTER_PCTYPE_NONF_IPV6_TCP) |
2979266423Sjfv		((u64)1 << I40E_FILTER_PCTYPE_NONF_IPV6_SCTP) |
2980266423Sjfv		((u64)1 << I40E_FILTER_PCTYPE_NONF_IPV6_OTHER) |
2981266423Sjfv		((u64)1 << I40E_FILTER_PCTYPE_FRAG_IPV6) |
2982266423Sjfv		((u64)1 << I40E_FILTER_PCTYPE_L2_PAYLOAD);
2983266423Sjfv
2984266423Sjfv	hena = (u64)rd32(hw, I40E_PFQF_HENA(0)) |
2985266423Sjfv	    ((u64)rd32(hw, I40E_PFQF_HENA(1)) << 32);
2986266423Sjfv	hena |= set_hena;
2987266423Sjfv	wr32(hw, I40E_PFQF_HENA(0), (u32)hena);
2988266423Sjfv	wr32(hw, I40E_PFQF_HENA(1), (u32)(hena >> 32));
2989266423Sjfv
2990266423Sjfv	/* Populate the LUT with max no. of queues in round robin fashion */
2991266423Sjfv	for (i = j = 0; i < pf->hw.func_caps.rss_table_size; i++, j++) {
2992266423Sjfv		if (j == vsi->num_queues)
2993266423Sjfv			j = 0;
2994266423Sjfv		/* lut = 4-byte sliding window of 4 lut entries */
2995266423Sjfv		lut = (lut << 8) | (j &
2996266423Sjfv		    ((0x1 << pf->hw.func_caps.rss_table_entry_width) - 1));
2997266423Sjfv		/* On i = 3, we have 4 entries in lut; write to the register */
2998266423Sjfv		if ((i & 3) == 3)
2999266423Sjfv			wr32(hw, I40E_PFQF_HLUT(i >> 2), lut);
3000266423Sjfv	}
3001266423Sjfv	i40e_flush(hw);
3002266423Sjfv}
3003266423Sjfv
3004266423Sjfv
3005266423Sjfv/*
3006266423Sjfv** This routine is run via an vlan config EVENT,
3007266423Sjfv** it enables us to use the HW Filter table since
3008266423Sjfv** we can get the vlan id. This just creates the
3009266423Sjfv** entry in the soft version of the VFTA, init will
3010266423Sjfv** repopulate the real table.
3011266423Sjfv*/
3012266423Sjfvstatic void
3013266423Sjfvi40e_register_vlan(void *arg, struct ifnet *ifp, u16 vtag)
3014266423Sjfv{
3015266423Sjfv	struct i40e_vsi	*vsi = ifp->if_softc;
3016266423Sjfv	struct i40e_hw	*hw = vsi->hw;
3017266423Sjfv	struct i40e_pf	*pf = (struct i40e_pf *)vsi->back;
3018266423Sjfv
3019266423Sjfv	if (ifp->if_softc !=  arg)   /* Not our event */
3020266423Sjfv		return;
3021266423Sjfv
3022266423Sjfv	if ((vtag == 0) || (vtag > 4095))	/* Invalid */
3023266423Sjfv		return;
3024266423Sjfv
3025266423Sjfv	I40E_PF_LOCK(pf);
3026266423Sjfv	++vsi->num_vlans;
3027266423Sjfv	i40e_add_filter(vsi, hw->mac.addr, vtag);
3028266423Sjfv	I40E_PF_UNLOCK(pf);
3029266423Sjfv}
3030266423Sjfv
3031266423Sjfv/*
3032266423Sjfv** This routine is run via an vlan
3033266423Sjfv** unconfig EVENT, remove our entry
3034266423Sjfv** in the soft vfta.
3035266423Sjfv*/
3036266423Sjfvstatic void
3037266423Sjfvi40e_unregister_vlan(void *arg, struct ifnet *ifp, u16 vtag)
3038266423Sjfv{
3039266423Sjfv	struct i40e_vsi	*vsi = ifp->if_softc;
3040266423Sjfv	struct i40e_hw	*hw = vsi->hw;
3041266423Sjfv	struct i40e_pf	*pf = (struct i40e_pf *)vsi->back;
3042266423Sjfv
3043266423Sjfv	if (ifp->if_softc !=  arg)
3044266423Sjfv		return;
3045266423Sjfv
3046266423Sjfv	if ((vtag == 0) || (vtag > 4095))	/* Invalid */
3047266423Sjfv		return;
3048266423Sjfv
3049266423Sjfv	I40E_PF_LOCK(pf);
3050266423Sjfv	--vsi->num_vlans;
3051266423Sjfv	i40e_del_filter(vsi, hw->mac.addr, vtag);
3052266423Sjfv	I40E_PF_UNLOCK(pf);
3053266423Sjfv}
3054266423Sjfv
3055266423Sjfv/*
3056266423Sjfv** This routine updates vlan filters, called by init
3057266423Sjfv** it scans the filter table and then updates the hw
3058266423Sjfv** after a soft reset.
3059266423Sjfv*/
3060266423Sjfvstatic void
3061266423Sjfvi40e_setup_vlan_filters(struct i40e_vsi *vsi)
3062266423Sjfv{
3063266423Sjfv	struct i40e_mac_filter	*f;
3064266423Sjfv	int			cnt = 0, flags;
3065266423Sjfv
3066266423Sjfv	if (vsi->num_vlans == 0)
3067266423Sjfv		return;
3068266423Sjfv	/*
3069266423Sjfv	** Scan the filter list for vlan entries,
3070266423Sjfv	** mark them for addition and then call
3071266423Sjfv	** for the AQ update.
3072266423Sjfv	*/
3073266423Sjfv	SLIST_FOREACH(f, &vsi->ftl, next) {
3074266423Sjfv		if (f->flags & I40E_FILTER_VLAN) {
3075266423Sjfv			f->flags |=
3076266423Sjfv			    (I40E_FILTER_ADD |
3077266423Sjfv			    I40E_FILTER_USED);
3078266423Sjfv			cnt++;
3079266423Sjfv		}
3080266423Sjfv	}
3081266423Sjfv	if (cnt == 0) {
3082266423Sjfv		printf("setup vlan: no filters found!\n");
3083266423Sjfv		return;
3084266423Sjfv	}
3085266423Sjfv	flags = I40E_FILTER_VLAN;
3086266423Sjfv	flags |= (I40E_FILTER_ADD | I40E_FILTER_USED);
3087266423Sjfv	i40e_add_hw_filters(vsi, flags, cnt);
3088266423Sjfv	return;
3089266423Sjfv}
3090266423Sjfv
3091266423Sjfv/*
3092266423Sjfv** Initialize filter list and add filters that the hardware
3093266423Sjfv** needs to know about.
3094266423Sjfv*/
3095266423Sjfvstatic void
3096266423Sjfvi40e_init_filters(struct i40e_vsi *vsi)
3097266423Sjfv{
3098266423Sjfv	/* Protocol addresses */
3099266423Sjfv	/* - Flow control multicast */
3100266423Sjfv	u8 mc[6] = {0x01, 0x80, 0xC2, 0x00, 0x00, 0x01};
3101266423Sjfv	i40e_add_filter(vsi, mc, I40E_VLAN_ANY);
3102266423Sjfv	/* TODO: other protocols */
3103266423Sjfv}
3104266423Sjfv
3105266423Sjfv/*
3106266423Sjfv** This routine adds mulicast filters
3107266423Sjfv*/
3108266423Sjfvstatic void
3109266423Sjfvi40e_add_mc_filter(struct i40e_vsi *vsi, u8 *macaddr)
3110266423Sjfv{
3111266423Sjfv	struct i40e_mac_filter *f;
3112266423Sjfv
3113266423Sjfv	/* Does one already exist */
3114266423Sjfv	f = i40e_find_filter(vsi, macaddr, I40E_VLAN_ANY);
3115266423Sjfv	if (f != NULL)
3116266423Sjfv		return;
3117266423Sjfv
3118266423Sjfv	f = i40e_get_filter(vsi);
3119266423Sjfv	if (f == NULL) {
3120266423Sjfv		printf("WARNING: no filter available!!\n");
3121266423Sjfv		return;
3122266423Sjfv	}
3123266423Sjfv	bcopy(macaddr, f->macaddr, ETHER_ADDR_LEN);
3124266423Sjfv	f->vlan = I40E_VLAN_ANY;
3125266423Sjfv	f->flags |= (I40E_FILTER_ADD | I40E_FILTER_USED
3126266423Sjfv	    | I40E_FILTER_MC);
3127266423Sjfv
3128266423Sjfv	return;
3129266423Sjfv}
3130266423Sjfv
3131266423Sjfv/*
3132266423Sjfv** This routine adds macvlan filters
3133266423Sjfv*/
3134266423Sjfvstatic void
3135266423Sjfvi40e_add_filter(struct i40e_vsi *vsi, u8 *macaddr, s16 vlan)
3136266423Sjfv{
3137266423Sjfv	struct i40e_mac_filter	*f, *tmp;
3138266423Sjfv	device_t		dev = vsi->dev;
3139266423Sjfv
3140266423Sjfv	DEBUGOUT("i40e_add_filter: begin");
3141266423Sjfv
3142266423Sjfv	/* Does one already exist */
3143266423Sjfv	f = i40e_find_filter(vsi, macaddr, vlan);
3144266423Sjfv	if (f != NULL)
3145266423Sjfv		return;
3146266423Sjfv	/*
3147266423Sjfv	** Is this the first vlan being registered, if so we
3148266423Sjfv	** need to remove the ANY filter that indicates we are
3149266423Sjfv	** not in a vlan, and replace that with a 0 filter.
3150266423Sjfv	*/
3151266423Sjfv	if ((vlan != I40E_VLAN_ANY) && (vsi->num_vlans == 1)) {
3152266423Sjfv		tmp = i40e_find_filter(vsi, macaddr, I40E_VLAN_ANY);
3153266423Sjfv		if (tmp != NULL) {
3154266423Sjfv			i40e_del_filter(vsi, macaddr, I40E_VLAN_ANY);
3155266423Sjfv			i40e_add_filter(vsi, macaddr, 0);
3156266423Sjfv		}
3157266423Sjfv	}
3158266423Sjfv
3159266423Sjfv	f = i40e_get_filter(vsi);
3160266423Sjfv	if (f == NULL) {
3161266423Sjfv		device_printf(dev, "WARNING: no filter available!!\n");
3162266423Sjfv		return;
3163266423Sjfv	}
3164266423Sjfv	bcopy(macaddr, f->macaddr, ETHER_ADDR_LEN);
3165266423Sjfv	f->vlan = vlan;
3166266423Sjfv	f->flags |= (I40E_FILTER_ADD | I40E_FILTER_USED);
3167266423Sjfv	if (f->vlan != I40E_VLAN_ANY)
3168266423Sjfv		f->flags |= I40E_FILTER_VLAN;
3169266423Sjfv
3170266423Sjfv	i40e_add_hw_filters(vsi, f->flags, 1);
3171266423Sjfv	return;
3172266423Sjfv}
3173266423Sjfv
3174266423Sjfvstatic void
3175266423Sjfvi40e_del_filter(struct i40e_vsi *vsi, u8 *macaddr, s16 vlan)
3176266423Sjfv{
3177266423Sjfv	struct i40e_mac_filter *f;
3178266423Sjfv
3179266423Sjfv	f = i40e_find_filter(vsi, macaddr, vlan);
3180266423Sjfv	if (f == NULL)
3181266423Sjfv		return;
3182266423Sjfv
3183266423Sjfv	f->flags |= I40E_FILTER_DEL;
3184266423Sjfv	i40e_del_hw_filters(vsi, 1);
3185266423Sjfv
3186266423Sjfv	/* Check if this is the last vlan removal */
3187266423Sjfv	if (vlan != I40E_VLAN_ANY && vsi->num_vlans == 0) {
3188266423Sjfv		/* Switch back to a non-vlan filter */
3189266423Sjfv		i40e_del_filter(vsi, macaddr, 0);
3190266423Sjfv		i40e_add_filter(vsi, macaddr, I40E_VLAN_ANY);
3191266423Sjfv	}
3192266423Sjfv	return;
3193266423Sjfv}
3194266423Sjfv
3195266423Sjfv/*
3196266423Sjfv** Find the filter with both matching mac addr and vlan id
3197266423Sjfv*/
3198266423Sjfvstatic struct i40e_mac_filter *
3199266423Sjfvi40e_find_filter(struct i40e_vsi *vsi, u8 *macaddr, s16 vlan)
3200266423Sjfv{
3201266423Sjfv	struct i40e_mac_filter	*f;
3202266423Sjfv	bool			match = FALSE;
3203266423Sjfv
3204266423Sjfv	SLIST_FOREACH(f, &vsi->ftl, next) {
3205266423Sjfv		if (!cmp_etheraddr(f->macaddr, macaddr))
3206266423Sjfv			continue;
3207266423Sjfv		if (f->vlan == vlan) {
3208266423Sjfv			match = TRUE;
3209266423Sjfv			break;
3210266423Sjfv		}
3211266423Sjfv	}
3212266423Sjfv
3213266423Sjfv	if (!match)
3214266423Sjfv		f = NULL;
3215266423Sjfv	return (f);
3216266423Sjfv}
3217266423Sjfv
3218266423Sjfv/*
3219266423Sjfv** This routine takes additions to the vsi filter
3220266423Sjfv** table and creates an Admin Queue call to create
3221266423Sjfv** the filters in the hardware.
3222266423Sjfv*/
3223266423Sjfvstatic void
3224266423Sjfvi40e_add_hw_filters(struct i40e_vsi *vsi, int flags, int cnt)
3225266423Sjfv{
3226266423Sjfv	struct i40e_aqc_add_macvlan_element_data *a, *b;
3227266423Sjfv	struct i40e_mac_filter	*f;
3228266423Sjfv	struct i40e_hw	*hw = vsi->hw;
3229266423Sjfv	device_t	dev = vsi->dev;
3230266423Sjfv	int		err, j = 0;
3231266423Sjfv
3232266423Sjfv	a = malloc(sizeof(struct i40e_aqc_add_macvlan_element_data) * cnt,
3233266423Sjfv	    M_DEVBUF, M_NOWAIT | M_ZERO);
3234266423Sjfv	if (a == NULL) {
3235266423Sjfv		device_printf(dev, "add hw filter failed to get memory\n");
3236266423Sjfv		return;
3237266423Sjfv	}
3238266423Sjfv
3239266423Sjfv	/*
3240266423Sjfv	** Scan the filter list, each time we find one
3241266423Sjfv	** we add it to the admin queue array and turn off
3242266423Sjfv	** the add bit.
3243266423Sjfv	*/
3244266423Sjfv	SLIST_FOREACH(f, &vsi->ftl, next) {
3245266423Sjfv		if (f->flags == flags) {
3246266423Sjfv			b = &a[j]; // a pox on fvl long names :)
3247266423Sjfv			bcopy(f->macaddr, b->mac_addr, ETHER_ADDR_LEN);
3248266423Sjfv			b->vlan_tag =
3249266423Sjfv			    (f->vlan == I40E_VLAN_ANY ? 0 : f->vlan);
3250266423Sjfv			b->flags = I40E_AQC_MACVLAN_ADD_PERFECT_MATCH;
3251266423Sjfv			f->flags &= ~I40E_FILTER_ADD;
3252266423Sjfv			j++;
3253266423Sjfv		}
3254266423Sjfv		if (j == cnt)
3255266423Sjfv			break;
3256266423Sjfv	}
3257266423Sjfv	if (j > 0) {
3258266423Sjfv		err = i40e_aq_add_macvlan(hw, vsi->seid, a, j, NULL);
3259266423Sjfv		if (err)
3260266423Sjfv			device_printf(dev, "aq_add_macvlan failure %d\n",
3261266423Sjfv			    hw->aq.asq_last_status);
3262266423Sjfv		else
3263266423Sjfv			vsi->hw_filters_add += j;
3264266423Sjfv	}
3265266423Sjfv	free(a, M_DEVBUF);
3266266423Sjfv	return;
3267266423Sjfv}
3268266423Sjfv
3269266423Sjfv/*
3270266423Sjfv** This routine takes removals in the vsi filter
3271266423Sjfv** table and creates an Admin Queue call to delete
3272266423Sjfv** the filters in the hardware.
3273266423Sjfv*/
3274266423Sjfvstatic void
3275266423Sjfvi40e_del_hw_filters(struct i40e_vsi *vsi, int cnt)
3276266423Sjfv{
3277266423Sjfv	struct i40e_aqc_remove_macvlan_element_data *d, *e;
3278266423Sjfv	struct i40e_hw		*hw = vsi->hw;
3279266423Sjfv	device_t		dev = vsi->dev;
3280266423Sjfv	struct i40e_mac_filter	*f, *f_temp;
3281266423Sjfv	int			err, j = 0;
3282266423Sjfv
3283266423Sjfv	DEBUGOUT("i40e_del_hw_filters: begin\n");
3284266423Sjfv
3285266423Sjfv	d = malloc(sizeof(struct i40e_aqc_remove_macvlan_element_data) * cnt,
3286266423Sjfv	    M_DEVBUF, M_NOWAIT | M_ZERO);
3287266423Sjfv	if (d == NULL) {
3288266423Sjfv		printf("del hw filter failed to get memory\n");
3289266423Sjfv		return;
3290266423Sjfv	}
3291266423Sjfv
3292266423Sjfv	SLIST_FOREACH_SAFE(f, &vsi->ftl, next, f_temp) {
3293266423Sjfv		if (f->flags & I40E_FILTER_DEL) {
3294266423Sjfv			e = &d[j]; // a pox on fvl long names :)
3295266423Sjfv			bcopy(f->macaddr, e->mac_addr, ETHER_ADDR_LEN);
3296266423Sjfv			e->vlan_tag = (f->vlan == I40E_VLAN_ANY ? 0 : f->vlan);
3297266423Sjfv			e->flags = I40E_AQC_MACVLAN_DEL_PERFECT_MATCH;
3298266423Sjfv			/* delete entry from vsi list */
3299266423Sjfv			SLIST_REMOVE(&vsi->ftl, f, i40e_mac_filter, next);
3300266423Sjfv			free(f, M_DEVBUF);
3301266423Sjfv			j++;
3302266423Sjfv		}
3303266423Sjfv		if (j == cnt)
3304266423Sjfv			break;
3305266423Sjfv	}
3306266423Sjfv	if (j > 0) {
3307266423Sjfv		err = i40e_aq_remove_macvlan(hw, vsi->seid, d, j, NULL);
3308266423Sjfv		/* NOTE: returns ENOENT every time but seems to work fine,
3309266423Sjfv		   so we'll ignore that specific error. */
3310266423Sjfv		if (err && hw->aq.asq_last_status != I40E_AQ_RC_ENOENT) {
3311266423Sjfv			int sc = 0;
3312266423Sjfv			for (int i = 0; i < j; i++)
3313266423Sjfv				sc += (!d[i].error_code);
3314266423Sjfv			vsi->hw_filters_del += sc;
3315266423Sjfv			device_printf(dev,
3316266423Sjfv			    "Failed to remove %d/%d filters, aq error %d\n",
3317266423Sjfv			    j - sc, j, hw->aq.asq_last_status);
3318266423Sjfv		} else
3319266423Sjfv			vsi->hw_filters_del += j;
3320266423Sjfv	}
3321266423Sjfv	free(d, M_DEVBUF);
3322266423Sjfv
3323266423Sjfv	DEBUGOUT("i40e_del_hw_filters: end\n");
3324266423Sjfv	return;
3325266423Sjfv}
3326266423Sjfv
3327266423Sjfv
3328266423Sjfvstatic void
3329266423Sjfvi40e_enable_rings(struct i40e_vsi *vsi)
3330266423Sjfv{
3331266423Sjfv	struct i40e_hw	*hw = vsi->hw;
3332266423Sjfv	u32		reg;
3333266423Sjfv
3334266423Sjfv	for (int i = 0; i < vsi->num_queues; i++) {
3335266423Sjfv		// ERJ: pre_tx_queue_cfg is B0-only?
3336266423Sjfv		i40e_pre_tx_queue_cfg(hw, i, TRUE);
3337266423Sjfv
3338266423Sjfv		reg = rd32(hw, I40E_QTX_ENA(i));
3339266423Sjfv		reg |= I40E_QTX_ENA_QENA_REQ_MASK |
3340266423Sjfv		    I40E_QTX_ENA_QENA_STAT_MASK;
3341266423Sjfv		wr32(hw, I40E_QTX_ENA(i), reg);
3342266423Sjfv		/* Verify the enable took */
3343266423Sjfv		for (int j = 0; j < 10; j++) {
3344266423Sjfv			reg = rd32(hw, I40E_QTX_ENA(i));
3345266423Sjfv			if (reg & I40E_QTX_ENA_QENA_STAT_MASK)
3346266423Sjfv				break;
3347266423Sjfv			i40e_msec_delay(10);
3348266423Sjfv		}
3349266423Sjfv		if ((reg & I40E_QTX_ENA_QENA_STAT_MASK) == 0)
3350266423Sjfv			printf("TX queue %d disabled!\n", i);
3351266423Sjfv
3352266423Sjfv		reg = rd32(hw, I40E_QRX_ENA(i));
3353266423Sjfv		reg |= I40E_QRX_ENA_QENA_REQ_MASK |
3354266423Sjfv		    I40E_QRX_ENA_QENA_STAT_MASK;
3355266423Sjfv		wr32(hw, I40E_QRX_ENA(i), reg);
3356266423Sjfv		/* Verify the enable took */
3357266423Sjfv		for (int j = 0; j < 10; j++) {
3358266423Sjfv			reg = rd32(hw, I40E_QRX_ENA(i));
3359266423Sjfv			if (reg & I40E_QRX_ENA_QENA_STAT_MASK)
3360266423Sjfv				break;
3361266423Sjfv			i40e_msec_delay(10);
3362266423Sjfv		}
3363266423Sjfv		if ((reg & I40E_QRX_ENA_QENA_STAT_MASK) == 0)
3364266423Sjfv			printf("RX queue %d disabled!\n", i);
3365266423Sjfv	}
3366266423Sjfv}
3367266423Sjfv
3368266423Sjfvstatic void
3369266423Sjfvi40e_disable_rings(struct i40e_vsi *vsi)
3370266423Sjfv{
3371266423Sjfv	struct i40e_hw	*hw = vsi->hw;
3372266423Sjfv	u32		reg;
3373266423Sjfv
3374266423Sjfv	for (int i = 0; i < vsi->num_queues; i++) {
3375266423Sjfv		// ERJ
3376266423Sjfv		// this step can be executed concurrently for each queue
3377266423Sjfv		i40e_pre_tx_queue_cfg(hw, i, FALSE);
3378266423Sjfv		// min 100usec for 2x10, 400usec for 1x10
3379266423Sjfv		i40e_usec_delay(500);
3380266423Sjfv
3381266423Sjfv		reg = rd32(hw, I40E_QTX_ENA(i));
3382266423Sjfv		reg &= ~I40E_QTX_ENA_QENA_REQ_MASK;
3383266423Sjfv		wr32(hw, I40E_QTX_ENA(i), reg);
3384266423Sjfv		/* Verify the disable took */
3385266423Sjfv		for (int j = 0; j < 10; j++) {
3386266423Sjfv			reg = rd32(hw, I40E_QTX_ENA(i));
3387266423Sjfv			if (!(reg & I40E_QTX_ENA_QENA_STAT_MASK))
3388266423Sjfv				break;
3389266423Sjfv			i40e_msec_delay(10);
3390266423Sjfv		}
3391266423Sjfv		if (reg & I40E_QTX_ENA_QENA_STAT_MASK)
3392266423Sjfv			printf("TX queue %d still enabled!\n", i);
3393266423Sjfv
3394266423Sjfv		reg = rd32(hw, I40E_QRX_ENA(i));
3395266423Sjfv		reg &= ~I40E_QRX_ENA_QENA_REQ_MASK;
3396266423Sjfv		wr32(hw, I40E_QRX_ENA(i), reg);
3397266423Sjfv		/* Verify the disable took */
3398266423Sjfv		for (int j = 0; j < 10; j++) {
3399266423Sjfv			reg = rd32(hw, I40E_QRX_ENA(i));
3400266423Sjfv			if (!(reg & I40E_QRX_ENA_QENA_STAT_MASK))
3401266423Sjfv				break;
3402266423Sjfv			i40e_msec_delay(10);
3403266423Sjfv		}
3404266423Sjfv		if (reg & I40E_QRX_ENA_QENA_STAT_MASK)
3405266423Sjfv			printf("RX queue %d still enabled!\n", i);
3406266423Sjfv	}
3407266423Sjfv}
3408266423Sjfv
3409266423Sjfvstatic void
3410266423Sjfvi40e_enable_intr(struct i40e_vsi *vsi)
3411266423Sjfv{
3412266423Sjfv	struct i40e_hw		*hw = vsi->hw;
3413266423Sjfv	struct i40e_queue	*que = vsi->queues;
3414266423Sjfv
3415266423Sjfv	if (i40e_enable_msix) {
3416266423Sjfv		i40e_enable_adminq(hw);
3417266423Sjfv		for (int i = 0; i < vsi->num_queues; i++, que++)
3418266423Sjfv			i40e_enable_queue(hw, que->me);
3419266423Sjfv	} else
3420266423Sjfv		i40e_enable_legacy(hw);
3421266423Sjfv}
3422266423Sjfv
3423266423Sjfvstatic void
3424266423Sjfvi40e_disable_intr(struct i40e_vsi *vsi)
3425266423Sjfv{
3426266423Sjfv	struct i40e_hw		*hw = vsi->hw;
3427266423Sjfv	struct i40e_queue	*que = vsi->queues;
3428266423Sjfv
3429266423Sjfv	if (i40e_enable_msix) {
3430266423Sjfv		i40e_disable_adminq(hw);
3431266423Sjfv		for (int i = 0; i < vsi->num_queues; i++, que++)
3432266423Sjfv			i40e_disable_queue(hw, que->me);
3433266423Sjfv	} else
3434266423Sjfv		i40e_disable_legacy(hw);
3435266423Sjfv}
3436266423Sjfv
3437266423Sjfvstatic void
3438266423Sjfvi40e_enable_adminq(struct i40e_hw *hw)
3439266423Sjfv{
3440266423Sjfv	u32		reg;
3441266423Sjfv
3442266423Sjfv	reg = I40E_PFINT_DYN_CTL0_INTENA_MASK |
3443266423Sjfv	    I40E_PFINT_DYN_CTL0_CLEARPBA_MASK |
3444266423Sjfv	    (I40E_ITR_NONE << I40E_PFINT_DYN_CTL0_ITR_INDX_SHIFT);
3445266423Sjfv	wr32(hw, I40E_PFINT_DYN_CTL0, reg);
3446266423Sjfv	i40e_flush(hw);
3447266423Sjfv	return;
3448266423Sjfv}
3449266423Sjfv
3450266423Sjfvstatic void
3451266423Sjfvi40e_disable_adminq(struct i40e_hw *hw)
3452266423Sjfv{
3453266423Sjfv	u32		reg;
3454266423Sjfv
3455266423Sjfv	reg = I40E_ITR_NONE << I40E_PFINT_DYN_CTL0_ITR_INDX_SHIFT;
3456266423Sjfv	wr32(hw, I40E_PFINT_DYN_CTL0, reg);
3457266423Sjfv
3458266423Sjfv	return;
3459266423Sjfv}
3460266423Sjfv
3461266423Sjfvstatic void
3462266423Sjfvi40e_enable_queue(struct i40e_hw *hw, int id)
3463266423Sjfv{
3464266423Sjfv	u32		reg;
3465266423Sjfv
3466266423Sjfv	reg = I40E_PFINT_DYN_CTLN_INTENA_MASK |
3467266423Sjfv	    I40E_PFINT_DYN_CTLN_CLEARPBA_MASK |
3468266423Sjfv	    (I40E_ITR_NONE << I40E_PFINT_DYN_CTLN_ITR_INDX_SHIFT);
3469266423Sjfv	wr32(hw, I40E_PFINT_DYN_CTLN(id), reg);
3470266423Sjfv}
3471266423Sjfv
3472266423Sjfvstatic void
3473266423Sjfvi40e_disable_queue(struct i40e_hw *hw, int id)
3474266423Sjfv{
3475266423Sjfv	u32		reg;
3476266423Sjfv
3477266423Sjfv	reg = I40E_ITR_NONE << I40E_PFINT_DYN_CTLN_ITR_INDX_SHIFT;
3478266423Sjfv	wr32(hw, I40E_PFINT_DYN_CTLN(id), reg);
3479266423Sjfv
3480266423Sjfv	return;
3481266423Sjfv}
3482266423Sjfv
3483266423Sjfvstatic void
3484266423Sjfvi40e_enable_legacy(struct i40e_hw *hw)
3485266423Sjfv{
3486266423Sjfv	u32		reg;
3487266423Sjfv	reg = I40E_PFINT_DYN_CTL0_INTENA_MASK |
3488266423Sjfv	    I40E_PFINT_DYN_CTL0_CLEARPBA_MASK |
3489266423Sjfv	    (I40E_ITR_NONE << I40E_PFINT_DYN_CTL0_ITR_INDX_SHIFT);
3490266423Sjfv	wr32(hw, I40E_PFINT_DYN_CTL0, reg);
3491266423Sjfv}
3492266423Sjfv
3493266423Sjfvstatic void
3494266423Sjfvi40e_disable_legacy(struct i40e_hw *hw)
3495266423Sjfv{
3496266423Sjfv	u32		reg;
3497266423Sjfv
3498266423Sjfv	reg = I40E_ITR_NONE << I40E_PFINT_DYN_CTL0_ITR_INDX_SHIFT;
3499266423Sjfv	wr32(hw, I40E_PFINT_DYN_CTL0, reg);
3500266423Sjfv
3501266423Sjfv	return;
3502266423Sjfv}
3503266423Sjfv
3504266423Sjfvstatic void
3505266423Sjfvi40e_update_stats_counters(struct i40e_pf *pf)
3506266423Sjfv{
3507266423Sjfv	struct i40e_hw	*hw = &pf->hw;
3508266423Sjfv	struct i40e_hw_port_stats *nsd = &pf->stats;
3509266423Sjfv	struct i40e_hw_port_stats *osd = &pf->stats_offsets;
3510266423Sjfv
3511266423Sjfv	/* Update hw stats */
3512266423Sjfv	i40e_stat_update32(hw, I40E_GLPRT_CRCERRS(hw->port),
3513266423Sjfv			   pf->stat_offsets_loaded,
3514266423Sjfv			   &osd->crc_errors, &nsd->crc_errors);
3515266423Sjfv	i40e_stat_update32(hw, I40E_GLPRT_ILLERRC(hw->port),
3516266423Sjfv			   pf->stat_offsets_loaded,
3517266423Sjfv			   &osd->illegal_bytes, &nsd->illegal_bytes);
3518266423Sjfv	i40e_stat_update48(hw, I40E_GLPRT_GORCH(hw->port),
3519266423Sjfv			   I40E_GLPRT_GORCL(hw->port),
3520266423Sjfv			   pf->stat_offsets_loaded,
3521266423Sjfv			   &osd->eth.rx_bytes, &nsd->eth.rx_bytes);
3522266423Sjfv	i40e_stat_update48(hw, I40E_GLPRT_GOTCH(hw->port),
3523266423Sjfv			   I40E_GLPRT_GOTCL(hw->port),
3524266423Sjfv			   pf->stat_offsets_loaded,
3525266423Sjfv			   &osd->eth.tx_bytes, &nsd->eth.tx_bytes);
3526266423Sjfv	i40e_stat_update32(hw, I40E_GLPRT_RDPC(hw->port),
3527266423Sjfv			   pf->stat_offsets_loaded,
3528266423Sjfv			   &osd->eth.rx_discards,
3529266423Sjfv			   &nsd->eth.rx_discards);
3530266423Sjfv	i40e_stat_update32(hw, I40E_GLPRT_TDPC(hw->port),
3531266423Sjfv			   pf->stat_offsets_loaded,
3532266423Sjfv			   &osd->eth.tx_discards,
3533266423Sjfv			   &nsd->eth.tx_discards);
3534266423Sjfv	i40e_stat_update48(hw, I40E_GLPRT_UPRCH(hw->port),
3535266423Sjfv			   I40E_GLPRT_UPRCL(hw->port),
3536266423Sjfv			   pf->stat_offsets_loaded,
3537266423Sjfv			   &osd->eth.rx_unicast,
3538266423Sjfv			   &nsd->eth.rx_unicast);
3539266423Sjfv	i40e_stat_update48(hw, I40E_GLPRT_UPTCH(hw->port),
3540266423Sjfv			   I40E_GLPRT_UPTCL(hw->port),
3541266423Sjfv			   pf->stat_offsets_loaded,
3542266423Sjfv			   &osd->eth.tx_unicast,
3543266423Sjfv			   &nsd->eth.tx_unicast);
3544266423Sjfv	i40e_stat_update48(hw, I40E_GLPRT_MPRCH(hw->port),
3545266423Sjfv			   I40E_GLPRT_MPRCL(hw->port),
3546266423Sjfv			   pf->stat_offsets_loaded,
3547266423Sjfv			   &osd->eth.rx_multicast,
3548266423Sjfv			   &nsd->eth.rx_multicast);
3549266423Sjfv	i40e_stat_update48(hw, I40E_GLPRT_MPTCH(hw->port),
3550266423Sjfv			   I40E_GLPRT_MPTCL(hw->port),
3551266423Sjfv			   pf->stat_offsets_loaded,
3552266423Sjfv			   &osd->eth.tx_multicast,
3553266423Sjfv			   &nsd->eth.tx_multicast);
3554266423Sjfv	i40e_stat_update48(hw, I40E_GLPRT_BPRCH(hw->port),
3555266423Sjfv			   I40E_GLPRT_BPRCL(hw->port),
3556266423Sjfv			   pf->stat_offsets_loaded,
3557266423Sjfv			   &osd->eth.rx_broadcast,
3558266423Sjfv			   &nsd->eth.rx_broadcast);
3559266423Sjfv	i40e_stat_update48(hw, I40E_GLPRT_BPTCH(hw->port),
3560266423Sjfv			   I40E_GLPRT_BPTCL(hw->port),
3561266423Sjfv			   pf->stat_offsets_loaded,
3562266423Sjfv			   &osd->eth.tx_broadcast,
3563266423Sjfv			   &nsd->eth.tx_broadcast);
3564266423Sjfv
3565266423Sjfv	i40e_stat_update32(hw, I40E_GLPRT_TDOLD(hw->port),
3566266423Sjfv			   pf->stat_offsets_loaded,
3567266423Sjfv			   &osd->tx_dropped_link_down,
3568266423Sjfv			   &nsd->tx_dropped_link_down);
3569266423Sjfv	i40e_stat_update32(hw, I40E_GLPRT_MLFC(hw->port),
3570266423Sjfv			   pf->stat_offsets_loaded,
3571266423Sjfv			   &osd->mac_local_faults,
3572266423Sjfv			   &nsd->mac_local_faults);
3573266423Sjfv	i40e_stat_update32(hw, I40E_GLPRT_MRFC(hw->port),
3574266423Sjfv			   pf->stat_offsets_loaded,
3575266423Sjfv			   &osd->mac_remote_faults,
3576266423Sjfv			   &nsd->mac_remote_faults);
3577266423Sjfv	i40e_stat_update32(hw, I40E_GLPRT_RLEC(hw->port),
3578266423Sjfv			   pf->stat_offsets_loaded,
3579266423Sjfv			   &osd->rx_length_errors,
3580266423Sjfv			   &nsd->rx_length_errors);
3581266423Sjfv
3582266423Sjfv	/* Update flow control stats */
3583266423Sjfv	i40e_stat_update32(hw, I40E_GLPRT_LXONRXC(hw->port),
3584266423Sjfv			   pf->stat_offsets_loaded,
3585266423Sjfv			   &osd->link_xon_rx, &nsd->link_xon_rx);
3586266423Sjfv	i40e_stat_update32(hw, I40E_GLPRT_LXONTXC(hw->port),
3587266423Sjfv			   pf->stat_offsets_loaded,
3588266423Sjfv			   &osd->link_xon_tx, &nsd->link_xon_tx);
3589266423Sjfv	i40e_stat_update32(hw, I40E_GLPRT_LXOFFRXC(hw->port),
3590266423Sjfv			   pf->stat_offsets_loaded,
3591266423Sjfv			   &osd->link_xoff_rx, &nsd->link_xoff_rx);
3592266423Sjfv	i40e_stat_update32(hw, I40E_GLPRT_LXOFFTXC(hw->port),
3593266423Sjfv			   pf->stat_offsets_loaded,
3594266423Sjfv			   &osd->link_xoff_tx, &nsd->link_xoff_tx);
3595266423Sjfv
3596266423Sjfv	/*
3597266423Sjfv	 * Uncomment these out when priority flow control
3598266423Sjfv	 * is implemented.
3599266423Sjfv	 */
3600266423Sjfv#if 0
3601266423Sjfv	for (int i = 0; i < 8; i++) {
3602266423Sjfv		i40e_stat_update32(hw, I40E_GLPRT_PXONRXC(hw->port, i),
3603266423Sjfv				   pf->stat_offsets_loaded,
3604266423Sjfv				   &osd->priority_xon_rx[i],
3605266423Sjfv				   &nsd->priority_xon_rx[i]);
3606266423Sjfv		i40e_stat_update32(hw, I40E_GLPRT_PXONTXC(hw->port, i),
3607266423Sjfv				   pf->stat_offsets_loaded,
3608266423Sjfv				   &osd->priority_xon_tx[i],
3609266423Sjfv				   &nsd->priority_xon_tx[i]);
3610266423Sjfv		i40e_stat_update32(hw, I40E_GLPRT_PXOFFTXC(hw->port, i),
3611266423Sjfv				   pf->stat_offsets_loaded,
3612266423Sjfv				   &osd->priority_xoff_tx[i],
3613266423Sjfv				   &nsd->priority_xoff_tx[i]);
3614266423Sjfv		i40e_stat_update32(hw,
3615266423Sjfv				   I40E_GLPRT_RXON2OFFCNT(hw->port, i),
3616266423Sjfv				   pf->stat_offsets_loaded,
3617266423Sjfv				   &osd->priority_xon_2_xoff[i],
3618266423Sjfv				   &nsd->priority_xon_2_xoff[i]);
3619266423Sjfv	}
3620266423Sjfv#endif
3621266423Sjfv
3622266423Sjfv	i40e_stat_update48(hw, I40E_GLPRT_PRC64H(hw->port),
3623266423Sjfv			   I40E_GLPRT_PRC64L(hw->port),
3624266423Sjfv			   pf->stat_offsets_loaded,
3625266423Sjfv			   &osd->rx_size_64, &nsd->rx_size_64);
3626266423Sjfv	i40e_stat_update48(hw, I40E_GLPRT_PRC127H(hw->port),
3627266423Sjfv			   I40E_GLPRT_PRC127L(hw->port),
3628266423Sjfv			   pf->stat_offsets_loaded,
3629266423Sjfv			   &osd->rx_size_127, &nsd->rx_size_127);
3630266423Sjfv	i40e_stat_update48(hw, I40E_GLPRT_PRC255H(hw->port),
3631266423Sjfv			   I40E_GLPRT_PRC255L(hw->port),
3632266423Sjfv			   pf->stat_offsets_loaded,
3633266423Sjfv			   &osd->rx_size_255, &nsd->rx_size_255);
3634266423Sjfv	i40e_stat_update48(hw, I40E_GLPRT_PRC511H(hw->port),
3635266423Sjfv			   I40E_GLPRT_PRC511L(hw->port),
3636266423Sjfv			   pf->stat_offsets_loaded,
3637266423Sjfv			   &osd->rx_size_511, &nsd->rx_size_511);
3638266423Sjfv	i40e_stat_update48(hw, I40E_GLPRT_PRC1023H(hw->port),
3639266423Sjfv			   I40E_GLPRT_PRC1023L(hw->port),
3640266423Sjfv			   pf->stat_offsets_loaded,
3641266423Sjfv			   &osd->rx_size_1023, &nsd->rx_size_1023);
3642266423Sjfv	i40e_stat_update48(hw, I40E_GLPRT_PRC1522H(hw->port),
3643266423Sjfv			   I40E_GLPRT_PRC1522L(hw->port),
3644266423Sjfv			   pf->stat_offsets_loaded,
3645266423Sjfv			   &osd->rx_size_1522, &nsd->rx_size_1522);
3646266423Sjfv	i40e_stat_update48(hw, I40E_GLPRT_PRC9522H(hw->port),
3647266423Sjfv			   I40E_GLPRT_PRC9522L(hw->port),
3648266423Sjfv			   pf->stat_offsets_loaded,
3649266423Sjfv			   &osd->rx_size_big, &nsd->rx_size_big);
3650266423Sjfv
3651266423Sjfv	i40e_stat_update48(hw, I40E_GLPRT_PTC64H(hw->port),
3652266423Sjfv			   I40E_GLPRT_PTC64L(hw->port),
3653266423Sjfv			   pf->stat_offsets_loaded,
3654266423Sjfv			   &osd->tx_size_64, &nsd->tx_size_64);
3655266423Sjfv	i40e_stat_update48(hw, I40E_GLPRT_PTC127H(hw->port),
3656266423Sjfv			   I40E_GLPRT_PTC127L(hw->port),
3657266423Sjfv			   pf->stat_offsets_loaded,
3658266423Sjfv			   &osd->tx_size_127, &nsd->tx_size_127);
3659266423Sjfv	i40e_stat_update48(hw, I40E_GLPRT_PTC255H(hw->port),
3660266423Sjfv			   I40E_GLPRT_PTC255L(hw->port),
3661266423Sjfv			   pf->stat_offsets_loaded,
3662266423Sjfv			   &osd->tx_size_255, &nsd->tx_size_255);
3663266423Sjfv	i40e_stat_update48(hw, I40E_GLPRT_PTC511H(hw->port),
3664266423Sjfv			   I40E_GLPRT_PTC511L(hw->port),
3665266423Sjfv			   pf->stat_offsets_loaded,
3666266423Sjfv			   &osd->tx_size_511, &nsd->tx_size_511);
3667266423Sjfv	i40e_stat_update48(hw, I40E_GLPRT_PTC1023H(hw->port),
3668266423Sjfv			   I40E_GLPRT_PTC1023L(hw->port),
3669266423Sjfv			   pf->stat_offsets_loaded,
3670266423Sjfv			   &osd->tx_size_1023, &nsd->tx_size_1023);
3671266423Sjfv	i40e_stat_update48(hw, I40E_GLPRT_PTC1522H(hw->port),
3672266423Sjfv			   I40E_GLPRT_PTC1522L(hw->port),
3673266423Sjfv			   pf->stat_offsets_loaded,
3674266423Sjfv			   &osd->tx_size_1522, &nsd->tx_size_1522);
3675266423Sjfv	i40e_stat_update48(hw, I40E_GLPRT_PTC9522H(hw->port),
3676266423Sjfv			   I40E_GLPRT_PTC9522L(hw->port),
3677266423Sjfv			   pf->stat_offsets_loaded,
3678266423Sjfv			   &osd->tx_size_big, &nsd->tx_size_big);
3679266423Sjfv
3680266423Sjfv	i40e_stat_update32(hw, I40E_GLPRT_RUC(hw->port),
3681266423Sjfv			   pf->stat_offsets_loaded,
3682266423Sjfv			   &osd->rx_undersize, &nsd->rx_undersize);
3683266423Sjfv	i40e_stat_update32(hw, I40E_GLPRT_RFC(hw->port),
3684266423Sjfv			   pf->stat_offsets_loaded,
3685266423Sjfv			   &osd->rx_fragments, &nsd->rx_fragments);
3686266423Sjfv	i40e_stat_update32(hw, I40E_GLPRT_ROC(hw->port),
3687266423Sjfv			   pf->stat_offsets_loaded,
3688266423Sjfv			   &osd->rx_oversize, &nsd->rx_oversize);
3689266423Sjfv	i40e_stat_update32(hw, I40E_GLPRT_RJC(hw->port),
3690266423Sjfv			   pf->stat_offsets_loaded,
3691266423Sjfv			   &osd->rx_jabber, &nsd->rx_jabber);
3692266423Sjfv	pf->stat_offsets_loaded = true;
3693266423Sjfv	/* End pf-only stats */
3694266423Sjfv
3695266423Sjfv	/* Update vsi stats */
3696266423Sjfv	struct i40e_vsi *vsi = &pf->vsi;
3697266423Sjfv	i40e_update_eth_stats(vsi);
3698266423Sjfv
3699266423Sjfv	/* ERJ - does something need these statistics?
3700266423Sjfv	u64 rx_p = 0, rx_b = 0, tx_p = 0, tx_b = 0;
3701266423Sjfv	u64 tx_no_desc;
3702266423Sjfv	u64 rx_split, rx_discarded, rx_not_done;
3703266423Sjfv	for (u16 q = 0; q < vsi->num_queues; q++)
3704266423Sjfv	{
3705266423Sjfv		struct i40e_queue *p = &vsi->queues[q];
3706266423Sjfv
3707266423Sjfv		rx_p += p->rxr.packets;
3708266423Sjfv		tx_p += p->txr.packets;
3709266423Sjfv		rx_b += p->rxr.bytes;
3710266423Sjfv		tx_b += p->txr.bytes;
3711266423Sjfv
3712266423Sjfv		tx_no_desc += p->txr.no_desc;
3713266423Sjfv		rx_split += p->rxr.split;
3714266423Sjfv		rx_discarded += p->rxr.discarded;
3715266423Sjfv		rx_not_done += p->rxr.not_done;
3716266423Sjfv	}
3717266423Sjfv	*/
3718266423Sjfv
3719266423Sjfv	/* OS statistics */
3720266423Sjfv	struct ifnet	*ifp = vsi->ifp;
3721266423Sjfv
3722266423Sjfv	// ifp->if_ipackets = rx_p; // no gprc
3723266423Sjfv	// ifp->if_opackets = tx_p; // no gptc
3724266423Sjfv	ifp->if_ibytes = nsd->eth.rx_bytes;
3725266423Sjfv	ifp->if_obytes = nsd->eth.tx_bytes;
3726266423Sjfv	ifp->if_imcasts = nsd->eth.rx_multicast;
3727266423Sjfv	ifp->if_omcasts = nsd->eth.tx_multicast;
3728266423Sjfv	ifp->if_collisions = 0;
3729266423Sjfv
3730266423Sjfv	/* Rx Errors */
3731266423Sjfv	// Linux uses illegal_bytes instead of rx_length_errors
3732266423Sjfv	ifp->if_ierrors = nsd->crc_errors + nsd->illegal_bytes;
3733266423Sjfv}
3734266423Sjfv
3735266423Sjfv/*
3736266423Sjfv** Tasklet handler for MSIX Adminq interrupts
3737266423Sjfv**  - do outside interrupt since it might sleep
3738266423Sjfv*/
3739266423Sjfvstatic void
3740266423Sjfvi40e_do_adminq(void *context, int pending)
3741266423Sjfv{
3742266423Sjfv	struct i40e_pf			*pf = context;
3743266423Sjfv	struct i40e_hw			*hw = &pf->hw;
3744266423Sjfv	struct i40e_vsi			*vsi = &pf->vsi;
3745266423Sjfv	struct i40e_arq_event_info	event;
3746266423Sjfv	i40e_status			ret;
3747266423Sjfv	u32				reg, loop = 0;
3748266423Sjfv	u16				opcode, result;
3749266423Sjfv
3750266423Sjfv	event.msg_size = I40E_AQ_BUF_SZ;
3751266423Sjfv	event.msg_buf = malloc(event.msg_size,
3752266423Sjfv	    M_DEVBUF, M_NOWAIT | M_ZERO);
3753266423Sjfv	if (!event.msg_buf) {
3754266423Sjfv		printf("Unable to allocate adminq memory\n");
3755266423Sjfv		return;
3756266423Sjfv	}
3757266423Sjfv
3758266423Sjfv	/* clean and process any events */
3759266423Sjfv	do {
3760266423Sjfv		ret = i40e_clean_arq_element(hw, &event, &result);
3761266423Sjfv		if (ret)
3762266423Sjfv			break;
3763266423Sjfv		opcode = LE16_TO_CPU(event.desc.opcode);
3764266423Sjfv		switch (opcode) {
3765266423Sjfv		case i40e_aqc_opc_get_link_status:
3766266423Sjfv			vsi->link_up = i40e_config_link(hw);
3767266423Sjfv			i40e_update_link_status(pf);
3768266423Sjfv			break;
3769266423Sjfv		case i40e_aqc_opc_send_msg_to_pf:
3770266423Sjfv			/* process pf/vf communication here */
3771266423Sjfv			break;
3772266423Sjfv		case i40e_aqc_opc_event_lan_overflow:
3773266423Sjfv			break;
3774266423Sjfv		default:
3775266423Sjfv#ifdef I40E_DEBUG
3776266423Sjfv			printf("AdminQ unknown event %x\n", opcode);
3777266423Sjfv#endif
3778266423Sjfv			break;
3779266423Sjfv		}
3780266423Sjfv
3781266423Sjfv	} while (result && (loop++ < I40E_ADM_LIMIT));
3782266423Sjfv
3783266423Sjfv	reg = rd32(hw, I40E_PFINT_ICR0_ENA);
3784266423Sjfv	reg |=  I40E_PFINT_ICR0_ENA_ADMINQ_MASK;
3785266423Sjfv	wr32(hw, I40E_PFINT_ICR0_ENA, reg);
3786266423Sjfv	free(event.msg_buf, M_DEVBUF);
3787266423Sjfv
3788266423Sjfv	if (pf->msix > 1)
3789266423Sjfv		i40e_enable_adminq(&pf->hw);
3790266423Sjfv	else
3791266423Sjfv		i40e_enable_intr(vsi);
3792266423Sjfv}
3793266423Sjfv
3794266423Sjfvstatic int
3795266423Sjfvi40e_debug_info(SYSCTL_HANDLER_ARGS)
3796266423Sjfv{
3797266423Sjfv	struct i40e_pf	*pf;
3798266423Sjfv	int		error, input = 0;
3799266423Sjfv
3800266423Sjfv	error = sysctl_handle_int(oidp, &input, 0, req);
3801266423Sjfv
3802266423Sjfv	if (error || !req->newptr)
3803266423Sjfv		return (error);
3804266423Sjfv
3805266423Sjfv	if (input == 1) {
3806266423Sjfv		pf = (struct i40e_pf *)arg1;
3807266423Sjfv		i40e_print_debug_info(pf);
3808266423Sjfv	}
3809266423Sjfv
3810266423Sjfv	return (error);
3811266423Sjfv}
3812266423Sjfv
3813266423Sjfvstatic void
3814266423Sjfvi40e_print_debug_info(struct i40e_pf *pf)
3815266423Sjfv{
3816266423Sjfv	struct i40e_hw		*hw = &pf->hw;
3817266423Sjfv	struct i40e_vsi		*vsi = &pf->vsi;
3818266423Sjfv	struct i40e_queue	*que = vsi->queues;
3819266423Sjfv	struct rx_ring		*rxr = &que->rxr;
3820266423Sjfv	struct tx_ring		*txr = &que->txr;
3821266423Sjfv	u32			reg;
3822266423Sjfv
3823266423Sjfv
3824266423Sjfv	printf("Queue irqs = %lx\n", que->irqs);
3825266423Sjfv	printf("AdminQ irqs = %lx\n", pf->admin_irq);
3826266423Sjfv	printf("RX next check = %x\n", rxr->next_check);
3827266423Sjfv	printf("RX not ready = %lx\n", rxr->not_done);
3828266423Sjfv	printf("RX packets = %lx\n", rxr->rx_packets);
3829266423Sjfv	printf("TX desc avail = %x\n", txr->avail);
3830266423Sjfv
3831266423Sjfv	reg = rd32(hw, I40E_GLV_GORCL(0xc));
3832266423Sjfv	 printf("RX Bytes = %x\n", reg);
3833266423Sjfv	reg = rd32(hw, I40E_GLPRT_GORCL(hw->port));
3834266423Sjfv	 printf("Port RX Bytes = %x\n", reg);
3835266423Sjfv	reg = rd32(hw, I40E_GLV_RDPC(0xc));
3836266423Sjfv	 printf("RX discard = %x\n", reg);
3837266423Sjfv	reg = rd32(hw, I40E_GLPRT_RDPC(hw->port));
3838266423Sjfv	 printf("Port RX discard = %x\n", reg);
3839266423Sjfv
3840266423Sjfv	reg = rd32(hw, I40E_GLV_TEPC(0xc));
3841266423Sjfv	 printf("TX errors = %x\n", reg);
3842266423Sjfv	reg = rd32(hw, I40E_GLV_GOTCL(0xc));
3843266423Sjfv	 printf("TX Bytes = %x\n", reg);
3844266423Sjfv
3845266423Sjfv	reg = rd32(hw, I40E_GLPRT_RUC(hw->port));
3846266423Sjfv	 printf("RX undersize = %x\n", reg);
3847266423Sjfv	reg = rd32(hw, I40E_GLPRT_RFC(hw->port));
3848266423Sjfv	 printf("RX fragments = %x\n", reg);
3849266423Sjfv	reg = rd32(hw, I40E_GLPRT_ROC(hw->port));
3850266423Sjfv	 printf("RX oversize = %x\n", reg);
3851266423Sjfv	reg = rd32(hw, I40E_GLPRT_RLEC(hw->port));
3852266423Sjfv	 printf("RX length error = %x\n", reg);
3853266423Sjfv	reg = rd32(hw, I40E_GLPRT_MRFC(hw->port));
3854266423Sjfv	 printf("mac remote fault = %x\n", reg);
3855266423Sjfv	reg = rd32(hw, I40E_GLPRT_MLFC(hw->port));
3856266423Sjfv	 printf("mac local fault = %x\n", reg);
3857266423Sjfv}
3858266423Sjfv
3859266423Sjfv/**
3860266423Sjfv * Update VSI-specific ethernet statistics counters.
3861266423Sjfv **/
3862266423Sjfvvoid i40e_update_eth_stats(struct i40e_vsi *vsi)
3863266423Sjfv{
3864266423Sjfv	struct i40e_pf	*pf = (struct i40e_pf *)vsi->back;
3865266423Sjfv	struct i40e_hw *hw = &pf->hw;
3866266423Sjfv	struct i40e_eth_stats *es;
3867266423Sjfv	struct i40e_eth_stats *oes;
3868266423Sjfv	u16 stat_idx = vsi->info.stat_counter_idx;
3869266423Sjfv
3870266423Sjfv	es = &vsi->eth_stats;
3871266423Sjfv	oes = &vsi->eth_stats_offsets;
3872266423Sjfv
3873266423Sjfv	/* Gather up the stats that the hw collects */
3874266423Sjfv	i40e_stat_update32(hw, I40E_GLV_TEPC(stat_idx),
3875266423Sjfv			   vsi->stat_offsets_loaded,
3876266423Sjfv			   &oes->tx_errors, &es->tx_errors);
3877266423Sjfv	i40e_stat_update32(hw, I40E_GLV_RDPC(stat_idx),
3878266423Sjfv			   vsi->stat_offsets_loaded,
3879266423Sjfv			   &oes->rx_discards, &es->rx_discards);
3880266423Sjfv
3881266423Sjfv	i40e_stat_update48(hw, I40E_GLV_GORCH(stat_idx),
3882266423Sjfv			   I40E_GLV_GORCL(stat_idx),
3883266423Sjfv			   vsi->stat_offsets_loaded,
3884266423Sjfv			   &oes->rx_bytes, &es->rx_bytes);
3885266423Sjfv	i40e_stat_update48(hw, I40E_GLV_UPRCH(stat_idx),
3886266423Sjfv			   I40E_GLV_UPRCL(stat_idx),
3887266423Sjfv			   vsi->stat_offsets_loaded,
3888266423Sjfv			   &oes->rx_unicast, &es->rx_unicast);
3889266423Sjfv	i40e_stat_update48(hw, I40E_GLV_MPRCH(stat_idx),
3890266423Sjfv			   I40E_GLV_MPRCL(stat_idx),
3891266423Sjfv			   vsi->stat_offsets_loaded,
3892266423Sjfv			   &oes->rx_multicast, &es->rx_multicast);
3893266423Sjfv	i40e_stat_update48(hw, I40E_GLV_BPRCH(stat_idx),
3894266423Sjfv			   I40E_GLV_BPRCL(stat_idx),
3895266423Sjfv			   vsi->stat_offsets_loaded,
3896266423Sjfv			   &oes->rx_broadcast, &es->rx_broadcast);
3897266423Sjfv
3898266423Sjfv	i40e_stat_update48(hw, I40E_GLV_GOTCH(stat_idx),
3899266423Sjfv			   I40E_GLV_GOTCL(stat_idx),
3900266423Sjfv			   vsi->stat_offsets_loaded,
3901266423Sjfv			   &oes->tx_bytes, &es->tx_bytes);
3902266423Sjfv	i40e_stat_update48(hw, I40E_GLV_UPTCH(stat_idx),
3903266423Sjfv			   I40E_GLV_UPTCL(stat_idx),
3904266423Sjfv			   vsi->stat_offsets_loaded,
3905266423Sjfv			   &oes->tx_unicast, &es->tx_unicast);
3906266423Sjfv	i40e_stat_update48(hw, I40E_GLV_MPTCH(stat_idx),
3907266423Sjfv			   I40E_GLV_MPTCL(stat_idx),
3908266423Sjfv			   vsi->stat_offsets_loaded,
3909266423Sjfv			   &oes->tx_multicast, &es->tx_multicast);
3910266423Sjfv	i40e_stat_update48(hw, I40E_GLV_BPTCH(stat_idx),
3911266423Sjfv			   I40E_GLV_BPTCL(stat_idx),
3912266423Sjfv			   vsi->stat_offsets_loaded,
3913266423Sjfv			   &oes->tx_broadcast, &es->tx_broadcast);
3914266423Sjfv	vsi->stat_offsets_loaded = true;
3915266423Sjfv}
3916266423Sjfv
3917266423Sjfv/**
3918266423Sjfv * Reset all of the stats for the given pf
3919266423Sjfv **/
3920266423Sjfvvoid i40e_pf_reset_stats(struct i40e_pf *pf)
3921266423Sjfv{
3922266423Sjfv	bzero(&pf->stats, sizeof(struct i40e_hw_port_stats));
3923266423Sjfv	bzero(&pf->stats_offsets, sizeof(struct i40e_hw_port_stats));
3924266423Sjfv	pf->stat_offsets_loaded = false;
3925266423Sjfv}
3926266423Sjfv
3927266423Sjfv/**
3928266423Sjfv * Resets all stats of the given vsi
3929266423Sjfv **/
3930266423Sjfvvoid i40e_vsi_reset_stats(struct i40e_vsi *vsi)
3931266423Sjfv{
3932266423Sjfv	bzero(&vsi->eth_stats, sizeof(struct i40e_eth_stats));
3933266423Sjfv	bzero(&vsi->eth_stats_offsets, sizeof(struct i40e_eth_stats));
3934266423Sjfv	vsi->stat_offsets_loaded = false;
3935266423Sjfv}
3936266423Sjfv
3937266423Sjfv/**
3938266423Sjfv * Read and update a 48 bit stat from the hw
3939266423Sjfv *
3940266423Sjfv * Since the device stats are not reset at PFReset, they likely will not
3941266423Sjfv * be zeroed when the driver starts.  We'll save the first values read
3942266423Sjfv * and use them as offsets to be subtracted from the raw values in order
3943266423Sjfv * to report stats that count from zero.
3944266423Sjfv **/
3945266423Sjfvstatic void
3946266423Sjfvi40e_stat_update48(struct i40e_hw *hw, u32 hireg, u32 loreg,
3947266423Sjfv	bool offset_loaded, u64 *offset, u64 *stat)
3948266423Sjfv{
3949266423Sjfv	u64 new_data;
3950266423Sjfv
3951266423Sjfv#if __FreeBSD__ >= 10 && __amd64__
3952266423Sjfv	new_data = rd64(hw, loreg);
3953266423Sjfv#else
3954266423Sjfv	/*
3955266423Sjfv	 * Use two rd32's instead of one rd64 because FreeBSD versions before
3956266423Sjfv	 * 10 don't support 8 byte bus reads/writes.
3957266423Sjfv	 */
3958266423Sjfv	new_data = rd32(hw, loreg);
3959266423Sjfv	new_data |= ((u64)(rd32(hw, hireg) & 0xFFFF)) << 32;
3960266423Sjfv#endif
3961266423Sjfv
3962266423Sjfv	if (!offset_loaded)
3963266423Sjfv		*offset = new_data;
3964266423Sjfv	if (new_data >= *offset)
3965266423Sjfv		*stat = new_data - *offset;
3966266423Sjfv	else
3967266423Sjfv		*stat = (new_data + ((u64)1 << 48)) - *offset;
3968266423Sjfv	*stat &= 0xFFFFFFFFFFFFULL;
3969266423Sjfv}
3970266423Sjfv
3971266423Sjfv/**
3972266423Sjfv * Read and update a 32 bit stat from the hw
3973266423Sjfv **/
3974266423Sjfvstatic void
3975266423Sjfvi40e_stat_update32(struct i40e_hw *hw, u32 reg,
3976266423Sjfv	bool offset_loaded, u64 *offset, u64 *stat)
3977266423Sjfv{
3978266423Sjfv	u32 new_data;
3979266423Sjfv
3980266423Sjfv	new_data = rd32(hw, reg);
3981266423Sjfv	if (!offset_loaded)
3982266423Sjfv		*offset = new_data;
3983266423Sjfv	if (new_data >= *offset)
3984266423Sjfv		*stat = (u32)(new_data - *offset);
3985266423Sjfv	else
3986266423Sjfv		*stat = (u32)((new_data + ((u64)1 << 32)) - *offset);
3987266423Sjfv}
3988266423Sjfv
3989266423Sjfv/*
3990266423Sjfv** Set flow control using sysctl:
3991266423Sjfv** Flow control values:
3992266423Sjfv** 	0 - off
3993266423Sjfv**	1 - rx pause
3994266423Sjfv**	2 - tx pause
3995266423Sjfv**	3 - full
3996266423Sjfv*/
3997266423Sjfvstatic int
3998266423Sjfvi40e_set_flowcntl(SYSCTL_HANDLER_ARGS)
3999266423Sjfv{
4000266423Sjfv	/*
4001266423Sjfv	 * TODO: ensure flow control is disabled if
4002266423Sjfv	 * priority flow control is enabled
4003266423Sjfv	 *
4004266423Sjfv	 * TODO: ensure tx CRC by hardware should be enabled
4005266423Sjfv	 * if tx flow control is enabled.
4006266423Sjfv	 */
4007266423Sjfv	struct i40e_pf *pf = (struct i40e_pf *)arg1;
4008266423Sjfv	struct i40e_hw *hw = &pf->hw;
4009266423Sjfv	device_t dev = pf->dev;
4010266423Sjfv	struct i40e_aq_get_phy_abilities_resp abilities;
4011266423Sjfv	int requested_fc = 0, error = 0;
4012266423Sjfv	enum i40e_status_code aq_error = 0;
4013266423Sjfv	u8 fc_aq_err = 0;
4014266423Sjfv
4015266423Sjfv	/* Get current capability information */
4016266423Sjfv	aq_error = i40e_aq_get_phy_capabilities(hw, FALSE, FALSE, &abilities, NULL);
4017266423Sjfv	if (aq_error)
4018266423Sjfv		device_printf(dev, "Error getting phy capabilities %d,"
4019266423Sjfv		    " aq error: %d\n", aq_error, hw->aq.asq_last_status);
4020266423Sjfv
4021266423Sjfv	if ((abilities.abilities & I40E_AQ_PHY_FLAG_PAUSE_TX) &&
4022266423Sjfv	    (abilities.abilities & I40E_AQ_PHY_FLAG_PAUSE_RX))
4023266423Sjfv		hw->fc.current_mode = I40E_FC_FULL;
4024266423Sjfv	else if (abilities.abilities & I40E_AQ_PHY_FLAG_PAUSE_TX)
4025266423Sjfv		hw->fc.current_mode = I40E_FC_TX_PAUSE;
4026266423Sjfv	else if (abilities.abilities & I40E_AQ_PHY_FLAG_PAUSE_RX)
4027266423Sjfv		hw->fc.current_mode = I40E_FC_RX_PAUSE;
4028266423Sjfv	else
4029266423Sjfv		hw->fc.current_mode = I40E_FC_NONE;
4030266423Sjfv
4031266423Sjfv	/* Read in new mode */
4032266423Sjfv	requested_fc = hw->fc.current_mode;
4033266423Sjfv	error = sysctl_handle_int(oidp, &requested_fc, 0, req);
4034266423Sjfv	if ((error) || (req->newptr == NULL))
4035266423Sjfv		goto no_set;
4036266423Sjfv	if (requested_fc < 0 || requested_fc > 3) {
4037266423Sjfv		device_printf(dev,
4038266423Sjfv		    "Invalid fc mode; valid modes are 0 through 3\n");
4039266423Sjfv		return (EINVAL);
4040266423Sjfv	}
4041266423Sjfv
4042266423Sjfv	/* Set fc ability for port */
4043266423Sjfv	hw->fc.requested_mode = requested_fc;
4044266423Sjfv	i40e_set_fc(hw, &fc_aq_err, TRUE);
4045266423Sjfv
4046266423Sjfv	// DEBUG: Verify flow control setting was successfully set
4047266423Sjfv	if (hw->fc.current_mode != hw->fc.requested_mode) {
4048266423Sjfv		device_printf(dev, "FC set failure:\n");
4049266423Sjfv		device_printf(dev, "Current: %s / Requested: %s\n",
4050266423Sjfv		    i40e_fc_string[hw->fc.current_mode],
4051266423Sjfv		    i40e_fc_string[hw->fc.requested_mode]);
4052266423Sjfv	}
4053266423Sjfv
4054266423Sjfvno_set:;
4055266423Sjfv#ifdef I40E_DEBUG
4056266423Sjfv	/* Print FC registers */
4057266423Sjfv	u32 reg = 0;
4058266423Sjfv	printf("Current FC mode: %s\n", i40e_fc_string[hw->fc.current_mode]);
4059266423Sjfv	if (i40e_is_40G_device(hw->device_id)) {
4060266423Sjfv		// XXX: Why are these names so long?
4061266423Sjfv		reg = rd32(hw, I40E_PRTMAC_HSEC_CTL_RX_ENABLE_GPP);
4062266423Sjfv		printf("PRTMAC_HSEC_CTL_RX_ENABLE_GPP (LFC)         : %s\n",
4063266423Sjfv		    ON_OFF_STR(reg & I40E_PRTMAC_HSEC_CTL_RX_ENABLE_GPP_HSEC_CTL_RX_ENABLE_GPP_MASK));
4064266423Sjfv
4065266423Sjfv		reg = rd32(hw, I40E_PRTMAC_HSEC_CTL_RX_ENABLE_PPP);
4066266423Sjfv		printf("PRTMAC_HSEC_CTL_RX_ENABLE_PPP (PFC)         : %s\n",
4067266423Sjfv		    ON_OFF_STR(reg & I40E_PRTMAC_HSEC_CTL_RX_ENABLE_GPP_HSEC_CTL_RX_ENABLE_GPP_MASK));
4068266423Sjfv
4069266423Sjfv		reg = rd32(hw, I40E_PRTMAC_HSEC_CTL_RX_PAUSE_ENABLE);
4070266423Sjfv		printf("PRTMAC_HSEC_CTL_RX_PAUSE_ENABLE (LFC)       : %s\n",
4071266423Sjfv		    ON_OFF_STR(reg & I40E_PRTMAC_HSEC_CTL_RX_PAUSE_ENABLE_HSEC_CTL_RX_PAUSE_ENABLE_MASK));
4072266423Sjfv
4073266423Sjfv		reg = rd32(hw, I40E_PRTMAC_HSEC_CTL_TX_PAUSE_ENABLE);
4074266423Sjfv		printf("PRTMAC_HSEC_CTL_TX_PAUSE_ENABLE (LFC)       : %s\n",
4075266423Sjfv		    ON_OFF_STR(reg & I40E_PRTMAC_HSEC_CTL_TX_PAUSE_ENABLE_HSEC_CTL_TX_PAUSE_ENABLE_MASK));
4076266423Sjfv
4077266423Sjfv		reg = rd32(hw, I40E_PRTMAC_HSEC_CTL_TX_PAUSE_REFRESH_TIMER(8));
4078266423Sjfv		printf("PRTMAC_HSEC_CTL_TX_PAUSE_REFRESH_TIMER (LFC): %#010x\n", reg);
4079266423Sjfv
4080266423Sjfv		reg = rd32(hw, I40E_PRTMAC_HSEC_CTL_TX_PAUSE_QUANTA(8));
4081266423Sjfv		printf("PRTMAC_HSEC_CTL_TX_PAUSE_QUANTA (LFC)       : %#010x\n",
4082266423Sjfv		    reg & I40E_PRTMAC_HSEC_CTL_TX_PAUSE_QUANTA_HSEC_CTL_TX_PAUSE_QUANTA_MASK);
4083266423Sjfv	} else {
4084266423Sjfv		reg = rd32(hw, I40E_PRTDCB_MFLCN);
4085266423Sjfv		printf("PRTDCB_MFLCN                     :\n");
4086266423Sjfv		printf("- PMCF  (Pass MAC Control Frames): %s\n",
4087266423Sjfv		    ON_OFF_STR(reg & I40E_PRTDCB_MFLCN_PMCF_MASK));
4088266423Sjfv		printf("- DPF   (Discard Pause Frames)   : %s\n",
4089266423Sjfv		    ON_OFF_STR(reg & I40E_PRTDCB_MFLCN_DPF_MASK));
4090266423Sjfv		printf("- RPFCM (Rx PFC Mode)            : %s\n",
4091266423Sjfv		    ON_OFF_STR(reg & I40E_PRTDCB_MFLCN_RPFCM_MASK));
4092266423Sjfv		printf("- RFCE  (Rx LFC Mode)            : %s\n",
4093266423Sjfv		    ON_OFF_STR(reg & I40E_PRTDCB_MFLCN_RFCE_MASK));
4094266423Sjfv		printf("- RPFCE (Rx PFC Enable Bitmap)   : %#04x\n",
4095266423Sjfv		    reg & I40E_PRTDCB_MFLCN_RPFCE_MASK);
4096266423Sjfv		reg = rd32(hw, I40E_PRTDCB_FCCFG);
4097266423Sjfv		printf("PRTDCB_FCCFG                     :\n");
4098266423Sjfv		u8 tfce = reg & I40E_PRTDCB_FCCFG_TFCE_MASK;
4099266423Sjfv		printf("- TFCE  (Tx FC Enable)           : %s\n",
4100266423Sjfv		    (tfce == 3) ? "Reserved" :
4101266423Sjfv		    (tfce == 2) ? "PFC Enabled" :
4102266423Sjfv		    (tfce == 1) ? "LFC Enabled" :
4103266423Sjfv				  "Tx FC Disabled");
4104266423Sjfv		reg = rd32(hw, I40E_PRTDCB_FCTTVN(0));
4105266423Sjfv		printf("PRTDCB_FCCTTVN (LFC)             : %#06x\n",
4106266423Sjfv		    reg & I40E_PRTDCB_FCTTVN_TTV_2N_MASK);
4107266423Sjfv		reg = rd32(hw, I40E_PRTDCB_FCRTV);
4108266423Sjfv		printf("PRTDCB_FCRTV (Pause ref thresh)  : %#06x\n",
4109266423Sjfv		    reg & I40E_PRTDCB_FCRTV_FC_REFRESH_TH_MASK);
4110266423Sjfv		reg = rd32(hw, I40E_PRTDCB_TC2PFC);
4111266423Sjfv		printf("PRTDCB_TC2PFC is 0xff            : %s\n",
4112266423Sjfv		    ((reg & I40E_PRTDCB_TC2PFC_TC2PFC_MASK) == 0xFF)
4113266423Sjfv		    ? "Yes" : "No");
4114266423Sjfv	}
4115266423Sjfv#endif
4116266423Sjfv	return (error);
4117266423Sjfv}
4118266423Sjfv
4119266423Sjfv/*
4120266423Sjfv** Get the width and transaction speed of
4121266423Sjfv** the bus this adapter is plugged into.
4122266423Sjfv*/
4123266423Sjfvstatic u16
4124266423Sjfvi40e_get_bus_info(struct i40e_hw *hw, device_t dev)
4125266423Sjfv{
4126266423Sjfv        u16                     link;
4127266423Sjfv        u32                     offset;
4128266423Sjfv
4129266423Sjfv
4130266423Sjfv        /* Get the PCI Express Capabilities offset */
4131266423Sjfv        pci_find_cap(dev, PCIY_EXPRESS, &offset);
4132266423Sjfv
4133266423Sjfv        /* ...and read the Link Status Register */
4134266423Sjfv        link = pci_read_config(dev, offset + PCIER_LINK_STA, 2);
4135266423Sjfv
4136266423Sjfv        switch (link & I40E_PCI_LINK_WIDTH) {
4137266423Sjfv        case I40E_PCI_LINK_WIDTH_1:
4138266423Sjfv                hw->bus.width = i40e_bus_width_pcie_x1;
4139266423Sjfv                break;
4140266423Sjfv        case I40E_PCI_LINK_WIDTH_2:
4141266423Sjfv                hw->bus.width = i40e_bus_width_pcie_x2;
4142266423Sjfv                break;
4143266423Sjfv        case I40E_PCI_LINK_WIDTH_4:
4144266423Sjfv                hw->bus.width = i40e_bus_width_pcie_x4;
4145266423Sjfv                break;
4146266423Sjfv        case I40E_PCI_LINK_WIDTH_8:
4147266423Sjfv                hw->bus.width = i40e_bus_width_pcie_x8;
4148266423Sjfv                break;
4149266423Sjfv        default:
4150266423Sjfv                hw->bus.width = i40e_bus_width_unknown;
4151266423Sjfv                break;
4152266423Sjfv        }
4153266423Sjfv
4154266423Sjfv        switch (link & I40E_PCI_LINK_SPEED) {
4155266423Sjfv        case I40E_PCI_LINK_SPEED_2500:
4156266423Sjfv                hw->bus.speed = i40e_bus_speed_2500;
4157266423Sjfv                break;
4158266423Sjfv        case I40E_PCI_LINK_SPEED_5000:
4159266423Sjfv                hw->bus.speed = i40e_bus_speed_5000;
4160266423Sjfv                break;
4161266423Sjfv        case I40E_PCI_LINK_SPEED_8000:
4162266423Sjfv                hw->bus.speed = i40e_bus_speed_8000;
4163266423Sjfv                break;
4164266423Sjfv        default:
4165266423Sjfv                hw->bus.speed = i40e_bus_speed_unknown;
4166266423Sjfv                break;
4167266423Sjfv        }
4168266423Sjfv
4169266423Sjfv
4170266423Sjfv        device_printf(dev,"PCI Express Bus: Speed %s %s\n",
4171266423Sjfv            ((hw->bus.speed == i40e_bus_speed_8000) ? "8.0GT/s":
4172266423Sjfv            (hw->bus.speed == i40e_bus_speed_5000) ? "5.0GT/s":
4173266423Sjfv            (hw->bus.speed == i40e_bus_speed_2500) ? "2.5GT/s":"Unknown"),
4174266423Sjfv            (hw->bus.width == i40e_bus_width_pcie_x8) ? "Width x8" :
4175266423Sjfv            (hw->bus.width == i40e_bus_width_pcie_x4) ? "Width x4" :
4176266423Sjfv            (hw->bus.width == i40e_bus_width_pcie_x1) ? "Width x1" :
4177266423Sjfv            ("Unknown"));
4178266423Sjfv
4179266423Sjfv        if ((hw->bus.width <= i40e_bus_width_pcie_x8) &&
4180266423Sjfv            (hw->bus.speed < i40e_bus_speed_8000)) {
4181266423Sjfv                device_printf(dev, "PCI-Express bandwidth available"
4182266423Sjfv                    " for this device\n     is not sufficient for"
4183266423Sjfv                    " normal operation.\n");
4184266423Sjfv                device_printf(dev, "For expected performance a x8 "
4185266423Sjfv                    "PCIE Gen3 slot is required.\n");
4186266423Sjfv        }
4187266423Sjfv
4188266423Sjfv        return (link);
4189266423Sjfv}
4190266423Sjfv
4191266423Sjfv#ifdef I40E_DEBUG
4192266423Sjfvstatic int
4193266423Sjfvi40e_sysctl_link_status(SYSCTL_HANDLER_ARGS)
4194266423Sjfv{
4195266423Sjfv	struct i40e_pf *pf = (struct i40e_pf *)arg1;
4196266423Sjfv	struct i40e_hw *hw = &pf->hw;
4197266423Sjfv	struct i40e_link_status link_status;
4198266423Sjfv	char buf[512];
4199266423Sjfv
4200266423Sjfv	enum i40e_status_code aq_error = 0;
4201266423Sjfv
4202266423Sjfv	aq_error = i40e_aq_get_link_info(hw, TRUE, &link_status, NULL);
4203266423Sjfv	if (aq_error) {
4204266423Sjfv		printf("i40e_aq_get_link_info() error %d\n", aq_error);
4205266423Sjfv		return (EPERM);
4206266423Sjfv	}
4207266423Sjfv
4208266423Sjfv	sprintf(buf, "\n"
4209266423Sjfv	    "PHY Type : %#04x\n"
4210266423Sjfv	    "Speed    : %#04x\n"
4211266423Sjfv	    "Link info: %#04x\n"
4212266423Sjfv	    "AN info  : %#04x\n"
4213266423Sjfv	    "Ext info : %#04x",
4214266423Sjfv	    link_status.phy_type, link_status.link_speed,
4215266423Sjfv	    link_status.link_info, link_status.an_info,
4216266423Sjfv	    link_status.ext_info);
4217266423Sjfv
4218266423Sjfv	return (sysctl_handle_string(oidp, buf, strlen(buf), req));
4219266423Sjfv}
4220266423Sjfv
4221266423Sjfvstatic int
4222266423Sjfvi40e_sysctl_phy_abilities(SYSCTL_HANDLER_ARGS)
4223266423Sjfv{
4224266423Sjfv	struct i40e_pf *pf = (struct i40e_pf *)arg1;
4225266423Sjfv	struct i40e_hw *hw = &pf->hw;
4226266423Sjfv	struct i40e_aq_get_phy_abilities_resp abilities_resp;
4227266423Sjfv	char buf[512];
4228266423Sjfv
4229266423Sjfv	enum i40e_status_code aq_error = 0;
4230266423Sjfv
4231266423Sjfv	// TODO: Print out list of qualified modules as well?
4232266423Sjfv	aq_error = i40e_aq_get_phy_capabilities(hw, TRUE, FALSE, &abilities_resp, NULL);
4233266423Sjfv	if (aq_error) {
4234266423Sjfv		printf("i40e_aq_get_phy_capabilities() error %d\n", aq_error);
4235266423Sjfv		return (EPERM);
4236266423Sjfv	}
4237266423Sjfv
4238266423Sjfv	sprintf(buf, "\n"
4239266423Sjfv	    "PHY Type : %#010x\n"
4240266423Sjfv	    "Speed    : %#04x\n"
4241266423Sjfv	    "Abilities: %#04x\n"
4242266423Sjfv	    "EEE cap  : %#06x\n"
4243266423Sjfv	    "EEER reg : %#010x\n"
4244266423Sjfv	    "D3 Lpan  : %#04x",
4245266423Sjfv	    abilities_resp.phy_type, abilities_resp.link_speed,
4246266423Sjfv	    abilities_resp.abilities, abilities_resp.eee_capability,
4247266423Sjfv	    abilities_resp.eeer_val, abilities_resp.d3_lpan);
4248266423Sjfv
4249266423Sjfv	return (sysctl_handle_string(oidp, buf, strlen(buf), req));
4250266423Sjfv}
4251266423Sjfv
4252266423Sjfvstatic int
4253266423Sjfvi40e_sysctl_sw_filter_list(SYSCTL_HANDLER_ARGS)
4254266423Sjfv{
4255266423Sjfv	struct i40e_pf *pf = (struct i40e_pf *)arg1;
4256266423Sjfv	struct i40e_vsi *vsi = &pf->vsi;
4257266423Sjfv	struct i40e_mac_filter *f;
4258266423Sjfv	char *buf, *buf_i;
4259266423Sjfv
4260266423Sjfv	int error = 0;
4261266423Sjfv	int ftl_len = 0;
4262266423Sjfv	int ftl_counter = 0;
4263266423Sjfv	int buf_len = 0;
4264266423Sjfv	int entry_len = 42;
4265266423Sjfv
4266266423Sjfv	SLIST_FOREACH(f, &vsi->ftl, next) {
4267266423Sjfv		ftl_len++;
4268266423Sjfv	}
4269266423Sjfv
4270266423Sjfv	if (ftl_len < 1) {
4271266423Sjfv		sysctl_handle_string(oidp, "(none)", 6, req);
4272266423Sjfv		return (0);
4273266423Sjfv	}
4274266423Sjfv
4275266423Sjfv	buf_len = sizeof(char) * (entry_len + 1) * ftl_len + 2;
4276266423Sjfv	buf = buf_i = malloc(buf_len, M_DEVBUF, M_NOWAIT);
4277266423Sjfv
4278266423Sjfv	sprintf(buf_i++, "\n");
4279266423Sjfv	SLIST_FOREACH(f, &vsi->ftl, next) {
4280266423Sjfv		sprintf(buf_i,
4281266423Sjfv		    MAC_FORMAT ", vlan %4d, flags %#06x",
4282266423Sjfv		    MAC_FORMAT_ARGS(f->macaddr), f->vlan, f->flags);
4283266423Sjfv		buf_i += entry_len;
4284266423Sjfv		/* don't print '\n' for last entry */
4285266423Sjfv		if (++ftl_counter != ftl_len) {
4286266423Sjfv			sprintf(buf_i, "\n");
4287266423Sjfv			buf_i++;
4288266423Sjfv		}
4289266423Sjfv	}
4290266423Sjfv
4291266423Sjfv	error = sysctl_handle_string(oidp, buf, strlen(buf), req);
4292266423Sjfv	if (error)
4293266423Sjfv		printf("sysctl error: %d\n", error);
4294266423Sjfv	free(buf, M_DEVBUF);
4295266423Sjfv	return error;
4296266423Sjfv}
4297266423Sjfv#endif
4298266423Sjfv
4299