xref: /freebsd/sys/dev/ixl/if_ixl.c (revision 1031d839aa127290f6ef6e11d16472bf268616d4)
161ae650dSJack F Vogel /******************************************************************************
261ae650dSJack F Vogel 
3ceebc2f3SEric Joyner   Copyright (c) 2013-2017, Intel Corporation
461ae650dSJack F Vogel   All rights reserved.
561ae650dSJack F Vogel 
661ae650dSJack F Vogel   Redistribution and use in source and binary forms, with or without
761ae650dSJack F Vogel   modification, are permitted provided that the following conditions are met:
861ae650dSJack F Vogel 
961ae650dSJack F Vogel    1. Redistributions of source code must retain the above copyright notice,
1061ae650dSJack F Vogel       this list of conditions and the following disclaimer.
1161ae650dSJack F Vogel 
1261ae650dSJack F Vogel    2. Redistributions in binary form must reproduce the above copyright
1361ae650dSJack F Vogel       notice, this list of conditions and the following disclaimer in the
1461ae650dSJack F Vogel       documentation and/or other materials provided with the distribution.
1561ae650dSJack F Vogel 
1661ae650dSJack F Vogel    3. Neither the name of the Intel Corporation nor the names of its
1761ae650dSJack F Vogel       contributors may be used to endorse or promote products derived from
1861ae650dSJack F Vogel       this software without specific prior written permission.
1961ae650dSJack F Vogel 
2061ae650dSJack F Vogel   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
2161ae650dSJack F Vogel   AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2261ae650dSJack F Vogel   IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2361ae650dSJack F Vogel   ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
2461ae650dSJack F Vogel   LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
2561ae650dSJack F Vogel   CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
2661ae650dSJack F Vogel   SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
2761ae650dSJack F Vogel   INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
2861ae650dSJack F Vogel   CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
2961ae650dSJack F Vogel   ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
3061ae650dSJack F Vogel   POSSIBILITY OF SUCH DAMAGE.
3161ae650dSJack F Vogel 
3261ae650dSJack F Vogel ******************************************************************************/
3361ae650dSJack F Vogel /*$FreeBSD$*/
3461ae650dSJack F Vogel 
3561ae650dSJack F Vogel #include "ixl.h"
3661ae650dSJack F Vogel #include "ixl_pf.h"
3761ae650dSJack F Vogel 
38cb6b8299SEric Joyner #ifdef IXL_IW
39cb6b8299SEric Joyner #include "ixl_iw.h"
40cb6b8299SEric Joyner #include "ixl_iw_int.h"
41cb6b8299SEric Joyner #endif
42cb6b8299SEric Joyner 
434294f337SSean Bruno #ifdef PCI_IOV
444294f337SSean Bruno #include "ixl_pf_iov.h"
45dcd7b3b2SJack F Vogel #endif
46dcd7b3b2SJack F Vogel 
4761ae650dSJack F Vogel /*********************************************************************
4861ae650dSJack F Vogel  *  Driver version
4961ae650dSJack F Vogel  *********************************************************************/
50ceebc2f3SEric Joyner #define IXL_DRIVER_VERSION_MAJOR	1
51ceebc2f3SEric Joyner #define IXL_DRIVER_VERSION_MINOR	9
52ceebc2f3SEric Joyner #define IXL_DRIVER_VERSION_BUILD	9
53ceebc2f3SEric Joyner 
54*1031d839SEric Joyner #define IXL_DRIVER_VERSION_STRING			\
55*1031d839SEric Joyner     __XSTRING(IXL_DRIVER_VERSION_MAJOR) "."		\
56*1031d839SEric Joyner     __XSTRING(IXL_DRIVER_VERSION_MINOR) "."		\
57*1031d839SEric Joyner     __XSTRING(IXL_DRIVER_VERSION_BUILD) "-iflib-k"
5861ae650dSJack F Vogel 
5961ae650dSJack F Vogel /*********************************************************************
6061ae650dSJack F Vogel  *  PCI Device ID Table
6161ae650dSJack F Vogel  *
6261ae650dSJack F Vogel  *  Used by probe to select devices to load on
6361ae650dSJack F Vogel  *
64*1031d839SEric Joyner  *  ( Vendor ID, Device ID, Branding String )
6561ae650dSJack F Vogel  *********************************************************************/
6661ae650dSJack F Vogel 
67*1031d839SEric Joyner static pci_vendor_info_t ixl_vendor_info_array[] =
6861ae650dSJack F Vogel {
69*1031d839SEric Joyner 	PVIDV(I40E_INTEL_VENDOR_ID, I40E_DEV_ID_SFP_XL710, "Intel(R) Ethernet Controller X710 for 10GbE SFP+"),
70*1031d839SEric Joyner 	PVIDV(I40E_INTEL_VENDOR_ID, I40E_DEV_ID_KX_B, "Intel(R) Ethernet Controller XL710 for 40GbE backplane"),
71*1031d839SEric Joyner 	PVIDV(I40E_INTEL_VENDOR_ID, I40E_DEV_ID_KX_C, "Intel(R) Ethernet Controller X710 for 10GbE backplane"),
72*1031d839SEric Joyner 	PVIDV(I40E_INTEL_VENDOR_ID, I40E_DEV_ID_QSFP_A, "Intel(R) Ethernet Controller XL710 for 40GbE QSFP+"),
73*1031d839SEric Joyner 	PVIDV(I40E_INTEL_VENDOR_ID, I40E_DEV_ID_QSFP_B, "Intel(R) Ethernet Controller XL710 for 40GbE QSFP+"),
74*1031d839SEric Joyner 	PVIDV(I40E_INTEL_VENDOR_ID, I40E_DEV_ID_QSFP_C, "Intel(R) Ethernet Controller X710 for 10GbE QSFP+"),
75*1031d839SEric Joyner 	PVIDV(I40E_INTEL_VENDOR_ID, I40E_DEV_ID_10G_BASE_T, "Intel(R) Ethernet Controller X710 for 10GBASE-T"),
76*1031d839SEric Joyner 	PVIDV(I40E_INTEL_VENDOR_ID, I40E_DEV_ID_10G_BASE_T4, "Intel(R) Ethernet Controller X710/X557-AT 10GBASE-T"),
77*1031d839SEric Joyner 	PVIDV(I40E_INTEL_VENDOR_ID, I40E_DEV_ID_KX_X722, "Intel(R) Ethernet Connection X722 for 10GbE backplane"),
78*1031d839SEric Joyner 	PVIDV(I40E_INTEL_VENDOR_ID, I40E_DEV_ID_QSFP_X722, "Intel(R) Ethernet Connection X722 for 10GbE QSFP+"),
79*1031d839SEric Joyner 	PVIDV(I40E_INTEL_VENDOR_ID, I40E_DEV_ID_SFP_X722, "Intel(R) Ethernet Connection X722 for 10GbE SFP+"),
80*1031d839SEric Joyner 	PVIDV(I40E_INTEL_VENDOR_ID, I40E_DEV_ID_1G_BASE_T_X722, "Intel(R) Ethernet Connection X722 for 1GbE"),
81*1031d839SEric Joyner 	PVIDV(I40E_INTEL_VENDOR_ID, I40E_DEV_ID_10G_BASE_T_X722, "Intel(R) Ethernet Connection X722 for 10GBASE-T"),
82*1031d839SEric Joyner 	PVIDV(I40E_INTEL_VENDOR_ID, I40E_DEV_ID_SFP_I_X722, "Intel(R) Ethernet Connection X722 for 10GbE SFP+"),
83*1031d839SEric Joyner 	PVIDV(I40E_INTEL_VENDOR_ID, I40E_DEV_ID_25G_B, "Intel(R) Ethernet Controller XXV710 for 25GbE backplane"),
84*1031d839SEric Joyner 	PVIDV(I40E_INTEL_VENDOR_ID, I40E_DEV_ID_25G_SFP28, "Intel(R) Ethernet Controller XXV710 for 25GbE SFP28"),
8561ae650dSJack F Vogel 	/* required last entry */
86*1031d839SEric Joyner 	PVID_END
8761ae650dSJack F Vogel };
8861ae650dSJack F Vogel 
8961ae650dSJack F Vogel /*********************************************************************
9061ae650dSJack F Vogel  *  Function prototypes
9161ae650dSJack F Vogel  *********************************************************************/
92*1031d839SEric Joyner /*** IFLIB interface ***/
93*1031d839SEric Joyner static void	*ixl_register(device_t dev);
94*1031d839SEric Joyner static int	 ixl_if_attach_pre(if_ctx_t ctx);
95*1031d839SEric Joyner static int	 ixl_if_attach_post(if_ctx_t ctx);
96*1031d839SEric Joyner static int	 ixl_if_detach(if_ctx_t ctx);
97*1031d839SEric Joyner static int	 ixl_if_shutdown(if_ctx_t ctx);
98*1031d839SEric Joyner static int	 ixl_if_suspend(if_ctx_t ctx);
99*1031d839SEric Joyner static int	 ixl_if_resume(if_ctx_t ctx);
100*1031d839SEric Joyner static int	 ixl_if_msix_intr_assign(if_ctx_t ctx, int msix);
101*1031d839SEric Joyner static void	 ixl_if_enable_intr(if_ctx_t ctx);
102*1031d839SEric Joyner static void	 ixl_if_disable_intr(if_ctx_t ctx);
103*1031d839SEric Joyner static int	 ixl_if_rx_queue_intr_enable(if_ctx_t ctx, uint16_t rxqid);
104*1031d839SEric Joyner static int	 ixl_if_tx_queue_intr_enable(if_ctx_t ctx, uint16_t txqid);
105*1031d839SEric Joyner static int	 ixl_if_tx_queues_alloc(if_ctx_t ctx, caddr_t *vaddrs, uint64_t *paddrs, int ntxqs, int ntxqsets);
106*1031d839SEric Joyner static int	 ixl_if_rx_queues_alloc(if_ctx_t ctx, caddr_t *vaddrs, uint64_t *paddrs, int nqs, int nqsets);
107*1031d839SEric Joyner static void	 ixl_if_queues_free(if_ctx_t ctx);
108*1031d839SEric Joyner static void	 ixl_if_update_admin_status(if_ctx_t ctx);
109*1031d839SEric Joyner static void	 ixl_if_multi_set(if_ctx_t ctx);
110*1031d839SEric Joyner static int	 ixl_if_mtu_set(if_ctx_t ctx, uint32_t mtu);
111*1031d839SEric Joyner static void	 ixl_if_media_status(if_ctx_t ctx, struct ifmediareq *ifmr);
112*1031d839SEric Joyner static int	 ixl_if_media_change(if_ctx_t ctx);
113*1031d839SEric Joyner static int	 ixl_if_promisc_set(if_ctx_t ctx, int flags);
114*1031d839SEric Joyner static void	 ixl_if_timer(if_ctx_t ctx, uint16_t qid);
115*1031d839SEric Joyner static void	 ixl_if_vlan_register(if_ctx_t ctx, u16 vtag);
116*1031d839SEric Joyner static void	 ixl_if_vlan_unregister(if_ctx_t ctx, u16 vtag);
117*1031d839SEric Joyner static uint64_t	 ixl_if_get_counter(if_ctx_t ctx, ift_counter cnt);
118*1031d839SEric Joyner static void	 ixl_if_vflr_handle(if_ctx_t ctx);
119*1031d839SEric Joyner // static void	 ixl_if_link_intr_enable(if_ctx_t ctx);
120*1031d839SEric Joyner static int	 ixl_if_i2c_req(if_ctx_t ctx, struct ifi2creq *req);
121*1031d839SEric Joyner static int	 ixl_if_priv_ioctl(if_ctx_t ctx, u_long command, caddr_t data);
1226c426059SEric Joyner 
123*1031d839SEric Joyner /*** Other ***/
124*1031d839SEric Joyner static int	 ixl_mc_filter_apply(void *arg, struct ifmultiaddr *ifma, int);
125*1031d839SEric Joyner static void	 ixl_save_pf_tunables(struct ixl_pf *);
126*1031d839SEric Joyner static int	 ixl_allocate_pci_resources(struct ixl_pf *);
12761ae650dSJack F Vogel 
12861ae650dSJack F Vogel /*********************************************************************
12961ae650dSJack F Vogel  *  FreeBSD Device Interface Entry Points
13061ae650dSJack F Vogel  *********************************************************************/
13161ae650dSJack F Vogel 
13261ae650dSJack F Vogel static device_method_t ixl_methods[] = {
13361ae650dSJack F Vogel 	/* Device interface */
134*1031d839SEric Joyner 	DEVMETHOD(device_register, ixl_register),
135*1031d839SEric Joyner 	DEVMETHOD(device_probe, iflib_device_probe),
136*1031d839SEric Joyner 	DEVMETHOD(device_attach, iflib_device_attach),
137*1031d839SEric Joyner 	DEVMETHOD(device_detach, iflib_device_detach),
138*1031d839SEric Joyner 	DEVMETHOD(device_shutdown, iflib_device_shutdown),
13956c2c47bSJack F Vogel #ifdef PCI_IOV
140a48d00d2SEric Joyner 	DEVMETHOD(pci_iov_init, ixl_iov_init),
141a48d00d2SEric Joyner 	DEVMETHOD(pci_iov_uninit, ixl_iov_uninit),
142a48d00d2SEric Joyner 	DEVMETHOD(pci_iov_add_vf, ixl_add_vf),
14356c2c47bSJack F Vogel #endif
144*1031d839SEric Joyner 	DEVMETHOD_END
14561ae650dSJack F Vogel };
14661ae650dSJack F Vogel 
14761ae650dSJack F Vogel static driver_t ixl_driver = {
14861ae650dSJack F Vogel 	"ixl", ixl_methods, sizeof(struct ixl_pf),
14961ae650dSJack F Vogel };
15061ae650dSJack F Vogel 
15161ae650dSJack F Vogel devclass_t ixl_devclass;
15261ae650dSJack F Vogel DRIVER_MODULE(ixl, pci, ixl_driver, ixl_devclass, 0, 0);
153*1031d839SEric Joyner MODULE_VERSION(ixl, 3);
154cb6b8299SEric Joyner 
15561ae650dSJack F Vogel MODULE_DEPEND(ixl, pci, 1, 1, 1);
15661ae650dSJack F Vogel MODULE_DEPEND(ixl, ether, 1, 1, 1);
157*1031d839SEric Joyner MODULE_DEPEND(ixl, iflib, 1, 1, 1);
158*1031d839SEric Joyner 
159*1031d839SEric Joyner static device_method_t ixl_if_methods[] = {
160*1031d839SEric Joyner 	DEVMETHOD(ifdi_attach_pre, ixl_if_attach_pre),
161*1031d839SEric Joyner 	DEVMETHOD(ifdi_attach_post, ixl_if_attach_post),
162*1031d839SEric Joyner 	DEVMETHOD(ifdi_detach, ixl_if_detach),
163*1031d839SEric Joyner 	DEVMETHOD(ifdi_shutdown, ixl_if_shutdown),
164*1031d839SEric Joyner 	DEVMETHOD(ifdi_suspend, ixl_if_suspend),
165*1031d839SEric Joyner 	DEVMETHOD(ifdi_resume, ixl_if_resume),
166*1031d839SEric Joyner 	DEVMETHOD(ifdi_init, ixl_if_init),
167*1031d839SEric Joyner 	DEVMETHOD(ifdi_stop, ixl_if_stop),
168*1031d839SEric Joyner 	DEVMETHOD(ifdi_msix_intr_assign, ixl_if_msix_intr_assign),
169*1031d839SEric Joyner 	DEVMETHOD(ifdi_intr_enable, ixl_if_enable_intr),
170*1031d839SEric Joyner 	DEVMETHOD(ifdi_intr_disable, ixl_if_disable_intr),
171*1031d839SEric Joyner 	//DEVMETHOD(ifdi_link_intr_enable, ixl_if_link_intr_enable),
172*1031d839SEric Joyner 	DEVMETHOD(ifdi_rx_queue_intr_enable, ixl_if_rx_queue_intr_enable),
173*1031d839SEric Joyner 	DEVMETHOD(ifdi_tx_queue_intr_enable, ixl_if_tx_queue_intr_enable),
174*1031d839SEric Joyner 	DEVMETHOD(ifdi_tx_queues_alloc, ixl_if_tx_queues_alloc),
175*1031d839SEric Joyner 	DEVMETHOD(ifdi_rx_queues_alloc, ixl_if_rx_queues_alloc),
176*1031d839SEric Joyner 	DEVMETHOD(ifdi_queues_free, ixl_if_queues_free),
177*1031d839SEric Joyner 	DEVMETHOD(ifdi_update_admin_status, ixl_if_update_admin_status),
178*1031d839SEric Joyner 	DEVMETHOD(ifdi_multi_set, ixl_if_multi_set),
179*1031d839SEric Joyner 	DEVMETHOD(ifdi_mtu_set, ixl_if_mtu_set),
180*1031d839SEric Joyner 	DEVMETHOD(ifdi_media_status, ixl_if_media_status),
181*1031d839SEric Joyner 	DEVMETHOD(ifdi_media_change, ixl_if_media_change),
182*1031d839SEric Joyner 	DEVMETHOD(ifdi_promisc_set, ixl_if_promisc_set),
183*1031d839SEric Joyner 	DEVMETHOD(ifdi_timer, ixl_if_timer),
184*1031d839SEric Joyner 	DEVMETHOD(ifdi_vlan_register, ixl_if_vlan_register),
185*1031d839SEric Joyner 	DEVMETHOD(ifdi_vlan_unregister, ixl_if_vlan_unregister),
186*1031d839SEric Joyner 	DEVMETHOD(ifdi_get_counter, ixl_if_get_counter),
187*1031d839SEric Joyner 	DEVMETHOD(ifdi_vflr_handle, ixl_if_vflr_handle),
188*1031d839SEric Joyner 	DEVMETHOD(ifdi_i2c_req, ixl_if_i2c_req),
189*1031d839SEric Joyner 	DEVMETHOD(ifdi_priv_ioctl, ixl_if_priv_ioctl),
190*1031d839SEric Joyner 	// ifdi_led_func
191*1031d839SEric Joyner 	// ifdi_debug
192*1031d839SEric Joyner 	DEVMETHOD_END
193*1031d839SEric Joyner };
194*1031d839SEric Joyner 
195*1031d839SEric Joyner static driver_t ixl_if_driver = {
196*1031d839SEric Joyner 	"ixl_if", ixl_if_methods, sizeof(struct ixl_pf)
197*1031d839SEric Joyner };
19831830672SJack F Vogel 
19961ae650dSJack F Vogel /*
20061ae650dSJack F Vogel ** TUNEABLE PARAMETERS:
20161ae650dSJack F Vogel */
20261ae650dSJack F Vogel 
20361ae650dSJack F Vogel static SYSCTL_NODE(_hw, OID_AUTO, ixl, CTLFLAG_RD, 0,
20461ae650dSJack F Vogel                    "IXL driver parameters");
20561ae650dSJack F Vogel 
20661ae650dSJack F Vogel /*
207ceebc2f3SEric Joyner  * Leave this on unless you need to send flow control
208ceebc2f3SEric Joyner  * frames (or other control frames) from software
209ceebc2f3SEric Joyner  */
2104294f337SSean Bruno static int ixl_enable_tx_fc_filter = 1;
2114294f337SSean Bruno TUNABLE_INT("hw.ixl.enable_tx_fc_filter",
2124294f337SSean Bruno     &ixl_enable_tx_fc_filter);
2134294f337SSean Bruno SYSCTL_INT(_hw_ixl, OID_AUTO, enable_tx_fc_filter, CTLFLAG_RDTUN,
2144294f337SSean Bruno     &ixl_enable_tx_fc_filter, 0,
2154294f337SSean Bruno     "Filter out packets with Ethertype 0x8808 from being sent out by non-HW sources");
2164294f337SSean Bruno 
217*1031d839SEric Joyner static int ixl_i2c_access_method = 0;
218*1031d839SEric Joyner TUNABLE_INT("hw.ixl.i2c_access_method",
219*1031d839SEric Joyner     &ixl_i2c_access_method);
220*1031d839SEric Joyner SYSCTL_INT(_hw_ixl, OID_AUTO, i2c_access_method, CTLFLAG_RDTUN,
221*1031d839SEric Joyner     &ixl_i2c_access_method, 0,
222*1031d839SEric Joyner     IXL_SYSCTL_HELP_I2C_METHOD);
223*1031d839SEric Joyner 
224ceebc2f3SEric Joyner /*
225ceebc2f3SEric Joyner  * Different method for processing TX descriptor
226ceebc2f3SEric Joyner  * completion.
227ceebc2f3SEric Joyner  */
228ceebc2f3SEric Joyner static int ixl_enable_head_writeback = 1;
229ceebc2f3SEric Joyner TUNABLE_INT("hw.ixl.enable_head_writeback",
230ceebc2f3SEric Joyner     &ixl_enable_head_writeback);
231ceebc2f3SEric Joyner SYSCTL_INT(_hw_ixl, OID_AUTO, enable_head_writeback, CTLFLAG_RDTUN,
232ceebc2f3SEric Joyner     &ixl_enable_head_writeback, 0,
233ceebc2f3SEric Joyner     "For detecting last completed TX descriptor by hardware, use value written by HW instead of checking descriptors");
234ceebc2f3SEric Joyner 
2354294f337SSean Bruno static int ixl_core_debug_mask = 0;
2364294f337SSean Bruno TUNABLE_INT("hw.ixl.core_debug_mask",
2374294f337SSean Bruno     &ixl_core_debug_mask);
2384294f337SSean Bruno SYSCTL_INT(_hw_ixl, OID_AUTO, core_debug_mask, CTLFLAG_RDTUN,
2394294f337SSean Bruno     &ixl_core_debug_mask, 0,
2404294f337SSean Bruno     "Display debug statements that are printed in non-shared code");
2414294f337SSean Bruno 
2424294f337SSean Bruno static int ixl_shared_debug_mask = 0;
2434294f337SSean Bruno TUNABLE_INT("hw.ixl.shared_debug_mask",
2444294f337SSean Bruno     &ixl_shared_debug_mask);
2454294f337SSean Bruno SYSCTL_INT(_hw_ixl, OID_AUTO, shared_debug_mask, CTLFLAG_RDTUN,
2464294f337SSean Bruno     &ixl_shared_debug_mask, 0,
2474294f337SSean Bruno     "Display debug statements that are printed in shared code");
2484294f337SSean Bruno 
249*1031d839SEric Joyner #if 0
25061ae650dSJack F Vogel /*
25161ae650dSJack F Vogel ** Controls for Interrupt Throttling
25261ae650dSJack F Vogel **	- true/false for dynamic adjustment
25361ae650dSJack F Vogel ** 	- default values for static ITR
25461ae650dSJack F Vogel */
255*1031d839SEric Joyner static int ixl_dynamic_rx_itr = 0;
25661ae650dSJack F Vogel TUNABLE_INT("hw.ixl.dynamic_rx_itr", &ixl_dynamic_rx_itr);
25761ae650dSJack F Vogel SYSCTL_INT(_hw_ixl, OID_AUTO, dynamic_rx_itr, CTLFLAG_RDTUN,
25861ae650dSJack F Vogel     &ixl_dynamic_rx_itr, 0, "Dynamic RX Interrupt Rate");
25961ae650dSJack F Vogel 
260*1031d839SEric Joyner static int ixl_dynamic_tx_itr = 0;
26161ae650dSJack F Vogel TUNABLE_INT("hw.ixl.dynamic_tx_itr", &ixl_dynamic_tx_itr);
26261ae650dSJack F Vogel SYSCTL_INT(_hw_ixl, OID_AUTO, dynamic_tx_itr, CTLFLAG_RDTUN,
26361ae650dSJack F Vogel     &ixl_dynamic_tx_itr, 0, "Dynamic TX Interrupt Rate");
264*1031d839SEric Joyner #endif
26561ae650dSJack F Vogel 
2664294f337SSean Bruno static int ixl_rx_itr = IXL_ITR_8K;
26761ae650dSJack F Vogel TUNABLE_INT("hw.ixl.rx_itr", &ixl_rx_itr);
26861ae650dSJack F Vogel SYSCTL_INT(_hw_ixl, OID_AUTO, rx_itr, CTLFLAG_RDTUN,
26961ae650dSJack F Vogel     &ixl_rx_itr, 0, "RX Interrupt Rate");
27061ae650dSJack F Vogel 
2714294f337SSean Bruno static int ixl_tx_itr = IXL_ITR_4K;
27261ae650dSJack F Vogel TUNABLE_INT("hw.ixl.tx_itr", &ixl_tx_itr);
27361ae650dSJack F Vogel SYSCTL_INT(_hw_ixl, OID_AUTO, tx_itr, CTLFLAG_RDTUN,
27461ae650dSJack F Vogel     &ixl_tx_itr, 0, "TX Interrupt Rate");
27561ae650dSJack F Vogel 
276cb6b8299SEric Joyner #ifdef IXL_IW
277cb6b8299SEric Joyner int ixl_enable_iwarp = 0;
278cb6b8299SEric Joyner TUNABLE_INT("hw.ixl.enable_iwarp", &ixl_enable_iwarp);
279ceebc2f3SEric Joyner SYSCTL_INT(_hw_ixl, OID_AUTO, enable_iwarp, CTLFLAG_RDTUN,
280ceebc2f3SEric Joyner     &ixl_enable_iwarp, 0, "iWARP enabled");
281ceebc2f3SEric Joyner 
282ceebc2f3SEric Joyner #if __FreeBSD_version < 1100000
283ceebc2f3SEric Joyner int ixl_limit_iwarp_msix = 1;
284ceebc2f3SEric Joyner #else
285ceebc2f3SEric Joyner int ixl_limit_iwarp_msix = IXL_IW_MAX_MSIX;
286ceebc2f3SEric Joyner #endif
287ceebc2f3SEric Joyner TUNABLE_INT("hw.ixl.limit_iwarp_msix", &ixl_limit_iwarp_msix);
288ceebc2f3SEric Joyner SYSCTL_INT(_hw_ixl, OID_AUTO, limit_iwarp_msix, CTLFLAG_RDTUN,
289ceebc2f3SEric Joyner     &ixl_limit_iwarp_msix, 0, "Limit MSIX vectors assigned to iWARP");
290cb6b8299SEric Joyner #endif
291cb6b8299SEric Joyner 
292*1031d839SEric Joyner extern struct if_txrx ixl_txrx_hwb;
293*1031d839SEric Joyner extern struct if_txrx ixl_txrx_dwb;
294e5100ee2SJack F Vogel 
295*1031d839SEric Joyner static struct if_shared_ctx ixl_sctx_init = {
296*1031d839SEric Joyner 	.isc_magic = IFLIB_MAGIC,
297*1031d839SEric Joyner 	.isc_q_align = PAGE_SIZE,
298*1031d839SEric Joyner 	.isc_tx_maxsize = IXL_TSO_SIZE,
299*1031d839SEric Joyner 	.isc_tx_maxsegsize = IXL_MAX_DMA_SEG_SIZE,
300*1031d839SEric Joyner 
301*1031d839SEric Joyner 	.isc_rx_maxsize = 16384,
302*1031d839SEric Joyner 	.isc_rx_nsegments = IXL_MAX_RX_SEGS,
303*1031d839SEric Joyner 	.isc_rx_maxsegsize = IXL_MAX_DMA_SEG_SIZE,
304*1031d839SEric Joyner 	.isc_nfl = 1,
305*1031d839SEric Joyner 	.isc_ntxqs = 1,
306*1031d839SEric Joyner 	.isc_nrxqs = 1,
307*1031d839SEric Joyner 
308*1031d839SEric Joyner 	.isc_admin_intrcnt = 1,
309*1031d839SEric Joyner 	.isc_vendor_info = ixl_vendor_info_array,
310*1031d839SEric Joyner 	.isc_driver_version = IXL_DRIVER_VERSION_STRING,
311*1031d839SEric Joyner 	.isc_driver = &ixl_if_driver,
312*1031d839SEric Joyner 	.isc_flags = IFLIB_NEED_SCRATCH | IFLIB_NEED_ZERO_CSUM | IFLIB_ADMIN_ALWAYS_RUN,
313*1031d839SEric Joyner 
314*1031d839SEric Joyner 	.isc_nrxd_min = {IXL_MIN_RING},
315*1031d839SEric Joyner 	.isc_ntxd_min = {IXL_MIN_RING},
316*1031d839SEric Joyner 	.isc_nrxd_max = {IXL_MAX_RING},
317*1031d839SEric Joyner 	.isc_ntxd_max = {IXL_MAX_RING},
318*1031d839SEric Joyner 	.isc_nrxd_default = {IXL_DEFAULT_RING},
319*1031d839SEric Joyner 	.isc_ntxd_default = {IXL_DEFAULT_RING},
320*1031d839SEric Joyner };
321*1031d839SEric Joyner 
322*1031d839SEric Joyner if_shared_ctx_t ixl_sctx = &ixl_sctx_init;
323*1031d839SEric Joyner 
324*1031d839SEric Joyner /*** Functions ***/
325*1031d839SEric Joyner static void *
326*1031d839SEric Joyner ixl_register(device_t dev)
327*1031d839SEric Joyner {
328*1031d839SEric Joyner 	return (ixl_sctx);
329*1031d839SEric Joyner }
33061ae650dSJack F Vogel 
33161ae650dSJack F Vogel static int
332*1031d839SEric Joyner ixl_allocate_pci_resources(struct ixl_pf *pf)
33361ae650dSJack F Vogel {
334*1031d839SEric Joyner 	int             rid;
335*1031d839SEric Joyner 	struct i40e_hw *hw = &pf->hw;
336*1031d839SEric Joyner 	device_t dev = iflib_get_dev(pf->vsi.ctx);
33761ae650dSJack F Vogel 
338*1031d839SEric Joyner 	/* Map BAR0 */
339*1031d839SEric Joyner 	rid = PCIR_BAR(0);
340*1031d839SEric Joyner 	pf->pci_mem = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
341*1031d839SEric Joyner 	    &rid, RF_ACTIVE);
34261ae650dSJack F Vogel 
343*1031d839SEric Joyner 	if (!(pf->pci_mem)) {
344*1031d839SEric Joyner 		device_printf(dev, "Unable to allocate bus resource: PCI memory\n");
34561ae650dSJack F Vogel 		return (ENXIO);
34661ae650dSJack F Vogel 	}
34761ae650dSJack F Vogel 
348*1031d839SEric Joyner 	/* Save off the PCI information */
349*1031d839SEric Joyner 	hw->vendor_id = pci_get_vendor(dev);
350*1031d839SEric Joyner 	hw->device_id = pci_get_device(dev);
351*1031d839SEric Joyner 	hw->revision_id = pci_read_config(dev, PCIR_REVID, 1);
352*1031d839SEric Joyner 	hw->subsystem_vendor_id =
353*1031d839SEric Joyner 	    pci_read_config(dev, PCIR_SUBVEND_0, 2);
354*1031d839SEric Joyner 	hw->subsystem_device_id =
355*1031d839SEric Joyner 	    pci_read_config(dev, PCIR_SUBDEV_0, 2);
3564294f337SSean Bruno 
357*1031d839SEric Joyner 	hw->bus.device = pci_get_slot(dev);
358*1031d839SEric Joyner 	hw->bus.func = pci_get_function(dev);
3594294f337SSean Bruno 
360*1031d839SEric Joyner 	/* Save off register access information */
361*1031d839SEric Joyner 	pf->osdep.mem_bus_space_tag =
362*1031d839SEric Joyner 		rman_get_bustag(pf->pci_mem);
363*1031d839SEric Joyner 	pf->osdep.mem_bus_space_handle =
364*1031d839SEric Joyner 		rman_get_bushandle(pf->pci_mem);
365*1031d839SEric Joyner 	pf->osdep.mem_bus_space_size = rman_get_size(pf->pci_mem);
366*1031d839SEric Joyner 	pf->osdep.flush_reg = I40E_GLGEN_STAT;
367*1031d839SEric Joyner 	pf->osdep.dev = dev;
368cb6b8299SEric Joyner 
369*1031d839SEric Joyner 	pf->hw.hw_addr = (u8 *) &pf->osdep.mem_bus_space_handle;
370*1031d839SEric Joyner 	pf->hw.back = &pf->osdep;
3714294f337SSean Bruno 
3724294f337SSean Bruno  	return (0);
3734294f337SSean Bruno  }
3744294f337SSean Bruno 
37561ae650dSJack F Vogel static int
376*1031d839SEric Joyner ixl_if_attach_pre(if_ctx_t ctx)
37761ae650dSJack F Vogel {
378*1031d839SEric Joyner 	device_t dev;
37961ae650dSJack F Vogel 	struct ixl_pf *pf;
38061ae650dSJack F Vogel 	struct i40e_hw *hw;
38161ae650dSJack F Vogel 	struct ixl_vsi *vsi;
382*1031d839SEric Joyner 	if_softc_ctx_t scctx;
383*1031d839SEric Joyner 	struct i40e_filter_control_settings filter;
3844294f337SSean Bruno 	enum i40e_status_code status;
38561ae650dSJack F Vogel 	int error = 0;
38661ae650dSJack F Vogel 
387*1031d839SEric Joyner 	INIT_DEBUGOUT("ixl_if_attach_pre: begin");
38861ae650dSJack F Vogel 
38961ae650dSJack F Vogel 	/* Allocate, clear, and link in our primary soft structure */
390*1031d839SEric Joyner 	dev = iflib_get_dev(ctx);
391*1031d839SEric Joyner 	pf = iflib_get_softc(ctx);
392*1031d839SEric Joyner 	vsi = &pf->vsi;
393*1031d839SEric Joyner 	vsi->back = pf;
394*1031d839SEric Joyner 	pf->dev = dev;
39561ae650dSJack F Vogel 	hw = &pf->hw;
39661ae650dSJack F Vogel 
39761ae650dSJack F Vogel 	/*
39861ae650dSJack F Vogel 	** Note this assumes we have a single embedded VSI,
39961ae650dSJack F Vogel 	** this could be enhanced later to allocate multiple
40061ae650dSJack F Vogel 	*/
401*1031d839SEric Joyner 	//vsi->dev = pf->dev;
402*1031d839SEric Joyner 	vsi->hw = &pf->hw;
403*1031d839SEric Joyner 	vsi->id = 0;
404*1031d839SEric Joyner 	vsi->num_vlans = 0;
405*1031d839SEric Joyner 	vsi->ctx = ctx;
406*1031d839SEric Joyner 	vsi->media = iflib_get_media(ctx);
407*1031d839SEric Joyner 	vsi->shared = scctx = iflib_get_softc_ctx(ctx);
40861ae650dSJack F Vogel 
4094294f337SSean Bruno 	/* Save tunable values */
410*1031d839SEric Joyner 	ixl_save_pf_tunables(pf);
41161ae650dSJack F Vogel 
41261ae650dSJack F Vogel 	/* Do PCI setup - map BAR0, etc */
41361ae650dSJack F Vogel 	if (ixl_allocate_pci_resources(pf)) {
41461ae650dSJack F Vogel 		device_printf(dev, "Allocation of PCI resources failed\n");
41561ae650dSJack F Vogel 		error = ENXIO;
416*1031d839SEric Joyner 		goto err_pci_res;
41761ae650dSJack F Vogel 	}
41861ae650dSJack F Vogel 
41961ae650dSJack F Vogel 	/* Establish a clean starting point */
42061ae650dSJack F Vogel 	i40e_clear_hw(hw);
4214294f337SSean Bruno 	status = i40e_pf_reset(hw);
4224294f337SSean Bruno 	if (status) {
4234294f337SSean Bruno 		device_printf(dev, "PF reset failure %s\n",
4244294f337SSean Bruno 		    i40e_stat_str(hw, status));
42561ae650dSJack F Vogel 		error = EIO;
42661ae650dSJack F Vogel 		goto err_out;
42761ae650dSJack F Vogel 	}
42861ae650dSJack F Vogel 
42961ae650dSJack F Vogel 	/* Initialize the shared code */
4304294f337SSean Bruno 	status = i40e_init_shared_code(hw);
4314294f337SSean Bruno 	if (status) {
4324294f337SSean Bruno 		device_printf(dev, "Unable to initialize shared code, error %s\n",
4334294f337SSean Bruno 		    i40e_stat_str(hw, status));
43461ae650dSJack F Vogel 		error = EIO;
43561ae650dSJack F Vogel 		goto err_out;
43661ae650dSJack F Vogel 	}
43761ae650dSJack F Vogel 
43861ae650dSJack F Vogel 	/* Set up the admin queue */
4394294f337SSean Bruno 	hw->aq.num_arq_entries = IXL_AQ_LEN;
4404294f337SSean Bruno 	hw->aq.num_asq_entries = IXL_AQ_LEN;
4414294f337SSean Bruno 	hw->aq.arq_buf_size = IXL_AQ_BUF_SZ;
4424294f337SSean Bruno 	hw->aq.asq_buf_size = IXL_AQ_BUF_SZ;
4434294f337SSean Bruno 
4444294f337SSean Bruno 	status = i40e_init_adminq(hw);
4454294f337SSean Bruno 	if (status != 0 && status != I40E_ERR_FIRMWARE_API_VERSION) {
4464294f337SSean Bruno 		device_printf(dev, "Unable to initialize Admin Queue, error %s\n",
4474294f337SSean Bruno 		    i40e_stat_str(hw, status));
448fdb6f38aSEric Joyner 		error = EIO;
449fdb6f38aSEric Joyner 		goto err_out;
450fdb6f38aSEric Joyner 	}
4511d767a8eSEric Joyner 	ixl_print_nvm_version(pf);
4521d767a8eSEric Joyner 
4534294f337SSean Bruno 	if (status == I40E_ERR_FIRMWARE_API_VERSION) {
45461ae650dSJack F Vogel 		device_printf(dev, "The driver for the device stopped "
455ceebc2f3SEric Joyner 		    "because the NVM image is newer than expected.\n");
456ceebc2f3SEric Joyner 		device_printf(dev, "You must install the most recent version of "
45761ae650dSJack F Vogel 		    "the network driver.\n");
458fdb6f38aSEric Joyner 		error = EIO;
45961ae650dSJack F Vogel 		goto err_out;
46061ae650dSJack F Vogel 	}
46161ae650dSJack F Vogel 
46261ae650dSJack F Vogel         if (hw->aq.api_maj_ver == I40E_FW_API_VERSION_MAJOR &&
463ceebc2f3SEric Joyner 	    hw->aq.api_min_ver > I40E_FW_MINOR_VERSION(hw)) {
46461ae650dSJack F Vogel 		device_printf(dev, "The driver for the device detected "
465ceebc2f3SEric Joyner 		    "a newer version of the NVM image than expected.\n");
466ceebc2f3SEric Joyner 		device_printf(dev, "Please install the most recent version "
467ceebc2f3SEric Joyner 		    "of the network driver.\n");
468ceebc2f3SEric Joyner 	} else if (hw->aq.api_maj_ver == 1 && hw->aq.api_min_ver < 4) {
46961ae650dSJack F Vogel 		device_printf(dev, "The driver for the device detected "
470ceebc2f3SEric Joyner 		    "an older version of the NVM image than expected.\n");
471ceebc2f3SEric Joyner 		device_printf(dev, "Please update the NVM image.\n");
472ceebc2f3SEric Joyner 	}
47361ae650dSJack F Vogel 
47461ae650dSJack F Vogel 	/* Clear PXE mode */
47561ae650dSJack F Vogel 	i40e_clear_pxe_mode(hw);
47661ae650dSJack F Vogel 
47761ae650dSJack F Vogel 	/* Get capabilities from the device */
47861ae650dSJack F Vogel 	error = ixl_get_hw_capabilities(pf);
47961ae650dSJack F Vogel 	if (error) {
480*1031d839SEric Joyner 		device_printf(dev, "get_hw_capabilities failed: %d\n",
481*1031d839SEric Joyner 		    error);
48261ae650dSJack F Vogel 		goto err_get_cap;
48361ae650dSJack F Vogel 	}
48461ae650dSJack F Vogel 
48561ae650dSJack F Vogel 	/* Set up host memory cache */
4864294f337SSean Bruno 	status = i40e_init_lan_hmc(hw, hw->func_caps.num_tx_qp,
48756c2c47bSJack F Vogel 	    hw->func_caps.num_rx_qp, 0, 0);
4884294f337SSean Bruno 	if (status) {
4894294f337SSean Bruno 		device_printf(dev, "init_lan_hmc failed: %s\n",
4904294f337SSean Bruno 		    i40e_stat_str(hw, status));
49161ae650dSJack F Vogel 		goto err_get_cap;
49261ae650dSJack F Vogel 	}
4934294f337SSean Bruno 	status = i40e_configure_lan_hmc(hw, I40E_HMC_MODEL_DIRECT_ONLY);
4944294f337SSean Bruno 	if (status) {
4954294f337SSean Bruno 		device_printf(dev, "configure_lan_hmc failed: %s\n",
4964294f337SSean Bruno 		    i40e_stat_str(hw, status));
49761ae650dSJack F Vogel 		goto err_mac_hmc;
49861ae650dSJack F Vogel 	}
49961ae650dSJack F Vogel 
500d4683565SEric Joyner 	/* Disable LLDP from the firmware for certain NVM versions */
501d4683565SEric Joyner 	if (((pf->hw.aq.fw_maj_ver == 4) && (pf->hw.aq.fw_min_ver < 3)) ||
502ceebc2f3SEric Joyner 	    (pf->hw.aq.fw_maj_ver < 4)) {
50361ae650dSJack F Vogel 		i40e_aq_stop_lldp(hw, TRUE, NULL);
504ceebc2f3SEric Joyner 		pf->state |= IXL_PF_STATE_FW_LLDP_DISABLED;
505ceebc2f3SEric Joyner 	}
50661ae650dSJack F Vogel 
5074294f337SSean Bruno 	/* Get MAC addresses from hardware */
50861ae650dSJack F Vogel 	i40e_get_mac_addr(hw, hw->mac.addr);
50961ae650dSJack F Vogel 	error = i40e_validate_mac_addr(hw->mac.addr);
51061ae650dSJack F Vogel 	if (error) {
51161ae650dSJack F Vogel 		device_printf(dev, "validate_mac_addr failed: %d\n", error);
51261ae650dSJack F Vogel 		goto err_mac_hmc;
51361ae650dSJack F Vogel 	}
51461ae650dSJack F Vogel 	bcopy(hw->mac.addr, hw->mac.perm_addr, ETHER_ADDR_LEN);
515*1031d839SEric Joyner 	iflib_set_mac(ctx, hw->mac.addr);
51661ae650dSJack F Vogel 	i40e_get_port_mac_addr(hw, hw->mac.port_addr);
51761ae650dSJack F Vogel 
518*1031d839SEric Joyner 	/* Set up the device filtering */
519*1031d839SEric Joyner 	bzero(&filter, sizeof(filter));
520*1031d839SEric Joyner 	filter.enable_ethtype = TRUE;
521*1031d839SEric Joyner 	filter.enable_macvlan = TRUE;
522*1031d839SEric Joyner 	filter.enable_fdir = FALSE;
523*1031d839SEric Joyner 	filter.hash_lut_size = I40E_HASH_LUT_SIZE_512;
524*1031d839SEric Joyner 	if (i40e_set_filter_control(hw, &filter))
525*1031d839SEric Joyner 		device_printf(dev, "i40e_set_filter_control() failed\n");
526*1031d839SEric Joyner 
527ceebc2f3SEric Joyner 	/* Query device FW LLDP status */
528ceebc2f3SEric Joyner 	ixl_get_fw_lldp_status(pf);
529ceebc2f3SEric Joyner 	/* Tell FW to apply DCB config on link up */
530ceebc2f3SEric Joyner 	i40e_aq_set_dcb_parameters(hw, true, NULL);
531ceebc2f3SEric Joyner 
532*1031d839SEric Joyner 	/* Fill out iflib parameters */
533*1031d839SEric Joyner 	if (hw->mac.type == I40E_MAC_X722)
534*1031d839SEric Joyner 		scctx->isc_ntxqsets_max = scctx->isc_nrxqsets_max = 128;
535*1031d839SEric Joyner 	else
536*1031d839SEric Joyner 		scctx->isc_ntxqsets_max = scctx->isc_nrxqsets_max = 64;
537*1031d839SEric Joyner 	if (vsi->enable_head_writeback) {
538*1031d839SEric Joyner 		scctx->isc_txqsizes[0] = roundup2(scctx->isc_ntxd[0]
539*1031d839SEric Joyner 		    * sizeof(struct i40e_tx_desc) + sizeof(u32), DBA_ALIGN);
540*1031d839SEric Joyner 		scctx->isc_txrx = &ixl_txrx_hwb;
541*1031d839SEric Joyner 	} else {
542*1031d839SEric Joyner 		scctx->isc_txqsizes[0] = roundup2(scctx->isc_ntxd[0]
543*1031d839SEric Joyner 		    * sizeof(struct i40e_tx_desc), DBA_ALIGN);
544*1031d839SEric Joyner 		scctx->isc_txrx = &ixl_txrx_dwb;
545*1031d839SEric Joyner 	}
546*1031d839SEric Joyner 	scctx->isc_rxqsizes[0] = roundup2(scctx->isc_nrxd[0]
547*1031d839SEric Joyner 	    * sizeof(union i40e_32byte_rx_desc), DBA_ALIGN);
548*1031d839SEric Joyner 	scctx->isc_msix_bar = PCIR_BAR(IXL_MSIX_BAR);
549*1031d839SEric Joyner 	scctx->isc_tx_nsegments = IXL_MAX_TX_SEGS;
550*1031d839SEric Joyner 	scctx->isc_tx_tso_segments_max = IXL_MAX_TSO_SEGS;
551*1031d839SEric Joyner 	scctx->isc_tx_tso_size_max = IXL_TSO_SIZE;
552*1031d839SEric Joyner 	scctx->isc_tx_tso_segsize_max = IXL_MAX_DMA_SEG_SIZE;
553*1031d839SEric Joyner 	scctx->isc_rss_table_size = pf->hw.func_caps.rss_table_size;
554*1031d839SEric Joyner 	scctx->isc_tx_csum_flags = CSUM_OFFLOAD;
555*1031d839SEric Joyner 	scctx->isc_capenable = IXL_CAPS;
5564294f337SSean Bruno 
557*1031d839SEric Joyner 	INIT_DEBUGOUT("ixl_if_attach_pre: end");
558*1031d839SEric Joyner 	return (0);
559*1031d839SEric Joyner 
560*1031d839SEric Joyner err_mac_hmc:
561*1031d839SEric Joyner 	i40e_shutdown_lan_hmc(hw);
562*1031d839SEric Joyner err_get_cap:
563*1031d839SEric Joyner 	i40e_shutdown_adminq(hw);
564*1031d839SEric Joyner err_out:
565*1031d839SEric Joyner 	ixl_free_pci_resources(pf);
566*1031d839SEric Joyner err_pci_res:
567*1031d839SEric Joyner 	return (error);
56861ae650dSJack F Vogel }
56961ae650dSJack F Vogel 
570*1031d839SEric Joyner static int
571*1031d839SEric Joyner ixl_if_attach_post(if_ctx_t ctx)
572*1031d839SEric Joyner {
573*1031d839SEric Joyner 	device_t dev;
574*1031d839SEric Joyner 	struct ixl_pf *pf;
575*1031d839SEric Joyner 	struct i40e_hw *hw;
576*1031d839SEric Joyner 	struct ixl_vsi *vsi;
577*1031d839SEric Joyner 	int error = 0;
578*1031d839SEric Joyner 	enum i40e_status_code status;
579*1031d839SEric Joyner 
580*1031d839SEric Joyner 	INIT_DEBUGOUT("ixl_if_attach_post: begin");
581*1031d839SEric Joyner 
582*1031d839SEric Joyner 	dev = iflib_get_dev(ctx);
583*1031d839SEric Joyner 	pf = iflib_get_softc(ctx);
584*1031d839SEric Joyner 	vsi = &pf->vsi;
585*1031d839SEric Joyner 	vsi->ifp = iflib_get_ifp(ctx);
586*1031d839SEric Joyner 	hw = &pf->hw;
587*1031d839SEric Joyner 
5884294f337SSean Bruno 	/* Setup OS network interface / ifnet */
589*1031d839SEric Joyner 	if (ixl_setup_interface(dev, pf)) {
5904294f337SSean Bruno 		device_printf(dev, "interface setup failed!\n");
5914294f337SSean Bruno 		error = EIO;
592*1031d839SEric Joyner 		goto err;
593223d846dSEric Joyner 	}
59461ae650dSJack F Vogel 
59561ae650dSJack F Vogel 	/* Determine link state */
5964294f337SSean Bruno 	if (ixl_attach_get_link_status(pf)) {
5974294f337SSean Bruno 		error = EINVAL;
598*1031d839SEric Joyner 		goto err;
599e5100ee2SJack F Vogel 	}
60061ae650dSJack F Vogel 
601b6c8f260SJack F Vogel 	error = ixl_switch_config(pf);
602b6c8f260SJack F Vogel 	if (error) {
6036c426059SEric Joyner 		device_printf(dev, "Initial ixl_switch_config() failed: %d\n",
6046c426059SEric Joyner 		     error);
605*1031d839SEric Joyner 		goto err;
606b6c8f260SJack F Vogel 	}
607b6c8f260SJack F Vogel 
608*1031d839SEric Joyner 	/* Add protocol filters to list */
609*1031d839SEric Joyner 	ixl_init_filters(vsi);
610*1031d839SEric Joyner 
611*1031d839SEric Joyner 	/* Init queue allocation manager */
612*1031d839SEric Joyner 	error = ixl_pf_qmgr_init(&pf->qmgr, hw->func_caps.num_tx_qp);
613*1031d839SEric Joyner 	if (error) {
614*1031d839SEric Joyner 		device_printf(dev, "Failed to init queue manager for PF queues, error %d\n",
615*1031d839SEric Joyner 		    error);
616*1031d839SEric Joyner 		goto err;
617*1031d839SEric Joyner 	}
618*1031d839SEric Joyner 	/* reserve a contiguous allocation for the PF's VSI */
619*1031d839SEric Joyner 	error = ixl_pf_qmgr_alloc_contiguous(&pf->qmgr,
620*1031d839SEric Joyner 	    max(vsi->num_rx_queues, vsi->num_tx_queues), &pf->qtag);
621*1031d839SEric Joyner 	if (error) {
622*1031d839SEric Joyner 		device_printf(dev, "Failed to reserve queues for PF LAN VSI, error %d\n",
623*1031d839SEric Joyner 		    error);
624*1031d839SEric Joyner 		goto err;
625*1031d839SEric Joyner 	}
626*1031d839SEric Joyner 	device_printf(dev, "Allocating %d queues for PF LAN VSI; %d queues active\n",
627*1031d839SEric Joyner 	    pf->qtag.num_allocated, pf->qtag.num_active);
628*1031d839SEric Joyner 
629223d846dSEric Joyner 	/* Limit PHY interrupts to link, autoneg, and modules failure */
6304294f337SSean Bruno 	status = i40e_aq_set_phy_int_mask(hw, IXL_DEFAULT_PHY_INT_MASK,
631223d846dSEric Joyner 	    NULL);
6324294f337SSean Bruno         if (status) {
6334294f337SSean Bruno 		device_printf(dev, "i40e_aq_set_phy_mask() failed: err %s,"
6344294f337SSean Bruno 		    " aq_err %s\n", i40e_stat_str(hw, status),
6354294f337SSean Bruno 		    i40e_aq_str(hw, hw->aq.asq_last_status));
636*1031d839SEric Joyner 		goto err;
637223d846dSEric Joyner 	}
638b6c8f260SJack F Vogel 
639*1031d839SEric Joyner 	/* Get the bus configuration and set the shared code */
640cb6b8299SEric Joyner 	ixl_get_bus_info(pf);
64161ae650dSJack F Vogel 
642*1031d839SEric Joyner 	/* Keep admin queue interrupts active while driver is loaded */
643*1031d839SEric Joyner 	if (vsi->shared->isc_intr == IFLIB_INTR_MSIX) {
6446c426059SEric Joyner  		ixl_configure_intr0_msix(pf);
645cb6b8299SEric Joyner  		ixl_enable_intr0(hw);
646cb6b8299SEric Joyner 	}
647cb6b8299SEric Joyner 
648cb6b8299SEric Joyner 	/* Set initial advertised speed sysctl value */
649ceebc2f3SEric Joyner 	ixl_set_initial_advertised_speeds(pf);
650cb6b8299SEric Joyner 
651fdb6f38aSEric Joyner 	/* Initialize statistics & add sysctls */
652fdb6f38aSEric Joyner 	ixl_add_device_sysctls(pf);
65361ae650dSJack F Vogel 	ixl_pf_reset_stats(pf);
65461ae650dSJack F Vogel 	ixl_update_stats_counters(pf);
65561ae650dSJack F Vogel 	ixl_add_hw_stats(pf);
65661ae650dSJack F Vogel 
657*1031d839SEric Joyner 	hw->phy.get_link_info = true;
658*1031d839SEric Joyner 	i40e_get_link_status(hw, &pf->link_up);
659*1031d839SEric Joyner 	ixl_update_link_status(pf);
66061ae650dSJack F Vogel 
66156c2c47bSJack F Vogel #ifdef PCI_IOV
6624294f337SSean Bruno 	ixl_initialize_sriov(pf);
66356c2c47bSJack F Vogel #endif
66456c2c47bSJack F Vogel 
665cb6b8299SEric Joyner #ifdef IXL_IW
666cb6b8299SEric Joyner 	if (hw->func_caps.iwarp && ixl_enable_iwarp) {
667cb6b8299SEric Joyner 		pf->iw_enabled = (pf->iw_msix > 0) ? true : false;
668cb6b8299SEric Joyner 		if (pf->iw_enabled) {
669cb6b8299SEric Joyner 			error = ixl_iw_pf_attach(pf);
670cb6b8299SEric Joyner 			if (error) {
671cb6b8299SEric Joyner 				device_printf(dev,
672cb6b8299SEric Joyner 				    "interfacing to iwarp driver failed: %d\n",
673cb6b8299SEric Joyner 				    error);
674*1031d839SEric Joyner 				goto err;
675ceebc2f3SEric Joyner 			} else
676ceebc2f3SEric Joyner 				device_printf(dev, "iWARP ready\n");
677cb6b8299SEric Joyner 		} else
678cb6b8299SEric Joyner 			device_printf(dev,
679cb6b8299SEric Joyner 			    "iwarp disabled on this device (no msix vectors)\n");
680cb6b8299SEric Joyner 	} else {
681cb6b8299SEric Joyner 		pf->iw_enabled = false;
682cb6b8299SEric Joyner 		device_printf(dev, "The device is not iWARP enabled\n");
683cb6b8299SEric Joyner 	}
684cb6b8299SEric Joyner #endif
685cb6b8299SEric Joyner 
686*1031d839SEric Joyner 	INIT_DBG_DEV(dev, "end");
68761ae650dSJack F Vogel 	return (0);
68861ae650dSJack F Vogel 
689*1031d839SEric Joyner err:
690*1031d839SEric Joyner 	INIT_DEBUGOUT("end: error %d", error);
691*1031d839SEric Joyner 	/* ixl_if_detach() is called on error from this */
69261ae650dSJack F Vogel 	return (error);
69361ae650dSJack F Vogel }
69461ae650dSJack F Vogel 
69561ae650dSJack F Vogel static int
696*1031d839SEric Joyner ixl_if_detach(if_ctx_t ctx)
69761ae650dSJack F Vogel {
698*1031d839SEric Joyner 	struct ixl_pf *pf = iflib_get_softc(ctx);
69961ae650dSJack F Vogel 	struct ixl_vsi *vsi = &pf->vsi;
700*1031d839SEric Joyner 	struct i40e_hw *hw = &pf->hw;
701*1031d839SEric Joyner 	device_t dev = pf->dev;
7026c426059SEric Joyner 	enum i40e_status_code	status;
703cb6b8299SEric Joyner #if defined(PCI_IOV) || defined(IXL_IW)
70456c2c47bSJack F Vogel 	int			error;
70556c2c47bSJack F Vogel #endif
70661ae650dSJack F Vogel 
707*1031d839SEric Joyner 	INIT_DBG_DEV(dev, "begin");
708cb6b8299SEric Joyner 
709cb6b8299SEric Joyner #ifdef IXL_IW
710cb6b8299SEric Joyner 	if (ixl_enable_iwarp && pf->iw_enabled) {
711cb6b8299SEric Joyner 		error = ixl_iw_pf_detach(pf);
712cb6b8299SEric Joyner 		if (error == EBUSY) {
713cb6b8299SEric Joyner 			device_printf(dev, "iwarp in use; stop it first.\n");
714cb6b8299SEric Joyner 			return (error);
715cb6b8299SEric Joyner 		}
716cb6b8299SEric Joyner 	}
717cb6b8299SEric Joyner #endif
718*1031d839SEric Joyner #ifdef PCI_IOV
719*1031d839SEric Joyner 	error = pci_iov_detach(dev);
720*1031d839SEric Joyner 	if (error != 0) {
721*1031d839SEric Joyner 		device_printf(dev, "SR-IOV in use; detach first.\n");
722*1031d839SEric Joyner 		return (error);
723*1031d839SEric Joyner 	}
724*1031d839SEric Joyner #endif
725*1031d839SEric Joyner 	/* Remove all previously allocated media types */
726*1031d839SEric Joyner 	ifmedia_removeall(vsi->media);
727cb6b8299SEric Joyner 
728*1031d839SEric Joyner 	/* Shutdown LAN HMC */
729*1031d839SEric Joyner 	if (hw->hmc.hmc_obj) {
730*1031d839SEric Joyner 		status = i40e_shutdown_lan_hmc(hw);
731*1031d839SEric Joyner 		if (status)
732*1031d839SEric Joyner 			device_printf(dev,
733*1031d839SEric Joyner 			    "i40e_shutdown_lan_hmc() failed with status %s\n",
734*1031d839SEric Joyner 			    i40e_stat_str(hw, status));
735*1031d839SEric Joyner 	}
736*1031d839SEric Joyner 
737*1031d839SEric Joyner 	/* Shutdown admin queue */
738*1031d839SEric Joyner 	ixl_disable_intr0(hw);
739*1031d839SEric Joyner 	status = i40e_shutdown_adminq(hw);
740*1031d839SEric Joyner 	if (status)
741*1031d839SEric Joyner 		device_printf(dev,
742*1031d839SEric Joyner 		    "i40e_shutdown_adminq() failed with status %s\n",
743*1031d839SEric Joyner 		    i40e_stat_str(hw, status));
744*1031d839SEric Joyner 
7454294f337SSean Bruno 	ixl_pf_qmgr_destroy(&pf->qmgr);
74661ae650dSJack F Vogel 	ixl_free_pci_resources(pf);
747*1031d839SEric Joyner 	ixl_free_mac_filters(vsi);
748*1031d839SEric Joyner 	INIT_DBG_DEV(dev, "end");
74961ae650dSJack F Vogel 	return (0);
75061ae650dSJack F Vogel }
75161ae650dSJack F Vogel 
752*1031d839SEric Joyner /* TODO: Do shutdown-specific stuff here */
753*1031d839SEric Joyner static int
754*1031d839SEric Joyner ixl_if_shutdown(if_ctx_t ctx)
755*1031d839SEric Joyner {
756*1031d839SEric Joyner 	int error = 0;
757*1031d839SEric Joyner 
758*1031d839SEric Joyner 	INIT_DEBUGOUT("ixl_if_shutdown: begin");
759*1031d839SEric Joyner 
760*1031d839SEric Joyner 	/* TODO: Call ixl_if_stop()? */
761*1031d839SEric Joyner 
762*1031d839SEric Joyner 	/* TODO: Then setup low power mode */
763*1031d839SEric Joyner 
764*1031d839SEric Joyner 	return (error);
765*1031d839SEric Joyner }
76661ae650dSJack F Vogel 
76761ae650dSJack F Vogel static int
768*1031d839SEric Joyner ixl_if_suspend(if_ctx_t ctx)
76961ae650dSJack F Vogel {
770*1031d839SEric Joyner 	int error = 0;
771*1031d839SEric Joyner 
772*1031d839SEric Joyner 	INIT_DEBUGOUT("ixl_if_suspend: begin");
773*1031d839SEric Joyner 
774*1031d839SEric Joyner 	/* TODO: Call ixl_if_stop()? */
775*1031d839SEric Joyner 
776*1031d839SEric Joyner 	/* TODO: Then setup low power mode */
777*1031d839SEric Joyner 
778*1031d839SEric Joyner 	return (error);
779*1031d839SEric Joyner }
780*1031d839SEric Joyner 
781*1031d839SEric Joyner static int
782*1031d839SEric Joyner ixl_if_resume(if_ctx_t ctx)
783*1031d839SEric Joyner {
784*1031d839SEric Joyner 	struct ifnet *ifp = iflib_get_ifp(ctx);
785*1031d839SEric Joyner 
786*1031d839SEric Joyner 	INIT_DEBUGOUT("ixl_if_resume: begin");
787*1031d839SEric Joyner 
788*1031d839SEric Joyner 	/* Read & clear wake-up registers */
789*1031d839SEric Joyner 
790*1031d839SEric Joyner 	/* Required after D3->D0 transition */
791*1031d839SEric Joyner 	if (ifp->if_flags & IFF_UP)
792*1031d839SEric Joyner 		ixl_if_init(ctx);
793*1031d839SEric Joyner 
79461ae650dSJack F Vogel 	return (0);
79561ae650dSJack F Vogel }
79661ae650dSJack F Vogel 
797*1031d839SEric Joyner /* Set Report Status queue fields to 0 */
798*1031d839SEric Joyner static void
799*1031d839SEric Joyner ixl_init_tx_rsqs(struct ixl_vsi *vsi)
800*1031d839SEric Joyner {
801*1031d839SEric Joyner 	if_softc_ctx_t scctx = vsi->shared;
802*1031d839SEric Joyner 	struct ixl_tx_queue *tx_que;
803*1031d839SEric Joyner 	int i, j;
804*1031d839SEric Joyner 
805*1031d839SEric Joyner 	for (i = 0, tx_que = vsi->tx_queues; i < vsi->num_tx_queues; i++, tx_que++) {
806*1031d839SEric Joyner 		struct tx_ring *txr = &tx_que->txr;
807*1031d839SEric Joyner 
808*1031d839SEric Joyner 		txr->tx_rs_cidx = txr->tx_rs_pidx = txr->tx_cidx_processed = 0;
809*1031d839SEric Joyner 
810*1031d839SEric Joyner 		for (j = 0; j < scctx->isc_ntxd[0]; j++)
811*1031d839SEric Joyner 			txr->tx_rsq[j] = QIDX_INVALID;
812*1031d839SEric Joyner 	}
813*1031d839SEric Joyner }
814*1031d839SEric Joyner 
815*1031d839SEric Joyner static void
816*1031d839SEric Joyner ixl_init_tx_cidx(struct ixl_vsi *vsi)
817*1031d839SEric Joyner {
818*1031d839SEric Joyner 	struct ixl_tx_queue *tx_que;
819*1031d839SEric Joyner 	int i;
820*1031d839SEric Joyner 
821*1031d839SEric Joyner 	for (i = 0, tx_que = vsi->tx_queues; i < vsi->num_tx_queues; i++, tx_que++) {
822*1031d839SEric Joyner 		struct tx_ring *txr = &tx_que->txr;
823*1031d839SEric Joyner 
824*1031d839SEric Joyner 		txr->tx_cidx_processed = 0;
825*1031d839SEric Joyner 	}
826*1031d839SEric Joyner }
827*1031d839SEric Joyner 
828*1031d839SEric Joyner void
829*1031d839SEric Joyner ixl_if_init(if_ctx_t ctx)
830*1031d839SEric Joyner {
831*1031d839SEric Joyner 	struct ixl_pf *pf = iflib_get_softc(ctx);
832*1031d839SEric Joyner 	struct ixl_vsi *vsi = &pf->vsi;
833*1031d839SEric Joyner 	struct i40e_hw	*hw = &pf->hw;
834*1031d839SEric Joyner 	device_t 	dev = iflib_get_dev(ctx);
835*1031d839SEric Joyner 	u8		tmpaddr[ETHER_ADDR_LEN];
836*1031d839SEric Joyner 	int		ret;
837*1031d839SEric Joyner 
838*1031d839SEric Joyner 	/*
839*1031d839SEric Joyner 	 * If the aq is dead here, it probably means something outside of the driver
840*1031d839SEric Joyner 	 * did something to the adapter, like a PF reset.
841*1031d839SEric Joyner 	 * So rebuild the driver's state here if that occurs.
842*1031d839SEric Joyner 	 */
843*1031d839SEric Joyner 	if (!i40e_check_asq_alive(&pf->hw)) {
844*1031d839SEric Joyner 		device_printf(dev, "Admin Queue is down; resetting...\n");
845*1031d839SEric Joyner 		ixl_teardown_hw_structs(pf);
846*1031d839SEric Joyner 		ixl_reset(pf);
847*1031d839SEric Joyner 	}
848*1031d839SEric Joyner 
849*1031d839SEric Joyner 	/* Get the latest mac address... User might use a LAA */
850*1031d839SEric Joyner 	bcopy(IF_LLADDR(vsi->ifp), tmpaddr, ETH_ALEN);
851*1031d839SEric Joyner 	if (!cmp_etheraddr(hw->mac.addr, tmpaddr) &&
852*1031d839SEric Joyner 	    (i40e_validate_mac_addr(tmpaddr) == I40E_SUCCESS)) {
853*1031d839SEric Joyner 		ixl_del_filter(vsi, hw->mac.addr, IXL_VLAN_ANY);
854*1031d839SEric Joyner 		bcopy(tmpaddr, hw->mac.addr, ETH_ALEN);
855*1031d839SEric Joyner 		ret = i40e_aq_mac_address_write(hw,
856*1031d839SEric Joyner 		    I40E_AQC_WRITE_TYPE_LAA_ONLY,
857*1031d839SEric Joyner 		    hw->mac.addr, NULL);
858*1031d839SEric Joyner 		if (ret) {
859*1031d839SEric Joyner 			device_printf(dev, "LLA address change failed!!\n");
860*1031d839SEric Joyner 			return;
861*1031d839SEric Joyner 		}
862*1031d839SEric Joyner 		ixl_add_filter(vsi, hw->mac.addr, IXL_VLAN_ANY);
863*1031d839SEric Joyner 	}
864*1031d839SEric Joyner 
865*1031d839SEric Joyner 	iflib_set_mac(ctx, hw->mac.addr);
866*1031d839SEric Joyner 
867*1031d839SEric Joyner 	/* Prepare the VSI: rings, hmc contexts, etc... */
868*1031d839SEric Joyner 	if (ixl_initialize_vsi(vsi)) {
869*1031d839SEric Joyner 		device_printf(dev, "initialize vsi failed!!\n");
870*1031d839SEric Joyner 		return;
871*1031d839SEric Joyner 	}
872*1031d839SEric Joyner 
873*1031d839SEric Joyner 	// TODO: Call iflib setup multicast filters here?
874*1031d839SEric Joyner 	// It's called in ixgbe in D5213
875*1031d839SEric Joyner 	ixl_if_multi_set(ctx);
876*1031d839SEric Joyner 
877*1031d839SEric Joyner 	/* Set up RSS */
878*1031d839SEric Joyner 	ixl_config_rss(pf);
879*1031d839SEric Joyner 
880*1031d839SEric Joyner 	/* Set up MSI/X routing and the ITR settings */
881*1031d839SEric Joyner 	if (vsi->shared->isc_intr == IFLIB_INTR_MSIX) {
882*1031d839SEric Joyner 		ixl_configure_queue_intr_msix(pf);
883*1031d839SEric Joyner 		ixl_configure_itr(pf);
884*1031d839SEric Joyner 	} else
885*1031d839SEric Joyner 		ixl_configure_legacy(pf);
886*1031d839SEric Joyner 
887*1031d839SEric Joyner 	if (vsi->enable_head_writeback)
888*1031d839SEric Joyner 		ixl_init_tx_cidx(vsi);
889*1031d839SEric Joyner 	else
890*1031d839SEric Joyner 		ixl_init_tx_rsqs(vsi);
891*1031d839SEric Joyner 
892*1031d839SEric Joyner 	ixl_enable_rings(vsi);
893*1031d839SEric Joyner 
894*1031d839SEric Joyner 	i40e_aq_set_default_vsi(hw, vsi->seid, NULL);
895*1031d839SEric Joyner 
896*1031d839SEric Joyner 	ixl_reconfigure_filters(vsi);
897*1031d839SEric Joyner 
898*1031d839SEric Joyner #ifdef IXL_IW
899*1031d839SEric Joyner 	if (ixl_enable_iwarp && pf->iw_enabled) {
900*1031d839SEric Joyner 		ret = ixl_iw_pf_init(pf);
901*1031d839SEric Joyner 		if (ret)
902*1031d839SEric Joyner 			device_printf(dev,
903*1031d839SEric Joyner 			    "initialize iwarp failed, code %d\n", ret);
904*1031d839SEric Joyner 	}
905*1031d839SEric Joyner #endif
906*1031d839SEric Joyner }
907*1031d839SEric Joyner 
908*1031d839SEric Joyner void
909*1031d839SEric Joyner ixl_if_stop(if_ctx_t ctx)
910*1031d839SEric Joyner {
911*1031d839SEric Joyner 	struct ixl_pf *pf = iflib_get_softc(ctx);
912*1031d839SEric Joyner 	struct ixl_vsi *vsi = &pf->vsi;
913*1031d839SEric Joyner 
914*1031d839SEric Joyner 	INIT_DEBUGOUT("ixl_if_stop: begin\n");
915*1031d839SEric Joyner 
916*1031d839SEric Joyner 	// TODO: This may need to be reworked
917*1031d839SEric Joyner #ifdef IXL_IW
918*1031d839SEric Joyner 	/* Stop iWARP device */
919*1031d839SEric Joyner 	if (ixl_enable_iwarp && pf->iw_enabled)
920*1031d839SEric Joyner 		ixl_iw_pf_stop(pf);
921*1031d839SEric Joyner #endif
922*1031d839SEric Joyner 
923*1031d839SEric Joyner 	ixl_disable_rings_intr(vsi);
924*1031d839SEric Joyner 	ixl_disable_rings(vsi);
925*1031d839SEric Joyner }
926*1031d839SEric Joyner 
927*1031d839SEric Joyner static int
928*1031d839SEric Joyner ixl_if_msix_intr_assign(if_ctx_t ctx, int msix)
929*1031d839SEric Joyner {
930*1031d839SEric Joyner 	struct ixl_pf *pf = iflib_get_softc(ctx);
931*1031d839SEric Joyner 	struct ixl_vsi *vsi = &pf->vsi;
932*1031d839SEric Joyner 	struct ixl_rx_queue *rx_que = vsi->rx_queues;
933*1031d839SEric Joyner 	struct ixl_tx_queue *tx_que = vsi->tx_queues;
934*1031d839SEric Joyner 	int err, i, rid, vector = 0;
935*1031d839SEric Joyner 	char buf[16];
936*1031d839SEric Joyner 
937*1031d839SEric Joyner 	/* Admin Que must use vector 0*/
938*1031d839SEric Joyner 	rid = vector + 1;
939*1031d839SEric Joyner 	err = iflib_irq_alloc_generic(ctx, &vsi->irq, rid, IFLIB_INTR_ADMIN,
940*1031d839SEric Joyner 	    ixl_msix_adminq, pf, 0, "aq");
941*1031d839SEric Joyner 	if (err) {
942*1031d839SEric Joyner 		iflib_irq_free(ctx, &vsi->irq);
943*1031d839SEric Joyner 		device_printf(iflib_get_dev(ctx),
944*1031d839SEric Joyner 		    "Failed to register Admin que handler");
945*1031d839SEric Joyner 		return (err);
946*1031d839SEric Joyner 	}
947*1031d839SEric Joyner 	// TODO: Re-enable this at some point
948*1031d839SEric Joyner 	// iflib_softirq_alloc_generic(ctx, rid, IFLIB_INTR_IOV, pf, 0, "ixl_iov");
949*1031d839SEric Joyner 
950*1031d839SEric Joyner 	/* Now set up the stations */
951*1031d839SEric Joyner 	for (i = 0, vector = 1; i < vsi->num_rx_queues; i++, vector++, rx_que++) {
952*1031d839SEric Joyner 		rid = vector + 1;
953*1031d839SEric Joyner 
954*1031d839SEric Joyner 		snprintf(buf, sizeof(buf), "rxq%d", i);
955*1031d839SEric Joyner 		err = iflib_irq_alloc_generic(ctx, &rx_que->que_irq, rid,
956*1031d839SEric Joyner 		    IFLIB_INTR_RX, ixl_msix_que, rx_que, rx_que->rxr.me, buf);
957*1031d839SEric Joyner 		/* XXX: Does the driver work as expected if there are fewer num_rx_queues than
958*1031d839SEric Joyner 		 * what's expected in the iflib context? */
959*1031d839SEric Joyner 		if (err) {
960*1031d839SEric Joyner 			device_printf(iflib_get_dev(ctx),
961*1031d839SEric Joyner 			    "Failed to allocate q int %d err: %d", i, err);
962*1031d839SEric Joyner 			vsi->num_rx_queues = i + 1;
963*1031d839SEric Joyner 			goto fail;
964*1031d839SEric Joyner 		}
965*1031d839SEric Joyner 		rx_que->msix = vector;
966*1031d839SEric Joyner 	}
967*1031d839SEric Joyner 
968*1031d839SEric Joyner 	bzero(buf, sizeof(buf));
969*1031d839SEric Joyner 
970*1031d839SEric Joyner 	for (i = 0; i < vsi->num_tx_queues; i++, tx_que++) {
971*1031d839SEric Joyner 		snprintf(buf, sizeof(buf), "txq%d", i);
972*1031d839SEric Joyner 		iflib_softirq_alloc_generic(ctx,
973*1031d839SEric Joyner 		    &vsi->rx_queues[i % vsi->num_rx_queues].que_irq,
974*1031d839SEric Joyner 		    IFLIB_INTR_TX, tx_que, tx_que->txr.me, buf);
975*1031d839SEric Joyner 
976*1031d839SEric Joyner 		/* TODO: Maybe call a strategy function for this to figure out which
977*1031d839SEric Joyner 		* interrupts to map Tx queues to. I don't know if there's an immediately
978*1031d839SEric Joyner 		* better way than this other than a user-supplied map, though. */
979*1031d839SEric Joyner 		tx_que->msix = (i % vsi->num_rx_queues) + 1;
980*1031d839SEric Joyner 	}
981*1031d839SEric Joyner 
982*1031d839SEric Joyner 	return (0);
983*1031d839SEric Joyner fail:
984*1031d839SEric Joyner 	iflib_irq_free(ctx, &vsi->irq);
985*1031d839SEric Joyner 	rx_que = vsi->rx_queues;
986*1031d839SEric Joyner 	for (int i = 0; i < vsi->num_rx_queues; i++, rx_que++)
987*1031d839SEric Joyner 		iflib_irq_free(ctx, &rx_que->que_irq);
988*1031d839SEric Joyner 	return (err);
989*1031d839SEric Joyner }
990*1031d839SEric Joyner 
991*1031d839SEric Joyner /*
992*1031d839SEric Joyner  * Enable all interrupts
993*1031d839SEric Joyner  *
994*1031d839SEric Joyner  * Called in:
995*1031d839SEric Joyner  * iflib_init_locked, after ixl_if_init()
996*1031d839SEric Joyner  */
997*1031d839SEric Joyner static void
998*1031d839SEric Joyner ixl_if_enable_intr(if_ctx_t ctx)
999*1031d839SEric Joyner {
1000*1031d839SEric Joyner 	struct ixl_pf *pf = iflib_get_softc(ctx);
1001*1031d839SEric Joyner 	struct ixl_vsi *vsi = &pf->vsi;
1002*1031d839SEric Joyner 	struct i40e_hw		*hw = vsi->hw;
1003*1031d839SEric Joyner 	struct ixl_rx_queue	*que = vsi->rx_queues;
1004*1031d839SEric Joyner 
1005*1031d839SEric Joyner 	ixl_enable_intr0(hw);
1006*1031d839SEric Joyner 	/* Enable queue interrupts */
1007*1031d839SEric Joyner 	for (int i = 0; i < vsi->num_rx_queues; i++, que++)
1008*1031d839SEric Joyner 		/* TODO: Queue index parameter is probably wrong */
1009*1031d839SEric Joyner 		ixl_enable_queue(hw, que->rxr.me);
1010*1031d839SEric Joyner }
1011*1031d839SEric Joyner 
1012*1031d839SEric Joyner /*
1013*1031d839SEric Joyner  * Disable queue interrupts
1014*1031d839SEric Joyner  *
1015*1031d839SEric Joyner  * Other interrupt causes need to remain active.
1016*1031d839SEric Joyner  */
1017*1031d839SEric Joyner static void
1018*1031d839SEric Joyner ixl_if_disable_intr(if_ctx_t ctx)
1019*1031d839SEric Joyner {
1020*1031d839SEric Joyner 	struct ixl_pf *pf = iflib_get_softc(ctx);
1021*1031d839SEric Joyner 	struct ixl_vsi *vsi = &pf->vsi;
1022*1031d839SEric Joyner 	struct i40e_hw		*hw = vsi->hw;
1023*1031d839SEric Joyner 	struct ixl_rx_queue	*rx_que = vsi->rx_queues;
1024*1031d839SEric Joyner 
1025*1031d839SEric Joyner 	if (vsi->shared->isc_intr == IFLIB_INTR_MSIX) {
1026*1031d839SEric Joyner 		for (int i = 0; i < vsi->num_rx_queues; i++, rx_que++)
1027*1031d839SEric Joyner 			ixl_disable_queue(hw, rx_que->msix - 1);
1028*1031d839SEric Joyner 	} else {
1029*1031d839SEric Joyner 		// Set PFINT_LNKLST0 FIRSTQ_INDX to 0x7FF
1030*1031d839SEric Joyner 		// stops queues from triggering interrupts
1031*1031d839SEric Joyner 		wr32(hw, I40E_PFINT_LNKLST0, 0x7FF);
1032*1031d839SEric Joyner 	}
1033*1031d839SEric Joyner }
1034*1031d839SEric Joyner 
1035*1031d839SEric Joyner static int
1036*1031d839SEric Joyner ixl_if_rx_queue_intr_enable(if_ctx_t ctx, uint16_t rxqid)
1037*1031d839SEric Joyner {
1038*1031d839SEric Joyner 	struct ixl_pf *pf = iflib_get_softc(ctx);
1039*1031d839SEric Joyner 	struct ixl_vsi *vsi = &pf->vsi;
1040*1031d839SEric Joyner 	struct i40e_hw		*hw = vsi->hw;
1041*1031d839SEric Joyner 	struct ixl_rx_queue	*rx_que = &vsi->rx_queues[rxqid];
1042*1031d839SEric Joyner 
1043*1031d839SEric Joyner 	ixl_enable_queue(hw, rx_que->msix - 1);
1044*1031d839SEric Joyner 	return (0);
1045*1031d839SEric Joyner }
1046*1031d839SEric Joyner 
1047*1031d839SEric Joyner static int
1048*1031d839SEric Joyner ixl_if_tx_queue_intr_enable(if_ctx_t ctx, uint16_t txqid)
1049*1031d839SEric Joyner {
1050*1031d839SEric Joyner 	struct ixl_pf *pf = iflib_get_softc(ctx);
1051*1031d839SEric Joyner 	struct ixl_vsi *vsi = &pf->vsi;
1052*1031d839SEric Joyner 	struct i40e_hw		*hw = vsi->hw;
1053*1031d839SEric Joyner 	struct ixl_tx_queue	*tx_que = &vsi->tx_queues[txqid];
1054*1031d839SEric Joyner 
1055*1031d839SEric Joyner 	ixl_enable_queue(hw, tx_que->msix - 1);
1056*1031d839SEric Joyner 
1057*1031d839SEric Joyner 	return (0);
1058*1031d839SEric Joyner }
1059*1031d839SEric Joyner 
1060*1031d839SEric Joyner static int
1061*1031d839SEric Joyner ixl_if_tx_queues_alloc(if_ctx_t ctx, caddr_t *vaddrs, uint64_t *paddrs, int ntxqs, int ntxqsets)
1062*1031d839SEric Joyner {
1063*1031d839SEric Joyner 	struct ixl_pf *pf = iflib_get_softc(ctx);
1064*1031d839SEric Joyner 	struct ixl_vsi *vsi = &pf->vsi;
1065*1031d839SEric Joyner 	if_softc_ctx_t scctx = vsi->shared;
1066*1031d839SEric Joyner 	struct ixl_tx_queue *que;
1067*1031d839SEric Joyner 	// int i;
1068*1031d839SEric Joyner 	int i, j, error = 0;
1069*1031d839SEric Joyner 
1070*1031d839SEric Joyner 	MPASS(vsi->num_tx_queues > 0);
1071*1031d839SEric Joyner 	MPASS(ntxqs == 1);
1072*1031d839SEric Joyner 	MPASS(vsi->num_tx_queues == ntxqsets);
1073*1031d839SEric Joyner 
1074*1031d839SEric Joyner 	/* Allocate queue structure memory */
1075*1031d839SEric Joyner 	if (!(vsi->tx_queues =
1076*1031d839SEric Joyner 	    (struct ixl_tx_queue *) malloc(sizeof(struct ixl_tx_queue) *ntxqsets, M_IXL, M_NOWAIT | M_ZERO))) {
1077*1031d839SEric Joyner 		device_printf(iflib_get_dev(ctx), "Unable to allocate TX ring memory\n");
1078*1031d839SEric Joyner 		return (ENOMEM);
1079*1031d839SEric Joyner 	}
1080*1031d839SEric Joyner 
1081*1031d839SEric Joyner 	for (i = 0, que = vsi->tx_queues; i < ntxqsets; i++, que++) {
1082*1031d839SEric Joyner 		struct tx_ring *txr = &que->txr;
1083*1031d839SEric Joyner 
1084*1031d839SEric Joyner 		txr->me = i;
1085*1031d839SEric Joyner 		que->vsi = vsi;
1086*1031d839SEric Joyner 
1087*1031d839SEric Joyner 		if (!vsi->enable_head_writeback) {
1088*1031d839SEric Joyner 			/* Allocate report status array */
1089*1031d839SEric Joyner 			if (!(txr->tx_rsq = malloc(sizeof(qidx_t) * scctx->isc_ntxd[0], M_IXL, M_NOWAIT))) {
1090*1031d839SEric Joyner 				device_printf(iflib_get_dev(ctx), "failed to allocate tx_rsq memory\n");
1091*1031d839SEric Joyner 				error = ENOMEM;
1092*1031d839SEric Joyner 				goto fail;
1093*1031d839SEric Joyner 			}
1094*1031d839SEric Joyner 			/* Init report status array */
1095*1031d839SEric Joyner 			for (j = 0; j < scctx->isc_ntxd[0]; j++)
1096*1031d839SEric Joyner 				txr->tx_rsq[j] = QIDX_INVALID;
1097*1031d839SEric Joyner 		}
1098*1031d839SEric Joyner 		/* get the virtual and physical address of the hardware queues */
1099*1031d839SEric Joyner 		txr->tail = I40E_QTX_TAIL(txr->me);
1100*1031d839SEric Joyner 		txr->tx_base = (struct i40e_tx_desc *)vaddrs[i * ntxqs];
1101*1031d839SEric Joyner 		txr->tx_paddr = paddrs[i * ntxqs];
1102*1031d839SEric Joyner 		txr->que = que;
1103*1031d839SEric Joyner 	}
1104*1031d839SEric Joyner 
1105*1031d839SEric Joyner 	return (0);
1106*1031d839SEric Joyner fail:
1107*1031d839SEric Joyner 	ixl_if_queues_free(ctx);
1108*1031d839SEric Joyner 	return (error);
1109*1031d839SEric Joyner }
1110*1031d839SEric Joyner 
1111*1031d839SEric Joyner static int
1112*1031d839SEric Joyner ixl_if_rx_queues_alloc(if_ctx_t ctx, caddr_t *vaddrs, uint64_t *paddrs, int nrxqs, int nrxqsets)
1113*1031d839SEric Joyner {
1114*1031d839SEric Joyner 	struct ixl_pf *pf = iflib_get_softc(ctx);
1115*1031d839SEric Joyner 	struct ixl_vsi *vsi = &pf->vsi;
1116*1031d839SEric Joyner 	struct ixl_rx_queue *que;
1117*1031d839SEric Joyner 	int i, error = 0;
1118*1031d839SEric Joyner 
1119*1031d839SEric Joyner 	MPASS(vsi->num_rx_queues > 0);
1120*1031d839SEric Joyner 	MPASS(nrxqs == 1);
1121*1031d839SEric Joyner 	MPASS(vsi->num_rx_queues == nrxqsets);
1122*1031d839SEric Joyner 
1123*1031d839SEric Joyner 	/* Allocate queue structure memory */
1124*1031d839SEric Joyner 	if (!(vsi->rx_queues =
1125*1031d839SEric Joyner 	    (struct ixl_rx_queue *) malloc(sizeof(struct ixl_rx_queue) *
1126*1031d839SEric Joyner 	    nrxqsets, M_IXL, M_NOWAIT | M_ZERO))) {
1127*1031d839SEric Joyner 		device_printf(iflib_get_dev(ctx), "Unable to allocate RX ring memory\n");
1128*1031d839SEric Joyner 		error = ENOMEM;
1129*1031d839SEric Joyner 		goto fail;
1130*1031d839SEric Joyner 	}
1131*1031d839SEric Joyner 
1132*1031d839SEric Joyner 	for (i = 0, que = vsi->rx_queues; i < nrxqsets; i++, que++) {
1133*1031d839SEric Joyner 		struct rx_ring *rxr = &que->rxr;
1134*1031d839SEric Joyner 
1135*1031d839SEric Joyner 		rxr->me = i;
1136*1031d839SEric Joyner 		que->vsi = vsi;
1137*1031d839SEric Joyner 
1138*1031d839SEric Joyner 		/* get the virtual and physical address of the hardware queues */
1139*1031d839SEric Joyner 		rxr->tail = I40E_QRX_TAIL(rxr->me);
1140*1031d839SEric Joyner 		rxr->rx_base = (union i40e_rx_desc *)vaddrs[i * nrxqs];
1141*1031d839SEric Joyner 		rxr->rx_paddr = paddrs[i * nrxqs];
1142*1031d839SEric Joyner 		rxr->que = que;
1143*1031d839SEric Joyner 	}
1144*1031d839SEric Joyner 
1145*1031d839SEric Joyner 	return (0);
1146*1031d839SEric Joyner fail:
1147*1031d839SEric Joyner 	ixl_if_queues_free(ctx);
1148*1031d839SEric Joyner 	return (error);
1149*1031d839SEric Joyner }
1150*1031d839SEric Joyner 
1151*1031d839SEric Joyner static void
1152*1031d839SEric Joyner ixl_if_queues_free(if_ctx_t ctx)
1153*1031d839SEric Joyner {
1154*1031d839SEric Joyner 	struct ixl_pf *pf = iflib_get_softc(ctx);
1155*1031d839SEric Joyner 	struct ixl_vsi *vsi = &pf->vsi;
1156*1031d839SEric Joyner 
1157*1031d839SEric Joyner 	if (vsi->enable_head_writeback) {
1158*1031d839SEric Joyner 		struct ixl_tx_queue *que;
1159*1031d839SEric Joyner 		int i = 0;
1160*1031d839SEric Joyner 
1161*1031d839SEric Joyner 		for (i = 0, que = vsi->tx_queues; i < vsi->num_tx_queues; i++, que++) {
1162*1031d839SEric Joyner 			struct tx_ring *txr = &que->txr;
1163*1031d839SEric Joyner 			if (txr->tx_rsq != NULL) {
1164*1031d839SEric Joyner 				free(txr->tx_rsq, M_IXL);
1165*1031d839SEric Joyner 				txr->tx_rsq = NULL;
1166*1031d839SEric Joyner 			}
1167*1031d839SEric Joyner 		}
1168*1031d839SEric Joyner 	}
1169*1031d839SEric Joyner 
1170*1031d839SEric Joyner 	if (vsi->tx_queues != NULL) {
1171*1031d839SEric Joyner 		free(vsi->tx_queues, M_IXL);
1172*1031d839SEric Joyner 		vsi->tx_queues = NULL;
1173*1031d839SEric Joyner 	}
1174*1031d839SEric Joyner 	if (vsi->rx_queues != NULL) {
1175*1031d839SEric Joyner 		free(vsi->rx_queues, M_IXL);
1176*1031d839SEric Joyner 		vsi->rx_queues = NULL;
1177*1031d839SEric Joyner 	}
1178*1031d839SEric Joyner }
1179*1031d839SEric Joyner 
1180*1031d839SEric Joyner void
1181*1031d839SEric Joyner ixl_update_link_status(struct ixl_pf *pf)
1182*1031d839SEric Joyner {
1183*1031d839SEric Joyner 	struct ixl_vsi *vsi = &pf->vsi;
1184*1031d839SEric Joyner 	u64 baudrate;
1185*1031d839SEric Joyner 
1186*1031d839SEric Joyner 	if (pf->link_up) {
1187*1031d839SEric Joyner 		if (vsi->link_active == FALSE) {
1188*1031d839SEric Joyner 			vsi->link_active = TRUE;
1189*1031d839SEric Joyner 			baudrate = ixl_max_aq_speed_to_value(pf->link_speed);
1190*1031d839SEric Joyner 			iflib_link_state_change(vsi->ctx, LINK_STATE_UP, baudrate);
1191*1031d839SEric Joyner 			ixl_link_up_msg(pf);
1192*1031d839SEric Joyner #ifdef PCI_IOV
1193*1031d839SEric Joyner 			ixl_broadcast_link_state(pf);
1194*1031d839SEric Joyner #endif
1195*1031d839SEric Joyner 
1196*1031d839SEric Joyner 		}
1197*1031d839SEric Joyner 	} else { /* Link down */
1198*1031d839SEric Joyner 		if (vsi->link_active == TRUE) {
1199*1031d839SEric Joyner 			vsi->link_active = FALSE;
1200*1031d839SEric Joyner 			iflib_link_state_change(vsi->ctx, LINK_STATE_DOWN, 0);
1201*1031d839SEric Joyner #ifdef PCI_IOV
1202*1031d839SEric Joyner 			ixl_broadcast_link_state(pf);
1203*1031d839SEric Joyner #endif
1204*1031d839SEric Joyner 		}
1205*1031d839SEric Joyner 	}
1206*1031d839SEric Joyner }
1207*1031d839SEric Joyner 
1208*1031d839SEric Joyner static int
1209*1031d839SEric Joyner ixl_process_adminq(struct ixl_pf *pf, u16 *pending)
1210*1031d839SEric Joyner {
1211*1031d839SEric Joyner 	enum i40e_status_code status = I40E_SUCCESS;
1212*1031d839SEric Joyner 	struct i40e_arq_event_info event;
1213*1031d839SEric Joyner 	struct i40e_hw *hw = &pf->hw;
1214*1031d839SEric Joyner 	device_t dev = pf->dev;
1215*1031d839SEric Joyner 	u16 opcode;
1216*1031d839SEric Joyner 	u32 loop = 0, reg;
1217*1031d839SEric Joyner 
1218*1031d839SEric Joyner 	event.buf_len = IXL_AQ_BUF_SZ;
1219*1031d839SEric Joyner 	event.msg_buf = malloc(event.buf_len, M_IXL, M_NOWAIT | M_ZERO);
1220*1031d839SEric Joyner 	if (!event.msg_buf) {
1221*1031d839SEric Joyner 		device_printf(dev, "%s: Unable to allocate memory for Admin"
1222*1031d839SEric Joyner 		    " Queue event!\n", __func__);
1223*1031d839SEric Joyner 		return (ENOMEM);
1224*1031d839SEric Joyner 	}
1225*1031d839SEric Joyner 
1226*1031d839SEric Joyner 	/* clean and process any events */
1227*1031d839SEric Joyner 	do {
1228*1031d839SEric Joyner 		status = i40e_clean_arq_element(hw, &event, pending);
1229*1031d839SEric Joyner 		if (status)
1230*1031d839SEric Joyner 			break;
1231*1031d839SEric Joyner 		opcode = LE16_TO_CPU(event.desc.opcode);
1232*1031d839SEric Joyner 		ixl_dbg(pf, IXL_DBG_AQ,
1233*1031d839SEric Joyner 		    "Admin Queue event: %#06x\n", opcode);
1234*1031d839SEric Joyner 		switch (opcode) {
1235*1031d839SEric Joyner 		case i40e_aqc_opc_get_link_status:
1236*1031d839SEric Joyner 			ixl_link_event(pf, &event);
1237*1031d839SEric Joyner 			break;
1238*1031d839SEric Joyner 		case i40e_aqc_opc_send_msg_to_pf:
1239*1031d839SEric Joyner #ifdef PCI_IOV
1240*1031d839SEric Joyner 			ixl_handle_vf_msg(pf, &event);
1241*1031d839SEric Joyner #endif
1242*1031d839SEric Joyner 			break;
1243*1031d839SEric Joyner 		/*
1244*1031d839SEric Joyner 		 * This should only occur on no-drop queues, which
1245*1031d839SEric Joyner 		 * aren't currently configured.
1246*1031d839SEric Joyner 		 */
1247*1031d839SEric Joyner 		case i40e_aqc_opc_event_lan_overflow:
1248*1031d839SEric Joyner 			device_printf(dev, "LAN overflow event\n");
1249*1031d839SEric Joyner 			break;
1250*1031d839SEric Joyner 		default:
1251*1031d839SEric Joyner 			break;
1252*1031d839SEric Joyner 		}
1253*1031d839SEric Joyner 	} while (*pending && (loop++ < IXL_ADM_LIMIT));
1254*1031d839SEric Joyner 
1255*1031d839SEric Joyner 	free(event.msg_buf, M_IXL);
1256*1031d839SEric Joyner 
1257*1031d839SEric Joyner 	/* Re-enable admin queue interrupt cause */
1258*1031d839SEric Joyner 	reg = rd32(hw, I40E_PFINT_ICR0_ENA);
1259*1031d839SEric Joyner 	reg |= I40E_PFINT_ICR0_ENA_ADMINQ_MASK;
1260*1031d839SEric Joyner 	wr32(hw, I40E_PFINT_ICR0_ENA, reg);
1261*1031d839SEric Joyner 
1262*1031d839SEric Joyner 	return (status);
1263*1031d839SEric Joyner }
1264*1031d839SEric Joyner 
1265*1031d839SEric Joyner static void
1266*1031d839SEric Joyner ixl_if_update_admin_status(if_ctx_t ctx)
1267*1031d839SEric Joyner {
1268*1031d839SEric Joyner 	struct ixl_pf			*pf = iflib_get_softc(ctx);
1269*1031d839SEric Joyner 	struct i40e_hw			*hw = &pf->hw;
1270*1031d839SEric Joyner 	u16				pending;
1271*1031d839SEric Joyner 
1272*1031d839SEric Joyner 	if (pf->state & IXL_PF_STATE_ADAPTER_RESETTING)
1273*1031d839SEric Joyner 		ixl_handle_empr_reset(pf);
1274*1031d839SEric Joyner 
1275*1031d839SEric Joyner 	if (pf->state & IXL_PF_STATE_MDD_PENDING)
1276*1031d839SEric Joyner 		ixl_handle_mdd_event(pf);
1277*1031d839SEric Joyner 
1278*1031d839SEric Joyner #ifdef PCI_IOV
1279*1031d839SEric Joyner 	if (pf->state & IXL_PF_STATE_VF_RESET_REQ)
1280*1031d839SEric Joyner 		iflib_iov_intr_deferred(ctx);
1281*1031d839SEric Joyner #endif
1282*1031d839SEric Joyner 
1283*1031d839SEric Joyner 	ixl_process_adminq(pf, &pending);
1284*1031d839SEric Joyner 	ixl_update_link_status(pf);
1285*1031d839SEric Joyner 
1286*1031d839SEric Joyner 	/*
1287*1031d839SEric Joyner 	 * If there are still messages to process, reschedule ourselves.
1288*1031d839SEric Joyner 	 * Otherwise, re-enable our interrupt and go to sleep.
1289*1031d839SEric Joyner 	 */
1290*1031d839SEric Joyner 	if (pending > 0)
1291*1031d839SEric Joyner 		iflib_admin_intr_deferred(ctx);
1292*1031d839SEric Joyner 	else
1293*1031d839SEric Joyner 		ixl_enable_intr0(hw);
1294*1031d839SEric Joyner }
1295*1031d839SEric Joyner 
1296*1031d839SEric Joyner static void
1297*1031d839SEric Joyner ixl_if_multi_set(if_ctx_t ctx)
1298*1031d839SEric Joyner {
1299*1031d839SEric Joyner 	struct ixl_pf *pf = iflib_get_softc(ctx);
1300*1031d839SEric Joyner 	struct ixl_vsi *vsi = &pf->vsi;
1301*1031d839SEric Joyner 	struct i40e_hw		*hw = vsi->hw;
1302*1031d839SEric Joyner 	int			mcnt = 0, flags;
1303*1031d839SEric Joyner 
1304*1031d839SEric Joyner 	IOCTL_DEBUGOUT("ixl_if_multi_set: begin");
1305*1031d839SEric Joyner 
1306*1031d839SEric Joyner 	mcnt = if_multiaddr_count(iflib_get_ifp(ctx), MAX_MULTICAST_ADDR);
1307*1031d839SEric Joyner 	/* delete existing MC filters */
1308*1031d839SEric Joyner 	ixl_del_multi(vsi);
1309*1031d839SEric Joyner 
1310*1031d839SEric Joyner 	if (__predict_false(mcnt == MAX_MULTICAST_ADDR)) {
1311*1031d839SEric Joyner 		i40e_aq_set_vsi_multicast_promiscuous(hw,
1312*1031d839SEric Joyner 		    vsi->seid, TRUE, NULL);
1313*1031d839SEric Joyner 		return;
1314*1031d839SEric Joyner 	}
1315*1031d839SEric Joyner 	/* (re-)install filters for all mcast addresses */
1316*1031d839SEric Joyner 	mcnt = if_multi_apply(iflib_get_ifp(ctx), ixl_mc_filter_apply, vsi);
1317*1031d839SEric Joyner 
1318*1031d839SEric Joyner 	if (mcnt > 0) {
1319*1031d839SEric Joyner 		flags = (IXL_FILTER_ADD | IXL_FILTER_USED | IXL_FILTER_MC);
1320*1031d839SEric Joyner 		ixl_add_hw_filters(vsi, flags, mcnt);
1321*1031d839SEric Joyner 	}
1322*1031d839SEric Joyner 
1323*1031d839SEric Joyner 	IOCTL_DEBUGOUT("ixl_if_multi_set: end");
1324*1031d839SEric Joyner }
1325*1031d839SEric Joyner 
1326*1031d839SEric Joyner static int
1327*1031d839SEric Joyner ixl_if_mtu_set(if_ctx_t ctx, uint32_t mtu)
1328*1031d839SEric Joyner {
1329*1031d839SEric Joyner 	struct ixl_pf *pf = iflib_get_softc(ctx);
1330*1031d839SEric Joyner 	struct ixl_vsi *vsi = &pf->vsi;
1331*1031d839SEric Joyner 
1332*1031d839SEric Joyner 	IOCTL_DEBUGOUT("ioctl: SIOCSIFMTU (Set Interface MTU)");
1333*1031d839SEric Joyner 	if (mtu > IXL_MAX_FRAME - ETHER_HDR_LEN - ETHER_CRC_LEN -
1334*1031d839SEric Joyner 		ETHER_VLAN_ENCAP_LEN)
1335*1031d839SEric Joyner 		return (EINVAL);
1336*1031d839SEric Joyner 
1337*1031d839SEric Joyner 	vsi->shared->isc_max_frame_size = mtu + ETHER_HDR_LEN + ETHER_CRC_LEN +
1338*1031d839SEric Joyner 		ETHER_VLAN_ENCAP_LEN;
1339*1031d839SEric Joyner 
1340*1031d839SEric Joyner 	return (0);
1341*1031d839SEric Joyner }
1342*1031d839SEric Joyner 
1343*1031d839SEric Joyner static void
1344*1031d839SEric Joyner ixl_if_media_status(if_ctx_t ctx, struct ifmediareq *ifmr)
1345*1031d839SEric Joyner {
1346*1031d839SEric Joyner 	struct ixl_pf *pf = iflib_get_softc(ctx);
1347*1031d839SEric Joyner 	struct i40e_hw  *hw = &pf->hw;
1348*1031d839SEric Joyner 
1349*1031d839SEric Joyner 	INIT_DEBUGOUT("ixl_media_status: begin");
1350*1031d839SEric Joyner 
1351*1031d839SEric Joyner 	ifmr->ifm_status = IFM_AVALID;
1352*1031d839SEric Joyner 	ifmr->ifm_active = IFM_ETHER;
1353*1031d839SEric Joyner 
1354*1031d839SEric Joyner 	if (!pf->link_up) {
1355*1031d839SEric Joyner 		return;
1356*1031d839SEric Joyner 	}
1357*1031d839SEric Joyner 
1358*1031d839SEric Joyner 	ifmr->ifm_status |= IFM_ACTIVE;
1359*1031d839SEric Joyner 	/* Hardware is always full-duplex */
1360*1031d839SEric Joyner 	ifmr->ifm_active |= IFM_FDX;
1361*1031d839SEric Joyner 
1362*1031d839SEric Joyner 	switch (hw->phy.link_info.phy_type) {
1363*1031d839SEric Joyner 		/* 100 M */
1364*1031d839SEric Joyner 		case I40E_PHY_TYPE_100BASE_TX:
1365*1031d839SEric Joyner 			ifmr->ifm_active |= IFM_100_TX;
1366*1031d839SEric Joyner 			break;
1367*1031d839SEric Joyner 		/* 1 G */
1368*1031d839SEric Joyner 		case I40E_PHY_TYPE_1000BASE_T:
1369*1031d839SEric Joyner 			ifmr->ifm_active |= IFM_1000_T;
1370*1031d839SEric Joyner 			break;
1371*1031d839SEric Joyner 		case I40E_PHY_TYPE_1000BASE_SX:
1372*1031d839SEric Joyner 			ifmr->ifm_active |= IFM_1000_SX;
1373*1031d839SEric Joyner 			break;
1374*1031d839SEric Joyner 		case I40E_PHY_TYPE_1000BASE_LX:
1375*1031d839SEric Joyner 			ifmr->ifm_active |= IFM_1000_LX;
1376*1031d839SEric Joyner 			break;
1377*1031d839SEric Joyner 		case I40E_PHY_TYPE_1000BASE_T_OPTICAL:
1378*1031d839SEric Joyner 			ifmr->ifm_active |= IFM_1000_T;
1379*1031d839SEric Joyner 			break;
1380*1031d839SEric Joyner 		/* 10 G */
1381*1031d839SEric Joyner 		case I40E_PHY_TYPE_10GBASE_SFPP_CU:
1382*1031d839SEric Joyner 			ifmr->ifm_active |= IFM_10G_TWINAX;
1383*1031d839SEric Joyner 			break;
1384*1031d839SEric Joyner 		case I40E_PHY_TYPE_10GBASE_SR:
1385*1031d839SEric Joyner 			ifmr->ifm_active |= IFM_10G_SR;
1386*1031d839SEric Joyner 			break;
1387*1031d839SEric Joyner 		case I40E_PHY_TYPE_10GBASE_LR:
1388*1031d839SEric Joyner 			ifmr->ifm_active |= IFM_10G_LR;
1389*1031d839SEric Joyner 			break;
1390*1031d839SEric Joyner 		case I40E_PHY_TYPE_10GBASE_T:
1391*1031d839SEric Joyner 			ifmr->ifm_active |= IFM_10G_T;
1392*1031d839SEric Joyner 			break;
1393*1031d839SEric Joyner 		case I40E_PHY_TYPE_XAUI:
1394*1031d839SEric Joyner 		case I40E_PHY_TYPE_XFI:
1395*1031d839SEric Joyner 			ifmr->ifm_active |= IFM_10G_TWINAX;
1396*1031d839SEric Joyner 			break;
1397*1031d839SEric Joyner 		case I40E_PHY_TYPE_10GBASE_AOC:
1398*1031d839SEric Joyner 			ifmr->ifm_active |= IFM_10G_AOC;
1399*1031d839SEric Joyner 			break;
1400*1031d839SEric Joyner 		/* 25 G */
1401*1031d839SEric Joyner 		case I40E_PHY_TYPE_25GBASE_KR:
1402*1031d839SEric Joyner 			ifmr->ifm_active |= IFM_25G_KR;
1403*1031d839SEric Joyner 			break;
1404*1031d839SEric Joyner 		case I40E_PHY_TYPE_25GBASE_CR:
1405*1031d839SEric Joyner 			ifmr->ifm_active |= IFM_25G_CR;
1406*1031d839SEric Joyner 			break;
1407*1031d839SEric Joyner 		case I40E_PHY_TYPE_25GBASE_SR:
1408*1031d839SEric Joyner 			ifmr->ifm_active |= IFM_25G_SR;
1409*1031d839SEric Joyner 			break;
1410*1031d839SEric Joyner 		case I40E_PHY_TYPE_25GBASE_LR:
1411*1031d839SEric Joyner 			ifmr->ifm_active |= IFM_25G_LR;
1412*1031d839SEric Joyner 			break;
1413*1031d839SEric Joyner 		case I40E_PHY_TYPE_25GBASE_AOC:
1414*1031d839SEric Joyner 			ifmr->ifm_active |= IFM_25G_AOC;
1415*1031d839SEric Joyner 			break;
1416*1031d839SEric Joyner 		case I40E_PHY_TYPE_25GBASE_ACC:
1417*1031d839SEric Joyner 			ifmr->ifm_active |= IFM_25G_ACC;
1418*1031d839SEric Joyner 			break;
1419*1031d839SEric Joyner 		/* 40 G */
1420*1031d839SEric Joyner 		case I40E_PHY_TYPE_40GBASE_CR4:
1421*1031d839SEric Joyner 		case I40E_PHY_TYPE_40GBASE_CR4_CU:
1422*1031d839SEric Joyner 			ifmr->ifm_active |= IFM_40G_CR4;
1423*1031d839SEric Joyner 			break;
1424*1031d839SEric Joyner 		case I40E_PHY_TYPE_40GBASE_SR4:
1425*1031d839SEric Joyner 			ifmr->ifm_active |= IFM_40G_SR4;
1426*1031d839SEric Joyner 			break;
1427*1031d839SEric Joyner 		case I40E_PHY_TYPE_40GBASE_LR4:
1428*1031d839SEric Joyner 			ifmr->ifm_active |= IFM_40G_LR4;
1429*1031d839SEric Joyner 			break;
1430*1031d839SEric Joyner 		case I40E_PHY_TYPE_XLAUI:
1431*1031d839SEric Joyner 			ifmr->ifm_active |= IFM_OTHER;
1432*1031d839SEric Joyner 			break;
1433*1031d839SEric Joyner 		case I40E_PHY_TYPE_1000BASE_KX:
1434*1031d839SEric Joyner 			ifmr->ifm_active |= IFM_1000_KX;
1435*1031d839SEric Joyner 			break;
1436*1031d839SEric Joyner 		case I40E_PHY_TYPE_SGMII:
1437*1031d839SEric Joyner 			ifmr->ifm_active |= IFM_1000_SGMII;
1438*1031d839SEric Joyner 			break;
1439*1031d839SEric Joyner 		/* ERJ: What's the difference between these? */
1440*1031d839SEric Joyner 		case I40E_PHY_TYPE_10GBASE_CR1_CU:
1441*1031d839SEric Joyner 		case I40E_PHY_TYPE_10GBASE_CR1:
1442*1031d839SEric Joyner 			ifmr->ifm_active |= IFM_10G_CR1;
1443*1031d839SEric Joyner 			break;
1444*1031d839SEric Joyner 		case I40E_PHY_TYPE_10GBASE_KX4:
1445*1031d839SEric Joyner 			ifmr->ifm_active |= IFM_10G_KX4;
1446*1031d839SEric Joyner 			break;
1447*1031d839SEric Joyner 		case I40E_PHY_TYPE_10GBASE_KR:
1448*1031d839SEric Joyner 			ifmr->ifm_active |= IFM_10G_KR;
1449*1031d839SEric Joyner 			break;
1450*1031d839SEric Joyner 		case I40E_PHY_TYPE_SFI:
1451*1031d839SEric Joyner 			ifmr->ifm_active |= IFM_10G_SFI;
1452*1031d839SEric Joyner 			break;
1453*1031d839SEric Joyner 		/* Our single 20G media type */
1454*1031d839SEric Joyner 		case I40E_PHY_TYPE_20GBASE_KR2:
1455*1031d839SEric Joyner 			ifmr->ifm_active |= IFM_20G_KR2;
1456*1031d839SEric Joyner 			break;
1457*1031d839SEric Joyner 		case I40E_PHY_TYPE_40GBASE_KR4:
1458*1031d839SEric Joyner 			ifmr->ifm_active |= IFM_40G_KR4;
1459*1031d839SEric Joyner 			break;
1460*1031d839SEric Joyner 		case I40E_PHY_TYPE_XLPPI:
1461*1031d839SEric Joyner 		case I40E_PHY_TYPE_40GBASE_AOC:
1462*1031d839SEric Joyner 			ifmr->ifm_active |= IFM_40G_XLPPI;
1463*1031d839SEric Joyner 			break;
1464*1031d839SEric Joyner 		/* Unknown to driver */
1465*1031d839SEric Joyner 		default:
1466*1031d839SEric Joyner 			ifmr->ifm_active |= IFM_UNKNOWN;
1467*1031d839SEric Joyner 			break;
1468*1031d839SEric Joyner 	}
1469*1031d839SEric Joyner 	/* Report flow control status as well */
1470*1031d839SEric Joyner 	if (hw->phy.link_info.an_info & I40E_AQ_LINK_PAUSE_TX)
1471*1031d839SEric Joyner 		ifmr->ifm_active |= IFM_ETH_TXPAUSE;
1472*1031d839SEric Joyner 	if (hw->phy.link_info.an_info & I40E_AQ_LINK_PAUSE_RX)
1473*1031d839SEric Joyner 		ifmr->ifm_active |= IFM_ETH_RXPAUSE;
1474*1031d839SEric Joyner }
1475*1031d839SEric Joyner 
1476*1031d839SEric Joyner static int
1477*1031d839SEric Joyner ixl_if_media_change(if_ctx_t ctx)
1478*1031d839SEric Joyner {
1479*1031d839SEric Joyner 	struct ifmedia *ifm = iflib_get_media(ctx);
1480*1031d839SEric Joyner 
1481*1031d839SEric Joyner 	INIT_DEBUGOUT("ixl_media_change: begin");
1482*1031d839SEric Joyner 
1483*1031d839SEric Joyner 	if (IFM_TYPE(ifm->ifm_media) != IFM_ETHER)
1484*1031d839SEric Joyner 		return (EINVAL);
1485*1031d839SEric Joyner 
1486*1031d839SEric Joyner 	if_printf(iflib_get_ifp(ctx), "Media change is not supported.\n");
1487*1031d839SEric Joyner 	return (ENODEV);
1488*1031d839SEric Joyner }
1489*1031d839SEric Joyner 
1490*1031d839SEric Joyner static int
1491*1031d839SEric Joyner ixl_if_promisc_set(if_ctx_t ctx, int flags)
1492*1031d839SEric Joyner {
1493*1031d839SEric Joyner 	struct ixl_pf *pf = iflib_get_softc(ctx);
1494*1031d839SEric Joyner 	struct ixl_vsi *vsi = &pf->vsi;
1495*1031d839SEric Joyner 	struct ifnet	*ifp = iflib_get_ifp(ctx);
1496*1031d839SEric Joyner 	struct i40e_hw	*hw = vsi->hw;
1497*1031d839SEric Joyner 	int		err;
1498*1031d839SEric Joyner 	bool		uni = FALSE, multi = FALSE;
1499*1031d839SEric Joyner 
1500*1031d839SEric Joyner 	if (flags & IFF_PROMISC)
1501*1031d839SEric Joyner 		uni = multi = TRUE;
1502*1031d839SEric Joyner 	else if (flags & IFF_ALLMULTI ||
1503*1031d839SEric Joyner 		if_multiaddr_count(ifp, MAX_MULTICAST_ADDR) == MAX_MULTICAST_ADDR)
1504*1031d839SEric Joyner 		multi = TRUE;
1505*1031d839SEric Joyner 
1506*1031d839SEric Joyner 	err = i40e_aq_set_vsi_unicast_promiscuous(hw,
1507*1031d839SEric Joyner 	    vsi->seid, uni, NULL, true);
1508*1031d839SEric Joyner 	if (err)
1509*1031d839SEric Joyner 		return (err);
1510*1031d839SEric Joyner 	err = i40e_aq_set_vsi_multicast_promiscuous(hw,
1511*1031d839SEric Joyner 	    vsi->seid, multi, NULL);
1512*1031d839SEric Joyner 	return (err);
1513*1031d839SEric Joyner }
1514*1031d839SEric Joyner 
1515*1031d839SEric Joyner static void
1516*1031d839SEric Joyner ixl_if_timer(if_ctx_t ctx, uint16_t qid)
1517*1031d839SEric Joyner {
1518*1031d839SEric Joyner 	struct ixl_pf			*pf = iflib_get_softc(ctx);
1519*1031d839SEric Joyner 	//struct i40e_hw		*hw = &pf->hw;
1520*1031d839SEric Joyner 	//struct ixl_tx_queue	*que = &vsi->tx_queues[qid];
1521*1031d839SEric Joyner  #if 0
1522*1031d839SEric Joyner 	u32			mask;
1523*1031d839SEric Joyner 
1524*1031d839SEric Joyner 	/*
1525*1031d839SEric Joyner 	** Check status of the queues
1526*1031d839SEric Joyner 	*/
1527*1031d839SEric Joyner 	mask = (I40E_PFINT_DYN_CTLN_INTENA_MASK |
1528*1031d839SEric Joyner 		I40E_PFINT_DYN_CTLN_SWINT_TRIG_MASK);
1529*1031d839SEric Joyner 
1530*1031d839SEric Joyner 	/* If queue param has outstanding work, trigger sw irq */
1531*1031d839SEric Joyner 	// TODO: TX queues in iflib don't use HW interrupts; does this do anything?
1532*1031d839SEric Joyner 	if (que->busy)
1533*1031d839SEric Joyner 		wr32(hw, I40E_PFINT_DYN_CTLN(que->txr.me), mask);
1534*1031d839SEric Joyner #endif
1535*1031d839SEric Joyner 
1536*1031d839SEric Joyner 	if (qid != 0)
1537*1031d839SEric Joyner 		return;
1538*1031d839SEric Joyner 
1539*1031d839SEric Joyner 	/* Fire off the adminq task */
1540*1031d839SEric Joyner 	iflib_admin_intr_deferred(ctx);
1541*1031d839SEric Joyner 
1542*1031d839SEric Joyner 	/* Update stats */
1543*1031d839SEric Joyner 	ixl_update_stats_counters(pf);
1544*1031d839SEric Joyner }
1545*1031d839SEric Joyner 
1546*1031d839SEric Joyner static void
1547*1031d839SEric Joyner ixl_if_vlan_register(if_ctx_t ctx, u16 vtag)
1548*1031d839SEric Joyner {
1549*1031d839SEric Joyner 	struct ixl_pf *pf = iflib_get_softc(ctx);
1550*1031d839SEric Joyner 	struct ixl_vsi *vsi = &pf->vsi;
1551*1031d839SEric Joyner 	struct i40e_hw	*hw = vsi->hw;
1552*1031d839SEric Joyner 
1553*1031d839SEric Joyner 	if ((vtag == 0) || (vtag > 4095))	/* Invalid */
1554*1031d839SEric Joyner 		return;
1555*1031d839SEric Joyner 
1556*1031d839SEric Joyner 	++vsi->num_vlans;
1557*1031d839SEric Joyner 	ixl_add_filter(vsi, hw->mac.addr, vtag);
1558*1031d839SEric Joyner }
1559*1031d839SEric Joyner 
1560*1031d839SEric Joyner static void
1561*1031d839SEric Joyner ixl_if_vlan_unregister(if_ctx_t ctx, u16 vtag)
1562*1031d839SEric Joyner {
1563*1031d839SEric Joyner 	struct ixl_pf *pf = iflib_get_softc(ctx);
1564*1031d839SEric Joyner 	struct ixl_vsi *vsi = &pf->vsi;
1565*1031d839SEric Joyner 	struct i40e_hw	*hw = vsi->hw;
1566*1031d839SEric Joyner 
1567*1031d839SEric Joyner 	if ((vtag == 0) || (vtag > 4095))	/* Invalid */
1568*1031d839SEric Joyner 		return;
1569*1031d839SEric Joyner 
1570*1031d839SEric Joyner 	--vsi->num_vlans;
1571*1031d839SEric Joyner 	ixl_del_filter(vsi, hw->mac.addr, vtag);
1572*1031d839SEric Joyner }
1573*1031d839SEric Joyner 
1574*1031d839SEric Joyner static uint64_t
1575*1031d839SEric Joyner ixl_if_get_counter(if_ctx_t ctx, ift_counter cnt)
1576*1031d839SEric Joyner {
1577*1031d839SEric Joyner 	struct ixl_pf *pf = iflib_get_softc(ctx);
1578*1031d839SEric Joyner 	struct ixl_vsi *vsi = &pf->vsi;
1579*1031d839SEric Joyner 	if_t ifp = iflib_get_ifp(ctx);
1580*1031d839SEric Joyner 
1581*1031d839SEric Joyner 	switch (cnt) {
1582*1031d839SEric Joyner 	case IFCOUNTER_IPACKETS:
1583*1031d839SEric Joyner 		return (vsi->ipackets);
1584*1031d839SEric Joyner 	case IFCOUNTER_IERRORS:
1585*1031d839SEric Joyner 		return (vsi->ierrors);
1586*1031d839SEric Joyner 	case IFCOUNTER_OPACKETS:
1587*1031d839SEric Joyner 		return (vsi->opackets);
1588*1031d839SEric Joyner 	case IFCOUNTER_OERRORS:
1589*1031d839SEric Joyner 		return (vsi->oerrors);
1590*1031d839SEric Joyner 	case IFCOUNTER_COLLISIONS:
1591*1031d839SEric Joyner 		/* Collisions are by standard impossible in 40G/10G Ethernet */
1592*1031d839SEric Joyner 		return (0);
1593*1031d839SEric Joyner 	case IFCOUNTER_IBYTES:
1594*1031d839SEric Joyner 		return (vsi->ibytes);
1595*1031d839SEric Joyner 	case IFCOUNTER_OBYTES:
1596*1031d839SEric Joyner 		return (vsi->obytes);
1597*1031d839SEric Joyner 	case IFCOUNTER_IMCASTS:
1598*1031d839SEric Joyner 		return (vsi->imcasts);
1599*1031d839SEric Joyner 	case IFCOUNTER_OMCASTS:
1600*1031d839SEric Joyner 		return (vsi->omcasts);
1601*1031d839SEric Joyner 	case IFCOUNTER_IQDROPS:
1602*1031d839SEric Joyner 		return (vsi->iqdrops);
1603*1031d839SEric Joyner 	case IFCOUNTER_OQDROPS:
1604*1031d839SEric Joyner 		return (vsi->oqdrops);
1605*1031d839SEric Joyner 	case IFCOUNTER_NOPROTO:
1606*1031d839SEric Joyner 		return (vsi->noproto);
1607*1031d839SEric Joyner 	default:
1608*1031d839SEric Joyner 		return (if_get_counter_default(ifp, cnt));
1609*1031d839SEric Joyner 	}
1610*1031d839SEric Joyner }
1611*1031d839SEric Joyner 
1612*1031d839SEric Joyner static void
1613*1031d839SEric Joyner ixl_if_vflr_handle(if_ctx_t ctx)
1614*1031d839SEric Joyner {
1615*1031d839SEric Joyner 	IXL_DEV_ERR(iflib_get_dev(ctx), "");
1616*1031d839SEric Joyner 
1617*1031d839SEric Joyner 	// TODO: call ixl_handle_vflr()
1618*1031d839SEric Joyner }
1619*1031d839SEric Joyner 
1620*1031d839SEric Joyner static int
1621*1031d839SEric Joyner ixl_if_i2c_req(if_ctx_t ctx, struct ifi2creq *req)
1622*1031d839SEric Joyner {
1623*1031d839SEric Joyner 	struct ixl_pf		*pf = iflib_get_softc(ctx);
1624*1031d839SEric Joyner 
1625*1031d839SEric Joyner 	if (pf->read_i2c_byte == NULL)
1626*1031d839SEric Joyner 		return (EINVAL);
1627*1031d839SEric Joyner 
1628*1031d839SEric Joyner 	for (int i = 0; i < req->len; i++)
1629*1031d839SEric Joyner 		if (pf->read_i2c_byte(pf, req->offset + i,
1630*1031d839SEric Joyner 		    req->dev_addr, &req->data[i]))
1631*1031d839SEric Joyner 			return (EIO);
1632*1031d839SEric Joyner 	return (0);
1633*1031d839SEric Joyner }
1634*1031d839SEric Joyner 
1635*1031d839SEric Joyner static int
1636*1031d839SEric Joyner ixl_if_priv_ioctl(if_ctx_t ctx, u_long command, caddr_t data)
1637*1031d839SEric Joyner {
1638*1031d839SEric Joyner 	struct ixl_pf *pf = iflib_get_softc(ctx);
1639*1031d839SEric Joyner 	struct ifdrv *ifd = (struct ifdrv *)data;
1640*1031d839SEric Joyner 	int error = 0;
1641*1031d839SEric Joyner 
1642*1031d839SEric Joyner 	/* NVM update command */
1643*1031d839SEric Joyner 	if (ifd->ifd_cmd == I40E_NVM_ACCESS)
1644*1031d839SEric Joyner 		error = ixl_handle_nvmupd_cmd(pf, ifd);
1645*1031d839SEric Joyner 	else
1646*1031d839SEric Joyner 		error = EINVAL;
1647*1031d839SEric Joyner 
1648*1031d839SEric Joyner 	return (error);
1649*1031d839SEric Joyner }
1650*1031d839SEric Joyner 
1651*1031d839SEric Joyner static int
1652*1031d839SEric Joyner ixl_mc_filter_apply(void *arg, struct ifmultiaddr *ifma, int count __unused)
1653*1031d839SEric Joyner {
1654*1031d839SEric Joyner 	struct ixl_vsi *vsi = arg;
1655*1031d839SEric Joyner 
1656*1031d839SEric Joyner 	if (ifma->ifma_addr->sa_family != AF_LINK)
1657*1031d839SEric Joyner 		return (0);
1658*1031d839SEric Joyner 	ixl_add_mc_filter(vsi,
1659*1031d839SEric Joyner 	    (u8*)LLADDR((struct sockaddr_dl *) ifma->ifma_addr));
1660*1031d839SEric Joyner 	return (1);
1661*1031d839SEric Joyner }
1662*1031d839SEric Joyner 
1663*1031d839SEric Joyner /*
1664*1031d839SEric Joyner  * Sanity check and save off tunable values.
1665*1031d839SEric Joyner  */
1666*1031d839SEric Joyner static void
1667*1031d839SEric Joyner ixl_save_pf_tunables(struct ixl_pf *pf)
1668*1031d839SEric Joyner {
1669*1031d839SEric Joyner 	device_t dev = pf->dev;
1670*1031d839SEric Joyner 
1671*1031d839SEric Joyner 	/* Save tunable information */
1672*1031d839SEric Joyner 	pf->enable_tx_fc_filter = ixl_enable_tx_fc_filter;
1673*1031d839SEric Joyner 	pf->dbg_mask = ixl_core_debug_mask;
1674*1031d839SEric Joyner 	pf->hw.debug_mask = ixl_shared_debug_mask;
1675*1031d839SEric Joyner 	pf->vsi.enable_head_writeback = !!(ixl_enable_head_writeback);
1676*1031d839SEric Joyner #if 0
1677*1031d839SEric Joyner 	pf->dynamic_rx_itr = ixl_dynamic_rx_itr;
1678*1031d839SEric Joyner 	pf->dynamic_tx_itr = ixl_dynamic_tx_itr;
1679*1031d839SEric Joyner #endif
1680*1031d839SEric Joyner 
1681*1031d839SEric Joyner 	if (ixl_i2c_access_method > 3 || ixl_i2c_access_method < 0)
1682*1031d839SEric Joyner 		pf->i2c_access_method = 0;
1683*1031d839SEric Joyner 	else
1684*1031d839SEric Joyner 		pf->i2c_access_method = ixl_i2c_access_method;
1685*1031d839SEric Joyner 
1686*1031d839SEric Joyner 	if (ixl_tx_itr < 0 || ixl_tx_itr > IXL_MAX_ITR) {
1687*1031d839SEric Joyner 		device_printf(dev, "Invalid tx_itr value of %d set!\n",
1688*1031d839SEric Joyner 		    ixl_tx_itr);
1689*1031d839SEric Joyner 		device_printf(dev, "tx_itr must be between %d and %d, "
1690*1031d839SEric Joyner 		    "inclusive\n",
1691*1031d839SEric Joyner 		    0, IXL_MAX_ITR);
1692*1031d839SEric Joyner 		device_printf(dev, "Using default value of %d instead\n",
1693*1031d839SEric Joyner 		    IXL_ITR_4K);
1694*1031d839SEric Joyner 		pf->tx_itr = IXL_ITR_4K;
1695*1031d839SEric Joyner 	} else
1696*1031d839SEric Joyner 		pf->tx_itr = ixl_tx_itr;
1697*1031d839SEric Joyner 
1698*1031d839SEric Joyner 	if (ixl_rx_itr < 0 || ixl_rx_itr > IXL_MAX_ITR) {
1699*1031d839SEric Joyner 		device_printf(dev, "Invalid rx_itr value of %d set!\n",
1700*1031d839SEric Joyner 		    ixl_rx_itr);
1701*1031d839SEric Joyner 		device_printf(dev, "rx_itr must be between %d and %d, "
1702*1031d839SEric Joyner 		    "inclusive\n",
1703*1031d839SEric Joyner 		    0, IXL_MAX_ITR);
1704*1031d839SEric Joyner 		device_printf(dev, "Using default value of %d instead\n",
1705*1031d839SEric Joyner 		    IXL_ITR_8K);
1706*1031d839SEric Joyner 		pf->rx_itr = IXL_ITR_8K;
1707*1031d839SEric Joyner 	} else
1708*1031d839SEric Joyner 		pf->rx_itr = ixl_rx_itr;
1709*1031d839SEric Joyner }
1710*1031d839SEric Joyner 
1711