xref: /freebsd/sys/dev/ixgbe/if_ix.c (revision fb6aa95d9f4331ec19073fc8aded1b2198e5f1e1)
1758cc3dcSJack F Vogel /******************************************************************************
2758cc3dcSJack F Vogel 
38eb6488eSEric Joyner   Copyright (c) 2001-2017, Intel Corporation
4758cc3dcSJack F Vogel   All rights reserved.
5758cc3dcSJack F Vogel 
6758cc3dcSJack F Vogel   Redistribution and use in source and binary forms, with or without
7758cc3dcSJack F Vogel   modification, are permitted provided that the following conditions are met:
8758cc3dcSJack F Vogel 
9758cc3dcSJack F Vogel    1. Redistributions of source code must retain the above copyright notice,
10758cc3dcSJack F Vogel       this list of conditions and the following disclaimer.
11758cc3dcSJack F Vogel 
12758cc3dcSJack F Vogel    2. Redistributions in binary form must reproduce the above copyright
13758cc3dcSJack F Vogel       notice, this list of conditions and the following disclaimer in the
14758cc3dcSJack F Vogel       documentation and/or other materials provided with the distribution.
15758cc3dcSJack F Vogel 
16758cc3dcSJack F Vogel    3. Neither the name of the Intel Corporation nor the names of its
17758cc3dcSJack F Vogel       contributors may be used to endorse or promote products derived from
18758cc3dcSJack F Vogel       this software without specific prior written permission.
19758cc3dcSJack F Vogel 
20758cc3dcSJack F Vogel   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21758cc3dcSJack F Vogel   AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22758cc3dcSJack F Vogel   IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23758cc3dcSJack F Vogel   ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
24758cc3dcSJack F Vogel   LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25758cc3dcSJack F Vogel   CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26758cc3dcSJack F Vogel   SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27758cc3dcSJack F Vogel   INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28758cc3dcSJack F Vogel   CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29758cc3dcSJack F Vogel   ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30758cc3dcSJack F Vogel   POSSIBILITY OF SUCH DAMAGE.
31758cc3dcSJack F Vogel 
32758cc3dcSJack F Vogel ******************************************************************************/
33758cc3dcSJack F Vogel /*$FreeBSD$*/
34758cc3dcSJack F Vogel 
35758cc3dcSJack F Vogel 
36758cc3dcSJack F Vogel #ifndef IXGBE_STANDALONE_BUILD
37758cc3dcSJack F Vogel #include "opt_inet.h"
38758cc3dcSJack F Vogel #include "opt_inet6.h"
39758cc3dcSJack F Vogel #include "opt_rss.h"
40758cc3dcSJack F Vogel #endif
41758cc3dcSJack F Vogel 
42758cc3dcSJack F Vogel #include "ixgbe.h"
43758cc3dcSJack F Vogel 
448eb6488eSEric Joyner /************************************************************************
45758cc3dcSJack F Vogel  * Driver version
468eb6488eSEric Joyner  ************************************************************************/
478eb6488eSEric Joyner char ixgbe_driver_version[] = "3.2.12-k";
48a9ca1c79SSean Bruno 
49758cc3dcSJack F Vogel 
508eb6488eSEric Joyner /************************************************************************
51758cc3dcSJack F Vogel  * PCI Device ID Table
52758cc3dcSJack F Vogel  *
53758cc3dcSJack F Vogel  *   Used by probe to select devices to load on
54758cc3dcSJack F Vogel  *   Last field stores an index into ixgbe_strings
55758cc3dcSJack F Vogel  *   Last entry must be all 0s
56758cc3dcSJack F Vogel  *
57758cc3dcSJack F Vogel  *   { Vendor ID, Device ID, SubVendor ID, SubDevice ID, String Index }
588eb6488eSEric Joyner  ************************************************************************/
59758cc3dcSJack F Vogel static ixgbe_vendor_info_t ixgbe_vendor_info_array[] =
60758cc3dcSJack F Vogel {
61758cc3dcSJack F Vogel 	{IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82598AF_DUAL_PORT, 0, 0, 0},
62758cc3dcSJack F Vogel 	{IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82598AF_SINGLE_PORT, 0, 0, 0},
63758cc3dcSJack F Vogel 	{IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82598EB_CX4, 0, 0, 0},
64758cc3dcSJack F Vogel 	{IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82598AT, 0, 0, 0},
65758cc3dcSJack F Vogel 	{IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82598AT2, 0, 0, 0},
66758cc3dcSJack F Vogel 	{IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82598, 0, 0, 0},
67758cc3dcSJack F Vogel 	{IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82598_DA_DUAL_PORT, 0, 0, 0},
68758cc3dcSJack F Vogel 	{IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82598_CX4_DUAL_PORT, 0, 0, 0},
69758cc3dcSJack F Vogel 	{IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82598EB_XF_LR, 0, 0, 0},
70758cc3dcSJack F Vogel 	{IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82598_SR_DUAL_PORT_EM, 0, 0, 0},
71758cc3dcSJack F Vogel 	{IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82598EB_SFP_LOM, 0, 0, 0},
72758cc3dcSJack F Vogel 	{IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82599_KX4, 0, 0, 0},
73758cc3dcSJack F Vogel 	{IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82599_KX4_MEZZ, 0, 0, 0},
74758cc3dcSJack F Vogel 	{IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82599_SFP, 0, 0, 0},
75758cc3dcSJack F Vogel 	{IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82599_XAUI_LOM, 0, 0, 0},
76758cc3dcSJack F Vogel 	{IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82599_CX4, 0, 0, 0},
77758cc3dcSJack F Vogel 	{IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82599_T3_LOM, 0, 0, 0},
78758cc3dcSJack F Vogel 	{IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82599_COMBO_BACKPLANE, 0, 0, 0},
79758cc3dcSJack F Vogel 	{IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82599_BACKPLANE_FCOE, 0, 0, 0},
80758cc3dcSJack F Vogel 	{IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82599_SFP_SF2, 0, 0, 0},
81758cc3dcSJack F Vogel 	{IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82599_SFP_FCOE, 0, 0, 0},
82758cc3dcSJack F Vogel 	{IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82599EN_SFP, 0, 0, 0},
83758cc3dcSJack F Vogel 	{IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82599_SFP_SF_QP, 0, 0, 0},
84758cc3dcSJack F Vogel 	{IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82599_QSFP_SF_QP, 0, 0, 0},
85758cc3dcSJack F Vogel 	{IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X540T, 0, 0, 0},
86758cc3dcSJack F Vogel 	{IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X540T1, 0, 0, 0},
87758cc3dcSJack F Vogel 	{IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X550T, 0, 0, 0},
88a9ca1c79SSean Bruno 	{IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X550T1, 0, 0, 0},
89758cc3dcSJack F Vogel 	{IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X550EM_X_KR, 0, 0, 0},
90758cc3dcSJack F Vogel 	{IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X550EM_X_KX4, 0, 0, 0},
91758cc3dcSJack F Vogel 	{IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X550EM_X_10G_T, 0, 0, 0},
928eb6488eSEric Joyner 	{IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X550EM_X_1G_T, 0, 0, 0},
93a9ca1c79SSean Bruno 	{IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X550EM_X_SFP, 0, 0, 0},
948eb6488eSEric Joyner 	{IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X550EM_A_KR, 0, 0, 0},
958eb6488eSEric Joyner 	{IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X550EM_A_KR_L, 0, 0, 0},
968eb6488eSEric Joyner 	{IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X550EM_A_SFP, 0, 0, 0},
978eb6488eSEric Joyner 	{IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X550EM_A_SFP_N, 0, 0, 0},
988eb6488eSEric Joyner 	{IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X550EM_A_SGMII, 0, 0, 0},
998eb6488eSEric Joyner 	{IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X550EM_A_SGMII_L, 0, 0, 0},
1008eb6488eSEric Joyner 	{IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X550EM_A_10G_T, 0, 0, 0},
1018eb6488eSEric Joyner 	{IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X550EM_A_1G_T, 0, 0, 0},
1028eb6488eSEric Joyner 	{IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X550EM_A_1G_T_L, 0, 0, 0},
1038eb6488eSEric Joyner 	{IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X540_BYPASS, 0, 0, 0},
1048eb6488eSEric Joyner 	{IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82599_BYPASS, 0, 0, 0},
105758cc3dcSJack F Vogel 	/* required last entry */
106758cc3dcSJack F Vogel 	{0, 0, 0, 0, 0}
107758cc3dcSJack F Vogel };
108758cc3dcSJack F Vogel 
1098eb6488eSEric Joyner /************************************************************************
110758cc3dcSJack F Vogel  * Table of branding strings
1118eb6488eSEric Joyner  ************************************************************************/
112758cc3dcSJack F Vogel static char    *ixgbe_strings[] = {
113758cc3dcSJack F Vogel 	"Intel(R) PRO/10GbE PCI-Express Network Driver"
114758cc3dcSJack F Vogel };
115758cc3dcSJack F Vogel 
1168eb6488eSEric Joyner /************************************************************************
117758cc3dcSJack F Vogel  * Function prototypes
1188eb6488eSEric Joyner  ************************************************************************/
119758cc3dcSJack F Vogel static int      ixgbe_probe(device_t);
120758cc3dcSJack F Vogel static int      ixgbe_attach(device_t);
121758cc3dcSJack F Vogel static int      ixgbe_detach(device_t);
122758cc3dcSJack F Vogel static int      ixgbe_shutdown(device_t);
1236f37f232SEric Joyner static int      ixgbe_suspend(device_t);
1246f37f232SEric Joyner static int      ixgbe_resume(device_t);
125758cc3dcSJack F Vogel static int      ixgbe_ioctl(struct ifnet *, u_long, caddr_t);
126758cc3dcSJack F Vogel static void     ixgbe_init(void *);
127758cc3dcSJack F Vogel static void     ixgbe_init_locked(struct adapter *);
128758cc3dcSJack F Vogel static void     ixgbe_stop(void *);
129758cc3dcSJack F Vogel #if __FreeBSD_version >= 1100036
130758cc3dcSJack F Vogel static uint64_t ixgbe_get_counter(struct ifnet *, ift_counter);
131758cc3dcSJack F Vogel #endif
1328eb6488eSEric Joyner static void     ixgbe_init_device_features(struct adapter *);
1338eb6488eSEric Joyner static void     ixgbe_check_fan_failure(struct adapter *, u32, bool);
134758cc3dcSJack F Vogel static void     ixgbe_add_media_types(struct adapter *);
135758cc3dcSJack F Vogel static void     ixgbe_media_status(struct ifnet *, struct ifmediareq *);
136758cc3dcSJack F Vogel static int      ixgbe_media_change(struct ifnet *);
137758cc3dcSJack F Vogel static int      ixgbe_allocate_pci_resources(struct adapter *);
138a9ca1c79SSean Bruno static void     ixgbe_get_slot_info(struct adapter *);
139758cc3dcSJack F Vogel static int      ixgbe_allocate_msix(struct adapter *);
140758cc3dcSJack F Vogel static int      ixgbe_allocate_legacy(struct adapter *);
1418eb6488eSEric Joyner static int      ixgbe_configure_interrupts(struct adapter *);
142758cc3dcSJack F Vogel static void     ixgbe_free_pci_resources(struct adapter *);
143758cc3dcSJack F Vogel static void     ixgbe_local_timer(void *);
144758cc3dcSJack F Vogel static int      ixgbe_setup_interface(device_t, struct adapter *);
14548056c88SJack F Vogel static void     ixgbe_config_gpie(struct adapter *);
1466f37f232SEric Joyner static void     ixgbe_config_dmac(struct adapter *);
1476f37f232SEric Joyner static void     ixgbe_config_delay_values(struct adapter *);
148758cc3dcSJack F Vogel static void     ixgbe_config_link(struct adapter *);
1496f37f232SEric Joyner static void     ixgbe_check_wol_support(struct adapter *);
1506f37f232SEric Joyner static int      ixgbe_setup_low_power_mode(struct adapter *);
151758cc3dcSJack F Vogel static void     ixgbe_rearm_queues(struct adapter *, u64);
152758cc3dcSJack F Vogel 
153758cc3dcSJack F Vogel static void     ixgbe_initialize_transmit_units(struct adapter *);
154758cc3dcSJack F Vogel static void     ixgbe_initialize_receive_units(struct adapter *);
155758cc3dcSJack F Vogel static void     ixgbe_enable_rx_drop(struct adapter *);
156758cc3dcSJack F Vogel static void     ixgbe_disable_rx_drop(struct adapter *);
157a9ca1c79SSean Bruno static void     ixgbe_initialize_rss_mapping(struct adapter *);
158758cc3dcSJack F Vogel 
159758cc3dcSJack F Vogel static void     ixgbe_enable_intr(struct adapter *);
160758cc3dcSJack F Vogel static void     ixgbe_disable_intr(struct adapter *);
161758cc3dcSJack F Vogel static void     ixgbe_update_stats_counters(struct adapter *);
162758cc3dcSJack F Vogel static void     ixgbe_set_promisc(struct adapter *);
163758cc3dcSJack F Vogel static void     ixgbe_set_multi(struct adapter *);
164758cc3dcSJack F Vogel static void     ixgbe_update_link_status(struct adapter *);
165758cc3dcSJack F Vogel static void     ixgbe_set_ivar(struct adapter *, u8, u8, s8);
166758cc3dcSJack F Vogel static void     ixgbe_configure_ivars(struct adapter *);
167758cc3dcSJack F Vogel static u8       *ixgbe_mc_array_itr(struct ixgbe_hw *, u8 **, u32 *);
168758cc3dcSJack F Vogel 
169758cc3dcSJack F Vogel static void     ixgbe_setup_vlan_hw_support(struct adapter *);
170758cc3dcSJack F Vogel static void     ixgbe_register_vlan(void *, struct ifnet *, u16);
171758cc3dcSJack F Vogel static void     ixgbe_unregister_vlan(void *, struct ifnet *, u16);
172758cc3dcSJack F Vogel 
1736f37f232SEric Joyner static void     ixgbe_add_device_sysctls(struct adapter *);
1746f37f232SEric Joyner static void     ixgbe_add_hw_stats(struct adapter *);
175f2c4db54SSteven Hartland static int      ixgbe_set_flowcntl(struct adapter *, int);
176f2c4db54SSteven Hartland static int      ixgbe_set_advertise(struct adapter *, int);
1778eb6488eSEric Joyner static int      ixgbe_get_advertise(struct adapter *);
1786f37f232SEric Joyner 
1796f37f232SEric Joyner /* Sysctl handlers */
180b0c041f8SSean Bruno static void     ixgbe_set_sysctl_value(struct adapter *, const char *,
181b0c041f8SSean Bruno                                        const char *, int *, int);
182f2c4db54SSteven Hartland static int      ixgbe_sysctl_flowcntl(SYSCTL_HANDLER_ARGS);
183f2c4db54SSteven Hartland static int      ixgbe_sysctl_advertise(SYSCTL_HANDLER_ARGS);
1848eb6488eSEric Joyner static int      ixgbe_sysctl_interrupt_rate_handler(SYSCTL_HANDLER_ARGS);
1856f37f232SEric Joyner static int      ixgbe_sysctl_dmac(SYSCTL_HANDLER_ARGS);
1866f37f232SEric Joyner static int      ixgbe_sysctl_phy_temp(SYSCTL_HANDLER_ARGS);
1876f37f232SEric Joyner static int      ixgbe_sysctl_phy_overtemp_occurred(SYSCTL_HANDLER_ARGS);
188a9ca1c79SSean Bruno #ifdef IXGBE_DEBUG
189a9ca1c79SSean Bruno static int      ixgbe_sysctl_power_state(SYSCTL_HANDLER_ARGS);
190a9ca1c79SSean Bruno static int      ixgbe_sysctl_print_rss_config(SYSCTL_HANDLER_ARGS);
191a9ca1c79SSean Bruno #endif
1928eb6488eSEric Joyner static int      ixgbe_sysctl_rdh_handler(SYSCTL_HANDLER_ARGS);
1938eb6488eSEric Joyner static int      ixgbe_sysctl_rdt_handler(SYSCTL_HANDLER_ARGS);
1948eb6488eSEric Joyner static int      ixgbe_sysctl_tdt_handler(SYSCTL_HANDLER_ARGS);
1958eb6488eSEric Joyner static int      ixgbe_sysctl_tdh_handler(SYSCTL_HANDLER_ARGS);
1968eb6488eSEric Joyner static int      ixgbe_sysctl_eee_state(SYSCTL_HANDLER_ARGS);
1976f37f232SEric Joyner static int      ixgbe_sysctl_wol_enable(SYSCTL_HANDLER_ARGS);
1986f37f232SEric Joyner static int      ixgbe_sysctl_wufc(SYSCTL_HANDLER_ARGS);
199758cc3dcSJack F Vogel 
200758cc3dcSJack F Vogel /* Support for pluggable optic modules */
201758cc3dcSJack F Vogel static bool     ixgbe_sfp_probe(struct adapter *);
202758cc3dcSJack F Vogel 
2038eb6488eSEric Joyner /* Legacy (single vector) interrupt handler */
204758cc3dcSJack F Vogel static void     ixgbe_legacy_irq(void *);
205758cc3dcSJack F Vogel 
2068eb6488eSEric Joyner /* The MSI/MSI-X Interrupt handlers */
207758cc3dcSJack F Vogel static void     ixgbe_msix_que(void *);
208758cc3dcSJack F Vogel static void     ixgbe_msix_link(void *);
209758cc3dcSJack F Vogel 
210758cc3dcSJack F Vogel /* Deferred interrupt tasklets */
211758cc3dcSJack F Vogel static void     ixgbe_handle_que(void *, int);
212758cc3dcSJack F Vogel static void     ixgbe_handle_link(void *, int);
213758cc3dcSJack F Vogel static void     ixgbe_handle_msf(void *, int);
214758cc3dcSJack F Vogel static void     ixgbe_handle_mod(void *, int);
2156f37f232SEric Joyner static void     ixgbe_handle_phy(void *, int);
216758cc3dcSJack F Vogel 
217758cc3dcSJack F Vogel 
2188eb6488eSEric Joyner /************************************************************************
219758cc3dcSJack F Vogel  *  FreeBSD Device Interface Entry Points
2208eb6488eSEric Joyner  ************************************************************************/
221a1edda90SAdrian Chadd static device_method_t ix_methods[] = {
222758cc3dcSJack F Vogel 	/* Device interface */
223758cc3dcSJack F Vogel 	DEVMETHOD(device_probe, ixgbe_probe),
224758cc3dcSJack F Vogel 	DEVMETHOD(device_attach, ixgbe_attach),
225758cc3dcSJack F Vogel 	DEVMETHOD(device_detach, ixgbe_detach),
226758cc3dcSJack F Vogel 	DEVMETHOD(device_shutdown, ixgbe_shutdown),
2276f37f232SEric Joyner 	DEVMETHOD(device_suspend, ixgbe_suspend),
2286f37f232SEric Joyner 	DEVMETHOD(device_resume, ixgbe_resume),
22948056c88SJack F Vogel #ifdef PCI_IOV
2309e34aea2SJohn Baldwin 	DEVMETHOD(pci_iov_init, ixgbe_init_iov),
2319e34aea2SJohn Baldwin 	DEVMETHOD(pci_iov_uninit, ixgbe_uninit_iov),
2329e34aea2SJohn Baldwin 	DEVMETHOD(pci_iov_add_vf, ixgbe_add_vf),
23348056c88SJack F Vogel #endif /* PCI_IOV */
234758cc3dcSJack F Vogel 	DEVMETHOD_END
235758cc3dcSJack F Vogel };
236758cc3dcSJack F Vogel 
237a1edda90SAdrian Chadd static driver_t ix_driver = {
238a1edda90SAdrian Chadd 	"ix", ix_methods, sizeof(struct adapter),
239758cc3dcSJack F Vogel };
240758cc3dcSJack F Vogel 
241a1edda90SAdrian Chadd devclass_t ix_devclass;
242a1edda90SAdrian Chadd DRIVER_MODULE(ix, pci, ix_driver, ix_devclass, 0, 0);
243758cc3dcSJack F Vogel 
244a1edda90SAdrian Chadd MODULE_DEPEND(ix, pci, 1, 1, 1);
245a1edda90SAdrian Chadd MODULE_DEPEND(ix, ether, 1, 1, 1);
246847bf383SLuigi Rizzo MODULE_DEPEND(ix, netmap, 1, 1, 1);
247758cc3dcSJack F Vogel 
248758cc3dcSJack F Vogel /*
2498eb6488eSEric Joyner  * TUNEABLE PARAMETERS:
250758cc3dcSJack F Vogel  */
251758cc3dcSJack F Vogel 
2528eb6488eSEric Joyner static SYSCTL_NODE(_hw, OID_AUTO, ix, CTLFLAG_RD, 0, "IXGBE driver parameters");
253758cc3dcSJack F Vogel 
254758cc3dcSJack F Vogel /*
2558eb6488eSEric Joyner  * AIM: Adaptive Interrupt Moderation
2568eb6488eSEric Joyner  * which means that the interrupt rate
2578eb6488eSEric Joyner  * is varied over time based on the
2588eb6488eSEric Joyner  * traffic for that interrupt vector
259758cc3dcSJack F Vogel  */
260758cc3dcSJack F Vogel static int ixgbe_enable_aim = TRUE;
2618eb6488eSEric Joyner SYSCTL_INT(_hw_ix, OID_AUTO, enable_aim, CTLFLAG_RDTUN, &ixgbe_enable_aim, 0,
262758cc3dcSJack F Vogel     "Enable adaptive interrupt moderation");
263758cc3dcSJack F Vogel 
264758cc3dcSJack F Vogel static int ixgbe_max_interrupt_rate = (4000000 / IXGBE_LOW_LATENCY);
265758cc3dcSJack F Vogel SYSCTL_INT(_hw_ix, OID_AUTO, max_interrupt_rate, CTLFLAG_RDTUN,
266758cc3dcSJack F Vogel     &ixgbe_max_interrupt_rate, 0, "Maximum interrupts per second");
267758cc3dcSJack F Vogel 
268758cc3dcSJack F Vogel /* How many packets rxeof tries to clean at a time */
269758cc3dcSJack F Vogel static int ixgbe_rx_process_limit = 256;
270758cc3dcSJack F Vogel SYSCTL_INT(_hw_ix, OID_AUTO, rx_process_limit, CTLFLAG_RDTUN,
2718eb6488eSEric Joyner     &ixgbe_rx_process_limit, 0, "Maximum number of received packets to process at a time, -1 means unlimited");
272758cc3dcSJack F Vogel 
273758cc3dcSJack F Vogel /* How many packets txeof tries to clean at a time */
274758cc3dcSJack F Vogel static int ixgbe_tx_process_limit = 256;
275758cc3dcSJack F Vogel SYSCTL_INT(_hw_ix, OID_AUTO, tx_process_limit, CTLFLAG_RDTUN,
276758cc3dcSJack F Vogel     &ixgbe_tx_process_limit, 0,
2778eb6488eSEric Joyner     "Maximum number of sent packets to process at a time, -1 means unlimited");
278758cc3dcSJack F Vogel 
279f2c4db54SSteven Hartland /* Flow control setting, default to full */
280f2c4db54SSteven Hartland static int ixgbe_flow_control = ixgbe_fc_full;
281f2c4db54SSteven Hartland SYSCTL_INT(_hw_ix, OID_AUTO, flow_control, CTLFLAG_RDTUN,
282f2c4db54SSteven Hartland     &ixgbe_flow_control, 0, "Default flow control used for all adapters");
283f2c4db54SSteven Hartland 
284f2c4db54SSteven Hartland /* Advertise Speed, default to 0 (auto) */
285f2c4db54SSteven Hartland static int ixgbe_advertise_speed = 0;
286f2c4db54SSteven Hartland SYSCTL_INT(_hw_ix, OID_AUTO, advertise_speed, CTLFLAG_RDTUN,
287f2c4db54SSteven Hartland     &ixgbe_advertise_speed, 0, "Default advertised speed for all adapters");
288f2c4db54SSteven Hartland 
289758cc3dcSJack F Vogel /*
2908eb6488eSEric Joyner  * Smart speed setting, default to on
2918eb6488eSEric Joyner  * this only works as a compile option
2928eb6488eSEric Joyner  * right now as its during attach, set
2938eb6488eSEric Joyner  * this to 'ixgbe_smart_speed_off' to
2948eb6488eSEric Joyner  * disable.
295758cc3dcSJack F Vogel  */
296758cc3dcSJack F Vogel static int ixgbe_smart_speed = ixgbe_smart_speed_on;
297758cc3dcSJack F Vogel 
298758cc3dcSJack F Vogel /*
2998eb6488eSEric Joyner  * MSI-X should be the default for best performance,
300758cc3dcSJack F Vogel  * but this allows it to be forced off for testing.
301758cc3dcSJack F Vogel  */
302758cc3dcSJack F Vogel static int ixgbe_enable_msix = 1;
303758cc3dcSJack F Vogel SYSCTL_INT(_hw_ix, OID_AUTO, enable_msix, CTLFLAG_RDTUN, &ixgbe_enable_msix, 0,
304758cc3dcSJack F Vogel     "Enable MSI-X interrupts");
305758cc3dcSJack F Vogel 
306758cc3dcSJack F Vogel /*
307758cc3dcSJack F Vogel  * Number of Queues, can be set to 0,
308758cc3dcSJack F Vogel  * it then autoconfigures based on the
309758cc3dcSJack F Vogel  * number of cpus with a max of 8. This
310758cc3dcSJack F Vogel  * can be overriden manually here.
311758cc3dcSJack F Vogel  */
312758cc3dcSJack F Vogel static int ixgbe_num_queues = 0;
313758cc3dcSJack F Vogel SYSCTL_INT(_hw_ix, OID_AUTO, num_queues, CTLFLAG_RDTUN, &ixgbe_num_queues, 0,
314758cc3dcSJack F Vogel     "Number of queues to configure, 0 indicates autoconfigure");
315758cc3dcSJack F Vogel 
316758cc3dcSJack F Vogel /*
3178eb6488eSEric Joyner  * Number of TX descriptors per ring,
3188eb6488eSEric Joyner  * setting higher than RX as this seems
3198eb6488eSEric Joyner  * the better performing choice.
320758cc3dcSJack F Vogel  */
321758cc3dcSJack F Vogel static int ixgbe_txd = PERFORM_TXD;
322758cc3dcSJack F Vogel SYSCTL_INT(_hw_ix, OID_AUTO, txd, CTLFLAG_RDTUN, &ixgbe_txd, 0,
323758cc3dcSJack F Vogel     "Number of transmit descriptors per queue");
324758cc3dcSJack F Vogel 
325758cc3dcSJack F Vogel /* Number of RX descriptors per ring */
326758cc3dcSJack F Vogel static int ixgbe_rxd = PERFORM_RXD;
327758cc3dcSJack F Vogel SYSCTL_INT(_hw_ix, OID_AUTO, rxd, CTLFLAG_RDTUN, &ixgbe_rxd, 0,
328758cc3dcSJack F Vogel     "Number of receive descriptors per queue");
329758cc3dcSJack F Vogel 
330758cc3dcSJack F Vogel /*
3318eb6488eSEric Joyner  * Defining this on will allow the use
3328eb6488eSEric Joyner  * of unsupported SFP+ modules, note that
3338eb6488eSEric Joyner  * doing so you are on your own :)
334758cc3dcSJack F Vogel  */
335758cc3dcSJack F Vogel static int allow_unsupported_sfp = FALSE;
336*fb6aa95dSSean Bruno SYSCTL_INT(_hw_ix, OID_AUTO, unsupported_sfp, CTLFLAG_RDTUN,
3378eb6488eSEric Joyner     &allow_unsupported_sfp, 0,
3388eb6488eSEric Joyner     "Allow unsupported SFP modules...use at your own risk");
3398eb6488eSEric Joyner 
3408eb6488eSEric Joyner /*
3418eb6488eSEric Joyner  * Not sure if Flow Director is fully baked,
3428eb6488eSEric Joyner  * so we'll default to turning it off.
3438eb6488eSEric Joyner  */
3448eb6488eSEric Joyner static int ixgbe_enable_fdir = 0;
3458eb6488eSEric Joyner SYSCTL_INT(_hw_ix, OID_AUTO, enable_fdir, CTLFLAG_RDTUN, &ixgbe_enable_fdir, 0,
3468eb6488eSEric Joyner     "Enable Flow Director");
3478eb6488eSEric Joyner 
3488eb6488eSEric Joyner /* Legacy Transmit (single queue) */
3498eb6488eSEric Joyner static int ixgbe_enable_legacy_tx = 0;
3508eb6488eSEric Joyner SYSCTL_INT(_hw_ix, OID_AUTO, enable_legacy_tx, CTLFLAG_RDTUN,
3518eb6488eSEric Joyner     &ixgbe_enable_legacy_tx, 0, "Enable Legacy TX flow");
3528eb6488eSEric Joyner 
3538eb6488eSEric Joyner /* Receive-Side Scaling */
3548eb6488eSEric Joyner static int ixgbe_enable_rss = 1;
3558eb6488eSEric Joyner SYSCTL_INT(_hw_ix, OID_AUTO, enable_rss, CTLFLAG_RDTUN, &ixgbe_enable_rss, 0,
3568eb6488eSEric Joyner     "Enable Receive-Side Scaling (RSS)");
357758cc3dcSJack F Vogel 
358758cc3dcSJack F Vogel /* Keep running tab on them for sanity check */
359758cc3dcSJack F Vogel static int ixgbe_total_ports;
360758cc3dcSJack F Vogel 
3618eb6488eSEric Joyner static int (*ixgbe_start_locked)(struct ifnet *, struct tx_ring *);
3628eb6488eSEric Joyner static int (*ixgbe_ring_empty)(struct ifnet *, struct buf_ring *);
363758cc3dcSJack F Vogel 
3648eb6488eSEric Joyner MALLOC_DEFINE(M_IXGBE, "ix", "ix driver allocations");
365758cc3dcSJack F Vogel 
3668eb6488eSEric Joyner /************************************************************************
3678eb6488eSEric Joyner  * ixgbe_initialize_rss_mapping
3688eb6488eSEric Joyner  ************************************************************************/
3698eb6488eSEric Joyner static void
3708eb6488eSEric Joyner ixgbe_initialize_rss_mapping(struct adapter *adapter)
371758cc3dcSJack F Vogel {
3726f37f232SEric Joyner 	struct ixgbe_hw *hw = &adapter->hw;
3738eb6488eSEric Joyner 	u32             reta = 0, mrqc, rss_key[10];
3748eb6488eSEric Joyner 	int             queue_id, table_size, index_mult;
3758eb6488eSEric Joyner 	int             i, j;
3768eb6488eSEric Joyner 	u32             rss_hash_config;
3776f37f232SEric Joyner 
3788eb6488eSEric Joyner 	if (adapter->feat_en & IXGBE_FEATURE_RSS) {
3798eb6488eSEric Joyner 		/* Fetch the configured RSS key */
3808eb6488eSEric Joyner 		rss_getkey((uint8_t *)&rss_key);
381758cc3dcSJack F Vogel 	} else {
3828eb6488eSEric Joyner 		/* set up random bits */
3838eb6488eSEric Joyner 		arc4rand(&rss_key, sizeof(rss_key), 0);
384758cc3dcSJack F Vogel 	}
385758cc3dcSJack F Vogel 
3868eb6488eSEric Joyner 	/* Set multiplier for RETA setup and table size based on MAC */
3878eb6488eSEric Joyner 	index_mult = 0x1;
3888eb6488eSEric Joyner 	table_size = 128;
3898eb6488eSEric Joyner 	switch (adapter->hw.mac.type) {
3908eb6488eSEric Joyner 	case ixgbe_mac_82598EB:
3918eb6488eSEric Joyner 		index_mult = 0x11;
392758cc3dcSJack F Vogel 		break;
3938eb6488eSEric Joyner 	case ixgbe_mac_X550:
3948eb6488eSEric Joyner 	case ixgbe_mac_X550EM_x:
3958eb6488eSEric Joyner 	case ixgbe_mac_X550EM_a:
3968eb6488eSEric Joyner 		table_size = 512;
3978eb6488eSEric Joyner 		break;
398758cc3dcSJack F Vogel 	default:
399758cc3dcSJack F Vogel 		break;
400758cc3dcSJack F Vogel 	}
401758cc3dcSJack F Vogel 
4028eb6488eSEric Joyner 	/* Set up the redirection table */
4038eb6488eSEric Joyner 	for (i = 0, j = 0; i < table_size; i++, j++) {
4048eb6488eSEric Joyner 		if (j == adapter->num_queues)
4058eb6488eSEric Joyner 			j = 0;
406758cc3dcSJack F Vogel 
4078eb6488eSEric Joyner 		if (adapter->feat_en & IXGBE_FEATURE_RSS) {
408a9ca1c79SSean Bruno 			/*
4098eb6488eSEric Joyner 			 * Fetch the RSS bucket id for the given indirection
4108eb6488eSEric Joyner 			 * entry. Cap it at the number of configured buckets
4118eb6488eSEric Joyner 			 * (which is num_queues.)
412a9ca1c79SSean Bruno 			 */
4138eb6488eSEric Joyner 			queue_id = rss_get_indirection_to_bucket(i);
4148eb6488eSEric Joyner 			queue_id = queue_id % adapter->num_queues;
415758cc3dcSJack F Vogel 		} else
4168eb6488eSEric Joyner 			queue_id = (j * index_mult);
4178eb6488eSEric Joyner 
4188eb6488eSEric Joyner 		/*
4198eb6488eSEric Joyner 		 * The low 8 bits are for hash value (n+0);
4208eb6488eSEric Joyner 		 * The next 8 bits are for hash value (n+1), etc.
4218eb6488eSEric Joyner 		 */
4228eb6488eSEric Joyner 		reta = reta >> 8;
4238eb6488eSEric Joyner 		reta = reta | (((uint32_t)queue_id) << 24);
4248eb6488eSEric Joyner 		if ((i & 3) == 3) {
4258eb6488eSEric Joyner 			if (i < 128)
4268eb6488eSEric Joyner 				IXGBE_WRITE_REG(hw, IXGBE_RETA(i >> 2), reta);
4278eb6488eSEric Joyner 			else
4288eb6488eSEric Joyner 				IXGBE_WRITE_REG(hw, IXGBE_ERETA((i >> 2) - 32),
4298eb6488eSEric Joyner 				    reta);
4308eb6488eSEric Joyner 			reta = 0;
4318eb6488eSEric Joyner 		}
432758cc3dcSJack F Vogel 	}
433758cc3dcSJack F Vogel 
4348eb6488eSEric Joyner 	/* Now fill our hash function seeds */
4358eb6488eSEric Joyner 	for (i = 0; i < 10; i++)
4368eb6488eSEric Joyner 		IXGBE_WRITE_REG(hw, IXGBE_RSSRK(i), rss_key[i]);
437758cc3dcSJack F Vogel 
4388eb6488eSEric Joyner 	/* Perform hash on these packet types */
4398eb6488eSEric Joyner 	if (adapter->feat_en & IXGBE_FEATURE_RSS)
4408eb6488eSEric Joyner 		rss_hash_config = rss_gethashconfig();
441758cc3dcSJack F Vogel 	else {
442758cc3dcSJack F Vogel 		/*
4438eb6488eSEric Joyner 		 * Disable UDP - IP fragments aren't currently being handled
4448eb6488eSEric Joyner 		 * and so we end up with a mix of 2-tuple and 4-tuple
4458eb6488eSEric Joyner 		 * traffic.
446758cc3dcSJack F Vogel 		 */
4478eb6488eSEric Joyner 		rss_hash_config = RSS_HASHTYPE_RSS_IPV4
4488eb6488eSEric Joyner 		                | RSS_HASHTYPE_RSS_TCP_IPV4
4498eb6488eSEric Joyner 		                | RSS_HASHTYPE_RSS_IPV6
4508eb6488eSEric Joyner 		                | RSS_HASHTYPE_RSS_TCP_IPV6
4518eb6488eSEric Joyner 		                | RSS_HASHTYPE_RSS_IPV6_EX
4528eb6488eSEric Joyner 		                | RSS_HASHTYPE_RSS_TCP_IPV6_EX;
453758cc3dcSJack F Vogel 	}
454758cc3dcSJack F Vogel 
4558eb6488eSEric Joyner 	mrqc = IXGBE_MRQC_RSSEN;
4568eb6488eSEric Joyner 	if (rss_hash_config & RSS_HASHTYPE_RSS_IPV4)
4578eb6488eSEric Joyner 		mrqc |= IXGBE_MRQC_RSS_FIELD_IPV4;
4588eb6488eSEric Joyner 	if (rss_hash_config & RSS_HASHTYPE_RSS_TCP_IPV4)
4598eb6488eSEric Joyner 		mrqc |= IXGBE_MRQC_RSS_FIELD_IPV4_TCP;
4608eb6488eSEric Joyner 	if (rss_hash_config & RSS_HASHTYPE_RSS_IPV6)
4618eb6488eSEric Joyner 		mrqc |= IXGBE_MRQC_RSS_FIELD_IPV6;
4628eb6488eSEric Joyner 	if (rss_hash_config & RSS_HASHTYPE_RSS_TCP_IPV6)
4638eb6488eSEric Joyner 		mrqc |= IXGBE_MRQC_RSS_FIELD_IPV6_TCP;
4648eb6488eSEric Joyner 	if (rss_hash_config & RSS_HASHTYPE_RSS_IPV6_EX)
4658eb6488eSEric Joyner 		mrqc |= IXGBE_MRQC_RSS_FIELD_IPV6_EX;
4668eb6488eSEric Joyner 	if (rss_hash_config & RSS_HASHTYPE_RSS_TCP_IPV6_EX)
4678eb6488eSEric Joyner 		mrqc |= IXGBE_MRQC_RSS_FIELD_IPV6_EX_TCP;
4688eb6488eSEric Joyner 	if (rss_hash_config & RSS_HASHTYPE_RSS_UDP_IPV4)
4698eb6488eSEric Joyner 		mrqc |= IXGBE_MRQC_RSS_FIELD_IPV4_UDP;
4708eb6488eSEric Joyner 	if (rss_hash_config & RSS_HASHTYPE_RSS_UDP_IPV4_EX)
4718eb6488eSEric Joyner 		device_printf(adapter->dev, "%s: RSS_HASHTYPE_RSS_UDP_IPV4_EX defined, but not supported\n",
4728eb6488eSEric Joyner 		    __func__);
4738eb6488eSEric Joyner 	if (rss_hash_config & RSS_HASHTYPE_RSS_UDP_IPV6)
4748eb6488eSEric Joyner 		mrqc |= IXGBE_MRQC_RSS_FIELD_IPV6_UDP;
4758eb6488eSEric Joyner 	if (rss_hash_config & RSS_HASHTYPE_RSS_UDP_IPV6_EX)
4768eb6488eSEric Joyner 		mrqc |= IXGBE_MRQC_RSS_FIELD_IPV6_EX_UDP;
4778eb6488eSEric Joyner 	mrqc |= ixgbe_get_mrqc(adapter->iov_mode);
4788eb6488eSEric Joyner 	IXGBE_WRITE_REG(hw, IXGBE_MRQC, mrqc);
4798eb6488eSEric Joyner } /* ixgbe_initialize_rss_mapping */
480758cc3dcSJack F Vogel 
4818eb6488eSEric Joyner /************************************************************************
4828eb6488eSEric Joyner  * ixgbe_initialize_receive_units - Setup receive registers and features.
4838eb6488eSEric Joyner  ************************************************************************/
4848eb6488eSEric Joyner #define BSIZEPKT_ROUNDUP ((1<<IXGBE_SRRCTL_BSIZEPKT_SHIFT)-1)
485758cc3dcSJack F Vogel 
486758cc3dcSJack F Vogel static void
4878eb6488eSEric Joyner ixgbe_initialize_receive_units(struct adapter *adapter)
488758cc3dcSJack F Vogel {
4898eb6488eSEric Joyner 	struct rx_ring  *rxr = adapter->rx_rings;
49048056c88SJack F Vogel 	struct ixgbe_hw *hw = &adapter->hw;
4918eb6488eSEric Joyner 	struct ifnet    *ifp = adapter->ifp;
4928eb6488eSEric Joyner 	int             i, j;
4938eb6488eSEric Joyner 	u32             bufsz, fctrl, srrctl, rxcsum;
4948eb6488eSEric Joyner 	u32             hlreg;
49548056c88SJack F Vogel 
49648056c88SJack F Vogel 	/*
4978eb6488eSEric Joyner 	 * Make sure receives are disabled while
4988eb6488eSEric Joyner 	 * setting up the descriptor ring
49948056c88SJack F Vogel 	 */
5008eb6488eSEric Joyner 	ixgbe_disable_rx(hw);
5018eb6488eSEric Joyner 
5028eb6488eSEric Joyner 	/* Enable broadcasts */
5038eb6488eSEric Joyner 	fctrl = IXGBE_READ_REG(hw, IXGBE_FCTRL);
5048eb6488eSEric Joyner 	fctrl |= IXGBE_FCTRL_BAM;
5058eb6488eSEric Joyner 	if (adapter->hw.mac.type == ixgbe_mac_82598EB) {
5068eb6488eSEric Joyner 		fctrl |= IXGBE_FCTRL_DPF;
5078eb6488eSEric Joyner 		fctrl |= IXGBE_FCTRL_PMCF;
50848056c88SJack F Vogel 	}
5098eb6488eSEric Joyner 	IXGBE_WRITE_REG(hw, IXGBE_FCTRL, fctrl);
5108eb6488eSEric Joyner 
5118eb6488eSEric Joyner 	/* Set for Jumbo Frames? */
5128eb6488eSEric Joyner 	hlreg = IXGBE_READ_REG(hw, IXGBE_HLREG0);
5138eb6488eSEric Joyner 	if (ifp->if_mtu > ETHERMTU)
5148eb6488eSEric Joyner 		hlreg |= IXGBE_HLREG0_JUMBOEN;
5158eb6488eSEric Joyner 	else
5168eb6488eSEric Joyner 		hlreg &= ~IXGBE_HLREG0_JUMBOEN;
5178eb6488eSEric Joyner 
5188eb6488eSEric Joyner #ifdef DEV_NETMAP
5198eb6488eSEric Joyner 	/* CRC stripping is conditional in Netmap */
5208eb6488eSEric Joyner 	if ((adapter->feat_en & IXGBE_FEATURE_NETMAP) &&
5218eb6488eSEric Joyner 	    (ifp->if_capenable & IFCAP_NETMAP) &&
5228eb6488eSEric Joyner 	    !ix_crcstrip)
5238eb6488eSEric Joyner 		hlreg &= ~IXGBE_HLREG0_RXCRCSTRP;
5248eb6488eSEric Joyner 	else
5258eb6488eSEric Joyner #endif /* DEV_NETMAP */
5268eb6488eSEric Joyner 		hlreg |= IXGBE_HLREG0_RXCRCSTRP;
5278eb6488eSEric Joyner 
5288eb6488eSEric Joyner 	IXGBE_WRITE_REG(hw, IXGBE_HLREG0, hlreg);
5298eb6488eSEric Joyner 
5308eb6488eSEric Joyner 	bufsz = (adapter->rx_mbuf_sz + BSIZEPKT_ROUNDUP) >>
5318eb6488eSEric Joyner 	    IXGBE_SRRCTL_BSIZEPKT_SHIFT;
5328eb6488eSEric Joyner 
5338eb6488eSEric Joyner 	for (i = 0; i < adapter->num_queues; i++, rxr++) {
5348eb6488eSEric Joyner 		u64 rdba = rxr->rxdma.dma_paddr;
5358eb6488eSEric Joyner 		j = rxr->me;
5368eb6488eSEric Joyner 
5378eb6488eSEric Joyner 		/* Setup the Base and Length of the Rx Descriptor Ring */
5388eb6488eSEric Joyner 		IXGBE_WRITE_REG(hw, IXGBE_RDBAL(j),
5398eb6488eSEric Joyner 		    (rdba & 0x00000000ffffffffULL));
5408eb6488eSEric Joyner 		IXGBE_WRITE_REG(hw, IXGBE_RDBAH(j), (rdba >> 32));
5418eb6488eSEric Joyner 		IXGBE_WRITE_REG(hw, IXGBE_RDLEN(j),
5428eb6488eSEric Joyner 		    adapter->num_rx_desc * sizeof(union ixgbe_adv_rx_desc));
5438eb6488eSEric Joyner 
5448eb6488eSEric Joyner 		/* Set up the SRRCTL register */
5458eb6488eSEric Joyner 		srrctl = IXGBE_READ_REG(hw, IXGBE_SRRCTL(j));
5468eb6488eSEric Joyner 		srrctl &= ~IXGBE_SRRCTL_BSIZEHDR_MASK;
5478eb6488eSEric Joyner 		srrctl &= ~IXGBE_SRRCTL_BSIZEPKT_MASK;
5488eb6488eSEric Joyner 		srrctl |= bufsz;
5498eb6488eSEric Joyner 		srrctl |= IXGBE_SRRCTL_DESCTYPE_ADV_ONEBUF;
55048056c88SJack F Vogel 
55148056c88SJack F Vogel 		/*
5528eb6488eSEric Joyner 		 * Set DROP_EN iff we have no flow control and >1 queue.
5538eb6488eSEric Joyner 		 * Note that srrctl was cleared shortly before during reset,
5548eb6488eSEric Joyner 		 * so we do not need to clear the bit, but do it just in case
5558eb6488eSEric Joyner 		 * this code is moved elsewhere.
55648056c88SJack F Vogel 		 */
5578eb6488eSEric Joyner 		if (adapter->num_queues > 1 &&
5588eb6488eSEric Joyner 		    adapter->hw.fc.requested_mode == ixgbe_fc_none) {
5598eb6488eSEric Joyner 			srrctl |= IXGBE_SRRCTL_DROP_EN;
560758cc3dcSJack F Vogel 		} else {
5618eb6488eSEric Joyner 			srrctl &= ~IXGBE_SRRCTL_DROP_EN;
562758cc3dcSJack F Vogel 		}
563758cc3dcSJack F Vogel 
5648eb6488eSEric Joyner 		IXGBE_WRITE_REG(hw, IXGBE_SRRCTL(j), srrctl);
565758cc3dcSJack F Vogel 
5668eb6488eSEric Joyner 		/* Setup the HW Rx Head and Tail Descriptor Pointers */
5678eb6488eSEric Joyner 		IXGBE_WRITE_REG(hw, IXGBE_RDH(j), 0);
5688eb6488eSEric Joyner 		IXGBE_WRITE_REG(hw, IXGBE_RDT(j), 0);
569758cc3dcSJack F Vogel 
5708eb6488eSEric Joyner 		/* Set the driver rx tail address */
5718eb6488eSEric Joyner 		rxr->tail =  IXGBE_RDT(rxr->me);
572a9ca1c79SSean Bruno 	}
573758cc3dcSJack F Vogel 
574758cc3dcSJack F Vogel 	if (adapter->hw.mac.type != ixgbe_mac_82598EB) {
5758eb6488eSEric Joyner 		u32 psrtype = IXGBE_PSRTYPE_TCPHDR
5768eb6488eSEric Joyner 		            | IXGBE_PSRTYPE_UDPHDR
5778eb6488eSEric Joyner 		            | IXGBE_PSRTYPE_IPV4HDR
5788eb6488eSEric Joyner 		            | IXGBE_PSRTYPE_IPV6HDR;
5798eb6488eSEric Joyner 		IXGBE_WRITE_REG(hw, IXGBE_PSRTYPE(0), psrtype);
5806f37f232SEric Joyner 	}
5816f37f232SEric Joyner 
5828eb6488eSEric Joyner 	rxcsum = IXGBE_READ_REG(hw, IXGBE_RXCSUM);
5838eb6488eSEric Joyner 
5848eb6488eSEric Joyner 	ixgbe_initialize_rss_mapping(adapter);
5858eb6488eSEric Joyner 
5868eb6488eSEric Joyner 	if (adapter->num_queues > 1) {
5878eb6488eSEric Joyner 		/* RSS and RX IPP Checksum are mutually exclusive */
5888eb6488eSEric Joyner 		rxcsum |= IXGBE_RXCSUM_PCSD;
5896f37f232SEric Joyner 	}
5906f37f232SEric Joyner 
5918eb6488eSEric Joyner 	if (ifp->if_capenable & IFCAP_RXCSUM)
5928eb6488eSEric Joyner 		rxcsum |= IXGBE_RXCSUM_PCSD;
593758cc3dcSJack F Vogel 
5948eb6488eSEric Joyner 	/* This is useful for calculating UDP/IP fragment checksums */
5958eb6488eSEric Joyner 	if (!(rxcsum & IXGBE_RXCSUM_PCSD))
5968eb6488eSEric Joyner 		rxcsum |= IXGBE_RXCSUM_IPPCSE;
597758cc3dcSJack F Vogel 
5988eb6488eSEric Joyner 	IXGBE_WRITE_REG(hw, IXGBE_RXCSUM, rxcsum);
599758cc3dcSJack F Vogel 
600758cc3dcSJack F Vogel 	return;
6018eb6488eSEric Joyner } /* ixgbe_initialize_receive_units */
602758cc3dcSJack F Vogel 
6038eb6488eSEric Joyner /************************************************************************
6048eb6488eSEric Joyner  * ixgbe_initialize_transmit_units - Enable transmit units.
6058eb6488eSEric Joyner  ************************************************************************/
606758cc3dcSJack F Vogel static void
607758cc3dcSJack F Vogel ixgbe_initialize_transmit_units(struct adapter *adapter)
608758cc3dcSJack F Vogel {
609758cc3dcSJack F Vogel 	struct tx_ring  *txr = adapter->tx_rings;
610758cc3dcSJack F Vogel 	struct ixgbe_hw *hw = &adapter->hw;
611758cc3dcSJack F Vogel 
612758cc3dcSJack F Vogel 	/* Setup the Base and Length of the Tx Descriptor Ring */
613758cc3dcSJack F Vogel 	for (int i = 0; i < adapter->num_queues; i++, txr++) {
614758cc3dcSJack F Vogel 		u64 tdba = txr->txdma.dma_paddr;
615758cc3dcSJack F Vogel 		u32 txctrl = 0;
61648056c88SJack F Vogel 		int j = txr->me;
617758cc3dcSJack F Vogel 
61848056c88SJack F Vogel 		IXGBE_WRITE_REG(hw, IXGBE_TDBAL(j),
619758cc3dcSJack F Vogel 		    (tdba & 0x00000000ffffffffULL));
62048056c88SJack F Vogel 		IXGBE_WRITE_REG(hw, IXGBE_TDBAH(j), (tdba >> 32));
62148056c88SJack F Vogel 		IXGBE_WRITE_REG(hw, IXGBE_TDLEN(j),
622758cc3dcSJack F Vogel 		    adapter->num_tx_desc * sizeof(union ixgbe_adv_tx_desc));
623758cc3dcSJack F Vogel 
624758cc3dcSJack F Vogel 		/* Setup the HW Tx Head and Tail descriptor pointers */
62548056c88SJack F Vogel 		IXGBE_WRITE_REG(hw, IXGBE_TDH(j), 0);
62648056c88SJack F Vogel 		IXGBE_WRITE_REG(hw, IXGBE_TDT(j), 0);
627758cc3dcSJack F Vogel 
628758cc3dcSJack F Vogel 		/* Cache the tail address */
62948056c88SJack F Vogel 		txr->tail = IXGBE_TDT(j);
630758cc3dcSJack F Vogel 
631758cc3dcSJack F Vogel 		/* Disable Head Writeback */
632a9ca1c79SSean Bruno 		/*
633a9ca1c79SSean Bruno 		 * Note: for X550 series devices, these registers are actually
634a9ca1c79SSean Bruno 		 * prefixed with TPH_ isntead of DCA_, but the addresses and
635a9ca1c79SSean Bruno 		 * fields remain the same.
636a9ca1c79SSean Bruno 		 */
637758cc3dcSJack F Vogel 		switch (hw->mac.type) {
638758cc3dcSJack F Vogel 		case ixgbe_mac_82598EB:
63948056c88SJack F Vogel 			txctrl = IXGBE_READ_REG(hw, IXGBE_DCA_TXCTRL(j));
640758cc3dcSJack F Vogel 			break;
641758cc3dcSJack F Vogel 		default:
64248056c88SJack F Vogel 			txctrl = IXGBE_READ_REG(hw, IXGBE_DCA_TXCTRL_82599(j));
643758cc3dcSJack F Vogel 			break;
644758cc3dcSJack F Vogel 		}
645758cc3dcSJack F Vogel 		txctrl &= ~IXGBE_DCA_TXCTRL_DESC_WRO_EN;
646758cc3dcSJack F Vogel 		switch (hw->mac.type) {
647758cc3dcSJack F Vogel 		case ixgbe_mac_82598EB:
64848056c88SJack F Vogel 			IXGBE_WRITE_REG(hw, IXGBE_DCA_TXCTRL(j), txctrl);
649758cc3dcSJack F Vogel 			break;
650758cc3dcSJack F Vogel 		default:
65148056c88SJack F Vogel 			IXGBE_WRITE_REG(hw, IXGBE_DCA_TXCTRL_82599(j), txctrl);
652758cc3dcSJack F Vogel 			break;
653758cc3dcSJack F Vogel 		}
654758cc3dcSJack F Vogel 
655758cc3dcSJack F Vogel 	}
656758cc3dcSJack F Vogel 
657758cc3dcSJack F Vogel 	if (hw->mac.type != ixgbe_mac_82598EB) {
658758cc3dcSJack F Vogel 		u32 dmatxctl, rttdcs;
6598eb6488eSEric Joyner 
660758cc3dcSJack F Vogel 		dmatxctl = IXGBE_READ_REG(hw, IXGBE_DMATXCTL);
661758cc3dcSJack F Vogel 		dmatxctl |= IXGBE_DMATXCTL_TE;
662758cc3dcSJack F Vogel 		IXGBE_WRITE_REG(hw, IXGBE_DMATXCTL, dmatxctl);
663758cc3dcSJack F Vogel 		/* Disable arbiter to set MTQC */
664758cc3dcSJack F Vogel 		rttdcs = IXGBE_READ_REG(hw, IXGBE_RTTDCS);
665758cc3dcSJack F Vogel 		rttdcs |= IXGBE_RTTDCS_ARBDIS;
666758cc3dcSJack F Vogel 		IXGBE_WRITE_REG(hw, IXGBE_RTTDCS, rttdcs);
6678eb6488eSEric Joyner 		IXGBE_WRITE_REG(hw, IXGBE_MTQC,
6688eb6488eSEric Joyner 		    ixgbe_get_mtqc(adapter->iov_mode));
669758cc3dcSJack F Vogel 		rttdcs &= ~IXGBE_RTTDCS_ARBDIS;
670758cc3dcSJack F Vogel 		IXGBE_WRITE_REG(hw, IXGBE_RTTDCS, rttdcs);
671758cc3dcSJack F Vogel 	}
672758cc3dcSJack F Vogel 
673758cc3dcSJack F Vogel 	return;
6748eb6488eSEric Joyner } /* ixgbe_initialize_transmit_units */
675758cc3dcSJack F Vogel 
6768eb6488eSEric Joyner /************************************************************************
6778eb6488eSEric Joyner  * ixgbe_attach - Device initialization routine
678758cc3dcSJack F Vogel  *
6798eb6488eSEric Joyner  *   Called when the driver is being loaded.
6808eb6488eSEric Joyner  *   Identifies the type of hardware, allocates all resources
6818eb6488eSEric Joyner  *   and initializes the hardware.
682758cc3dcSJack F Vogel  *
6838eb6488eSEric Joyner  *   return 0 on success, positive on failure
6848eb6488eSEric Joyner  ************************************************************************/
6858eb6488eSEric Joyner static int
6868eb6488eSEric Joyner ixgbe_attach(device_t dev)
687758cc3dcSJack F Vogel {
6888eb6488eSEric Joyner 	struct adapter  *adapter;
6898eb6488eSEric Joyner 	struct ixgbe_hw *hw;
6908eb6488eSEric Joyner 	int             error = 0;
6918eb6488eSEric Joyner 	u32             ctrl_ext;
6928eb6488eSEric Joyner 
6938eb6488eSEric Joyner 	INIT_DEBUGOUT("ixgbe_attach: begin");
6948eb6488eSEric Joyner 
6958eb6488eSEric Joyner 	/* Allocate, clear, and link in our adapter structure */
6968eb6488eSEric Joyner 	adapter = device_get_softc(dev);
6978eb6488eSEric Joyner 	adapter->hw.back = adapter;
6988eb6488eSEric Joyner 	adapter->dev = dev;
6998eb6488eSEric Joyner 	hw = &adapter->hw;
7008eb6488eSEric Joyner 
7018eb6488eSEric Joyner 	/* Core Lock Init*/
7028eb6488eSEric Joyner 	IXGBE_CORE_LOCK_INIT(adapter, device_get_nameunit(dev));
7038eb6488eSEric Joyner 
7048eb6488eSEric Joyner 	/* Set up the timer callout */
7058eb6488eSEric Joyner 	callout_init_mtx(&adapter->timer, &adapter->core_mtx, 0);
7068eb6488eSEric Joyner 
7078eb6488eSEric Joyner 	/* Determine hardware revision */
7088eb6488eSEric Joyner 	hw->vendor_id = pci_get_vendor(dev);
7098eb6488eSEric Joyner 	hw->device_id = pci_get_device(dev);
7108eb6488eSEric Joyner 	hw->revision_id = pci_get_revid(dev);
7118eb6488eSEric Joyner 	hw->subsystem_vendor_id = pci_get_subvendor(dev);
7128eb6488eSEric Joyner 	hw->subsystem_device_id = pci_get_subdevice(dev);
713758cc3dcSJack F Vogel 
714758cc3dcSJack F Vogel 	/*
7158eb6488eSEric Joyner 	 * Make sure BUSMASTER is set
716758cc3dcSJack F Vogel 	 */
7178eb6488eSEric Joyner 	pci_enable_busmaster(dev);
718758cc3dcSJack F Vogel 
7198eb6488eSEric Joyner 	/* Do base PCI setup - map BAR0 */
7208eb6488eSEric Joyner 	if (ixgbe_allocate_pci_resources(adapter)) {
7218eb6488eSEric Joyner 		device_printf(dev, "Allocation of PCI resources failed\n");
7228eb6488eSEric Joyner 		error = ENXIO;
7238eb6488eSEric Joyner 		goto err_out;
7246f37f232SEric Joyner 	}
725758cc3dcSJack F Vogel 
7268eb6488eSEric Joyner 	/* let hardware know driver is loaded */
7278eb6488eSEric Joyner 	ctrl_ext = IXGBE_READ_REG(hw, IXGBE_CTRL_EXT);
7288eb6488eSEric Joyner 	ctrl_ext |= IXGBE_CTRL_EXT_DRV_LOAD;
7298eb6488eSEric Joyner 	IXGBE_WRITE_REG(hw, IXGBE_CTRL_EXT, ctrl_ext);
730758cc3dcSJack F Vogel 
731758cc3dcSJack F Vogel 	/*
7328eb6488eSEric Joyner 	 * Initialize the shared code
733758cc3dcSJack F Vogel 	 */
7348eb6488eSEric Joyner 	if (ixgbe_init_shared_code(hw)) {
7358eb6488eSEric Joyner 		device_printf(dev, "Unable to initialize the shared code\n");
7368eb6488eSEric Joyner 		error = ENXIO;
7378eb6488eSEric Joyner 		goto err_out;
73830126537SJack F Vogel 	}
739758cc3dcSJack F Vogel 
7408eb6488eSEric Joyner 	if (hw->mbx.ops.init_params)
7418eb6488eSEric Joyner 		hw->mbx.ops.init_params(hw);
742758cc3dcSJack F Vogel 
7438eb6488eSEric Joyner 	hw->allow_unsupported_sfp = allow_unsupported_sfp;
744758cc3dcSJack F Vogel 
7458eb6488eSEric Joyner 	/* Pick up the 82599 settings */
746758cc3dcSJack F Vogel 	if (hw->mac.type != ixgbe_mac_82598EB) {
7478eb6488eSEric Joyner 		hw->phy.smart_speed = ixgbe_smart_speed;
7488eb6488eSEric Joyner 		adapter->num_segs = IXGBE_82599_SCATTER;
749758cc3dcSJack F Vogel 	} else
7508eb6488eSEric Joyner 		adapter->num_segs = IXGBE_82598_SCATTER;
7518eb6488eSEric Joyner 
7528eb6488eSEric Joyner 	ixgbe_init_device_features(adapter);
7538eb6488eSEric Joyner 
7548eb6488eSEric Joyner 	if (ixgbe_configure_interrupts(adapter)) {
7558eb6488eSEric Joyner 		error = ENXIO;
7568eb6488eSEric Joyner 		goto err_out;
757758cc3dcSJack F Vogel 	}
7588eb6488eSEric Joyner 
7598eb6488eSEric Joyner 	/* Allocate multicast array memory. */
7608eb6488eSEric Joyner 	adapter->mta = malloc(sizeof(*adapter->mta) *
7618eb6488eSEric Joyner 	    MAX_NUM_MULTICAST_ADDRESSES, M_IXGBE, M_NOWAIT);
7628eb6488eSEric Joyner 	if (adapter->mta == NULL) {
7638eb6488eSEric Joyner 		device_printf(dev, "Can not allocate multicast setup array\n");
7648eb6488eSEric Joyner 		error = ENOMEM;
7658eb6488eSEric Joyner 		goto err_out;
766758cc3dcSJack F Vogel 	}
767758cc3dcSJack F Vogel 
7688eb6488eSEric Joyner 	/* Enable WoL (if supported) */
7698eb6488eSEric Joyner 	ixgbe_check_wol_support(adapter);
7708eb6488eSEric Joyner 
7718eb6488eSEric Joyner 	/* Register for VLAN events */
7728eb6488eSEric Joyner 	adapter->vlan_attach = EVENTHANDLER_REGISTER(vlan_config,
7738eb6488eSEric Joyner 	    ixgbe_register_vlan, adapter, EVENTHANDLER_PRI_FIRST);
7748eb6488eSEric Joyner 	adapter->vlan_detach = EVENTHANDLER_REGISTER(vlan_unconfig,
7758eb6488eSEric Joyner 	    ixgbe_unregister_vlan, adapter, EVENTHANDLER_PRI_FIRST);
7768eb6488eSEric Joyner 
7778eb6488eSEric Joyner 	/* Verify adapter fan is still functional (if applicable) */
7788eb6488eSEric Joyner 	if (adapter->feat_en & IXGBE_FEATURE_FAN_FAIL) {
7798eb6488eSEric Joyner 		u32 esdp = IXGBE_READ_REG(hw, IXGBE_ESDP);
7808eb6488eSEric Joyner 		ixgbe_check_fan_failure(adapter, esdp, FALSE);
7818eb6488eSEric Joyner 	}
7828eb6488eSEric Joyner 
7838eb6488eSEric Joyner 	/* Ensure SW/FW semaphore is free */
7848eb6488eSEric Joyner 	ixgbe_init_swfw_semaphore(hw);
7858eb6488eSEric Joyner 
7868eb6488eSEric Joyner 	/* Enable EEE power saving */
7878eb6488eSEric Joyner 	if (adapter->feat_en & IXGBE_FEATURE_EEE)
7888eb6488eSEric Joyner 		hw->mac.ops.setup_eee(hw, TRUE);
7898eb6488eSEric Joyner 
7908eb6488eSEric Joyner 	/* Set an initial default flow control value */
7918eb6488eSEric Joyner 	hw->fc.requested_mode = ixgbe_flow_control;
7928eb6488eSEric Joyner 
7938eb6488eSEric Joyner 	/* Sysctls for limiting the amount of work done in the taskqueues */
7948eb6488eSEric Joyner 	ixgbe_set_sysctl_value(adapter, "rx_processing_limit",
7958eb6488eSEric Joyner 	    "max number of rx packets to process",
7968eb6488eSEric Joyner 	    &adapter->rx_process_limit, ixgbe_rx_process_limit);
7978eb6488eSEric Joyner 
7988eb6488eSEric Joyner 	ixgbe_set_sysctl_value(adapter, "tx_processing_limit",
7998eb6488eSEric Joyner 	    "max number of tx packets to process",
8008eb6488eSEric Joyner 	    &adapter->tx_process_limit, ixgbe_tx_process_limit);
8018eb6488eSEric Joyner 
8028eb6488eSEric Joyner 	/* Do descriptor calc and sanity checks */
8038eb6488eSEric Joyner 	if (((ixgbe_txd * sizeof(union ixgbe_adv_tx_desc)) % DBA_ALIGN) != 0 ||
8048eb6488eSEric Joyner 	    ixgbe_txd < MIN_TXD || ixgbe_txd > MAX_TXD) {
8058eb6488eSEric Joyner 		device_printf(dev, "TXD config issue, using default!\n");
8068eb6488eSEric Joyner 		adapter->num_tx_desc = DEFAULT_TXD;
8078eb6488eSEric Joyner 	} else
8088eb6488eSEric Joyner 		adapter->num_tx_desc = ixgbe_txd;
8098eb6488eSEric Joyner 
810758cc3dcSJack F Vogel 	/*
8118eb6488eSEric Joyner 	 * With many RX rings it is easy to exceed the
8128eb6488eSEric Joyner 	 * system mbuf allocation. Tuning nmbclusters
8138eb6488eSEric Joyner 	 * can alleviate this.
814758cc3dcSJack F Vogel 	 */
8158eb6488eSEric Joyner 	if (nmbclusters > 0) {
8168eb6488eSEric Joyner 		int s;
8178eb6488eSEric Joyner 		s = (ixgbe_rxd * adapter->num_queues) * ixgbe_total_ports;
8188eb6488eSEric Joyner 		if (s > nmbclusters) {
8198eb6488eSEric Joyner 			device_printf(dev, "RX Descriptors exceed system mbuf max, using default instead!\n");
8208eb6488eSEric Joyner 			ixgbe_rxd = DEFAULT_RXD;
8218eb6488eSEric Joyner 		}
822758cc3dcSJack F Vogel 	}
823758cc3dcSJack F Vogel 
8248eb6488eSEric Joyner 	if (((ixgbe_rxd * sizeof(union ixgbe_adv_rx_desc)) % DBA_ALIGN) != 0 ||
8258eb6488eSEric Joyner 	    ixgbe_rxd < MIN_RXD || ixgbe_rxd > MAX_RXD) {
8268eb6488eSEric Joyner 		device_printf(dev, "RXD config issue, using default!\n");
8278eb6488eSEric Joyner 		adapter->num_rx_desc = DEFAULT_RXD;
8288eb6488eSEric Joyner 	} else
8298eb6488eSEric Joyner 		adapter->num_rx_desc = ixgbe_rxd;
8308eb6488eSEric Joyner 
8318eb6488eSEric Joyner 	/* Allocate our TX/RX Queues */
8328eb6488eSEric Joyner 	if (ixgbe_allocate_queues(adapter)) {
8338eb6488eSEric Joyner 		error = ENOMEM;
8348eb6488eSEric Joyner 		goto err_out;
8358eb6488eSEric Joyner 	}
8368eb6488eSEric Joyner 
8378eb6488eSEric Joyner 	hw->phy.reset_if_overtemp = TRUE;
8388eb6488eSEric Joyner 	error = ixgbe_reset_hw(hw);
8398eb6488eSEric Joyner 	hw->phy.reset_if_overtemp = FALSE;
8408eb6488eSEric Joyner 	if (error == IXGBE_ERR_SFP_NOT_PRESENT) {
841758cc3dcSJack F Vogel 		/*
8428eb6488eSEric Joyner 		 * No optics in this port, set up
8438eb6488eSEric Joyner 		 * so the timer routine will probe
8448eb6488eSEric Joyner 		 * for later insertion.
845758cc3dcSJack F Vogel 		 */
8468eb6488eSEric Joyner 		adapter->sfp_probe = TRUE;
8478eb6488eSEric Joyner 		error = IXGBE_SUCCESS;
8488eb6488eSEric Joyner 	} else if (error == IXGBE_ERR_SFP_NOT_SUPPORTED) {
8498eb6488eSEric Joyner 		device_printf(dev, "Unsupported SFP+ module detected!\n");
8508eb6488eSEric Joyner 		error = EIO;
8518eb6488eSEric Joyner 		goto err_late;
8528eb6488eSEric Joyner 	} else if (error) {
8538eb6488eSEric Joyner 		device_printf(dev, "Hardware initialization failed\n");
8548eb6488eSEric Joyner 		error = EIO;
8558eb6488eSEric Joyner 		goto err_late;
85697f9586eSSean Bruno 	}
85797f9586eSSean Bruno 
8588eb6488eSEric Joyner 	/* Make sure we have a good EEPROM before we read from it */
8598eb6488eSEric Joyner 	if (ixgbe_validate_eeprom_checksum(&adapter->hw, NULL) < 0) {
8608eb6488eSEric Joyner 		device_printf(dev, "The EEPROM Checksum Is Not Valid\n");
8618eb6488eSEric Joyner 		error = EIO;
8628eb6488eSEric Joyner 		goto err_late;
86397f9586eSSean Bruno 	}
86497f9586eSSean Bruno 
8658eb6488eSEric Joyner 	/* Setup OS specific network interface */
8668eb6488eSEric Joyner 	if (ixgbe_setup_interface(dev, adapter) != 0)
8678eb6488eSEric Joyner 		goto err_late;
86897f9586eSSean Bruno 
8698eb6488eSEric Joyner 	if (adapter->feat_en & IXGBE_FEATURE_MSIX)
8708eb6488eSEric Joyner 		error = ixgbe_allocate_msix(adapter);
8718eb6488eSEric Joyner 	else
8728eb6488eSEric Joyner 		error = ixgbe_allocate_legacy(adapter);
8738eb6488eSEric Joyner 	if (error)
8748eb6488eSEric Joyner 		goto err_late;
87548056c88SJack F Vogel 
8768eb6488eSEric Joyner 	error = ixgbe_start_hw(hw);
8778eb6488eSEric Joyner 	switch (error) {
8788eb6488eSEric Joyner 	case IXGBE_ERR_EEPROM_VERSION:
8798eb6488eSEric Joyner 		device_printf(dev, "This device is a pre-production adapter/LOM.  Please be aware there may be issues associated with your hardware.\nIf you are experiencing problems please contact your Intel or hardware representative who provided you with this hardware.\n");
88097f9586eSSean Bruno 		break;
8818eb6488eSEric Joyner 	case IXGBE_ERR_SFP_NOT_SUPPORTED:
8828eb6488eSEric Joyner 		device_printf(dev, "Unsupported SFP+ Module\n");
8838eb6488eSEric Joyner 		error = EIO;
8848eb6488eSEric Joyner 		goto err_late;
8858eb6488eSEric Joyner 	case IXGBE_ERR_SFP_NOT_PRESENT:
8868eb6488eSEric Joyner 		device_printf(dev, "No SFP+ Module found\n");
8878eb6488eSEric Joyner 		/* falls thru */
88897f9586eSSean Bruno 	default:
88997f9586eSSean Bruno 		break;
89097f9586eSSean Bruno 	}
89197f9586eSSean Bruno 
8928eb6488eSEric Joyner 	/* Enable the optics for 82599 SFP+ fiber */
8938eb6488eSEric Joyner 	ixgbe_enable_tx_laser(hw);
894758cc3dcSJack F Vogel 
8958eb6488eSEric Joyner 	/* Enable power to the phy. */
8968eb6488eSEric Joyner 	ixgbe_set_phy_power(hw, TRUE);
8978eb6488eSEric Joyner 
8988eb6488eSEric Joyner 	/* Initialize statistics */
8998eb6488eSEric Joyner 	ixgbe_update_stats_counters(adapter);
9008eb6488eSEric Joyner 
9018eb6488eSEric Joyner 	/* Check PCIE slot type/speed/width */
9028eb6488eSEric Joyner 	ixgbe_get_slot_info(adapter);
903758cc3dcSJack F Vogel 
904758cc3dcSJack F Vogel 	/*
9058eb6488eSEric Joyner 	 * Do time init and sysctl init here, but
9068eb6488eSEric Joyner 	 * only on the first port of a bypass adapter.
907758cc3dcSJack F Vogel 	 */
9088eb6488eSEric Joyner 	ixgbe_bypass_init(adapter);
909758cc3dcSJack F Vogel 
9108eb6488eSEric Joyner 	/* Set an initial dmac value */
9118eb6488eSEric Joyner 	adapter->dmac = 0;
9128eb6488eSEric Joyner 	/* Set initial advertised speeds (if applicable) */
9138eb6488eSEric Joyner 	adapter->advertise = ixgbe_get_advertise(adapter);
914758cc3dcSJack F Vogel 
9158eb6488eSEric Joyner 	if (adapter->feat_cap & IXGBE_FEATURE_SRIOV)
9168eb6488eSEric Joyner 		ixgbe_define_iov_schemas(dev, &error);
917758cc3dcSJack F Vogel 
9188eb6488eSEric Joyner 	/* Add sysctls */
9198eb6488eSEric Joyner 	ixgbe_add_device_sysctls(adapter);
9208eb6488eSEric Joyner 	ixgbe_add_hw_stats(adapter);
921758cc3dcSJack F Vogel 
9228eb6488eSEric Joyner 	/* For Netmap */
9238eb6488eSEric Joyner 	adapter->init_locked = ixgbe_init_locked;
9248eb6488eSEric Joyner 	adapter->stop_locked = ixgbe_stop;
9256f37f232SEric Joyner 
9268eb6488eSEric Joyner 	if (adapter->feat_en & IXGBE_FEATURE_NETMAP)
9278eb6488eSEric Joyner 		ixgbe_netmap_attach(adapter);
9286f37f232SEric Joyner 
9298eb6488eSEric Joyner 	INIT_DEBUGOUT("ixgbe_attach: end");
930758cc3dcSJack F Vogel 
9318eb6488eSEric Joyner 	return (0);
932758cc3dcSJack F Vogel 
9338eb6488eSEric Joyner err_late:
9348eb6488eSEric Joyner 	ixgbe_free_transmit_structures(adapter);
9358eb6488eSEric Joyner 	ixgbe_free_receive_structures(adapter);
9368eb6488eSEric Joyner 	free(adapter->queues, M_DEVBUF);
9378eb6488eSEric Joyner err_out:
9388eb6488eSEric Joyner 	if (adapter->ifp != NULL)
9398eb6488eSEric Joyner 		if_free(adapter->ifp);
9408eb6488eSEric Joyner 	ctrl_ext = IXGBE_READ_REG(&adapter->hw, IXGBE_CTRL_EXT);
9418eb6488eSEric Joyner 	ctrl_ext &= ~IXGBE_CTRL_EXT_DRV_LOAD;
9428eb6488eSEric Joyner 	IXGBE_WRITE_REG(&adapter->hw, IXGBE_CTRL_EXT, ctrl_ext);
9438eb6488eSEric Joyner 	ixgbe_free_pci_resources(adapter);
9448eb6488eSEric Joyner 	free(adapter->mta, M_IXGBE);
9458eb6488eSEric Joyner 	IXGBE_CORE_LOCK_DESTROY(adapter);
9468eb6488eSEric Joyner 
9478eb6488eSEric Joyner 	return (error);
9488eb6488eSEric Joyner } /* ixgbe_attach */
9498eb6488eSEric Joyner 
9508eb6488eSEric Joyner /************************************************************************
9518eb6488eSEric Joyner  * ixgbe_check_wol_support
9526f37f232SEric Joyner  *
9536f37f232SEric Joyner  *   Checks whether the adapter's ports are capable of
9546f37f232SEric Joyner  *   Wake On LAN by reading the adapter's NVM.
9556f37f232SEric Joyner  *
9566f37f232SEric Joyner  *   Sets each port's hw->wol_enabled value depending
9576f37f232SEric Joyner  *   on the value read here.
9588eb6488eSEric Joyner  ************************************************************************/
9596f37f232SEric Joyner static void
9606f37f232SEric Joyner ixgbe_check_wol_support(struct adapter *adapter)
9616f37f232SEric Joyner {
9626f37f232SEric Joyner 	struct ixgbe_hw *hw = &adapter->hw;
9636f37f232SEric Joyner 	u16             dev_caps = 0;
9646f37f232SEric Joyner 
9656f37f232SEric Joyner 	/* Find out WoL support for port */
9666f37f232SEric Joyner 	adapter->wol_support = hw->wol_enabled = 0;
9676f37f232SEric Joyner 	ixgbe_get_device_caps(hw, &dev_caps);
9686f37f232SEric Joyner 	if ((dev_caps & IXGBE_DEVICE_CAPS_WOL_PORT0_1) ||
9696f37f232SEric Joyner 	    ((dev_caps & IXGBE_DEVICE_CAPS_WOL_PORT0) &&
9706f37f232SEric Joyner 	     hw->bus.func == 0))
9716f37f232SEric Joyner 		adapter->wol_support = hw->wol_enabled = 1;
9726f37f232SEric Joyner 
9736f37f232SEric Joyner 	/* Save initial wake up filter configuration */
9746f37f232SEric Joyner 	adapter->wufc = IXGBE_READ_REG(hw, IXGBE_WUFC);
9756f37f232SEric Joyner 
9766f37f232SEric Joyner 	return;
9778eb6488eSEric Joyner } /* ixgbe_check_wol_support */
9786f37f232SEric Joyner 
9798eb6488eSEric Joyner /************************************************************************
9808eb6488eSEric Joyner  * ixgbe_setup_interface
9818eb6488eSEric Joyner  *
9828eb6488eSEric Joyner  *   Setup networking device structure and register an interface.
9838eb6488eSEric Joyner  ************************************************************************/
9846f37f232SEric Joyner static int
9858eb6488eSEric Joyner ixgbe_setup_interface(device_t dev, struct adapter *adapter)
9866f37f232SEric Joyner {
9878eb6488eSEric Joyner 	struct ifnet *ifp;
9886f37f232SEric Joyner 
9898eb6488eSEric Joyner 	INIT_DEBUGOUT("ixgbe_setup_interface: begin");
9906f37f232SEric Joyner 
9918eb6488eSEric Joyner 	ifp = adapter->ifp = if_alloc(IFT_ETHER);
9928eb6488eSEric Joyner 	if (ifp == NULL) {
9938eb6488eSEric Joyner 		device_printf(dev, "can not allocate ifnet structure\n");
9948eb6488eSEric Joyner 		return (-1);
9958eb6488eSEric Joyner 	}
9968eb6488eSEric Joyner 	if_initname(ifp, device_get_name(dev), device_get_unit(dev));
9978eb6488eSEric Joyner 	ifp->if_baudrate = IF_Gbps(10);
9988eb6488eSEric Joyner 	ifp->if_init = ixgbe_init;
9998eb6488eSEric Joyner 	ifp->if_softc = adapter;
10008eb6488eSEric Joyner 	ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
10018eb6488eSEric Joyner 	ifp->if_ioctl = ixgbe_ioctl;
10028eb6488eSEric Joyner #if __FreeBSD_version >= 1100036
10038eb6488eSEric Joyner 	if_setgetcounterfn(ifp, ixgbe_get_counter);
10048eb6488eSEric Joyner #endif
10058eb6488eSEric Joyner #if __FreeBSD_version >= 1100045
10068eb6488eSEric Joyner 	/* TSO parameters */
10078eb6488eSEric Joyner 	ifp->if_hw_tsomax = 65518;
10088eb6488eSEric Joyner 	ifp->if_hw_tsomaxsegcount = IXGBE_82599_SCATTER;
10098eb6488eSEric Joyner 	ifp->if_hw_tsomaxsegsize = 2048;
10108eb6488eSEric Joyner #endif
10118eb6488eSEric Joyner 	if (adapter->feat_en & IXGBE_FEATURE_LEGACY_TX) {
10128eb6488eSEric Joyner 		ifp->if_start = ixgbe_legacy_start;
10138eb6488eSEric Joyner 		IFQ_SET_MAXLEN(&ifp->if_snd, adapter->num_tx_desc - 2);
10148eb6488eSEric Joyner 		ifp->if_snd.ifq_drv_maxlen = adapter->num_tx_desc - 2;
10158eb6488eSEric Joyner 		IFQ_SET_READY(&ifp->if_snd);
10168eb6488eSEric Joyner 		ixgbe_start_locked = ixgbe_legacy_start_locked;
10178eb6488eSEric Joyner 		ixgbe_ring_empty = ixgbe_legacy_ring_empty;
10186f37f232SEric Joyner 	} else {
10198eb6488eSEric Joyner 		ifp->if_transmit = ixgbe_mq_start;
10208eb6488eSEric Joyner 		ifp->if_qflush = ixgbe_qflush;
10218eb6488eSEric Joyner 		ixgbe_start_locked = ixgbe_mq_start_locked;
10228eb6488eSEric Joyner 		ixgbe_ring_empty = drbr_empty;
10236f37f232SEric Joyner 	}
10246f37f232SEric Joyner 
10258eb6488eSEric Joyner 	ether_ifattach(ifp, adapter->hw.mac.addr);
10266f37f232SEric Joyner 
10278eb6488eSEric Joyner 	adapter->max_frame_size = ifp->if_mtu + ETHER_HDR_LEN + ETHER_CRC_LEN;
1028758cc3dcSJack F Vogel 
1029758cc3dcSJack F Vogel 	/*
10308eb6488eSEric Joyner 	 * Tell the upper layer(s) we support long frames.
1031758cc3dcSJack F Vogel 	 */
10328eb6488eSEric Joyner 	ifp->if_hdrlen = sizeof(struct ether_vlan_header);
1033758cc3dcSJack F Vogel 
10348eb6488eSEric Joyner 	/* Set capability flags */
10358eb6488eSEric Joyner 	ifp->if_capabilities |= IFCAP_HWCSUM
10368eb6488eSEric Joyner 	                     |  IFCAP_HWCSUM_IPV6
10378eb6488eSEric Joyner 	                     |  IFCAP_TSO
10388eb6488eSEric Joyner 	                     |  IFCAP_LRO
10398eb6488eSEric Joyner 	                     |  IFCAP_VLAN_HWTAGGING
10408eb6488eSEric Joyner 	                     |  IFCAP_VLAN_HWTSO
10418eb6488eSEric Joyner 	                     |  IFCAP_VLAN_HWCSUM
10428eb6488eSEric Joyner 	                     |  IFCAP_JUMBO_MTU
10438eb6488eSEric Joyner 	                     |  IFCAP_VLAN_MTU
10448eb6488eSEric Joyner 	                     |  IFCAP_HWSTATS;
1045758cc3dcSJack F Vogel 
10468eb6488eSEric Joyner 	/* Enable the above capabilities by default */
10478eb6488eSEric Joyner 	ifp->if_capenable = ifp->if_capabilities;
1048758cc3dcSJack F Vogel 
10498eb6488eSEric Joyner 	/*
10508eb6488eSEric Joyner 	 * Don't turn this on by default, if vlans are
10518eb6488eSEric Joyner 	 * created on another pseudo device (eg. lagg)
10528eb6488eSEric Joyner 	 * then vlan events are not passed thru, breaking
10538eb6488eSEric Joyner 	 * operation, but with HW FILTER off it works. If
10548eb6488eSEric Joyner 	 * using vlans directly on the ixgbe driver you can
10558eb6488eSEric Joyner 	 * enable this and get full hardware tag filtering.
10568eb6488eSEric Joyner 	 */
10578eb6488eSEric Joyner 	ifp->if_capabilities |= IFCAP_VLAN_HWFILTER;
1058758cc3dcSJack F Vogel 
10598eb6488eSEric Joyner 	/*
10608eb6488eSEric Joyner 	 * Specify the media types supported by this adapter and register
10618eb6488eSEric Joyner 	 * callbacks to update media and link information
10628eb6488eSEric Joyner 	 */
10638eb6488eSEric Joyner 	ifmedia_init(&adapter->media, IFM_IMASK, ixgbe_media_change,
10648eb6488eSEric Joyner 	    ixgbe_media_status);
1065758cc3dcSJack F Vogel 
10668eb6488eSEric Joyner 	adapter->phy_layer = ixgbe_get_supported_physical_layer(&adapter->hw);
10678eb6488eSEric Joyner 	ixgbe_add_media_types(adapter);
10688eb6488eSEric Joyner 
10698eb6488eSEric Joyner 	/* Set autoselect media by default */
10708eb6488eSEric Joyner 	ifmedia_set(&adapter->media, IFM_ETHER | IFM_AUTO);
10718eb6488eSEric Joyner 
10728eb6488eSEric Joyner 	return (0);
10738eb6488eSEric Joyner } /* ixgbe_setup_interface */
1074758cc3dcSJack F Vogel 
1075758cc3dcSJack F Vogel #if __FreeBSD_version >= 1100036
10768eb6488eSEric Joyner /************************************************************************
10778eb6488eSEric Joyner  * ixgbe_get_counter
10788eb6488eSEric Joyner  ************************************************************************/
1079758cc3dcSJack F Vogel static uint64_t
1080758cc3dcSJack F Vogel ixgbe_get_counter(struct ifnet *ifp, ift_counter cnt)
1081758cc3dcSJack F Vogel {
1082758cc3dcSJack F Vogel 	struct adapter *adapter;
1083625d12c6SJohn Baldwin 	struct tx_ring *txr;
1084625d12c6SJohn Baldwin 	uint64_t       rv;
1085758cc3dcSJack F Vogel 
1086758cc3dcSJack F Vogel 	adapter = if_getsoftc(ifp);
1087758cc3dcSJack F Vogel 
1088758cc3dcSJack F Vogel 	switch (cnt) {
1089758cc3dcSJack F Vogel 	case IFCOUNTER_IPACKETS:
1090758cc3dcSJack F Vogel 		return (adapter->ipackets);
1091758cc3dcSJack F Vogel 	case IFCOUNTER_OPACKETS:
1092758cc3dcSJack F Vogel 		return (adapter->opackets);
1093758cc3dcSJack F Vogel 	case IFCOUNTER_IBYTES:
1094758cc3dcSJack F Vogel 		return (adapter->ibytes);
1095758cc3dcSJack F Vogel 	case IFCOUNTER_OBYTES:
1096758cc3dcSJack F Vogel 		return (adapter->obytes);
1097758cc3dcSJack F Vogel 	case IFCOUNTER_IMCASTS:
1098758cc3dcSJack F Vogel 		return (adapter->imcasts);
1099758cc3dcSJack F Vogel 	case IFCOUNTER_OMCASTS:
1100758cc3dcSJack F Vogel 		return (adapter->omcasts);
1101758cc3dcSJack F Vogel 	case IFCOUNTER_COLLISIONS:
1102758cc3dcSJack F Vogel 		return (0);
1103758cc3dcSJack F Vogel 	case IFCOUNTER_IQDROPS:
1104758cc3dcSJack F Vogel 		return (adapter->iqdrops);
1105625d12c6SJohn Baldwin 	case IFCOUNTER_OQDROPS:
1106625d12c6SJohn Baldwin 		rv = 0;
1107625d12c6SJohn Baldwin 		txr = adapter->tx_rings;
1108625d12c6SJohn Baldwin 		for (int i = 0; i < adapter->num_queues; i++, txr++)
1109625d12c6SJohn Baldwin 			rv += txr->br->br_drops;
1110625d12c6SJohn Baldwin 		return (rv);
1111758cc3dcSJack F Vogel 	case IFCOUNTER_IERRORS:
1112758cc3dcSJack F Vogel 		return (adapter->ierrors);
1113758cc3dcSJack F Vogel 	default:
1114758cc3dcSJack F Vogel 		return (if_get_counter_default(ifp, cnt));
1115758cc3dcSJack F Vogel 	}
11168eb6488eSEric Joyner } /* ixgbe_get_counter */
1117758cc3dcSJack F Vogel #endif
1118758cc3dcSJack F Vogel 
11198eb6488eSEric Joyner /************************************************************************
11208eb6488eSEric Joyner  * ixgbe_add_media_types
11218eb6488eSEric Joyner  ************************************************************************/
11228eb6488eSEric Joyner static void
11238eb6488eSEric Joyner ixgbe_add_media_types(struct adapter *adapter)
11248eb6488eSEric Joyner {
11258eb6488eSEric Joyner 	struct ixgbe_hw *hw = &adapter->hw;
11268eb6488eSEric Joyner 	device_t        dev = adapter->dev;
11278eb6488eSEric Joyner 	u64             layer;
11288eb6488eSEric Joyner 
11298eb6488eSEric Joyner 	layer = adapter->phy_layer;
11308eb6488eSEric Joyner 
11318eb6488eSEric Joyner 	/* Media types with matching FreeBSD media defines */
11328eb6488eSEric Joyner 	if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_T)
11338eb6488eSEric Joyner 		ifmedia_add(&adapter->media, IFM_ETHER | IFM_10G_T, 0, NULL);
11348eb6488eSEric Joyner 	if (layer & IXGBE_PHYSICAL_LAYER_1000BASE_T)
11358eb6488eSEric Joyner 		ifmedia_add(&adapter->media, IFM_ETHER | IFM_1000_T, 0, NULL);
11368eb6488eSEric Joyner 	if (layer & IXGBE_PHYSICAL_LAYER_100BASE_TX)
11378eb6488eSEric Joyner 		ifmedia_add(&adapter->media, IFM_ETHER | IFM_100_TX, 0, NULL);
11388eb6488eSEric Joyner 	if (layer & IXGBE_PHYSICAL_LAYER_10BASE_T)
11398eb6488eSEric Joyner 		ifmedia_add(&adapter->media, IFM_ETHER | IFM_10_T, 0, NULL);
11408eb6488eSEric Joyner 
11418eb6488eSEric Joyner 	if (layer & IXGBE_PHYSICAL_LAYER_SFP_PLUS_CU ||
11428eb6488eSEric Joyner 	    layer & IXGBE_PHYSICAL_LAYER_SFP_ACTIVE_DA)
11438eb6488eSEric Joyner 		ifmedia_add(&adapter->media, IFM_ETHER | IFM_10G_TWINAX, 0,
11448eb6488eSEric Joyner 		    NULL);
11458eb6488eSEric Joyner 
11468eb6488eSEric Joyner 	if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_LR) {
11478eb6488eSEric Joyner 		ifmedia_add(&adapter->media, IFM_ETHER | IFM_10G_LR, 0, NULL);
11488eb6488eSEric Joyner 		if (hw->phy.multispeed_fiber)
11498eb6488eSEric Joyner 			ifmedia_add(&adapter->media, IFM_ETHER | IFM_1000_LX, 0,
11508eb6488eSEric Joyner 			    NULL);
11518eb6488eSEric Joyner 	}
11528eb6488eSEric Joyner 	if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_SR) {
11538eb6488eSEric Joyner 		ifmedia_add(&adapter->media, IFM_ETHER | IFM_10G_SR, 0, NULL);
11548eb6488eSEric Joyner 		if (hw->phy.multispeed_fiber)
11558eb6488eSEric Joyner 			ifmedia_add(&adapter->media, IFM_ETHER | IFM_1000_SX, 0,
11568eb6488eSEric Joyner 			    NULL);
11578eb6488eSEric Joyner 	} else if (layer & IXGBE_PHYSICAL_LAYER_1000BASE_SX)
11588eb6488eSEric Joyner 		ifmedia_add(&adapter->media, IFM_ETHER | IFM_1000_SX, 0, NULL);
11598eb6488eSEric Joyner 	if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_CX4)
11608eb6488eSEric Joyner 		ifmedia_add(&adapter->media, IFM_ETHER | IFM_10G_CX4, 0, NULL);
11618eb6488eSEric Joyner 
11628eb6488eSEric Joyner #ifdef IFM_ETH_XTYPE
11638eb6488eSEric Joyner 	if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_KR)
11648eb6488eSEric Joyner 		ifmedia_add(&adapter->media, IFM_ETHER | IFM_10G_KR, 0, NULL);
11658eb6488eSEric Joyner 	if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_KX4)
11668eb6488eSEric Joyner 		ifmedia_add(&adapter->media, IFM_ETHER | IFM_10G_KX4, 0, NULL);
11678eb6488eSEric Joyner 	if (layer & IXGBE_PHYSICAL_LAYER_1000BASE_KX)
11688eb6488eSEric Joyner 		ifmedia_add(&adapter->media, IFM_ETHER | IFM_1000_KX, 0, NULL);
11698eb6488eSEric Joyner 	if (layer & IXGBE_PHYSICAL_LAYER_2500BASE_KX)
11708eb6488eSEric Joyner 		ifmedia_add(&adapter->media, IFM_ETHER | IFM_2500_KX, 0, NULL);
11718eb6488eSEric Joyner #else
11728eb6488eSEric Joyner 	if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_KR) {
11738eb6488eSEric Joyner 		device_printf(dev, "Media supported: 10GbaseKR\n");
11748eb6488eSEric Joyner 		device_printf(dev, "10GbaseKR mapped to 10GbaseSR\n");
11758eb6488eSEric Joyner 		ifmedia_add(&adapter->media, IFM_ETHER | IFM_10G_SR, 0, NULL);
11768eb6488eSEric Joyner 	}
11778eb6488eSEric Joyner 	if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_KX4) {
11788eb6488eSEric Joyner 		device_printf(dev, "Media supported: 10GbaseKX4\n");
11798eb6488eSEric Joyner 		device_printf(dev, "10GbaseKX4 mapped to 10GbaseCX4\n");
11808eb6488eSEric Joyner 		ifmedia_add(&adapter->media, IFM_ETHER | IFM_10G_CX4, 0, NULL);
11818eb6488eSEric Joyner 	}
11828eb6488eSEric Joyner 	if (layer & IXGBE_PHYSICAL_LAYER_1000BASE_KX) {
11838eb6488eSEric Joyner 		device_printf(dev, "Media supported: 1000baseKX\n");
11848eb6488eSEric Joyner 		device_printf(dev, "1000baseKX mapped to 1000baseCX\n");
11858eb6488eSEric Joyner 		ifmedia_add(&adapter->media, IFM_ETHER | IFM_1000_CX, 0, NULL);
11868eb6488eSEric Joyner 	}
11878eb6488eSEric Joyner 	if (layer & IXGBE_PHYSICAL_LAYER_2500BASE_KX) {
11888eb6488eSEric Joyner 		device_printf(dev, "Media supported: 2500baseKX\n");
11898eb6488eSEric Joyner 		device_printf(dev, "2500baseKX mapped to 2500baseSX\n");
11908eb6488eSEric Joyner 		ifmedia_add(&adapter->media, IFM_ETHER | IFM_2500_SX, 0, NULL);
11918eb6488eSEric Joyner 	}
11928eb6488eSEric Joyner #endif
11938eb6488eSEric Joyner 	if (layer & IXGBE_PHYSICAL_LAYER_1000BASE_BX)
11948eb6488eSEric Joyner 		device_printf(dev, "Media supported: 1000baseBX\n");
11958eb6488eSEric Joyner 
11968eb6488eSEric Joyner 	if (hw->device_id == IXGBE_DEV_ID_82598AT) {
11978eb6488eSEric Joyner 		ifmedia_add(&adapter->media, IFM_ETHER | IFM_1000_T | IFM_FDX,
11988eb6488eSEric Joyner 		    0, NULL);
11998eb6488eSEric Joyner 		ifmedia_add(&adapter->media, IFM_ETHER | IFM_1000_T, 0, NULL);
12008eb6488eSEric Joyner 	}
12018eb6488eSEric Joyner 
12028eb6488eSEric Joyner 	ifmedia_add(&adapter->media, IFM_ETHER | IFM_AUTO, 0, NULL);
12038eb6488eSEric Joyner } /* ixgbe_add_media_types */
12048eb6488eSEric Joyner 
12058eb6488eSEric Joyner /************************************************************************
12068eb6488eSEric Joyner  * ixgbe_is_sfp
12078eb6488eSEric Joyner  ************************************************************************/
12088eb6488eSEric Joyner static inline bool
12098eb6488eSEric Joyner ixgbe_is_sfp(struct ixgbe_hw *hw)
12108eb6488eSEric Joyner {
12118eb6488eSEric Joyner 	switch (hw->mac.type) {
12128eb6488eSEric Joyner 	case ixgbe_mac_82598EB:
12138eb6488eSEric Joyner 		if (hw->phy.type == ixgbe_phy_nl)
12148eb6488eSEric Joyner 			return TRUE;
12158eb6488eSEric Joyner 		return FALSE;
12168eb6488eSEric Joyner 	case ixgbe_mac_82599EB:
12178eb6488eSEric Joyner 		switch (hw->mac.ops.get_media_type(hw)) {
12188eb6488eSEric Joyner 		case ixgbe_media_type_fiber:
12198eb6488eSEric Joyner 		case ixgbe_media_type_fiber_qsfp:
12208eb6488eSEric Joyner 			return TRUE;
12218eb6488eSEric Joyner 		default:
12228eb6488eSEric Joyner 			return FALSE;
12238eb6488eSEric Joyner 		}
12248eb6488eSEric Joyner 	case ixgbe_mac_X550EM_x:
12258eb6488eSEric Joyner 	case ixgbe_mac_X550EM_a:
12268eb6488eSEric Joyner 		if (hw->mac.ops.get_media_type(hw) == ixgbe_media_type_fiber)
12278eb6488eSEric Joyner 			return TRUE;
12288eb6488eSEric Joyner 		return FALSE;
12298eb6488eSEric Joyner 	default:
12308eb6488eSEric Joyner 		return FALSE;
12318eb6488eSEric Joyner 	}
12328eb6488eSEric Joyner } /* ixgbe_is_sfp */
12338eb6488eSEric Joyner 
12348eb6488eSEric Joyner /************************************************************************
12358eb6488eSEric Joyner  * ixgbe_config_link
12368eb6488eSEric Joyner  ************************************************************************/
12378eb6488eSEric Joyner static void
12388eb6488eSEric Joyner ixgbe_config_link(struct adapter *adapter)
12398eb6488eSEric Joyner {
12408eb6488eSEric Joyner 	struct ixgbe_hw *hw = &adapter->hw;
12418eb6488eSEric Joyner 	u32             autoneg, err = 0;
12428eb6488eSEric Joyner 	bool            sfp, negotiate;
12438eb6488eSEric Joyner 
12448eb6488eSEric Joyner 	sfp = ixgbe_is_sfp(hw);
12458eb6488eSEric Joyner 
12468eb6488eSEric Joyner 	if (sfp) {
12478eb6488eSEric Joyner 		if (hw->phy.multispeed_fiber) {
12488eb6488eSEric Joyner 			hw->mac.ops.setup_sfp(hw);
12498eb6488eSEric Joyner 			ixgbe_enable_tx_laser(hw);
12508eb6488eSEric Joyner 			taskqueue_enqueue(adapter->tq, &adapter->msf_task);
12518eb6488eSEric Joyner 		} else
12528eb6488eSEric Joyner 			taskqueue_enqueue(adapter->tq, &adapter->mod_task);
12538eb6488eSEric Joyner 	} else {
12548eb6488eSEric Joyner 		if (hw->mac.ops.check_link)
12558eb6488eSEric Joyner 			err = ixgbe_check_link(hw, &adapter->link_speed,
12568eb6488eSEric Joyner 			    &adapter->link_up, FALSE);
12578eb6488eSEric Joyner 		if (err)
12588eb6488eSEric Joyner 			goto out;
12598eb6488eSEric Joyner 		autoneg = hw->phy.autoneg_advertised;
12608eb6488eSEric Joyner 		if ((!autoneg) && (hw->mac.ops.get_link_capabilities))
12618eb6488eSEric Joyner 			err = hw->mac.ops.get_link_capabilities(hw, &autoneg,
12628eb6488eSEric Joyner 			    &negotiate);
12638eb6488eSEric Joyner 		if (err)
12648eb6488eSEric Joyner 			goto out;
12658eb6488eSEric Joyner 		if (hw->mac.ops.setup_link)
12668eb6488eSEric Joyner 			err = hw->mac.ops.setup_link(hw, autoneg,
12678eb6488eSEric Joyner 			    adapter->link_up);
12688eb6488eSEric Joyner 	}
12698eb6488eSEric Joyner out:
12708eb6488eSEric Joyner 
12718eb6488eSEric Joyner 	return;
12728eb6488eSEric Joyner } /* ixgbe_config_link */
12738eb6488eSEric Joyner 
12748eb6488eSEric Joyner /************************************************************************
12758eb6488eSEric Joyner  * ixgbe_update_stats_counters - Update board statistics counters.
12768eb6488eSEric Joyner  ************************************************************************/
12778eb6488eSEric Joyner static void
12788eb6488eSEric Joyner ixgbe_update_stats_counters(struct adapter *adapter)
12798eb6488eSEric Joyner {
12808eb6488eSEric Joyner 	struct ixgbe_hw       *hw = &adapter->hw;
12818eb6488eSEric Joyner 	struct ixgbe_hw_stats *stats = &adapter->stats.pf;
12828eb6488eSEric Joyner 	u32                   missed_rx = 0, bprc, lxon, lxoff, total;
12838eb6488eSEric Joyner 	u64                   total_missed_rx = 0;
12848eb6488eSEric Joyner 
12858eb6488eSEric Joyner 	stats->crcerrs += IXGBE_READ_REG(hw, IXGBE_CRCERRS);
12868eb6488eSEric Joyner 	stats->illerrc += IXGBE_READ_REG(hw, IXGBE_ILLERRC);
12878eb6488eSEric Joyner 	stats->errbc += IXGBE_READ_REG(hw, IXGBE_ERRBC);
12888eb6488eSEric Joyner 	stats->mspdc += IXGBE_READ_REG(hw, IXGBE_MSPDC);
12898eb6488eSEric Joyner 	stats->mpc[0] += IXGBE_READ_REG(hw, IXGBE_MPC(0));
12908eb6488eSEric Joyner 
12918eb6488eSEric Joyner 	for (int i = 0; i < 16; i++) {
12928eb6488eSEric Joyner 		stats->qprc[i] += IXGBE_READ_REG(hw, IXGBE_QPRC(i));
12938eb6488eSEric Joyner 		stats->qptc[i] += IXGBE_READ_REG(hw, IXGBE_QPTC(i));
12948eb6488eSEric Joyner 		stats->qprdc[i] += IXGBE_READ_REG(hw, IXGBE_QPRDC(i));
12958eb6488eSEric Joyner 	}
12968eb6488eSEric Joyner 	stats->mlfc += IXGBE_READ_REG(hw, IXGBE_MLFC);
12978eb6488eSEric Joyner 	stats->mrfc += IXGBE_READ_REG(hw, IXGBE_MRFC);
12988eb6488eSEric Joyner 	stats->rlec += IXGBE_READ_REG(hw, IXGBE_RLEC);
12998eb6488eSEric Joyner 
13008eb6488eSEric Joyner 	/* Hardware workaround, gprc counts missed packets */
13018eb6488eSEric Joyner 	stats->gprc += IXGBE_READ_REG(hw, IXGBE_GPRC);
13028eb6488eSEric Joyner 	stats->gprc -= missed_rx;
13038eb6488eSEric Joyner 
13048eb6488eSEric Joyner 	if (hw->mac.type != ixgbe_mac_82598EB) {
13058eb6488eSEric Joyner 		stats->gorc += IXGBE_READ_REG(hw, IXGBE_GORCL) +
13068eb6488eSEric Joyner 		    ((u64)IXGBE_READ_REG(hw, IXGBE_GORCH) << 32);
13078eb6488eSEric Joyner 		stats->gotc += IXGBE_READ_REG(hw, IXGBE_GOTCL) +
13088eb6488eSEric Joyner 		    ((u64)IXGBE_READ_REG(hw, IXGBE_GOTCH) << 32);
13098eb6488eSEric Joyner 		stats->tor += IXGBE_READ_REG(hw, IXGBE_TORL) +
13108eb6488eSEric Joyner 		    ((u64)IXGBE_READ_REG(hw, IXGBE_TORH) << 32);
13118eb6488eSEric Joyner 		stats->lxonrxc += IXGBE_READ_REG(hw, IXGBE_LXONRXCNT);
13128eb6488eSEric Joyner 		stats->lxoffrxc += IXGBE_READ_REG(hw, IXGBE_LXOFFRXCNT);
13138eb6488eSEric Joyner 	} else {
13148eb6488eSEric Joyner 		stats->lxonrxc += IXGBE_READ_REG(hw, IXGBE_LXONRXC);
13158eb6488eSEric Joyner 		stats->lxoffrxc += IXGBE_READ_REG(hw, IXGBE_LXOFFRXC);
13168eb6488eSEric Joyner 		/* 82598 only has a counter in the high register */
13178eb6488eSEric Joyner 		stats->gorc += IXGBE_READ_REG(hw, IXGBE_GORCH);
13188eb6488eSEric Joyner 		stats->gotc += IXGBE_READ_REG(hw, IXGBE_GOTCH);
13198eb6488eSEric Joyner 		stats->tor += IXGBE_READ_REG(hw, IXGBE_TORH);
13208eb6488eSEric Joyner 	}
13218eb6488eSEric Joyner 
13228eb6488eSEric Joyner 	/*
13238eb6488eSEric Joyner 	 * Workaround: mprc hardware is incorrectly counting
13248eb6488eSEric Joyner 	 * broadcasts, so for now we subtract those.
1325758cc3dcSJack F Vogel 	 */
13268eb6488eSEric Joyner 	bprc = IXGBE_READ_REG(hw, IXGBE_BPRC);
13278eb6488eSEric Joyner 	stats->bprc += bprc;
13288eb6488eSEric Joyner 	stats->mprc += IXGBE_READ_REG(hw, IXGBE_MPRC);
13298eb6488eSEric Joyner 	if (hw->mac.type == ixgbe_mac_82598EB)
13308eb6488eSEric Joyner 		stats->mprc -= bprc;
13318eb6488eSEric Joyner 
13328eb6488eSEric Joyner 	stats->prc64 += IXGBE_READ_REG(hw, IXGBE_PRC64);
13338eb6488eSEric Joyner 	stats->prc127 += IXGBE_READ_REG(hw, IXGBE_PRC127);
13348eb6488eSEric Joyner 	stats->prc255 += IXGBE_READ_REG(hw, IXGBE_PRC255);
13358eb6488eSEric Joyner 	stats->prc511 += IXGBE_READ_REG(hw, IXGBE_PRC511);
13368eb6488eSEric Joyner 	stats->prc1023 += IXGBE_READ_REG(hw, IXGBE_PRC1023);
13378eb6488eSEric Joyner 	stats->prc1522 += IXGBE_READ_REG(hw, IXGBE_PRC1522);
13388eb6488eSEric Joyner 
13398eb6488eSEric Joyner 	lxon = IXGBE_READ_REG(hw, IXGBE_LXONTXC);
13408eb6488eSEric Joyner 	stats->lxontxc += lxon;
13418eb6488eSEric Joyner 	lxoff = IXGBE_READ_REG(hw, IXGBE_LXOFFTXC);
13428eb6488eSEric Joyner 	stats->lxofftxc += lxoff;
13438eb6488eSEric Joyner 	total = lxon + lxoff;
13448eb6488eSEric Joyner 
13458eb6488eSEric Joyner 	stats->gptc += IXGBE_READ_REG(hw, IXGBE_GPTC);
13468eb6488eSEric Joyner 	stats->mptc += IXGBE_READ_REG(hw, IXGBE_MPTC);
13478eb6488eSEric Joyner 	stats->ptc64 += IXGBE_READ_REG(hw, IXGBE_PTC64);
13488eb6488eSEric Joyner 	stats->gptc -= total;
13498eb6488eSEric Joyner 	stats->mptc -= total;
13508eb6488eSEric Joyner 	stats->ptc64 -= total;
13518eb6488eSEric Joyner 	stats->gotc -= total * ETHER_MIN_LEN;
13528eb6488eSEric Joyner 
13538eb6488eSEric Joyner 	stats->ruc += IXGBE_READ_REG(hw, IXGBE_RUC);
13548eb6488eSEric Joyner 	stats->rfc += IXGBE_READ_REG(hw, IXGBE_RFC);
13558eb6488eSEric Joyner 	stats->roc += IXGBE_READ_REG(hw, IXGBE_ROC);
13568eb6488eSEric Joyner 	stats->rjc += IXGBE_READ_REG(hw, IXGBE_RJC);
13578eb6488eSEric Joyner 	stats->mngprc += IXGBE_READ_REG(hw, IXGBE_MNGPRC);
13588eb6488eSEric Joyner 	stats->mngpdc += IXGBE_READ_REG(hw, IXGBE_MNGPDC);
13598eb6488eSEric Joyner 	stats->mngptc += IXGBE_READ_REG(hw, IXGBE_MNGPTC);
13608eb6488eSEric Joyner 	stats->tpr += IXGBE_READ_REG(hw, IXGBE_TPR);
13618eb6488eSEric Joyner 	stats->tpt += IXGBE_READ_REG(hw, IXGBE_TPT);
13628eb6488eSEric Joyner 	stats->ptc127 += IXGBE_READ_REG(hw, IXGBE_PTC127);
13638eb6488eSEric Joyner 	stats->ptc255 += IXGBE_READ_REG(hw, IXGBE_PTC255);
13648eb6488eSEric Joyner 	stats->ptc511 += IXGBE_READ_REG(hw, IXGBE_PTC511);
13658eb6488eSEric Joyner 	stats->ptc1023 += IXGBE_READ_REG(hw, IXGBE_PTC1023);
13668eb6488eSEric Joyner 	stats->ptc1522 += IXGBE_READ_REG(hw, IXGBE_PTC1522);
13678eb6488eSEric Joyner 	stats->bptc += IXGBE_READ_REG(hw, IXGBE_BPTC);
13688eb6488eSEric Joyner 	stats->xec += IXGBE_READ_REG(hw, IXGBE_XEC);
13698eb6488eSEric Joyner 	stats->fccrc += IXGBE_READ_REG(hw, IXGBE_FCCRC);
13708eb6488eSEric Joyner 	stats->fclast += IXGBE_READ_REG(hw, IXGBE_FCLAST);
13718eb6488eSEric Joyner 	/* Only read FCOE on 82599 */
13728eb6488eSEric Joyner 	if (hw->mac.type != ixgbe_mac_82598EB) {
13738eb6488eSEric Joyner 		stats->fcoerpdc += IXGBE_READ_REG(hw, IXGBE_FCOERPDC);
13748eb6488eSEric Joyner 		stats->fcoeprc += IXGBE_READ_REG(hw, IXGBE_FCOEPRC);
13758eb6488eSEric Joyner 		stats->fcoeptc += IXGBE_READ_REG(hw, IXGBE_FCOEPTC);
13768eb6488eSEric Joyner 		stats->fcoedwrc += IXGBE_READ_REG(hw, IXGBE_FCOEDWRC);
13778eb6488eSEric Joyner 		stats->fcoedwtc += IXGBE_READ_REG(hw, IXGBE_FCOEDWTC);
13788eb6488eSEric Joyner 	}
13798eb6488eSEric Joyner 
13808eb6488eSEric Joyner 	/* Fill out the OS statistics structure */
13818eb6488eSEric Joyner 	IXGBE_SET_IPACKETS(adapter, stats->gprc);
13828eb6488eSEric Joyner 	IXGBE_SET_OPACKETS(adapter, stats->gptc);
13838eb6488eSEric Joyner 	IXGBE_SET_IBYTES(adapter, stats->gorc);
13848eb6488eSEric Joyner 	IXGBE_SET_OBYTES(adapter, stats->gotc);
13858eb6488eSEric Joyner 	IXGBE_SET_IMCASTS(adapter, stats->mprc);
13868eb6488eSEric Joyner 	IXGBE_SET_OMCASTS(adapter, stats->mptc);
13878eb6488eSEric Joyner 	IXGBE_SET_COLLISIONS(adapter, 0);
13888eb6488eSEric Joyner 	IXGBE_SET_IQDROPS(adapter, total_missed_rx);
13898eb6488eSEric Joyner 	IXGBE_SET_IERRORS(adapter, stats->crcerrs + stats->rlec);
13908eb6488eSEric Joyner } /* ixgbe_update_stats_counters */
13918eb6488eSEric Joyner 
13928eb6488eSEric Joyner /************************************************************************
13938eb6488eSEric Joyner  * ixgbe_add_hw_stats
13948eb6488eSEric Joyner  *
13958eb6488eSEric Joyner  *   Add sysctl variables, one per statistic, to the system.
13968eb6488eSEric Joyner  ************************************************************************/
13978eb6488eSEric Joyner static void
13988eb6488eSEric Joyner ixgbe_add_hw_stats(struct adapter *adapter)
13998eb6488eSEric Joyner {
14008eb6488eSEric Joyner 	device_t               dev = adapter->dev;
14018eb6488eSEric Joyner 	struct tx_ring         *txr = adapter->tx_rings;
14028eb6488eSEric Joyner 	struct rx_ring         *rxr = adapter->rx_rings;
14038eb6488eSEric Joyner 	struct sysctl_ctx_list *ctx = device_get_sysctl_ctx(dev);
14048eb6488eSEric Joyner 	struct sysctl_oid      *tree = device_get_sysctl_tree(dev);
14058eb6488eSEric Joyner 	struct sysctl_oid_list *child = SYSCTL_CHILDREN(tree);
14068eb6488eSEric Joyner 	struct ixgbe_hw_stats  *stats = &adapter->stats.pf;
14078eb6488eSEric Joyner 	struct sysctl_oid      *stat_node, *queue_node;
14088eb6488eSEric Joyner 	struct sysctl_oid_list *stat_list, *queue_list;
14098eb6488eSEric Joyner 
14108eb6488eSEric Joyner #define QUEUE_NAME_LEN 32
14118eb6488eSEric Joyner 	char                   namebuf[QUEUE_NAME_LEN];
14128eb6488eSEric Joyner 
14138eb6488eSEric Joyner 	/* Driver Statistics */
14148eb6488eSEric Joyner 	SYSCTL_ADD_ULONG(ctx, child, OID_AUTO, "dropped",
14158eb6488eSEric Joyner 	    CTLFLAG_RD, &adapter->dropped_pkts, "Driver dropped packets");
14168eb6488eSEric Joyner 	SYSCTL_ADD_ULONG(ctx, child, OID_AUTO, "mbuf_defrag_failed",
14178eb6488eSEric Joyner 	    CTLFLAG_RD, &adapter->mbuf_defrag_failed, "m_defrag() failed");
14188eb6488eSEric Joyner 	SYSCTL_ADD_ULONG(ctx, child, OID_AUTO, "watchdog_events",
14198eb6488eSEric Joyner 	    CTLFLAG_RD, &adapter->watchdog_events, "Watchdog timeouts");
14208eb6488eSEric Joyner 	SYSCTL_ADD_ULONG(ctx, child, OID_AUTO, "link_irq",
14218eb6488eSEric Joyner 	    CTLFLAG_RD, &adapter->link_irq, "Link MSI-X IRQ Handled");
14228eb6488eSEric Joyner 
14238eb6488eSEric Joyner 	for (int i = 0; i < adapter->num_queues; i++, txr++) {
14248eb6488eSEric Joyner 		snprintf(namebuf, QUEUE_NAME_LEN, "queue%d", i);
14258eb6488eSEric Joyner 		queue_node = SYSCTL_ADD_NODE(ctx, child, OID_AUTO, namebuf,
14268eb6488eSEric Joyner 		    CTLFLAG_RD, NULL, "Queue Name");
14278eb6488eSEric Joyner 		queue_list = SYSCTL_CHILDREN(queue_node);
14288eb6488eSEric Joyner 
14298eb6488eSEric Joyner 		SYSCTL_ADD_PROC(ctx, queue_list, OID_AUTO, "interrupt_rate",
14308eb6488eSEric Joyner 		    CTLTYPE_UINT | CTLFLAG_RW, &adapter->queues[i],
14318eb6488eSEric Joyner 		    sizeof(&adapter->queues[i]),
14328eb6488eSEric Joyner 		    ixgbe_sysctl_interrupt_rate_handler, "IU",
14338eb6488eSEric Joyner 		    "Interrupt Rate");
14348eb6488eSEric Joyner 		SYSCTL_ADD_UQUAD(ctx, queue_list, OID_AUTO, "irqs",
14358eb6488eSEric Joyner 		    CTLFLAG_RD, &(adapter->queues[i].irqs),
14368eb6488eSEric Joyner 		    "irqs on this queue");
14378eb6488eSEric Joyner 		SYSCTL_ADD_PROC(ctx, queue_list, OID_AUTO, "txd_head",
14388eb6488eSEric Joyner 		    CTLTYPE_UINT | CTLFLAG_RD, txr, sizeof(txr),
14398eb6488eSEric Joyner 		    ixgbe_sysctl_tdh_handler, "IU", "Transmit Descriptor Head");
14408eb6488eSEric Joyner 		SYSCTL_ADD_PROC(ctx, queue_list, OID_AUTO, "txd_tail",
14418eb6488eSEric Joyner 		    CTLTYPE_UINT | CTLFLAG_RD, txr, sizeof(txr),
14428eb6488eSEric Joyner 		    ixgbe_sysctl_tdt_handler, "IU", "Transmit Descriptor Tail");
14438eb6488eSEric Joyner 		SYSCTL_ADD_UQUAD(ctx, queue_list, OID_AUTO, "tso_tx",
14448eb6488eSEric Joyner 		    CTLFLAG_RD, &txr->tso_tx, "TSO");
14458eb6488eSEric Joyner 		SYSCTL_ADD_UQUAD(ctx, queue_list, OID_AUTO, "no_tx_dma_setup",
14468eb6488eSEric Joyner 		    CTLFLAG_RD, &txr->no_tx_dma_setup,
14478eb6488eSEric Joyner 		    "Driver tx dma failure in xmit");
14488eb6488eSEric Joyner 		SYSCTL_ADD_UQUAD(ctx, queue_list, OID_AUTO, "no_desc_avail",
14498eb6488eSEric Joyner 		    CTLFLAG_RD, &txr->no_desc_avail,
14508eb6488eSEric Joyner 		    "Queue No Descriptor Available");
14518eb6488eSEric Joyner 		SYSCTL_ADD_UQUAD(ctx, queue_list, OID_AUTO, "tx_packets",
14528eb6488eSEric Joyner 		    CTLFLAG_RD, &txr->total_packets,
14538eb6488eSEric Joyner 		    "Queue Packets Transmitted");
14548eb6488eSEric Joyner 		SYSCTL_ADD_UQUAD(ctx, queue_list, OID_AUTO, "br_drops",
14558eb6488eSEric Joyner 		    CTLFLAG_RD, &txr->br->br_drops,
14568eb6488eSEric Joyner 		    "Packets dropped in buf_ring");
14578eb6488eSEric Joyner 	}
14588eb6488eSEric Joyner 
14598eb6488eSEric Joyner 	for (int i = 0; i < adapter->num_queues; i++, rxr++) {
14608eb6488eSEric Joyner 		struct lro_ctrl *lro = &rxr->lro;
14618eb6488eSEric Joyner 
14628eb6488eSEric Joyner 		snprintf(namebuf, QUEUE_NAME_LEN, "queue%d", i);
14638eb6488eSEric Joyner 		queue_node = SYSCTL_ADD_NODE(ctx, child, OID_AUTO, namebuf,
14648eb6488eSEric Joyner 		    CTLFLAG_RD, NULL, "Queue Name");
14658eb6488eSEric Joyner 		queue_list = SYSCTL_CHILDREN(queue_node);
14668eb6488eSEric Joyner 
14678eb6488eSEric Joyner 		SYSCTL_ADD_PROC(ctx, queue_list, OID_AUTO, "rxd_head",
14688eb6488eSEric Joyner 		    CTLTYPE_UINT | CTLFLAG_RD, rxr, sizeof(rxr),
14698eb6488eSEric Joyner 		    ixgbe_sysctl_rdh_handler, "IU", "Receive Descriptor Head");
14708eb6488eSEric Joyner 		SYSCTL_ADD_PROC(ctx, queue_list, OID_AUTO, "rxd_tail",
14718eb6488eSEric Joyner 		    CTLTYPE_UINT | CTLFLAG_RD, rxr, sizeof(rxr),
14728eb6488eSEric Joyner 		    ixgbe_sysctl_rdt_handler, "IU", "Receive Descriptor Tail");
14738eb6488eSEric Joyner 		SYSCTL_ADD_UQUAD(ctx, queue_list, OID_AUTO, "rx_packets",
14748eb6488eSEric Joyner 		    CTLFLAG_RD, &rxr->rx_packets, "Queue Packets Received");
14758eb6488eSEric Joyner 		SYSCTL_ADD_UQUAD(ctx, queue_list, OID_AUTO, "rx_bytes",
14768eb6488eSEric Joyner 		    CTLFLAG_RD, &rxr->rx_bytes, "Queue Bytes Received");
14778eb6488eSEric Joyner 		SYSCTL_ADD_UQUAD(ctx, queue_list, OID_AUTO, "rx_copies",
14788eb6488eSEric Joyner 		    CTLFLAG_RD, &rxr->rx_copies, "Copied RX Frames");
14798eb6488eSEric Joyner 		SYSCTL_ADD_UQUAD(ctx, queue_list, OID_AUTO, "rx_discarded",
14808eb6488eSEric Joyner 		    CTLFLAG_RD, &rxr->rx_discarded, "Discarded RX packets");
14818eb6488eSEric Joyner 		SYSCTL_ADD_U64(ctx, queue_list, OID_AUTO, "lro_queued",
14828eb6488eSEric Joyner 		    CTLFLAG_RD, &lro->lro_queued, 0, "LRO Queued");
14838eb6488eSEric Joyner 		SYSCTL_ADD_U64(ctx, queue_list, OID_AUTO, "lro_flushed",
14848eb6488eSEric Joyner 		    CTLFLAG_RD, &lro->lro_flushed, 0, "LRO Flushed");
14858eb6488eSEric Joyner 	}
14868eb6488eSEric Joyner 
14878eb6488eSEric Joyner 	/* MAC stats get their own sub node */
14888eb6488eSEric Joyner 
14898eb6488eSEric Joyner 	stat_node = SYSCTL_ADD_NODE(ctx, child, OID_AUTO, "mac_stats",
14908eb6488eSEric Joyner 	    CTLFLAG_RD, NULL, "MAC Statistics");
14918eb6488eSEric Joyner 	stat_list = SYSCTL_CHILDREN(stat_node);
14928eb6488eSEric Joyner 
14938eb6488eSEric Joyner 	SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "crc_errs",
14948eb6488eSEric Joyner 	    CTLFLAG_RD, &stats->crcerrs, "CRC Errors");
14958eb6488eSEric Joyner 	SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "ill_errs",
14968eb6488eSEric Joyner 	    CTLFLAG_RD, &stats->illerrc, "Illegal Byte Errors");
14978eb6488eSEric Joyner 	SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "byte_errs",
14988eb6488eSEric Joyner 	    CTLFLAG_RD, &stats->errbc, "Byte Errors");
14998eb6488eSEric Joyner 	SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "short_discards",
15008eb6488eSEric Joyner 	    CTLFLAG_RD, &stats->mspdc, "MAC Short Packets Discarded");
15018eb6488eSEric Joyner 	SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "local_faults",
15028eb6488eSEric Joyner 	    CTLFLAG_RD, &stats->mlfc, "MAC Local Faults");
15038eb6488eSEric Joyner 	SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "remote_faults",
15048eb6488eSEric Joyner 	    CTLFLAG_RD, &stats->mrfc, "MAC Remote Faults");
15058eb6488eSEric Joyner 	SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "rec_len_errs",
15068eb6488eSEric Joyner 	    CTLFLAG_RD, &stats->rlec, "Receive Length Errors");
15078eb6488eSEric Joyner 	SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "rx_missed_packets",
15088eb6488eSEric Joyner 	    CTLFLAG_RD, &stats->mpc[0], "RX Missed Packet Count");
15098eb6488eSEric Joyner 
15108eb6488eSEric Joyner 	/* Flow Control stats */
15118eb6488eSEric Joyner 	SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "xon_txd",
15128eb6488eSEric Joyner 	    CTLFLAG_RD, &stats->lxontxc, "Link XON Transmitted");
15138eb6488eSEric Joyner 	SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "xon_recvd",
15148eb6488eSEric Joyner 	    CTLFLAG_RD, &stats->lxonrxc, "Link XON Received");
15158eb6488eSEric Joyner 	SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "xoff_txd",
15168eb6488eSEric Joyner 	    CTLFLAG_RD, &stats->lxofftxc, "Link XOFF Transmitted");
15178eb6488eSEric Joyner 	SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "xoff_recvd",
15188eb6488eSEric Joyner 	    CTLFLAG_RD, &stats->lxoffrxc, "Link XOFF Received");
15198eb6488eSEric Joyner 
15208eb6488eSEric Joyner 	/* Packet Reception Stats */
15218eb6488eSEric Joyner 	SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "total_octets_rcvd",
15228eb6488eSEric Joyner 	    CTLFLAG_RD, &stats->tor, "Total Octets Received");
15238eb6488eSEric Joyner 	SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "good_octets_rcvd",
15248eb6488eSEric Joyner 	    CTLFLAG_RD, &stats->gorc, "Good Octets Received");
15258eb6488eSEric Joyner 	SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "total_pkts_rcvd",
15268eb6488eSEric Joyner 	    CTLFLAG_RD, &stats->tpr, "Total Packets Received");
15278eb6488eSEric Joyner 	SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "good_pkts_rcvd",
15288eb6488eSEric Joyner 	    CTLFLAG_RD, &stats->gprc, "Good Packets Received");
15298eb6488eSEric Joyner 	SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "mcast_pkts_rcvd",
15308eb6488eSEric Joyner 	    CTLFLAG_RD, &stats->mprc, "Multicast Packets Received");
15318eb6488eSEric Joyner 	SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "bcast_pkts_rcvd",
15328eb6488eSEric Joyner 	    CTLFLAG_RD, &stats->bprc, "Broadcast Packets Received");
15338eb6488eSEric Joyner 	SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "rx_frames_64",
15348eb6488eSEric Joyner 	    CTLFLAG_RD, &stats->prc64, "64 byte frames received ");
15358eb6488eSEric Joyner 	SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "rx_frames_65_127",
15368eb6488eSEric Joyner 	    CTLFLAG_RD, &stats->prc127, "65-127 byte frames received");
15378eb6488eSEric Joyner 	SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "rx_frames_128_255",
15388eb6488eSEric Joyner 	    CTLFLAG_RD, &stats->prc255, "128-255 byte frames received");
15398eb6488eSEric Joyner 	SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "rx_frames_256_511",
15408eb6488eSEric Joyner 	    CTLFLAG_RD, &stats->prc511, "256-511 byte frames received");
15418eb6488eSEric Joyner 	SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "rx_frames_512_1023",
15428eb6488eSEric Joyner 	    CTLFLAG_RD, &stats->prc1023, "512-1023 byte frames received");
15438eb6488eSEric Joyner 	SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "rx_frames_1024_1522",
15448eb6488eSEric Joyner 	    CTLFLAG_RD, &stats->prc1522, "1023-1522 byte frames received");
15458eb6488eSEric Joyner 	SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "recv_undersized",
15468eb6488eSEric Joyner 	    CTLFLAG_RD, &stats->ruc, "Receive Undersized");
15478eb6488eSEric Joyner 	SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "recv_fragmented",
15488eb6488eSEric Joyner 	    CTLFLAG_RD, &stats->rfc, "Fragmented Packets Received ");
15498eb6488eSEric Joyner 	SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "recv_oversized",
15508eb6488eSEric Joyner 	    CTLFLAG_RD, &stats->roc, "Oversized Packets Received");
15518eb6488eSEric Joyner 	SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "recv_jabberd",
15528eb6488eSEric Joyner 	    CTLFLAG_RD, &stats->rjc, "Received Jabber");
15538eb6488eSEric Joyner 	SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "management_pkts_rcvd",
15548eb6488eSEric Joyner 	    CTLFLAG_RD, &stats->mngprc, "Management Packets Received");
15558eb6488eSEric Joyner 	SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "management_pkts_drpd",
15568eb6488eSEric Joyner 	    CTLFLAG_RD, &stats->mngptc, "Management Packets Dropped");
15578eb6488eSEric Joyner 	SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "checksum_errs",
15588eb6488eSEric Joyner 	    CTLFLAG_RD, &stats->xec, "Checksum Errors");
15598eb6488eSEric Joyner 
15608eb6488eSEric Joyner 	/* Packet Transmission Stats */
15618eb6488eSEric Joyner 	SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "good_octets_txd",
15628eb6488eSEric Joyner 	    CTLFLAG_RD, &stats->gotc, "Good Octets Transmitted");
15638eb6488eSEric Joyner 	SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "total_pkts_txd",
15648eb6488eSEric Joyner 	    CTLFLAG_RD, &stats->tpt, "Total Packets Transmitted");
15658eb6488eSEric Joyner 	SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "good_pkts_txd",
15668eb6488eSEric Joyner 	    CTLFLAG_RD, &stats->gptc, "Good Packets Transmitted");
15678eb6488eSEric Joyner 	SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "bcast_pkts_txd",
15688eb6488eSEric Joyner 	    CTLFLAG_RD, &stats->bptc, "Broadcast Packets Transmitted");
15698eb6488eSEric Joyner 	SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "mcast_pkts_txd",
15708eb6488eSEric Joyner 	    CTLFLAG_RD, &stats->mptc, "Multicast Packets Transmitted");
15718eb6488eSEric Joyner 	SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "management_pkts_txd",
15728eb6488eSEric Joyner 	    CTLFLAG_RD, &stats->mngptc, "Management Packets Transmitted");
15738eb6488eSEric Joyner 	SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "tx_frames_64",
15748eb6488eSEric Joyner 	    CTLFLAG_RD, &stats->ptc64, "64 byte frames transmitted ");
15758eb6488eSEric Joyner 	SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "tx_frames_65_127",
15768eb6488eSEric Joyner 	    CTLFLAG_RD, &stats->ptc127, "65-127 byte frames transmitted");
15778eb6488eSEric Joyner 	SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "tx_frames_128_255",
15788eb6488eSEric Joyner 	    CTLFLAG_RD, &stats->ptc255, "128-255 byte frames transmitted");
15798eb6488eSEric Joyner 	SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "tx_frames_256_511",
15808eb6488eSEric Joyner 	    CTLFLAG_RD, &stats->ptc511, "256-511 byte frames transmitted");
15818eb6488eSEric Joyner 	SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "tx_frames_512_1023",
15828eb6488eSEric Joyner 	    CTLFLAG_RD, &stats->ptc1023, "512-1023 byte frames transmitted");
15838eb6488eSEric Joyner 	SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "tx_frames_1024_1522",
15848eb6488eSEric Joyner 	    CTLFLAG_RD, &stats->ptc1522, "1024-1522 byte frames transmitted");
15858eb6488eSEric Joyner } /* ixgbe_add_hw_stats */
15868eb6488eSEric Joyner 
15878eb6488eSEric Joyner /************************************************************************
15888eb6488eSEric Joyner  * ixgbe_sysctl_tdh_handler - Transmit Descriptor Head handler function
15898eb6488eSEric Joyner  *
15908eb6488eSEric Joyner  *   Retrieves the TDH value from the hardware
15918eb6488eSEric Joyner  ************************************************************************/
1592758cc3dcSJack F Vogel static int
1593758cc3dcSJack F Vogel ixgbe_sysctl_tdh_handler(SYSCTL_HANDLER_ARGS)
1594758cc3dcSJack F Vogel {
1595758cc3dcSJack F Vogel 	struct tx_ring *txr = ((struct tx_ring *)oidp->oid_arg1);
15968eb6488eSEric Joyner 	int            error;
15978eb6488eSEric Joyner 	unsigned int   val;
1598758cc3dcSJack F Vogel 
15998eb6488eSEric Joyner 	if (!txr)
16008eb6488eSEric Joyner 		return (0);
16018eb6488eSEric Joyner 
16028eb6488eSEric Joyner 	val = IXGBE_READ_REG(&txr->adapter->hw, IXGBE_TDH(txr->me));
1603758cc3dcSJack F Vogel 	error = sysctl_handle_int(oidp, &val, 0, req);
1604758cc3dcSJack F Vogel 	if (error || !req->newptr)
1605758cc3dcSJack F Vogel 		return error;
1606758cc3dcSJack F Vogel 
16078eb6488eSEric Joyner 	return (0);
16088eb6488eSEric Joyner } /* ixgbe_sysctl_tdh_handler */
16098eb6488eSEric Joyner 
16108eb6488eSEric Joyner /************************************************************************
16118eb6488eSEric Joyner  * ixgbe_sysctl_tdt_handler - Transmit Descriptor Tail handler function
16128eb6488eSEric Joyner  *
1613758cc3dcSJack F Vogel  *   Retrieves the TDT value from the hardware
16148eb6488eSEric Joyner  ************************************************************************/
1615758cc3dcSJack F Vogel static int
1616758cc3dcSJack F Vogel ixgbe_sysctl_tdt_handler(SYSCTL_HANDLER_ARGS)
1617758cc3dcSJack F Vogel {
1618758cc3dcSJack F Vogel 	struct tx_ring *txr = ((struct tx_ring *)oidp->oid_arg1);
16198eb6488eSEric Joyner 	int            error;
16208eb6488eSEric Joyner 	unsigned int   val;
1621758cc3dcSJack F Vogel 
16228eb6488eSEric Joyner 	if (!txr)
16238eb6488eSEric Joyner 		return (0);
16248eb6488eSEric Joyner 
16258eb6488eSEric Joyner 	val = IXGBE_READ_REG(&txr->adapter->hw, IXGBE_TDT(txr->me));
1626758cc3dcSJack F Vogel 	error = sysctl_handle_int(oidp, &val, 0, req);
1627758cc3dcSJack F Vogel 	if (error || !req->newptr)
1628758cc3dcSJack F Vogel 		return error;
1629758cc3dcSJack F Vogel 
16308eb6488eSEric Joyner 	return (0);
16318eb6488eSEric Joyner } /* ixgbe_sysctl_tdt_handler */
16328eb6488eSEric Joyner 
16338eb6488eSEric Joyner /************************************************************************
16348eb6488eSEric Joyner  * ixgbe_sysctl_rdh_handler - Receive Descriptor Head handler function
16358eb6488eSEric Joyner  *
1636758cc3dcSJack F Vogel  *   Retrieves the RDH value from the hardware
16378eb6488eSEric Joyner  ************************************************************************/
1638758cc3dcSJack F Vogel static int
1639758cc3dcSJack F Vogel ixgbe_sysctl_rdh_handler(SYSCTL_HANDLER_ARGS)
1640758cc3dcSJack F Vogel {
1641758cc3dcSJack F Vogel 	struct rx_ring *rxr = ((struct rx_ring *)oidp->oid_arg1);
16428eb6488eSEric Joyner 	int            error;
16438eb6488eSEric Joyner 	unsigned int   val;
1644758cc3dcSJack F Vogel 
16458eb6488eSEric Joyner 	if (!rxr)
16468eb6488eSEric Joyner 		return (0);
16478eb6488eSEric Joyner 
16488eb6488eSEric Joyner 	val = IXGBE_READ_REG(&rxr->adapter->hw, IXGBE_RDH(rxr->me));
1649758cc3dcSJack F Vogel 	error = sysctl_handle_int(oidp, &val, 0, req);
1650758cc3dcSJack F Vogel 	if (error || !req->newptr)
1651758cc3dcSJack F Vogel 		return error;
1652758cc3dcSJack F Vogel 
16538eb6488eSEric Joyner 	return (0);
16548eb6488eSEric Joyner } /* ixgbe_sysctl_rdh_handler */
16558eb6488eSEric Joyner 
16568eb6488eSEric Joyner /************************************************************************
16578eb6488eSEric Joyner  * ixgbe_sysctl_rdt_handler - Receive Descriptor Tail handler function
16588eb6488eSEric Joyner  *
1659758cc3dcSJack F Vogel  *   Retrieves the RDT value from the hardware
16608eb6488eSEric Joyner  ************************************************************************/
1661758cc3dcSJack F Vogel static int
1662758cc3dcSJack F Vogel ixgbe_sysctl_rdt_handler(SYSCTL_HANDLER_ARGS)
1663758cc3dcSJack F Vogel {
1664758cc3dcSJack F Vogel 	struct rx_ring *rxr = ((struct rx_ring *)oidp->oid_arg1);
16658eb6488eSEric Joyner 	int            error;
16668eb6488eSEric Joyner 	unsigned int   val;
1667758cc3dcSJack F Vogel 
16688eb6488eSEric Joyner 	if (!rxr)
16698eb6488eSEric Joyner 		return (0);
16708eb6488eSEric Joyner 
16718eb6488eSEric Joyner 	val = IXGBE_READ_REG(&rxr->adapter->hw, IXGBE_RDT(rxr->me));
1672758cc3dcSJack F Vogel 	error = sysctl_handle_int(oidp, &val, 0, req);
1673758cc3dcSJack F Vogel 	if (error || !req->newptr)
1674758cc3dcSJack F Vogel 		return error;
16758eb6488eSEric Joyner 
16768eb6488eSEric Joyner 	return (0);
16778eb6488eSEric Joyner } /* ixgbe_sysctl_rdt_handler */
16788eb6488eSEric Joyner 
16798eb6488eSEric Joyner /************************************************************************
16808eb6488eSEric Joyner  * ixgbe_register_vlan
16818eb6488eSEric Joyner  *
16828eb6488eSEric Joyner  *   Run via vlan config EVENT, it enables us to use the
16838eb6488eSEric Joyner  *   HW Filter table since we can get the vlan id. This
16848eb6488eSEric Joyner  *   just creates the entry in the soft version of the
16858eb6488eSEric Joyner  *   VFTA, init will repopulate the real table.
16868eb6488eSEric Joyner  ************************************************************************/
16878eb6488eSEric Joyner static void
16888eb6488eSEric Joyner ixgbe_register_vlan(void *arg, struct ifnet *ifp, u16 vtag)
16898eb6488eSEric Joyner {
16908eb6488eSEric Joyner 	struct adapter *adapter = ifp->if_softc;
16918eb6488eSEric Joyner 	u16            index, bit;
16928eb6488eSEric Joyner 
16938eb6488eSEric Joyner 	if (ifp->if_softc != arg)   /* Not our event */
16948eb6488eSEric Joyner 		return;
16958eb6488eSEric Joyner 
16968eb6488eSEric Joyner 	if ((vtag == 0) || (vtag > 4095))  /* Invalid */
16978eb6488eSEric Joyner 		return;
16988eb6488eSEric Joyner 
16998eb6488eSEric Joyner 	IXGBE_CORE_LOCK(adapter);
17008eb6488eSEric Joyner 	index = (vtag >> 5) & 0x7F;
17018eb6488eSEric Joyner 	bit = vtag & 0x1F;
17028eb6488eSEric Joyner 	adapter->shadow_vfta[index] |= (1 << bit);
17038eb6488eSEric Joyner 	++adapter->num_vlans;
17048eb6488eSEric Joyner 	ixgbe_setup_vlan_hw_support(adapter);
17058eb6488eSEric Joyner 	IXGBE_CORE_UNLOCK(adapter);
17068eb6488eSEric Joyner } /* ixgbe_register_vlan */
17078eb6488eSEric Joyner 
17088eb6488eSEric Joyner /************************************************************************
17098eb6488eSEric Joyner  * ixgbe_unregister_vlan
17108eb6488eSEric Joyner  *
17118eb6488eSEric Joyner  *   Run via vlan unconfig EVENT, remove our entry in the soft vfta.
17128eb6488eSEric Joyner  ************************************************************************/
17138eb6488eSEric Joyner static void
17148eb6488eSEric Joyner ixgbe_unregister_vlan(void *arg, struct ifnet *ifp, u16 vtag)
17158eb6488eSEric Joyner {
17168eb6488eSEric Joyner 	struct adapter *adapter = ifp->if_softc;
17178eb6488eSEric Joyner 	u16            index, bit;
17188eb6488eSEric Joyner 
17198eb6488eSEric Joyner 	if (ifp->if_softc != arg)
17208eb6488eSEric Joyner 		return;
17218eb6488eSEric Joyner 
17228eb6488eSEric Joyner 	if ((vtag == 0) || (vtag > 4095))  /* Invalid */
17238eb6488eSEric Joyner 		return;
17248eb6488eSEric Joyner 
17258eb6488eSEric Joyner 	IXGBE_CORE_LOCK(adapter);
17268eb6488eSEric Joyner 	index = (vtag >> 5) & 0x7F;
17278eb6488eSEric Joyner 	bit = vtag & 0x1F;
17288eb6488eSEric Joyner 	adapter->shadow_vfta[index] &= ~(1 << bit);
17298eb6488eSEric Joyner 	--adapter->num_vlans;
17308eb6488eSEric Joyner 	/* Re-init to load the changes */
17318eb6488eSEric Joyner 	ixgbe_setup_vlan_hw_support(adapter);
17328eb6488eSEric Joyner 	IXGBE_CORE_UNLOCK(adapter);
17338eb6488eSEric Joyner } /* ixgbe_unregister_vlan */
17348eb6488eSEric Joyner 
17358eb6488eSEric Joyner /************************************************************************
17368eb6488eSEric Joyner  * ixgbe_setup_vlan_hw_support
17378eb6488eSEric Joyner  ************************************************************************/
17388eb6488eSEric Joyner static void
17398eb6488eSEric Joyner ixgbe_setup_vlan_hw_support(struct adapter *adapter)
17408eb6488eSEric Joyner {
17418eb6488eSEric Joyner 	struct ifnet    *ifp = adapter->ifp;
17428eb6488eSEric Joyner 	struct ixgbe_hw *hw = &adapter->hw;
17438eb6488eSEric Joyner 	struct rx_ring  *rxr;
17448eb6488eSEric Joyner 	int             i;
17458eb6488eSEric Joyner 	u32             ctrl;
17468eb6488eSEric Joyner 
17478eb6488eSEric Joyner 
17488eb6488eSEric Joyner 	/*
17498eb6488eSEric Joyner 	 * We get here thru init_locked, meaning
17508eb6488eSEric Joyner 	 * a soft reset, this has already cleared
17518eb6488eSEric Joyner 	 * the VFTA and other state, so if there
17528eb6488eSEric Joyner 	 * have been no vlan's registered do nothing.
17538eb6488eSEric Joyner 	 */
17548eb6488eSEric Joyner 	if (adapter->num_vlans == 0)
17558eb6488eSEric Joyner 		return;
17568eb6488eSEric Joyner 
17578eb6488eSEric Joyner 	/* Setup the queues for vlans */
17588eb6488eSEric Joyner 	for (i = 0; i < adapter->num_queues; i++) {
17598eb6488eSEric Joyner 		rxr = &adapter->rx_rings[i];
17608eb6488eSEric Joyner 		/* On 82599 the VLAN enable is per/queue in RXDCTL */
17618eb6488eSEric Joyner 		if (hw->mac.type != ixgbe_mac_82598EB) {
17628eb6488eSEric Joyner 			ctrl = IXGBE_READ_REG(hw, IXGBE_RXDCTL(rxr->me));
17638eb6488eSEric Joyner 			ctrl |= IXGBE_RXDCTL_VME;
17648eb6488eSEric Joyner 			IXGBE_WRITE_REG(hw, IXGBE_RXDCTL(rxr->me), ctrl);
17658eb6488eSEric Joyner 		}
17668eb6488eSEric Joyner 		rxr->vtag_strip = TRUE;
1767758cc3dcSJack F Vogel 	}
1768758cc3dcSJack F Vogel 
17698eb6488eSEric Joyner 	if ((ifp->if_capenable & IFCAP_VLAN_HWFILTER) == 0)
17708eb6488eSEric Joyner 		return;
17718eb6488eSEric Joyner 	/*
17728eb6488eSEric Joyner 	 * A soft reset zero's out the VFTA, so
17738eb6488eSEric Joyner 	 * we need to repopulate it now.
17748eb6488eSEric Joyner 	 */
17758eb6488eSEric Joyner 	for (i = 0; i < IXGBE_VFTA_SIZE; i++)
17768eb6488eSEric Joyner 		if (adapter->shadow_vfta[i] != 0)
17778eb6488eSEric Joyner 			IXGBE_WRITE_REG(hw, IXGBE_VFTA(i),
17788eb6488eSEric Joyner 			    adapter->shadow_vfta[i]);
17798eb6488eSEric Joyner 
17808eb6488eSEric Joyner 	ctrl = IXGBE_READ_REG(hw, IXGBE_VLNCTRL);
17818eb6488eSEric Joyner 	/* Enable the Filter Table if enabled */
17828eb6488eSEric Joyner 	if (ifp->if_capenable & IFCAP_VLAN_HWFILTER) {
17838eb6488eSEric Joyner 		ctrl &= ~IXGBE_VLNCTRL_CFIEN;
17848eb6488eSEric Joyner 		ctrl |= IXGBE_VLNCTRL_VFE;
17858eb6488eSEric Joyner 	}
17868eb6488eSEric Joyner 	if (hw->mac.type == ixgbe_mac_82598EB)
17878eb6488eSEric Joyner 		ctrl |= IXGBE_VLNCTRL_VME;
17888eb6488eSEric Joyner 	IXGBE_WRITE_REG(hw, IXGBE_VLNCTRL, ctrl);
17898eb6488eSEric Joyner } /* ixgbe_setup_vlan_hw_support */
17908eb6488eSEric Joyner 
17918eb6488eSEric Joyner /************************************************************************
17928eb6488eSEric Joyner  * ixgbe_get_slot_info
17938eb6488eSEric Joyner  *
17948eb6488eSEric Joyner  *   Get the width and transaction speed of
17958eb6488eSEric Joyner  *   the slot this adapter is plugged into.
17968eb6488eSEric Joyner  ************************************************************************/
17978eb6488eSEric Joyner static void
17988eb6488eSEric Joyner ixgbe_get_slot_info(struct adapter *adapter)
17998eb6488eSEric Joyner {
18008eb6488eSEric Joyner 	device_t              dev = adapter->dev;
18018eb6488eSEric Joyner 	struct ixgbe_hw       *hw = &adapter->hw;
18028eb6488eSEric Joyner 	u32                   offset;
18038eb6488eSEric Joyner 	u16                   link;
18048eb6488eSEric Joyner 	int                   bus_info_valid = TRUE;
18058eb6488eSEric Joyner 
18068eb6488eSEric Joyner 	/* Some devices are behind an internal bridge */
18078eb6488eSEric Joyner 	switch (hw->device_id) {
18088eb6488eSEric Joyner 	case IXGBE_DEV_ID_82599_SFP_SF_QP:
18098eb6488eSEric Joyner 	case IXGBE_DEV_ID_82599_QSFP_SF_QP:
18108eb6488eSEric Joyner 		goto get_parent_info;
18118eb6488eSEric Joyner 	default:
18128eb6488eSEric Joyner 		break;
18138eb6488eSEric Joyner 	}
18148eb6488eSEric Joyner 
18158eb6488eSEric Joyner 	ixgbe_get_bus_info(hw);
18168eb6488eSEric Joyner 
18178eb6488eSEric Joyner 	/*
18188eb6488eSEric Joyner 	 * Some devices don't use PCI-E, but there is no need
18198eb6488eSEric Joyner 	 * to display "Unknown" for bus speed and width.
18208eb6488eSEric Joyner 	 */
18218eb6488eSEric Joyner 	switch (hw->mac.type) {
18228eb6488eSEric Joyner 	case ixgbe_mac_X550EM_x:
18238eb6488eSEric Joyner 	case ixgbe_mac_X550EM_a:
18248eb6488eSEric Joyner 		return;
18258eb6488eSEric Joyner 	default:
18268eb6488eSEric Joyner 		goto display;
18278eb6488eSEric Joyner 	}
18288eb6488eSEric Joyner 
18298eb6488eSEric Joyner get_parent_info:
18308eb6488eSEric Joyner 	/*
18318eb6488eSEric Joyner 	 * For the Quad port adapter we need to parse back
18328eb6488eSEric Joyner 	 * up the PCI tree to find the speed of the expansion
18338eb6488eSEric Joyner 	 * slot into which this adapter is plugged. A bit more work.
18348eb6488eSEric Joyner 	 */
18358eb6488eSEric Joyner 	dev = device_get_parent(device_get_parent(dev));
18368eb6488eSEric Joyner #ifdef IXGBE_DEBUG
18378eb6488eSEric Joyner 	device_printf(dev, "parent pcib = %x,%x,%x\n", pci_get_bus(dev),
18388eb6488eSEric Joyner 	    pci_get_slot(dev), pci_get_function(dev));
18398eb6488eSEric Joyner #endif
18408eb6488eSEric Joyner 	dev = device_get_parent(device_get_parent(dev));
18418eb6488eSEric Joyner #ifdef IXGBE_DEBUG
18428eb6488eSEric Joyner 	device_printf(dev, "slot pcib = %x,%x,%x\n", pci_get_bus(dev),
18438eb6488eSEric Joyner 	    pci_get_slot(dev), pci_get_function(dev));
18448eb6488eSEric Joyner #endif
18458eb6488eSEric Joyner 	/* Now get the PCI Express Capabilities offset */
18468eb6488eSEric Joyner 	if (pci_find_cap(dev, PCIY_EXPRESS, &offset)) {
18478eb6488eSEric Joyner 		/*
18488eb6488eSEric Joyner 		 * Hmm...can't get PCI-Express capabilities.
18498eb6488eSEric Joyner 		 * Falling back to default method.
18508eb6488eSEric Joyner 		 */
18518eb6488eSEric Joyner 		bus_info_valid = FALSE;
18528eb6488eSEric Joyner 		ixgbe_get_bus_info(hw);
18538eb6488eSEric Joyner 		goto display;
18548eb6488eSEric Joyner 	}
18558eb6488eSEric Joyner 	/* ...and read the Link Status Register */
18568eb6488eSEric Joyner 	link = pci_read_config(dev, offset + PCIER_LINK_STA, 2);
18578eb6488eSEric Joyner 	ixgbe_set_pci_config_data_generic(hw, link);
18588eb6488eSEric Joyner 
18598eb6488eSEric Joyner display:
18608eb6488eSEric Joyner 	device_printf(dev, "PCI Express Bus: Speed %s %s\n",
18618eb6488eSEric Joyner 	    ((hw->bus.speed == ixgbe_bus_speed_8000)    ? "8.0GT/s"  :
18628eb6488eSEric Joyner 	     (hw->bus.speed == ixgbe_bus_speed_5000)    ? "5.0GT/s"  :
18638eb6488eSEric Joyner 	     (hw->bus.speed == ixgbe_bus_speed_2500)    ? "2.5GT/s"  :
18648eb6488eSEric Joyner 	     "Unknown"),
18658eb6488eSEric Joyner 	    ((hw->bus.width == ixgbe_bus_width_pcie_x8) ? "Width x8" :
18668eb6488eSEric Joyner 	     (hw->bus.width == ixgbe_bus_width_pcie_x4) ? "Width x4" :
18678eb6488eSEric Joyner 	     (hw->bus.width == ixgbe_bus_width_pcie_x1) ? "Width x1" :
18688eb6488eSEric Joyner 	     "Unknown"));
18698eb6488eSEric Joyner 
18708eb6488eSEric Joyner 	if (bus_info_valid) {
18718eb6488eSEric Joyner 		if ((hw->device_id != IXGBE_DEV_ID_82599_SFP_SF_QP) &&
18728eb6488eSEric Joyner 		    ((hw->bus.width <= ixgbe_bus_width_pcie_x4) &&
18738eb6488eSEric Joyner 		    (hw->bus.speed == ixgbe_bus_speed_2500))) {
18748eb6488eSEric Joyner 			device_printf(dev, "PCI-Express bandwidth available for this card\n     is not sufficient for optimal performance.\n");
18758eb6488eSEric Joyner 			device_printf(dev, "For optimal performance a x8 PCIE, or x4 PCIE Gen2 slot is required.\n");
18768eb6488eSEric Joyner 		}
18778eb6488eSEric Joyner 		if ((hw->device_id == IXGBE_DEV_ID_82599_SFP_SF_QP) &&
18788eb6488eSEric Joyner 		    ((hw->bus.width <= ixgbe_bus_width_pcie_x8) &&
18798eb6488eSEric Joyner 		    (hw->bus.speed < ixgbe_bus_speed_8000))) {
18808eb6488eSEric Joyner 			device_printf(dev, "PCI-Express bandwidth available for this card\n     is not sufficient for optimal performance.\n");
18818eb6488eSEric Joyner 			device_printf(dev, "For optimal performance a x8 PCIE Gen3 slot is required.\n");
18828eb6488eSEric Joyner 		}
18838eb6488eSEric Joyner 	} else
18848eb6488eSEric Joyner 		device_printf(dev, "Unable to determine slot speed/width. The speed/width reported are that of the internal switch.\n");
18858eb6488eSEric Joyner 
18868eb6488eSEric Joyner 	return;
18878eb6488eSEric Joyner } /* ixgbe_get_slot_info */
18888eb6488eSEric Joyner 
18898eb6488eSEric Joyner /************************************************************************
18908eb6488eSEric Joyner  * ixgbe_enable_queue - MSI-X Interrupt Handlers and Tasklets
18918eb6488eSEric Joyner  ************************************************************************/
18928eb6488eSEric Joyner static inline void
18938eb6488eSEric Joyner ixgbe_enable_queue(struct adapter *adapter, u32 vector)
18948eb6488eSEric Joyner {
18958eb6488eSEric Joyner 	struct ixgbe_hw *hw = &adapter->hw;
18968eb6488eSEric Joyner 	u64             queue = (u64)(1 << vector);
18978eb6488eSEric Joyner 	u32             mask;
18988eb6488eSEric Joyner 
18998eb6488eSEric Joyner 	if (hw->mac.type == ixgbe_mac_82598EB) {
19008eb6488eSEric Joyner 		mask = (IXGBE_EIMS_RTX_QUEUE & queue);
19018eb6488eSEric Joyner 		IXGBE_WRITE_REG(hw, IXGBE_EIMS, mask);
19028eb6488eSEric Joyner 	} else {
19038eb6488eSEric Joyner 		mask = (queue & 0xFFFFFFFF);
19048eb6488eSEric Joyner 		if (mask)
19058eb6488eSEric Joyner 			IXGBE_WRITE_REG(hw, IXGBE_EIMS_EX(0), mask);
19068eb6488eSEric Joyner 		mask = (queue >> 32);
19078eb6488eSEric Joyner 		if (mask)
19088eb6488eSEric Joyner 			IXGBE_WRITE_REG(hw, IXGBE_EIMS_EX(1), mask);
19098eb6488eSEric Joyner 	}
19108eb6488eSEric Joyner } /* ixgbe_enable_queue */
19118eb6488eSEric Joyner 
19128eb6488eSEric Joyner /************************************************************************
19138eb6488eSEric Joyner  * ixgbe_disable_queue
19148eb6488eSEric Joyner  ************************************************************************/
19158eb6488eSEric Joyner static inline void
19168eb6488eSEric Joyner ixgbe_disable_queue(struct adapter *adapter, u32 vector)
19178eb6488eSEric Joyner {
19188eb6488eSEric Joyner 	struct ixgbe_hw *hw = &adapter->hw;
19198eb6488eSEric Joyner 	u64             queue = (u64)(1 << vector);
19208eb6488eSEric Joyner 	u32             mask;
19218eb6488eSEric Joyner 
19228eb6488eSEric Joyner 	if (hw->mac.type == ixgbe_mac_82598EB) {
19238eb6488eSEric Joyner 		mask = (IXGBE_EIMS_RTX_QUEUE & queue);
19248eb6488eSEric Joyner 		IXGBE_WRITE_REG(hw, IXGBE_EIMC, mask);
19258eb6488eSEric Joyner 	} else {
19268eb6488eSEric Joyner 		mask = (queue & 0xFFFFFFFF);
19278eb6488eSEric Joyner 		if (mask)
19288eb6488eSEric Joyner 			IXGBE_WRITE_REG(hw, IXGBE_EIMC_EX(0), mask);
19298eb6488eSEric Joyner 		mask = (queue >> 32);
19308eb6488eSEric Joyner 		if (mask)
19318eb6488eSEric Joyner 			IXGBE_WRITE_REG(hw, IXGBE_EIMC_EX(1), mask);
19328eb6488eSEric Joyner 	}
19338eb6488eSEric Joyner } /* ixgbe_disable_queue */
19348eb6488eSEric Joyner 
19358eb6488eSEric Joyner /************************************************************************
19368eb6488eSEric Joyner  * ixgbe_msix_que - MSI-X Queue Interrupt Service routine
19378eb6488eSEric Joyner  ************************************************************************/
19388eb6488eSEric Joyner void
19398eb6488eSEric Joyner ixgbe_msix_que(void *arg)
19408eb6488eSEric Joyner {
19418eb6488eSEric Joyner 	struct ix_queue *que = arg;
19428eb6488eSEric Joyner 	struct adapter  *adapter = que->adapter;
19438eb6488eSEric Joyner 	struct ifnet    *ifp = adapter->ifp;
19448eb6488eSEric Joyner 	struct tx_ring  *txr = que->txr;
19458eb6488eSEric Joyner 	struct rx_ring  *rxr = que->rxr;
19468eb6488eSEric Joyner 	bool            more;
19478eb6488eSEric Joyner 	u32             newitr = 0;
19488eb6488eSEric Joyner 
19498eb6488eSEric Joyner 
19508eb6488eSEric Joyner 	/* Protect against spurious interrupts */
19518eb6488eSEric Joyner 	if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0)
19528eb6488eSEric Joyner 		return;
19538eb6488eSEric Joyner 
19548eb6488eSEric Joyner 	ixgbe_disable_queue(adapter, que->msix);
19558eb6488eSEric Joyner 	++que->irqs;
19568eb6488eSEric Joyner 
19578eb6488eSEric Joyner 	more = ixgbe_rxeof(que);
19588eb6488eSEric Joyner 
19598eb6488eSEric Joyner 	IXGBE_TX_LOCK(txr);
19608eb6488eSEric Joyner 	ixgbe_txeof(txr);
19618eb6488eSEric Joyner 	if (!ixgbe_ring_empty(ifp, txr->br))
19628eb6488eSEric Joyner 		ixgbe_start_locked(ifp, txr);
19638eb6488eSEric Joyner 	IXGBE_TX_UNLOCK(txr);
19648eb6488eSEric Joyner 
19658eb6488eSEric Joyner 	/* Do AIM now? */
19668eb6488eSEric Joyner 
19678eb6488eSEric Joyner 	if (adapter->enable_aim == FALSE)
19688eb6488eSEric Joyner 		goto no_calc;
19698eb6488eSEric Joyner 	/*
19708eb6488eSEric Joyner 	 * Do Adaptive Interrupt Moderation:
19718eb6488eSEric Joyner 	 *  - Write out last calculated setting
19728eb6488eSEric Joyner 	 *  - Calculate based on average size over
19738eb6488eSEric Joyner 	 *    the last interval.
19748eb6488eSEric Joyner 	 */
19758eb6488eSEric Joyner 	if (que->eitr_setting)
19768eb6488eSEric Joyner 		IXGBE_WRITE_REG(&adapter->hw, IXGBE_EITR(que->msix),
19778eb6488eSEric Joyner 		    que->eitr_setting);
19788eb6488eSEric Joyner 
19798eb6488eSEric Joyner 	que->eitr_setting = 0;
19808eb6488eSEric Joyner 
19818eb6488eSEric Joyner 	/* Idle, do nothing */
19828eb6488eSEric Joyner 	if ((txr->bytes == 0) && (rxr->bytes == 0))
19838eb6488eSEric Joyner 		goto no_calc;
19848eb6488eSEric Joyner 
19858eb6488eSEric Joyner 	if ((txr->bytes) && (txr->packets))
19868eb6488eSEric Joyner 		newitr = txr->bytes/txr->packets;
19878eb6488eSEric Joyner 	if ((rxr->bytes) && (rxr->packets))
19888eb6488eSEric Joyner 		newitr = max(newitr, (rxr->bytes / rxr->packets));
19898eb6488eSEric Joyner 	newitr += 24; /* account for hardware frame, crc */
19908eb6488eSEric Joyner 
19918eb6488eSEric Joyner 	/* set an upper boundary */
19928eb6488eSEric Joyner 	newitr = min(newitr, 3000);
19938eb6488eSEric Joyner 
19948eb6488eSEric Joyner 	/* Be nice to the mid range */
19958eb6488eSEric Joyner 	if ((newitr > 300) && (newitr < 1200))
19968eb6488eSEric Joyner 		newitr = (newitr / 3);
19978eb6488eSEric Joyner 	else
19988eb6488eSEric Joyner 		newitr = (newitr / 2);
19998eb6488eSEric Joyner 
20008eb6488eSEric Joyner 	if (adapter->hw.mac.type == ixgbe_mac_82598EB)
20018eb6488eSEric Joyner 		newitr |= newitr << 16;
20028eb6488eSEric Joyner 	else
20038eb6488eSEric Joyner 		newitr |= IXGBE_EITR_CNT_WDIS;
20048eb6488eSEric Joyner 
20058eb6488eSEric Joyner 	/* save for next interrupt */
20068eb6488eSEric Joyner 	que->eitr_setting = newitr;
20078eb6488eSEric Joyner 
20088eb6488eSEric Joyner 	/* Reset state */
20098eb6488eSEric Joyner 	txr->bytes = 0;
20108eb6488eSEric Joyner 	txr->packets = 0;
20118eb6488eSEric Joyner 	rxr->bytes = 0;
20128eb6488eSEric Joyner 	rxr->packets = 0;
20138eb6488eSEric Joyner 
20148eb6488eSEric Joyner no_calc:
20158eb6488eSEric Joyner 	if (more)
20168eb6488eSEric Joyner 		taskqueue_enqueue(que->tq, &que->que_task);
20178eb6488eSEric Joyner 	else
20188eb6488eSEric Joyner 		ixgbe_enable_queue(adapter, que->msix);
20198eb6488eSEric Joyner 
20208eb6488eSEric Joyner 	return;
20218eb6488eSEric Joyner } /* ixgbe_msix_que */
20228eb6488eSEric Joyner 
20238eb6488eSEric Joyner /************************************************************************
20248eb6488eSEric Joyner  * ixgbe_media_status - Media Ioctl callback
20258eb6488eSEric Joyner  *
20268eb6488eSEric Joyner  *   Called whenever the user queries the status of
20278eb6488eSEric Joyner  *   the interface using ifconfig.
20288eb6488eSEric Joyner  ************************************************************************/
20298eb6488eSEric Joyner static void
20308eb6488eSEric Joyner ixgbe_media_status(struct ifnet *ifp, struct ifmediareq *ifmr)
20318eb6488eSEric Joyner {
20328eb6488eSEric Joyner 	struct adapter  *adapter = ifp->if_softc;
20338eb6488eSEric Joyner 	struct ixgbe_hw *hw = &adapter->hw;
20348eb6488eSEric Joyner 	int             layer;
20358eb6488eSEric Joyner 
20368eb6488eSEric Joyner 	INIT_DEBUGOUT("ixgbe_media_status: begin");
20378eb6488eSEric Joyner 	IXGBE_CORE_LOCK(adapter);
20388eb6488eSEric Joyner 	ixgbe_update_link_status(adapter);
20398eb6488eSEric Joyner 
20408eb6488eSEric Joyner 	ifmr->ifm_status = IFM_AVALID;
20418eb6488eSEric Joyner 	ifmr->ifm_active = IFM_ETHER;
20428eb6488eSEric Joyner 
20438eb6488eSEric Joyner 	if (!adapter->link_active) {
20448eb6488eSEric Joyner 		IXGBE_CORE_UNLOCK(adapter);
20458eb6488eSEric Joyner 		return;
20468eb6488eSEric Joyner 	}
20478eb6488eSEric Joyner 
20488eb6488eSEric Joyner 	ifmr->ifm_status |= IFM_ACTIVE;
20498eb6488eSEric Joyner 	layer = adapter->phy_layer;
20508eb6488eSEric Joyner 
20518eb6488eSEric Joyner 	if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_T ||
20528eb6488eSEric Joyner 	    layer & IXGBE_PHYSICAL_LAYER_1000BASE_T ||
20538eb6488eSEric Joyner 	    layer & IXGBE_PHYSICAL_LAYER_100BASE_TX ||
20548eb6488eSEric Joyner 	    layer & IXGBE_PHYSICAL_LAYER_10BASE_T)
20558eb6488eSEric Joyner 		switch (adapter->link_speed) {
20568eb6488eSEric Joyner 		case IXGBE_LINK_SPEED_10GB_FULL:
20578eb6488eSEric Joyner 			ifmr->ifm_active |= IFM_10G_T | IFM_FDX;
20588eb6488eSEric Joyner 			break;
20598eb6488eSEric Joyner 		case IXGBE_LINK_SPEED_1GB_FULL:
20608eb6488eSEric Joyner 			ifmr->ifm_active |= IFM_1000_T | IFM_FDX;
20618eb6488eSEric Joyner 			break;
20628eb6488eSEric Joyner 		case IXGBE_LINK_SPEED_100_FULL:
20638eb6488eSEric Joyner 			ifmr->ifm_active |= IFM_100_TX | IFM_FDX;
20648eb6488eSEric Joyner 			break;
20658eb6488eSEric Joyner 		case IXGBE_LINK_SPEED_10_FULL:
20668eb6488eSEric Joyner 			ifmr->ifm_active |= IFM_10_T | IFM_FDX;
20678eb6488eSEric Joyner 			break;
20688eb6488eSEric Joyner 		}
20698eb6488eSEric Joyner 	if (layer & IXGBE_PHYSICAL_LAYER_SFP_PLUS_CU ||
20708eb6488eSEric Joyner 	    layer & IXGBE_PHYSICAL_LAYER_SFP_ACTIVE_DA)
20718eb6488eSEric Joyner 		switch (adapter->link_speed) {
20728eb6488eSEric Joyner 		case IXGBE_LINK_SPEED_10GB_FULL:
20738eb6488eSEric Joyner 			ifmr->ifm_active |= IFM_10G_TWINAX | IFM_FDX;
20748eb6488eSEric Joyner 			break;
20758eb6488eSEric Joyner 		}
20768eb6488eSEric Joyner 	if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_LR)
20778eb6488eSEric Joyner 		switch (adapter->link_speed) {
20788eb6488eSEric Joyner 		case IXGBE_LINK_SPEED_10GB_FULL:
20798eb6488eSEric Joyner 			ifmr->ifm_active |= IFM_10G_LR | IFM_FDX;
20808eb6488eSEric Joyner 			break;
20818eb6488eSEric Joyner 		case IXGBE_LINK_SPEED_1GB_FULL:
20828eb6488eSEric Joyner 			ifmr->ifm_active |= IFM_1000_LX | IFM_FDX;
20838eb6488eSEric Joyner 			break;
20848eb6488eSEric Joyner 		}
20858eb6488eSEric Joyner 	if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_LRM)
20868eb6488eSEric Joyner 		switch (adapter->link_speed) {
20878eb6488eSEric Joyner 		case IXGBE_LINK_SPEED_10GB_FULL:
20888eb6488eSEric Joyner 			ifmr->ifm_active |= IFM_10G_LRM | IFM_FDX;
20898eb6488eSEric Joyner 			break;
20908eb6488eSEric Joyner 		case IXGBE_LINK_SPEED_1GB_FULL:
20918eb6488eSEric Joyner 			ifmr->ifm_active |= IFM_1000_LX | IFM_FDX;
20928eb6488eSEric Joyner 			break;
20938eb6488eSEric Joyner 		}
20948eb6488eSEric Joyner 	if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_SR ||
20958eb6488eSEric Joyner 	    layer & IXGBE_PHYSICAL_LAYER_1000BASE_SX)
20968eb6488eSEric Joyner 		switch (adapter->link_speed) {
20978eb6488eSEric Joyner 		case IXGBE_LINK_SPEED_10GB_FULL:
20988eb6488eSEric Joyner 			ifmr->ifm_active |= IFM_10G_SR | IFM_FDX;
20998eb6488eSEric Joyner 			break;
21008eb6488eSEric Joyner 		case IXGBE_LINK_SPEED_1GB_FULL:
21018eb6488eSEric Joyner 			ifmr->ifm_active |= IFM_1000_SX | IFM_FDX;
21028eb6488eSEric Joyner 			break;
21038eb6488eSEric Joyner 		}
21048eb6488eSEric Joyner 	if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_CX4)
21058eb6488eSEric Joyner 		switch (adapter->link_speed) {
21068eb6488eSEric Joyner 		case IXGBE_LINK_SPEED_10GB_FULL:
21078eb6488eSEric Joyner 			ifmr->ifm_active |= IFM_10G_CX4 | IFM_FDX;
21088eb6488eSEric Joyner 			break;
21098eb6488eSEric Joyner 		}
21108eb6488eSEric Joyner 	/*
21118eb6488eSEric Joyner 	 * XXX: These need to use the proper media types once
21128eb6488eSEric Joyner 	 * they're added.
21138eb6488eSEric Joyner 	 */
21148eb6488eSEric Joyner #ifndef IFM_ETH_XTYPE
21158eb6488eSEric Joyner 	if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_KR)
21168eb6488eSEric Joyner 		switch (adapter->link_speed) {
21178eb6488eSEric Joyner 		case IXGBE_LINK_SPEED_10GB_FULL:
21188eb6488eSEric Joyner 			ifmr->ifm_active |= IFM_10G_SR | IFM_FDX;
21198eb6488eSEric Joyner 			break;
21208eb6488eSEric Joyner 		case IXGBE_LINK_SPEED_2_5GB_FULL:
21218eb6488eSEric Joyner 			ifmr->ifm_active |= IFM_2500_SX | IFM_FDX;
21228eb6488eSEric Joyner 			break;
21238eb6488eSEric Joyner 		case IXGBE_LINK_SPEED_1GB_FULL:
21248eb6488eSEric Joyner 			ifmr->ifm_active |= IFM_1000_CX | IFM_FDX;
21258eb6488eSEric Joyner 			break;
21268eb6488eSEric Joyner 		}
21278eb6488eSEric Joyner 	else if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_KX4 ||
21288eb6488eSEric Joyner 	    layer & IXGBE_PHYSICAL_LAYER_2500BASE_KX ||
21298eb6488eSEric Joyner 	    layer & IXGBE_PHYSICAL_LAYER_1000BASE_KX)
21308eb6488eSEric Joyner 		switch (adapter->link_speed) {
21318eb6488eSEric Joyner 		case IXGBE_LINK_SPEED_10GB_FULL:
21328eb6488eSEric Joyner 			ifmr->ifm_active |= IFM_10G_CX4 | IFM_FDX;
21338eb6488eSEric Joyner 			break;
21348eb6488eSEric Joyner 		case IXGBE_LINK_SPEED_2_5GB_FULL:
21358eb6488eSEric Joyner 			ifmr->ifm_active |= IFM_2500_SX | IFM_FDX;
21368eb6488eSEric Joyner 			break;
21378eb6488eSEric Joyner 		case IXGBE_LINK_SPEED_1GB_FULL:
21388eb6488eSEric Joyner 			ifmr->ifm_active |= IFM_1000_CX | IFM_FDX;
21398eb6488eSEric Joyner 			break;
21408eb6488eSEric Joyner 		}
21418eb6488eSEric Joyner #else
21428eb6488eSEric Joyner 	if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_KR)
21438eb6488eSEric Joyner 		switch (adapter->link_speed) {
21448eb6488eSEric Joyner 		case IXGBE_LINK_SPEED_10GB_FULL:
21458eb6488eSEric Joyner 			ifmr->ifm_active |= IFM_10G_KR | IFM_FDX;
21468eb6488eSEric Joyner 			break;
21478eb6488eSEric Joyner 		case IXGBE_LINK_SPEED_2_5GB_FULL:
21488eb6488eSEric Joyner 			ifmr->ifm_active |= IFM_2500_KX | IFM_FDX;
21498eb6488eSEric Joyner 			break;
21508eb6488eSEric Joyner 		case IXGBE_LINK_SPEED_1GB_FULL:
21518eb6488eSEric Joyner 			ifmr->ifm_active |= IFM_1000_KX | IFM_FDX;
21528eb6488eSEric Joyner 			break;
21538eb6488eSEric Joyner 		}
21548eb6488eSEric Joyner 	else if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_KX4 ||
21558eb6488eSEric Joyner 	    layer & IXGBE_PHYSICAL_LAYER_2500BASE_KX ||
21568eb6488eSEric Joyner 	    layer & IXGBE_PHYSICAL_LAYER_1000BASE_KX)
21578eb6488eSEric Joyner 		switch (adapter->link_speed) {
21588eb6488eSEric Joyner 		case IXGBE_LINK_SPEED_10GB_FULL:
21598eb6488eSEric Joyner 			ifmr->ifm_active |= IFM_10G_KX4 | IFM_FDX;
21608eb6488eSEric Joyner 			break;
21618eb6488eSEric Joyner 		case IXGBE_LINK_SPEED_2_5GB_FULL:
21628eb6488eSEric Joyner 			ifmr->ifm_active |= IFM_2500_KX | IFM_FDX;
21638eb6488eSEric Joyner 			break;
21648eb6488eSEric Joyner 		case IXGBE_LINK_SPEED_1GB_FULL:
21658eb6488eSEric Joyner 			ifmr->ifm_active |= IFM_1000_KX | IFM_FDX;
21668eb6488eSEric Joyner 			break;
21678eb6488eSEric Joyner 		}
21688eb6488eSEric Joyner #endif
21698eb6488eSEric Joyner 
21708eb6488eSEric Joyner 	/* If nothing is recognized... */
21718eb6488eSEric Joyner 	if (IFM_SUBTYPE(ifmr->ifm_active) == 0)
21728eb6488eSEric Joyner 		ifmr->ifm_active |= IFM_UNKNOWN;
21738eb6488eSEric Joyner 
21748eb6488eSEric Joyner #if __FreeBSD_version >= 900025
21758eb6488eSEric Joyner 	/* Display current flow control setting used on link */
21768eb6488eSEric Joyner 	if (hw->fc.current_mode == ixgbe_fc_rx_pause ||
21778eb6488eSEric Joyner 	    hw->fc.current_mode == ixgbe_fc_full)
21788eb6488eSEric Joyner 		ifmr->ifm_active |= IFM_ETH_RXPAUSE;
21798eb6488eSEric Joyner 	if (hw->fc.current_mode == ixgbe_fc_tx_pause ||
21808eb6488eSEric Joyner 	    hw->fc.current_mode == ixgbe_fc_full)
21818eb6488eSEric Joyner 		ifmr->ifm_active |= IFM_ETH_TXPAUSE;
21828eb6488eSEric Joyner #endif
21838eb6488eSEric Joyner 
21848eb6488eSEric Joyner 	IXGBE_CORE_UNLOCK(adapter);
21858eb6488eSEric Joyner 
21868eb6488eSEric Joyner 	return;
21878eb6488eSEric Joyner } /* ixgbe_media_status */
21888eb6488eSEric Joyner 
21898eb6488eSEric Joyner /************************************************************************
21908eb6488eSEric Joyner  * ixgbe_media_change - Media Ioctl callback
21918eb6488eSEric Joyner  *
21928eb6488eSEric Joyner  *   Called when the user changes speed/duplex using
21938eb6488eSEric Joyner  *   media/mediopt option with ifconfig.
21948eb6488eSEric Joyner  ************************************************************************/
21958eb6488eSEric Joyner static int
21968eb6488eSEric Joyner ixgbe_media_change(struct ifnet *ifp)
21978eb6488eSEric Joyner {
21988eb6488eSEric Joyner 	struct adapter   *adapter = ifp->if_softc;
21998eb6488eSEric Joyner 	struct ifmedia   *ifm = &adapter->media;
22008eb6488eSEric Joyner 	struct ixgbe_hw  *hw = &adapter->hw;
22018eb6488eSEric Joyner 	ixgbe_link_speed speed = 0;
22028eb6488eSEric Joyner 
22038eb6488eSEric Joyner 	INIT_DEBUGOUT("ixgbe_media_change: begin");
22048eb6488eSEric Joyner 
22058eb6488eSEric Joyner 	if (IFM_TYPE(ifm->ifm_media) != IFM_ETHER)
22068eb6488eSEric Joyner 		return (EINVAL);
22078eb6488eSEric Joyner 
22088eb6488eSEric Joyner 	if (hw->phy.media_type == ixgbe_media_type_backplane)
22098eb6488eSEric Joyner 		return (ENODEV);
22108eb6488eSEric Joyner 
22118eb6488eSEric Joyner 	/*
22128eb6488eSEric Joyner 	 * We don't actually need to check against the supported
22138eb6488eSEric Joyner 	 * media types of the adapter; ifmedia will take care of
22148eb6488eSEric Joyner 	 * that for us.
22158eb6488eSEric Joyner 	 */
22168eb6488eSEric Joyner 	switch (IFM_SUBTYPE(ifm->ifm_media)) {
22178eb6488eSEric Joyner 		case IFM_AUTO:
22188eb6488eSEric Joyner 		case IFM_10G_T:
22198eb6488eSEric Joyner 			speed |= IXGBE_LINK_SPEED_100_FULL;
22208eb6488eSEric Joyner 			speed |= IXGBE_LINK_SPEED_1GB_FULL;
22218eb6488eSEric Joyner 			speed |= IXGBE_LINK_SPEED_10GB_FULL;
22228eb6488eSEric Joyner 			break;
22238eb6488eSEric Joyner 		case IFM_10G_LRM:
22248eb6488eSEric Joyner 		case IFM_10G_LR:
22258eb6488eSEric Joyner #ifndef IFM_ETH_XTYPE
22268eb6488eSEric Joyner 		case IFM_10G_SR: /* KR, too */
22278eb6488eSEric Joyner 		case IFM_10G_CX4: /* KX4 */
22288eb6488eSEric Joyner #else
22298eb6488eSEric Joyner 		case IFM_10G_KR:
22308eb6488eSEric Joyner 		case IFM_10G_KX4:
22318eb6488eSEric Joyner #endif
22328eb6488eSEric Joyner 			speed |= IXGBE_LINK_SPEED_1GB_FULL;
22338eb6488eSEric Joyner 			speed |= IXGBE_LINK_SPEED_10GB_FULL;
22348eb6488eSEric Joyner 			break;
22358eb6488eSEric Joyner #ifndef IFM_ETH_XTYPE
22368eb6488eSEric Joyner 		case IFM_1000_CX: /* KX */
22378eb6488eSEric Joyner #else
22388eb6488eSEric Joyner 		case IFM_1000_KX:
22398eb6488eSEric Joyner #endif
22408eb6488eSEric Joyner 		case IFM_1000_LX:
22418eb6488eSEric Joyner 		case IFM_1000_SX:
22428eb6488eSEric Joyner 			speed |= IXGBE_LINK_SPEED_1GB_FULL;
22438eb6488eSEric Joyner 			break;
22448eb6488eSEric Joyner 		case IFM_1000_T:
22458eb6488eSEric Joyner 			speed |= IXGBE_LINK_SPEED_100_FULL;
22468eb6488eSEric Joyner 			speed |= IXGBE_LINK_SPEED_1GB_FULL;
22478eb6488eSEric Joyner 			break;
22488eb6488eSEric Joyner 		case IFM_10G_TWINAX:
22498eb6488eSEric Joyner 			speed |= IXGBE_LINK_SPEED_10GB_FULL;
22508eb6488eSEric Joyner 			break;
22518eb6488eSEric Joyner 		case IFM_100_TX:
22528eb6488eSEric Joyner 			speed |= IXGBE_LINK_SPEED_100_FULL;
22538eb6488eSEric Joyner 			break;
22548eb6488eSEric Joyner 		case IFM_10_T:
22558eb6488eSEric Joyner 			speed |= IXGBE_LINK_SPEED_10_FULL;
22568eb6488eSEric Joyner 			break;
22578eb6488eSEric Joyner 		default:
22588eb6488eSEric Joyner 			goto invalid;
22598eb6488eSEric Joyner 	}
22608eb6488eSEric Joyner 
22618eb6488eSEric Joyner 	hw->mac.autotry_restart = TRUE;
22628eb6488eSEric Joyner 	hw->mac.ops.setup_link(hw, speed, TRUE);
22638eb6488eSEric Joyner 	adapter->advertise =
22648eb6488eSEric Joyner 	    ((speed & IXGBE_LINK_SPEED_10GB_FULL) ? 4 : 0) |
22658eb6488eSEric Joyner 	    ((speed & IXGBE_LINK_SPEED_1GB_FULL)  ? 2 : 0) |
22668eb6488eSEric Joyner 	    ((speed & IXGBE_LINK_SPEED_100_FULL)  ? 1 : 0) |
22678eb6488eSEric Joyner 	    ((speed & IXGBE_LINK_SPEED_10_FULL)   ? 8 : 0);
22688eb6488eSEric Joyner 
22698eb6488eSEric Joyner 	return (0);
22708eb6488eSEric Joyner 
22718eb6488eSEric Joyner invalid:
22728eb6488eSEric Joyner 	device_printf(adapter->dev, "Invalid media type!\n");
22738eb6488eSEric Joyner 
22748eb6488eSEric Joyner 	return (EINVAL);
22758eb6488eSEric Joyner } /* ixgbe_media_change */
22768eb6488eSEric Joyner 
22778eb6488eSEric Joyner /************************************************************************
22788eb6488eSEric Joyner  * ixgbe_set_promisc
22798eb6488eSEric Joyner  ************************************************************************/
22808eb6488eSEric Joyner static void
22818eb6488eSEric Joyner ixgbe_set_promisc(struct adapter *adapter)
22828eb6488eSEric Joyner {
22838eb6488eSEric Joyner 	struct ifnet *ifp = adapter->ifp;
22848eb6488eSEric Joyner 	int          mcnt = 0;
22858eb6488eSEric Joyner 	u32          rctl;
22868eb6488eSEric Joyner 
22878eb6488eSEric Joyner 	rctl = IXGBE_READ_REG(&adapter->hw, IXGBE_FCTRL);
22888eb6488eSEric Joyner 	rctl &= (~IXGBE_FCTRL_UPE);
22898eb6488eSEric Joyner 	if (ifp->if_flags & IFF_ALLMULTI)
22908eb6488eSEric Joyner 		mcnt = MAX_NUM_MULTICAST_ADDRESSES;
22918eb6488eSEric Joyner 	else {
22928eb6488eSEric Joyner 		struct ifmultiaddr *ifma;
22938eb6488eSEric Joyner #if __FreeBSD_version < 800000
22948eb6488eSEric Joyner 		IF_ADDR_LOCK(ifp);
22958eb6488eSEric Joyner #else
22968eb6488eSEric Joyner 		if_maddr_rlock(ifp);
22978eb6488eSEric Joyner #endif
22988eb6488eSEric Joyner 		TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
22998eb6488eSEric Joyner 			if (ifma->ifma_addr->sa_family != AF_LINK)
23008eb6488eSEric Joyner 				continue;
23018eb6488eSEric Joyner 			if (mcnt == MAX_NUM_MULTICAST_ADDRESSES)
23028eb6488eSEric Joyner 				break;
23038eb6488eSEric Joyner 			mcnt++;
23048eb6488eSEric Joyner 		}
23058eb6488eSEric Joyner #if __FreeBSD_version < 800000
23068eb6488eSEric Joyner 		IF_ADDR_UNLOCK(ifp);
23078eb6488eSEric Joyner #else
23088eb6488eSEric Joyner 		if_maddr_runlock(ifp);
23098eb6488eSEric Joyner #endif
23108eb6488eSEric Joyner 	}
23118eb6488eSEric Joyner 	if (mcnt < MAX_NUM_MULTICAST_ADDRESSES)
23128eb6488eSEric Joyner 		rctl &= (~IXGBE_FCTRL_MPE);
23138eb6488eSEric Joyner 	IXGBE_WRITE_REG(&adapter->hw, IXGBE_FCTRL, rctl);
23148eb6488eSEric Joyner 
23158eb6488eSEric Joyner 	if (ifp->if_flags & IFF_PROMISC) {
23168eb6488eSEric Joyner 		rctl |= (IXGBE_FCTRL_UPE | IXGBE_FCTRL_MPE);
23178eb6488eSEric Joyner 		IXGBE_WRITE_REG(&adapter->hw, IXGBE_FCTRL, rctl);
23188eb6488eSEric Joyner 	} else if (ifp->if_flags & IFF_ALLMULTI) {
23198eb6488eSEric Joyner 		rctl |= IXGBE_FCTRL_MPE;
23208eb6488eSEric Joyner 		rctl &= ~IXGBE_FCTRL_UPE;
23218eb6488eSEric Joyner 		IXGBE_WRITE_REG(&adapter->hw, IXGBE_FCTRL, rctl);
23228eb6488eSEric Joyner 	}
23238eb6488eSEric Joyner } /* ixgbe_set_promisc */
23248eb6488eSEric Joyner 
23258eb6488eSEric Joyner /************************************************************************
23268eb6488eSEric Joyner  * ixgbe_msix_link - Link status change ISR (MSI/MSI-X)
23278eb6488eSEric Joyner  ************************************************************************/
23288eb6488eSEric Joyner static void
23298eb6488eSEric Joyner ixgbe_msix_link(void *arg)
23308eb6488eSEric Joyner {
23318eb6488eSEric Joyner 	struct adapter  *adapter = arg;
23328eb6488eSEric Joyner 	struct ixgbe_hw *hw = &adapter->hw;
23338eb6488eSEric Joyner 	u32             eicr, eicr_mask;
23348eb6488eSEric Joyner 	s32             retval;
23358eb6488eSEric Joyner 
23368eb6488eSEric Joyner 	++adapter->link_irq;
23378eb6488eSEric Joyner 
23388eb6488eSEric Joyner 	/* Pause other interrupts */
23398eb6488eSEric Joyner 	IXGBE_WRITE_REG(hw, IXGBE_EIMC, IXGBE_EIMC_OTHER);
23408eb6488eSEric Joyner 
23418eb6488eSEric Joyner 	/* First get the cause */
23428eb6488eSEric Joyner 	eicr = IXGBE_READ_REG(hw, IXGBE_EICS);
23438eb6488eSEric Joyner 	/* Be sure the queue bits are not cleared */
23448eb6488eSEric Joyner 	eicr &= ~IXGBE_EICR_RTX_QUEUE;
23458eb6488eSEric Joyner 	/* Clear interrupt with write */
23468eb6488eSEric Joyner 	IXGBE_WRITE_REG(hw, IXGBE_EICR, eicr);
23478eb6488eSEric Joyner 
23488eb6488eSEric Joyner 	/* Link status change */
23498eb6488eSEric Joyner 	if (eicr & IXGBE_EICR_LSC) {
23508eb6488eSEric Joyner 		IXGBE_WRITE_REG(hw, IXGBE_EIMC, IXGBE_EIMC_LSC);
23518eb6488eSEric Joyner 		taskqueue_enqueue(adapter->tq, &adapter->link_task);
23528eb6488eSEric Joyner 	}
23538eb6488eSEric Joyner 
23548eb6488eSEric Joyner 	if (adapter->hw.mac.type != ixgbe_mac_82598EB) {
23558eb6488eSEric Joyner 		if ((adapter->feat_en & IXGBE_FEATURE_FDIR) &&
23568eb6488eSEric Joyner 		    (eicr & IXGBE_EICR_FLOW_DIR)) {
23578eb6488eSEric Joyner 			/* This is probably overkill :) */
23588eb6488eSEric Joyner 			if (!atomic_cmpset_int(&adapter->fdir_reinit, 0, 1))
23598eb6488eSEric Joyner 				return;
23608eb6488eSEric Joyner 			/* Disable the interrupt */
23618eb6488eSEric Joyner 			IXGBE_WRITE_REG(hw, IXGBE_EIMC, IXGBE_EIMC_FLOW_DIR);
23628eb6488eSEric Joyner 			taskqueue_enqueue(adapter->tq, &adapter->fdir_task);
23638eb6488eSEric Joyner 		}
23648eb6488eSEric Joyner 
23658eb6488eSEric Joyner 		if (eicr & IXGBE_EICR_ECC) {
23668eb6488eSEric Joyner 			device_printf(adapter->dev,
23678eb6488eSEric Joyner 			    "CRITICAL: ECC ERROR!!  Please Reboot!!\n");
23688eb6488eSEric Joyner 			IXGBE_WRITE_REG(hw, IXGBE_EICR, IXGBE_EICR_ECC);
23698eb6488eSEric Joyner 		}
23708eb6488eSEric Joyner 
23718eb6488eSEric Joyner 		/* Check for over temp condition */
23728eb6488eSEric Joyner 		if (adapter->feat_en & IXGBE_FEATURE_TEMP_SENSOR) {
23738eb6488eSEric Joyner 			switch (adapter->hw.mac.type) {
23748eb6488eSEric Joyner 			case ixgbe_mac_X550EM_a:
23758eb6488eSEric Joyner 				if (!(eicr & IXGBE_EICR_GPI_SDP0_X550EM_a))
23768eb6488eSEric Joyner 					break;
23778eb6488eSEric Joyner 				IXGBE_WRITE_REG(hw, IXGBE_EIMC,
23788eb6488eSEric Joyner 				    IXGBE_EICR_GPI_SDP0_X550EM_a);
23798eb6488eSEric Joyner 				IXGBE_WRITE_REG(hw, IXGBE_EICR,
23808eb6488eSEric Joyner 				    IXGBE_EICR_GPI_SDP0_X550EM_a);
23818eb6488eSEric Joyner 				retval = hw->phy.ops.check_overtemp(hw);
23828eb6488eSEric Joyner 				if (retval != IXGBE_ERR_OVERTEMP)
23838eb6488eSEric Joyner 					break;
23848eb6488eSEric Joyner 				device_printf(adapter->dev, "CRITICAL: OVER TEMP!! PHY IS SHUT DOWN!!\n");
23858eb6488eSEric Joyner 				device_printf(adapter->dev, "System shutdown required!\n");
23868eb6488eSEric Joyner 				break;
23878eb6488eSEric Joyner 			default:
23888eb6488eSEric Joyner 				if (!(eicr & IXGBE_EICR_TS))
23898eb6488eSEric Joyner 					break;
23908eb6488eSEric Joyner 				retval = hw->phy.ops.check_overtemp(hw);
23918eb6488eSEric Joyner 				if (retval != IXGBE_ERR_OVERTEMP)
23928eb6488eSEric Joyner 					break;
23938eb6488eSEric Joyner 				device_printf(adapter->dev, "CRITICAL: OVER TEMP!! PHY IS SHUT DOWN!!\n");
23948eb6488eSEric Joyner 				device_printf(adapter->dev, "System shutdown required!\n");
23958eb6488eSEric Joyner 				IXGBE_WRITE_REG(hw, IXGBE_EICR, IXGBE_EICR_TS);
23968eb6488eSEric Joyner 				break;
23978eb6488eSEric Joyner 			}
23988eb6488eSEric Joyner 		}
23998eb6488eSEric Joyner 
24008eb6488eSEric Joyner 		/* Check for VF message */
24018eb6488eSEric Joyner 		if ((adapter->feat_en & IXGBE_FEATURE_SRIOV) &&
24028eb6488eSEric Joyner 		    (eicr & IXGBE_EICR_MAILBOX))
24038eb6488eSEric Joyner 			taskqueue_enqueue(adapter->tq, &adapter->mbx_task);
24048eb6488eSEric Joyner 	}
24058eb6488eSEric Joyner 
24068eb6488eSEric Joyner 	if (ixgbe_is_sfp(hw)) {
24078eb6488eSEric Joyner 		/* Pluggable optics-related interrupt */
24088eb6488eSEric Joyner 		if (hw->mac.type >= ixgbe_mac_X540)
24098eb6488eSEric Joyner 			eicr_mask = IXGBE_EICR_GPI_SDP0_X540;
24108eb6488eSEric Joyner 		else
24118eb6488eSEric Joyner 			eicr_mask = IXGBE_EICR_GPI_SDP2_BY_MAC(hw);
24128eb6488eSEric Joyner 
24138eb6488eSEric Joyner 		if (eicr & eicr_mask) {
24148eb6488eSEric Joyner 			IXGBE_WRITE_REG(hw, IXGBE_EICR, eicr_mask);
24158eb6488eSEric Joyner 			taskqueue_enqueue(adapter->tq, &adapter->mod_task);
24168eb6488eSEric Joyner 		}
24178eb6488eSEric Joyner 
24188eb6488eSEric Joyner 		if ((hw->mac.type == ixgbe_mac_82599EB) &&
24198eb6488eSEric Joyner 		    (eicr & IXGBE_EICR_GPI_SDP1_BY_MAC(hw))) {
24208eb6488eSEric Joyner 			IXGBE_WRITE_REG(hw, IXGBE_EICR,
24218eb6488eSEric Joyner 			    IXGBE_EICR_GPI_SDP1_BY_MAC(hw));
24228eb6488eSEric Joyner 			taskqueue_enqueue(adapter->tq, &adapter->msf_task);
24238eb6488eSEric Joyner 		}
24248eb6488eSEric Joyner 	}
24258eb6488eSEric Joyner 
24268eb6488eSEric Joyner 	/* Check for fan failure */
24278eb6488eSEric Joyner 	if (adapter->feat_en & IXGBE_FEATURE_FAN_FAIL) {
24288eb6488eSEric Joyner 		ixgbe_check_fan_failure(adapter, eicr, TRUE);
24298eb6488eSEric Joyner 		IXGBE_WRITE_REG(hw, IXGBE_EICR, IXGBE_EICR_GPI_SDP1_BY_MAC(hw));
24308eb6488eSEric Joyner 	}
24318eb6488eSEric Joyner 
24328eb6488eSEric Joyner 	/* External PHY interrupt */
24338eb6488eSEric Joyner 	if ((hw->phy.type == ixgbe_phy_x550em_ext_t) &&
24348eb6488eSEric Joyner 	    (eicr & IXGBE_EICR_GPI_SDP0_X540)) {
24358eb6488eSEric Joyner 		IXGBE_WRITE_REG(hw, IXGBE_EICR, IXGBE_EICR_GPI_SDP0_X540);
24368eb6488eSEric Joyner 		taskqueue_enqueue(adapter->tq, &adapter->phy_task);
24378eb6488eSEric Joyner 	}
24388eb6488eSEric Joyner 
24398eb6488eSEric Joyner 	/* Re-enable other interrupts */
24408eb6488eSEric Joyner 	IXGBE_WRITE_REG(hw, IXGBE_EIMS, IXGBE_EIMS_OTHER);
24418eb6488eSEric Joyner } /* ixgbe_msix_link */
24428eb6488eSEric Joyner 
24438eb6488eSEric Joyner /************************************************************************
24448eb6488eSEric Joyner  * ixgbe_sysctl_interrupt_rate_handler
24458eb6488eSEric Joyner  ************************************************************************/
2446758cc3dcSJack F Vogel static int
2447758cc3dcSJack F Vogel ixgbe_sysctl_interrupt_rate_handler(SYSCTL_HANDLER_ARGS)
2448758cc3dcSJack F Vogel {
2449758cc3dcSJack F Vogel 	struct ix_queue *que = ((struct ix_queue *)oidp->oid_arg1);
24508eb6488eSEric Joyner 	int             error;
2451758cc3dcSJack F Vogel 	unsigned int    reg, usec, rate;
2452758cc3dcSJack F Vogel 
2453758cc3dcSJack F Vogel 	reg = IXGBE_READ_REG(&que->adapter->hw, IXGBE_EITR(que->msix));
2454758cc3dcSJack F Vogel 	usec = ((reg & 0x0FF8) >> 3);
2455758cc3dcSJack F Vogel 	if (usec > 0)
2456758cc3dcSJack F Vogel 		rate = 500000 / usec;
2457758cc3dcSJack F Vogel 	else
2458758cc3dcSJack F Vogel 		rate = 0;
2459758cc3dcSJack F Vogel 	error = sysctl_handle_int(oidp, &rate, 0, req);
2460758cc3dcSJack F Vogel 	if (error || !req->newptr)
2461758cc3dcSJack F Vogel 		return error;
2462758cc3dcSJack F Vogel 	reg &= ~0xfff; /* default, no limitation */
2463758cc3dcSJack F Vogel 	ixgbe_max_interrupt_rate = 0;
2464758cc3dcSJack F Vogel 	if (rate > 0 && rate < 500000) {
2465758cc3dcSJack F Vogel 		if (rate < 1000)
2466758cc3dcSJack F Vogel 			rate = 1000;
2467758cc3dcSJack F Vogel 		ixgbe_max_interrupt_rate = rate;
2468758cc3dcSJack F Vogel 		reg |= ((4000000/rate) & 0xff8);
2469758cc3dcSJack F Vogel 	}
2470758cc3dcSJack F Vogel 	IXGBE_WRITE_REG(&que->adapter->hw, IXGBE_EITR(que->msix), reg);
2471758cc3dcSJack F Vogel 
24728eb6488eSEric Joyner 	return (0);
24738eb6488eSEric Joyner } /* ixgbe_sysctl_interrupt_rate_handler */
24748eb6488eSEric Joyner 
24758eb6488eSEric Joyner /************************************************************************
24768eb6488eSEric Joyner  * ixgbe_add_device_sysctls
24778eb6488eSEric Joyner  ************************************************************************/
24786f37f232SEric Joyner static void
24796f37f232SEric Joyner ixgbe_add_device_sysctls(struct adapter *adapter)
24806f37f232SEric Joyner {
24816f37f232SEric Joyner 	device_t               dev = adapter->dev;
24826f37f232SEric Joyner 	struct ixgbe_hw        *hw = &adapter->hw;
24836f37f232SEric Joyner 	struct sysctl_oid_list *child;
24846f37f232SEric Joyner 	struct sysctl_ctx_list *ctx;
24856f37f232SEric Joyner 
24866f37f232SEric Joyner 	ctx = device_get_sysctl_ctx(dev);
24876f37f232SEric Joyner 	child = SYSCTL_CHILDREN(device_get_sysctl_tree(dev));
24886f37f232SEric Joyner 
24896f37f232SEric Joyner 	/* Sysctls for all devices */
24908eb6488eSEric Joyner 	SYSCTL_ADD_PROC(ctx, child, OID_AUTO, "fc", CTLTYPE_INT | CTLFLAG_RW,
24918eb6488eSEric Joyner 	    adapter, 0, ixgbe_sysctl_flowcntl, "I", IXGBE_SYSCTL_DESC_SET_FC);
24926f37f232SEric Joyner 
24938eb6488eSEric Joyner 	adapter->enable_aim = ixgbe_enable_aim;
24948eb6488eSEric Joyner 	SYSCTL_ADD_INT(ctx, child, OID_AUTO, "enable_aim", CTLFLAG_RW,
24958eb6488eSEric Joyner 	    &adapter->enable_aim, 1, "Interrupt Moderation");
24966f37f232SEric Joyner 
24976f37f232SEric Joyner 	SYSCTL_ADD_PROC(ctx, child, OID_AUTO, "advertise_speed",
24988eb6488eSEric Joyner 	    CTLTYPE_INT | CTLFLAG_RW, adapter, 0, ixgbe_sysctl_advertise, "I",
24998eb6488eSEric Joyner 	    IXGBE_SYSCTL_DESC_ADV_SPEED);
25006f37f232SEric Joyner 
2501a9ca1c79SSean Bruno #ifdef IXGBE_DEBUG
2502a9ca1c79SSean Bruno 	/* testing sysctls (for all devices) */
2503a9ca1c79SSean Bruno 	SYSCTL_ADD_PROC(ctx, child, OID_AUTO, "power_state",
25048eb6488eSEric Joyner 	    CTLTYPE_INT | CTLFLAG_RW, adapter, 0, ixgbe_sysctl_power_state,
25058eb6488eSEric Joyner 	    "I", "PCI Power State");
2506a9ca1c79SSean Bruno 
2507a9ca1c79SSean Bruno 	SYSCTL_ADD_PROC(ctx, child, OID_AUTO, "print_rss_config",
2508a9ca1c79SSean Bruno 	    CTLTYPE_STRING | CTLFLAG_RD, adapter, 0,
2509a9ca1c79SSean Bruno 	    ixgbe_sysctl_print_rss_config, "A", "Prints RSS Configuration");
2510a9ca1c79SSean Bruno #endif
2511a9ca1c79SSean Bruno 	/* for X550 series devices */
25126f37f232SEric Joyner 	if (hw->mac.type >= ixgbe_mac_X550)
25136f37f232SEric Joyner 		SYSCTL_ADD_PROC(ctx, child, OID_AUTO, "dmac",
25148eb6488eSEric Joyner 		    CTLTYPE_INT | CTLFLAG_RW, adapter, 0, ixgbe_sysctl_dmac,
25158eb6488eSEric Joyner 		    "I", "DMA Coalesce");
25166f37f232SEric Joyner 
2517a9ca1c79SSean Bruno 	/* for WoL-capable devices */
2518a9ca1c79SSean Bruno 	if (hw->device_id == IXGBE_DEV_ID_X550EM_X_10G_T) {
25196f37f232SEric Joyner 		SYSCTL_ADD_PROC(ctx, child, OID_AUTO, "wol_enable",
25206f37f232SEric Joyner 		    CTLTYPE_INT | CTLFLAG_RW, adapter, 0,
25218eb6488eSEric Joyner 		    ixgbe_sysctl_wol_enable, "I", "Enable/Disable Wake on LAN");
25226f37f232SEric Joyner 
25236f37f232SEric Joyner 		SYSCTL_ADD_PROC(ctx, child, OID_AUTO, "wufc",
25248eb6488eSEric Joyner 		    CTLTYPE_INT | CTLFLAG_RW, adapter, 0, ixgbe_sysctl_wufc,
25258eb6488eSEric Joyner 		    "I", "Enable/Disable Wake Up Filters");
25266f37f232SEric Joyner 	}
25276f37f232SEric Joyner 
2528a9ca1c79SSean Bruno 	/* for X552/X557-AT devices */
25296f37f232SEric Joyner 	if (hw->device_id == IXGBE_DEV_ID_X550EM_X_10G_T) {
25306f37f232SEric Joyner 		struct sysctl_oid *phy_node;
25316f37f232SEric Joyner 		struct sysctl_oid_list *phy_list;
25326f37f232SEric Joyner 
25336f37f232SEric Joyner 		phy_node = SYSCTL_ADD_NODE(ctx, child, OID_AUTO, "phy",
25348eb6488eSEric Joyner 		    CTLFLAG_RD, NULL, "External PHY sysctls");
25356f37f232SEric Joyner 		phy_list = SYSCTL_CHILDREN(phy_node);
25366f37f232SEric Joyner 
25376f37f232SEric Joyner 		SYSCTL_ADD_PROC(ctx, phy_list, OID_AUTO, "temp",
25388eb6488eSEric Joyner 		    CTLTYPE_INT | CTLFLAG_RD, adapter, 0, ixgbe_sysctl_phy_temp,
25398eb6488eSEric Joyner 		    "I", "Current External PHY Temperature (Celsius)");
25406f37f232SEric Joyner 
25416f37f232SEric Joyner 		SYSCTL_ADD_PROC(ctx, phy_list, OID_AUTO, "overtemp_occurred",
25426f37f232SEric Joyner 		    CTLTYPE_INT | CTLFLAG_RD, adapter, 0,
25436f37f232SEric Joyner 		    ixgbe_sysctl_phy_overtemp_occurred, "I",
25446f37f232SEric Joyner 		    "External PHY High Temperature Event Occurred");
25456f37f232SEric Joyner 	}
25468eb6488eSEric Joyner 
25478eb6488eSEric Joyner 	if (adapter->feat_cap & IXGBE_FEATURE_EEE) {
25488eb6488eSEric Joyner 		SYSCTL_ADD_PROC(ctx, child, OID_AUTO, "eee_state",
25498eb6488eSEric Joyner 		    CTLTYPE_INT | CTLFLAG_RW, adapter, 0,
25508eb6488eSEric Joyner 		    ixgbe_sysctl_eee_state, "I", "EEE Power Save State");
25518eb6488eSEric Joyner 	}
25528eb6488eSEric Joyner } /* ixgbe_add_device_sysctls */
25538eb6488eSEric Joyner 
25548eb6488eSEric Joyner /************************************************************************
25558eb6488eSEric Joyner  * ixgbe_allocate_pci_resources
25568eb6488eSEric Joyner  ************************************************************************/
25578eb6488eSEric Joyner static int
25588eb6488eSEric Joyner ixgbe_allocate_pci_resources(struct adapter *adapter)
25598eb6488eSEric Joyner {
25608eb6488eSEric Joyner 	device_t dev = adapter->dev;
25618eb6488eSEric Joyner 	int      rid;
25628eb6488eSEric Joyner 
25638eb6488eSEric Joyner 	rid = PCIR_BAR(0);
25648eb6488eSEric Joyner 	adapter->pci_mem = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
25658eb6488eSEric Joyner 	    RF_ACTIVE);
25668eb6488eSEric Joyner 
25678eb6488eSEric Joyner 	if (!(adapter->pci_mem)) {
25688eb6488eSEric Joyner 		device_printf(dev, "Unable to allocate bus resource: memory\n");
25698eb6488eSEric Joyner 		return (ENXIO);
25708eb6488eSEric Joyner 	}
25718eb6488eSEric Joyner 
25728eb6488eSEric Joyner 	/* Save bus_space values for READ/WRITE_REG macros */
25738eb6488eSEric Joyner 	adapter->osdep.mem_bus_space_tag = rman_get_bustag(adapter->pci_mem);
25748eb6488eSEric Joyner 	adapter->osdep.mem_bus_space_handle =
25758eb6488eSEric Joyner 	    rman_get_bushandle(adapter->pci_mem);
25768eb6488eSEric Joyner 	/* Set hw values for shared code */
25778eb6488eSEric Joyner 	adapter->hw.hw_addr = (u8 *)&adapter->osdep.mem_bus_space_handle;
25788eb6488eSEric Joyner 
25798eb6488eSEric Joyner 	return (0);
25808eb6488eSEric Joyner } /* ixgbe_allocate_pci_resources */
25818eb6488eSEric Joyner 
25828eb6488eSEric Joyner /************************************************************************
25838eb6488eSEric Joyner  * ixgbe_detach - Device removal routine
25848eb6488eSEric Joyner  *
25858eb6488eSEric Joyner  *   Called when the driver is being removed.
25868eb6488eSEric Joyner  *   Stops the adapter and deallocates all the resources
25878eb6488eSEric Joyner  *   that were allocated for driver operation.
25888eb6488eSEric Joyner  *
25898eb6488eSEric Joyner  *   return 0 on success, positive on failure
25908eb6488eSEric Joyner  ************************************************************************/
25918eb6488eSEric Joyner static int
25928eb6488eSEric Joyner ixgbe_detach(device_t dev)
25938eb6488eSEric Joyner {
25948eb6488eSEric Joyner 	struct adapter  *adapter = device_get_softc(dev);
25958eb6488eSEric Joyner 	struct ix_queue *que = adapter->queues;
25968eb6488eSEric Joyner 	struct tx_ring  *txr = adapter->tx_rings;
25978eb6488eSEric Joyner 	u32             ctrl_ext;
25988eb6488eSEric Joyner 
25998eb6488eSEric Joyner 	INIT_DEBUGOUT("ixgbe_detach: begin");
26008eb6488eSEric Joyner 
26018eb6488eSEric Joyner 	/* Make sure VLANS are not using driver */
26028eb6488eSEric Joyner 	if (adapter->ifp->if_vlantrunk != NULL) {
26038eb6488eSEric Joyner 		device_printf(dev, "Vlan in use, detach first\n");
26048eb6488eSEric Joyner 		return (EBUSY);
26058eb6488eSEric Joyner 	}
26068eb6488eSEric Joyner 
26078eb6488eSEric Joyner 	if (ixgbe_pci_iov_detach(dev) != 0) {
26088eb6488eSEric Joyner 		device_printf(dev, "SR-IOV in use; detach first.\n");
26098eb6488eSEric Joyner 		return (EBUSY);
26108eb6488eSEric Joyner 	}
26118eb6488eSEric Joyner 
26128eb6488eSEric Joyner 	ether_ifdetach(adapter->ifp);
26138eb6488eSEric Joyner 	/* Stop the adapter */
26148eb6488eSEric Joyner 	IXGBE_CORE_LOCK(adapter);
26158eb6488eSEric Joyner 	ixgbe_setup_low_power_mode(adapter);
26168eb6488eSEric Joyner 	IXGBE_CORE_UNLOCK(adapter);
26178eb6488eSEric Joyner 
26188eb6488eSEric Joyner 	for (int i = 0; i < adapter->num_queues; i++, que++, txr++) {
26198eb6488eSEric Joyner 		if (que->tq) {
26208eb6488eSEric Joyner 			if (!(adapter->feat_en & IXGBE_FEATURE_LEGACY_TX))
26218eb6488eSEric Joyner 				taskqueue_drain(que->tq, &txr->txq_task);
26228eb6488eSEric Joyner 			taskqueue_drain(que->tq, &que->que_task);
26238eb6488eSEric Joyner 			taskqueue_free(que->tq);
26248eb6488eSEric Joyner 		}
26258eb6488eSEric Joyner 	}
26268eb6488eSEric Joyner 
26278eb6488eSEric Joyner 	/* Drain the Link queue */
26288eb6488eSEric Joyner 	if (adapter->tq) {
26298eb6488eSEric Joyner 		taskqueue_drain(adapter->tq, &adapter->link_task);
26308eb6488eSEric Joyner 		taskqueue_drain(adapter->tq, &adapter->mod_task);
26318eb6488eSEric Joyner 		taskqueue_drain(adapter->tq, &adapter->msf_task);
26328eb6488eSEric Joyner 		if (adapter->feat_cap & IXGBE_FEATURE_SRIOV)
26338eb6488eSEric Joyner 			taskqueue_drain(adapter->tq, &adapter->mbx_task);
26348eb6488eSEric Joyner 		taskqueue_drain(adapter->tq, &adapter->phy_task);
26358eb6488eSEric Joyner 		if (adapter->feat_en & IXGBE_FEATURE_FDIR)
26368eb6488eSEric Joyner 			taskqueue_drain(adapter->tq, &adapter->fdir_task);
26378eb6488eSEric Joyner 		taskqueue_free(adapter->tq);
26388eb6488eSEric Joyner 	}
26398eb6488eSEric Joyner 
26408eb6488eSEric Joyner 	/* let hardware know driver is unloading */
26418eb6488eSEric Joyner 	ctrl_ext = IXGBE_READ_REG(&adapter->hw, IXGBE_CTRL_EXT);
26428eb6488eSEric Joyner 	ctrl_ext &= ~IXGBE_CTRL_EXT_DRV_LOAD;
26438eb6488eSEric Joyner 	IXGBE_WRITE_REG(&adapter->hw, IXGBE_CTRL_EXT, ctrl_ext);
26448eb6488eSEric Joyner 
26458eb6488eSEric Joyner 	/* Unregister VLAN events */
26468eb6488eSEric Joyner 	if (adapter->vlan_attach != NULL)
26478eb6488eSEric Joyner 		EVENTHANDLER_DEREGISTER(vlan_config, adapter->vlan_attach);
26488eb6488eSEric Joyner 	if (adapter->vlan_detach != NULL)
26498eb6488eSEric Joyner 		EVENTHANDLER_DEREGISTER(vlan_unconfig, adapter->vlan_detach);
26508eb6488eSEric Joyner 
26518eb6488eSEric Joyner 	callout_drain(&adapter->timer);
26528eb6488eSEric Joyner 
26538eb6488eSEric Joyner 	if (adapter->feat_en & IXGBE_FEATURE_NETMAP)
26548eb6488eSEric Joyner 		netmap_detach(adapter->ifp);
26558eb6488eSEric Joyner 
26568eb6488eSEric Joyner 	ixgbe_free_pci_resources(adapter);
26578eb6488eSEric Joyner 	bus_generic_detach(dev);
26588eb6488eSEric Joyner 	if_free(adapter->ifp);
26598eb6488eSEric Joyner 
26608eb6488eSEric Joyner 	ixgbe_free_transmit_structures(adapter);
26618eb6488eSEric Joyner 	ixgbe_free_receive_structures(adapter);
26628eb6488eSEric Joyner 	free(adapter->queues, M_DEVBUF);
26638eb6488eSEric Joyner 	free(adapter->mta, M_IXGBE);
26648eb6488eSEric Joyner 
26658eb6488eSEric Joyner 	IXGBE_CORE_LOCK_DESTROY(adapter);
26668eb6488eSEric Joyner 
26678eb6488eSEric Joyner 	return (0);
26688eb6488eSEric Joyner } /* ixgbe_detach */
26698eb6488eSEric Joyner 
26708eb6488eSEric Joyner /************************************************************************
26718eb6488eSEric Joyner  * ixgbe_setup_low_power_mode - LPLU/WoL preparation
26728eb6488eSEric Joyner  *
26738eb6488eSEric Joyner  *   Prepare the adapter/port for LPLU and/or WoL
26748eb6488eSEric Joyner  ************************************************************************/
26758eb6488eSEric Joyner static int
26768eb6488eSEric Joyner ixgbe_setup_low_power_mode(struct adapter *adapter)
26778eb6488eSEric Joyner {
26788eb6488eSEric Joyner 	struct ixgbe_hw *hw = &adapter->hw;
26798eb6488eSEric Joyner 	device_t        dev = adapter->dev;
26808eb6488eSEric Joyner 	s32             error = 0;
26818eb6488eSEric Joyner 
26828eb6488eSEric Joyner 	mtx_assert(&adapter->core_mtx, MA_OWNED);
26838eb6488eSEric Joyner 
26848eb6488eSEric Joyner 	/* Limit power management flow to X550EM baseT */
26858eb6488eSEric Joyner 	if (hw->device_id == IXGBE_DEV_ID_X550EM_X_10G_T &&
26868eb6488eSEric Joyner 	    hw->phy.ops.enter_lplu) {
26878eb6488eSEric Joyner 		/* Turn off support for APM wakeup. (Using ACPI instead) */
26888eb6488eSEric Joyner 		IXGBE_WRITE_REG(hw, IXGBE_GRC,
26898eb6488eSEric Joyner 		    IXGBE_READ_REG(hw, IXGBE_GRC) & ~(u32)2);
26908eb6488eSEric Joyner 
26918eb6488eSEric Joyner 		/*
26928eb6488eSEric Joyner 		 * Clear Wake Up Status register to prevent any previous wakeup
26938eb6488eSEric Joyner 		 * events from waking us up immediately after we suspend.
26948eb6488eSEric Joyner 		 */
26958eb6488eSEric Joyner 		IXGBE_WRITE_REG(hw, IXGBE_WUS, 0xffffffff);
26968eb6488eSEric Joyner 
26978eb6488eSEric Joyner 		/*
26988eb6488eSEric Joyner 		 * Program the Wakeup Filter Control register with user filter
26998eb6488eSEric Joyner 		 * settings
27008eb6488eSEric Joyner 		 */
27018eb6488eSEric Joyner 		IXGBE_WRITE_REG(hw, IXGBE_WUFC, adapter->wufc);
27028eb6488eSEric Joyner 
27038eb6488eSEric Joyner 		/* Enable wakeups and power management in Wakeup Control */
27048eb6488eSEric Joyner 		IXGBE_WRITE_REG(hw, IXGBE_WUC,
27058eb6488eSEric Joyner 		    IXGBE_WUC_WKEN | IXGBE_WUC_PME_EN);
27068eb6488eSEric Joyner 
27078eb6488eSEric Joyner 		/* X550EM baseT adapters need a special LPLU flow */
27088eb6488eSEric Joyner 		hw->phy.reset_disable = true;
27098eb6488eSEric Joyner 		ixgbe_stop(adapter);
27108eb6488eSEric Joyner 		error = hw->phy.ops.enter_lplu(hw);
27118eb6488eSEric Joyner 		if (error)
27128eb6488eSEric Joyner 			device_printf(dev, "Error entering LPLU: %d\n", error);
27138eb6488eSEric Joyner 		hw->phy.reset_disable = false;
27148eb6488eSEric Joyner 	} else {
27158eb6488eSEric Joyner 		/* Just stop for other adapters */
27168eb6488eSEric Joyner 		ixgbe_stop(adapter);
27178eb6488eSEric Joyner 	}
27188eb6488eSEric Joyner 
27198eb6488eSEric Joyner 	return error;
27208eb6488eSEric Joyner } /* ixgbe_setup_low_power_mode */
27218eb6488eSEric Joyner 
27228eb6488eSEric Joyner /************************************************************************
27238eb6488eSEric Joyner  * ixgbe_shutdown - Shutdown entry point
27248eb6488eSEric Joyner  ************************************************************************/
27258eb6488eSEric Joyner static int
27268eb6488eSEric Joyner ixgbe_shutdown(device_t dev)
27278eb6488eSEric Joyner {
27288eb6488eSEric Joyner 	struct adapter *adapter = device_get_softc(dev);
27298eb6488eSEric Joyner 	int            error = 0;
27308eb6488eSEric Joyner 
27318eb6488eSEric Joyner 	INIT_DEBUGOUT("ixgbe_shutdown: begin");
27328eb6488eSEric Joyner 
27338eb6488eSEric Joyner 	IXGBE_CORE_LOCK(adapter);
27348eb6488eSEric Joyner 	error = ixgbe_setup_low_power_mode(adapter);
27358eb6488eSEric Joyner 	IXGBE_CORE_UNLOCK(adapter);
27368eb6488eSEric Joyner 
27378eb6488eSEric Joyner 	return (error);
27388eb6488eSEric Joyner } /* ixgbe_shutdown */
27398eb6488eSEric Joyner 
27408eb6488eSEric Joyner /************************************************************************
27418eb6488eSEric Joyner  * ixgbe_suspend
27428eb6488eSEric Joyner  *
27438eb6488eSEric Joyner  *   From D0 to D3
27448eb6488eSEric Joyner  ************************************************************************/
27458eb6488eSEric Joyner static int
27468eb6488eSEric Joyner ixgbe_suspend(device_t dev)
27478eb6488eSEric Joyner {
27488eb6488eSEric Joyner 	struct adapter *adapter = device_get_softc(dev);
27498eb6488eSEric Joyner 	int            error = 0;
27508eb6488eSEric Joyner 
27518eb6488eSEric Joyner 	INIT_DEBUGOUT("ixgbe_suspend: begin");
27528eb6488eSEric Joyner 
27538eb6488eSEric Joyner 	IXGBE_CORE_LOCK(adapter);
27548eb6488eSEric Joyner 
27558eb6488eSEric Joyner 	error = ixgbe_setup_low_power_mode(adapter);
27568eb6488eSEric Joyner 
27578eb6488eSEric Joyner 	IXGBE_CORE_UNLOCK(adapter);
27588eb6488eSEric Joyner 
27598eb6488eSEric Joyner 	return (error);
27608eb6488eSEric Joyner } /* ixgbe_suspend */
27618eb6488eSEric Joyner 
27628eb6488eSEric Joyner /************************************************************************
27638eb6488eSEric Joyner  * ixgbe_resume
27648eb6488eSEric Joyner  *
27658eb6488eSEric Joyner  *   From D3 to D0
27668eb6488eSEric Joyner  ************************************************************************/
27678eb6488eSEric Joyner static int
27688eb6488eSEric Joyner ixgbe_resume(device_t dev)
27698eb6488eSEric Joyner {
27708eb6488eSEric Joyner 	struct adapter  *adapter = device_get_softc(dev);
27718eb6488eSEric Joyner 	struct ifnet    *ifp = adapter->ifp;
27728eb6488eSEric Joyner 	struct ixgbe_hw *hw = &adapter->hw;
27738eb6488eSEric Joyner 	u32             wus;
27748eb6488eSEric Joyner 
27758eb6488eSEric Joyner 	INIT_DEBUGOUT("ixgbe_resume: begin");
27768eb6488eSEric Joyner 
27778eb6488eSEric Joyner 	IXGBE_CORE_LOCK(adapter);
27788eb6488eSEric Joyner 
27798eb6488eSEric Joyner 	/* Read & clear WUS register */
27808eb6488eSEric Joyner 	wus = IXGBE_READ_REG(hw, IXGBE_WUS);
27818eb6488eSEric Joyner 	if (wus)
27828eb6488eSEric Joyner 		device_printf(dev, "Woken up by (WUS): %#010x\n",
27838eb6488eSEric Joyner 		    IXGBE_READ_REG(hw, IXGBE_WUS));
27848eb6488eSEric Joyner 	IXGBE_WRITE_REG(hw, IXGBE_WUS, 0xffffffff);
27858eb6488eSEric Joyner 	/* And clear WUFC until next low-power transition */
27868eb6488eSEric Joyner 	IXGBE_WRITE_REG(hw, IXGBE_WUFC, 0);
27878eb6488eSEric Joyner 
27888eb6488eSEric Joyner 	/*
27898eb6488eSEric Joyner 	 * Required after D3->D0 transition;
27908eb6488eSEric Joyner 	 * will re-advertise all previous advertised speeds
27918eb6488eSEric Joyner 	 */
27928eb6488eSEric Joyner 	if (ifp->if_flags & IFF_UP)
27938eb6488eSEric Joyner 		ixgbe_init_locked(adapter);
27948eb6488eSEric Joyner 
27958eb6488eSEric Joyner 	IXGBE_CORE_UNLOCK(adapter);
27968eb6488eSEric Joyner 
27978eb6488eSEric Joyner 	return (0);
27988eb6488eSEric Joyner } /* ixgbe_resume */
27998eb6488eSEric Joyner 
28008eb6488eSEric Joyner /************************************************************************
28018eb6488eSEric Joyner  * ixgbe_set_if_hwassist - Set the various hardware offload abilities.
28028eb6488eSEric Joyner  *
28038eb6488eSEric Joyner  *   Takes the ifnet's if_capenable flags (e.g. set by the user using
28048eb6488eSEric Joyner  *   ifconfig) and indicates to the OS via the ifnet's if_hwassist
28058eb6488eSEric Joyner  *   field what mbuf offload flags the driver will understand.
28068eb6488eSEric Joyner  ************************************************************************/
28078eb6488eSEric Joyner static void
28088eb6488eSEric Joyner ixgbe_set_if_hwassist(struct adapter *adapter)
28098eb6488eSEric Joyner {
28108eb6488eSEric Joyner 	struct ifnet *ifp = adapter->ifp;
28118eb6488eSEric Joyner 
28128eb6488eSEric Joyner 	ifp->if_hwassist = 0;
28138eb6488eSEric Joyner #if __FreeBSD_version >= 1000000
28148eb6488eSEric Joyner 	if (ifp->if_capenable & IFCAP_TSO4)
28158eb6488eSEric Joyner 		ifp->if_hwassist |= CSUM_IP_TSO;
28168eb6488eSEric Joyner 	if (ifp->if_capenable & IFCAP_TSO6)
28178eb6488eSEric Joyner 		ifp->if_hwassist |= CSUM_IP6_TSO;
28188eb6488eSEric Joyner 	if (ifp->if_capenable & IFCAP_TXCSUM) {
28198eb6488eSEric Joyner 		ifp->if_hwassist |= (CSUM_IP | CSUM_IP_UDP | CSUM_IP_TCP);
28208eb6488eSEric Joyner 		if (adapter->hw.mac.type != ixgbe_mac_82598EB)
28218eb6488eSEric Joyner 			ifp->if_hwassist |= CSUM_IP_SCTP;
28228eb6488eSEric Joyner 	}
28238eb6488eSEric Joyner 	if (ifp->if_capenable & IFCAP_TXCSUM_IPV6) {
28248eb6488eSEric Joyner 		ifp->if_hwassist |= (CSUM_IP6_UDP | CSUM_IP6_TCP);
28258eb6488eSEric Joyner 		if (adapter->hw.mac.type != ixgbe_mac_82598EB)
28268eb6488eSEric Joyner 			ifp->if_hwassist |= CSUM_IP6_SCTP;
28278eb6488eSEric Joyner 	}
28288eb6488eSEric Joyner #else
28298eb6488eSEric Joyner 	if (ifp->if_capenable & IFCAP_TSO)
28308eb6488eSEric Joyner 		ifp->if_hwassist |= CSUM_TSO;
28318eb6488eSEric Joyner 	if (ifp->if_capenable & IFCAP_TXCSUM) {
28328eb6488eSEric Joyner 		ifp->if_hwassist |= (CSUM_TCP | CSUM_UDP);
28338eb6488eSEric Joyner 		if (adapter->hw.mac.type != ixgbe_mac_82598EB)
28348eb6488eSEric Joyner 			ifp->if_hwassist |= CSUM_SCTP;
28358eb6488eSEric Joyner 	}
28368eb6488eSEric Joyner #endif
28378eb6488eSEric Joyner } /* ixgbe_set_if_hwassist */
28388eb6488eSEric Joyner 
28398eb6488eSEric Joyner /************************************************************************
28408eb6488eSEric Joyner  * ixgbe_init_locked - Init entry point
28418eb6488eSEric Joyner  *
28428eb6488eSEric Joyner  *   Used in two ways: It is used by the stack as an init
28438eb6488eSEric Joyner  *   entry point in network interface structure. It is also
28448eb6488eSEric Joyner  *   used by the driver as a hw/sw initialization routine to
28458eb6488eSEric Joyner  *   get to a consistent state.
28468eb6488eSEric Joyner  *
28478eb6488eSEric Joyner  *   return 0 on success, positive on failure
28488eb6488eSEric Joyner  ************************************************************************/
28498eb6488eSEric Joyner void
28508eb6488eSEric Joyner ixgbe_init_locked(struct adapter *adapter)
28518eb6488eSEric Joyner {
28528eb6488eSEric Joyner 	struct ifnet    *ifp = adapter->ifp;
28538eb6488eSEric Joyner 	device_t        dev = adapter->dev;
28548eb6488eSEric Joyner 	struct ixgbe_hw *hw = &adapter->hw;
28558eb6488eSEric Joyner 	struct tx_ring  *txr;
28568eb6488eSEric Joyner 	struct rx_ring  *rxr;
28578eb6488eSEric Joyner 	u32             txdctl, mhadd;
28588eb6488eSEric Joyner 	u32             rxdctl, rxctrl;
28598eb6488eSEric Joyner 	u32             ctrl_ext;
28608eb6488eSEric Joyner 	int             err = 0;
28618eb6488eSEric Joyner 
28628eb6488eSEric Joyner 	mtx_assert(&adapter->core_mtx, MA_OWNED);
28638eb6488eSEric Joyner 	INIT_DEBUGOUT("ixgbe_init_locked: begin");
28648eb6488eSEric Joyner 
28658eb6488eSEric Joyner 	hw->adapter_stopped = FALSE;
28668eb6488eSEric Joyner 	ixgbe_stop_adapter(hw);
28678eb6488eSEric Joyner 	callout_stop(&adapter->timer);
28688eb6488eSEric Joyner 
28698eb6488eSEric Joyner 	/* Queue indices may change with IOV mode */
28708eb6488eSEric Joyner 	ixgbe_align_all_queue_indices(adapter);
28718eb6488eSEric Joyner 
28728eb6488eSEric Joyner 	/* reprogram the RAR[0] in case user changed it. */
28738eb6488eSEric Joyner 	ixgbe_set_rar(hw, 0, hw->mac.addr, adapter->pool, IXGBE_RAH_AV);
28748eb6488eSEric Joyner 
28758eb6488eSEric Joyner 	/* Get the latest mac address, User can use a LAA */
28768eb6488eSEric Joyner 	bcopy(IF_LLADDR(ifp), hw->mac.addr, IXGBE_ETH_LENGTH_OF_ADDRESS);
28778eb6488eSEric Joyner 	ixgbe_set_rar(hw, 0, hw->mac.addr, adapter->pool, 1);
28788eb6488eSEric Joyner 	hw->addr_ctrl.rar_used_count = 1;
28798eb6488eSEric Joyner 
28808eb6488eSEric Joyner 	/* Set hardware offload abilities from ifnet flags */
28818eb6488eSEric Joyner 	ixgbe_set_if_hwassist(adapter);
28828eb6488eSEric Joyner 
28838eb6488eSEric Joyner 	/* Prepare transmit descriptors and buffers */
28848eb6488eSEric Joyner 	if (ixgbe_setup_transmit_structures(adapter)) {
28858eb6488eSEric Joyner 		device_printf(dev, "Could not setup transmit structures\n");
28868eb6488eSEric Joyner 		ixgbe_stop(adapter);
28878eb6488eSEric Joyner 		return;
28888eb6488eSEric Joyner 	}
28898eb6488eSEric Joyner 
28908eb6488eSEric Joyner 	ixgbe_init_hw(hw);
28918eb6488eSEric Joyner 	ixgbe_initialize_iov(adapter);
28928eb6488eSEric Joyner 	ixgbe_initialize_transmit_units(adapter);
28938eb6488eSEric Joyner 
28948eb6488eSEric Joyner 	/* Setup Multicast table */
28958eb6488eSEric Joyner 	ixgbe_set_multi(adapter);
28968eb6488eSEric Joyner 
28978eb6488eSEric Joyner 	/* Determine the correct mbuf pool, based on frame size */
28988eb6488eSEric Joyner 	if (adapter->max_frame_size <= MCLBYTES)
28998eb6488eSEric Joyner 		adapter->rx_mbuf_sz = MCLBYTES;
29008eb6488eSEric Joyner 	else
29018eb6488eSEric Joyner 		adapter->rx_mbuf_sz = MJUMPAGESIZE;
29028eb6488eSEric Joyner 
29038eb6488eSEric Joyner 	/* Prepare receive descriptors and buffers */
29048eb6488eSEric Joyner 	if (ixgbe_setup_receive_structures(adapter)) {
29058eb6488eSEric Joyner 		device_printf(dev, "Could not setup receive structures\n");
29068eb6488eSEric Joyner 		ixgbe_stop(adapter);
29078eb6488eSEric Joyner 		return;
29088eb6488eSEric Joyner 	}
29098eb6488eSEric Joyner 
29108eb6488eSEric Joyner 	/* Configure RX settings */
29118eb6488eSEric Joyner 	ixgbe_initialize_receive_units(adapter);
29128eb6488eSEric Joyner 
29138eb6488eSEric Joyner 	/* Enable SDP & MSI-X interrupts based on adapter */
29148eb6488eSEric Joyner 	ixgbe_config_gpie(adapter);
29158eb6488eSEric Joyner 
29168eb6488eSEric Joyner 	/* Set MTU size */
29178eb6488eSEric Joyner 	if (ifp->if_mtu > ETHERMTU) {
29188eb6488eSEric Joyner 		/* aka IXGBE_MAXFRS on 82599 and newer */
29198eb6488eSEric Joyner 		mhadd = IXGBE_READ_REG(hw, IXGBE_MHADD);
29208eb6488eSEric Joyner 		mhadd &= ~IXGBE_MHADD_MFS_MASK;
29218eb6488eSEric Joyner 		mhadd |= adapter->max_frame_size << IXGBE_MHADD_MFS_SHIFT;
29228eb6488eSEric Joyner 		IXGBE_WRITE_REG(hw, IXGBE_MHADD, mhadd);
29238eb6488eSEric Joyner 	}
29248eb6488eSEric Joyner 
29258eb6488eSEric Joyner 	/* Now enable all the queues */
29268eb6488eSEric Joyner 	for (int i = 0; i < adapter->num_queues; i++) {
29278eb6488eSEric Joyner 		txr = &adapter->tx_rings[i];
29288eb6488eSEric Joyner 		txdctl = IXGBE_READ_REG(hw, IXGBE_TXDCTL(txr->me));
29298eb6488eSEric Joyner 		txdctl |= IXGBE_TXDCTL_ENABLE;
29308eb6488eSEric Joyner 		/* Set WTHRESH to 8, burst writeback */
29318eb6488eSEric Joyner 		txdctl |= (8 << 16);
29328eb6488eSEric Joyner 		/*
29338eb6488eSEric Joyner 		 * When the internal queue falls below PTHRESH (32),
29348eb6488eSEric Joyner 		 * start prefetching as long as there are at least
29358eb6488eSEric Joyner 		 * HTHRESH (1) buffers ready. The values are taken
29368eb6488eSEric Joyner 		 * from the Intel linux driver 3.8.21.
29378eb6488eSEric Joyner 		 * Prefetching enables tx line rate even with 1 queue.
29388eb6488eSEric Joyner 		 */
29398eb6488eSEric Joyner 		txdctl |= (32 << 0) | (1 << 8);
29408eb6488eSEric Joyner 		IXGBE_WRITE_REG(hw, IXGBE_TXDCTL(txr->me), txdctl);
29418eb6488eSEric Joyner 	}
29428eb6488eSEric Joyner 
29438eb6488eSEric Joyner 	for (int i = 0, j = 0; i < adapter->num_queues; i++) {
29448eb6488eSEric Joyner 		rxr = &adapter->rx_rings[i];
29458eb6488eSEric Joyner 		rxdctl = IXGBE_READ_REG(hw, IXGBE_RXDCTL(rxr->me));
29468eb6488eSEric Joyner 		if (hw->mac.type == ixgbe_mac_82598EB) {
29478eb6488eSEric Joyner 			/*
29488eb6488eSEric Joyner 			 * PTHRESH = 21
29498eb6488eSEric Joyner 			 * HTHRESH = 4
29508eb6488eSEric Joyner 			 * WTHRESH = 8
29518eb6488eSEric Joyner 			 */
29528eb6488eSEric Joyner 			rxdctl &= ~0x3FFFFF;
29538eb6488eSEric Joyner 			rxdctl |= 0x080420;
29548eb6488eSEric Joyner 		}
29558eb6488eSEric Joyner 		rxdctl |= IXGBE_RXDCTL_ENABLE;
29568eb6488eSEric Joyner 		IXGBE_WRITE_REG(hw, IXGBE_RXDCTL(rxr->me), rxdctl);
29578eb6488eSEric Joyner 		for (; j < 10; j++) {
29588eb6488eSEric Joyner 			if (IXGBE_READ_REG(hw, IXGBE_RXDCTL(rxr->me)) &
29598eb6488eSEric Joyner 			    IXGBE_RXDCTL_ENABLE)
29608eb6488eSEric Joyner 				break;
29618eb6488eSEric Joyner 			else
29628eb6488eSEric Joyner 				msec_delay(1);
29638eb6488eSEric Joyner 		}
29648eb6488eSEric Joyner 		wmb();
29658eb6488eSEric Joyner 
29668eb6488eSEric Joyner 		/*
29678eb6488eSEric Joyner 		 * In netmap mode, we must preserve the buffers made
29688eb6488eSEric Joyner 		 * available to userspace before the if_init()
29698eb6488eSEric Joyner 		 * (this is true by default on the TX side, because
29708eb6488eSEric Joyner 		 * init makes all buffers available to userspace).
29718eb6488eSEric Joyner 		 *
29728eb6488eSEric Joyner 		 * netmap_reset() and the device specific routines
29738eb6488eSEric Joyner 		 * (e.g. ixgbe_setup_receive_rings()) map these
29748eb6488eSEric Joyner 		 * buffers at the end of the NIC ring, so here we
29758eb6488eSEric Joyner 		 * must set the RDT (tail) register to make sure
29768eb6488eSEric Joyner 		 * they are not overwritten.
29778eb6488eSEric Joyner 		 *
29788eb6488eSEric Joyner 		 * In this driver the NIC ring starts at RDH = 0,
29798eb6488eSEric Joyner 		 * RDT points to the last slot available for reception (?),
29808eb6488eSEric Joyner 		 * so RDT = num_rx_desc - 1 means the whole ring is available.
29818eb6488eSEric Joyner 		 */
29828eb6488eSEric Joyner #ifdef DEV_NETMAP
29838eb6488eSEric Joyner 		if ((adapter->feat_en & IXGBE_FEATURE_NETMAP) &&
29848eb6488eSEric Joyner 		    (ifp->if_capenable & IFCAP_NETMAP)) {
29858eb6488eSEric Joyner 			struct netmap_adapter *na = NA(adapter->ifp);
29868eb6488eSEric Joyner 			struct netmap_kring *kring = &na->rx_rings[i];
29878eb6488eSEric Joyner 			int t = na->num_rx_desc - 1 - nm_kr_rxspace(kring);
29888eb6488eSEric Joyner 
29898eb6488eSEric Joyner 			IXGBE_WRITE_REG(hw, IXGBE_RDT(rxr->me), t);
29908eb6488eSEric Joyner 		} else
29918eb6488eSEric Joyner #endif /* DEV_NETMAP */
29928eb6488eSEric Joyner 			IXGBE_WRITE_REG(hw, IXGBE_RDT(rxr->me),
29938eb6488eSEric Joyner 			    adapter->num_rx_desc - 1);
29948eb6488eSEric Joyner 	}
29958eb6488eSEric Joyner 
29968eb6488eSEric Joyner 	/* Enable Receive engine */
29978eb6488eSEric Joyner 	rxctrl = IXGBE_READ_REG(hw, IXGBE_RXCTRL);
29988eb6488eSEric Joyner 	if (hw->mac.type == ixgbe_mac_82598EB)
29998eb6488eSEric Joyner 		rxctrl |= IXGBE_RXCTRL_DMBYPS;
30008eb6488eSEric Joyner 	rxctrl |= IXGBE_RXCTRL_RXEN;
30018eb6488eSEric Joyner 	ixgbe_enable_rx_dma(hw, rxctrl);
30028eb6488eSEric Joyner 
30038eb6488eSEric Joyner 	callout_reset(&adapter->timer, hz, ixgbe_local_timer, adapter);
30048eb6488eSEric Joyner 
30058eb6488eSEric Joyner 	/* Set up MSI-X routing */
30068eb6488eSEric Joyner 	if (adapter->feat_en & IXGBE_FEATURE_MSIX) {
30078eb6488eSEric Joyner 		ixgbe_configure_ivars(adapter);
30088eb6488eSEric Joyner 		/* Set up auto-mask */
30098eb6488eSEric Joyner 		if (hw->mac.type == ixgbe_mac_82598EB)
30108eb6488eSEric Joyner 			IXGBE_WRITE_REG(hw, IXGBE_EIAM, IXGBE_EICS_RTX_QUEUE);
30118eb6488eSEric Joyner 		else {
30128eb6488eSEric Joyner 			IXGBE_WRITE_REG(hw, IXGBE_EIAM_EX(0), 0xFFFFFFFF);
30138eb6488eSEric Joyner 			IXGBE_WRITE_REG(hw, IXGBE_EIAM_EX(1), 0xFFFFFFFF);
30148eb6488eSEric Joyner 		}
30158eb6488eSEric Joyner 	} else {  /* Simple settings for Legacy/MSI */
30168eb6488eSEric Joyner 		ixgbe_set_ivar(adapter, 0, 0, 0);
30178eb6488eSEric Joyner 		ixgbe_set_ivar(adapter, 0, 0, 1);
30188eb6488eSEric Joyner 		IXGBE_WRITE_REG(hw, IXGBE_EIAM, IXGBE_EICS_RTX_QUEUE);
30198eb6488eSEric Joyner 	}
30208eb6488eSEric Joyner 
30218eb6488eSEric Joyner 	ixgbe_init_fdir(adapter);
30228eb6488eSEric Joyner 
30238eb6488eSEric Joyner 	/*
30248eb6488eSEric Joyner 	 * Check on any SFP devices that
30258eb6488eSEric Joyner 	 * need to be kick-started
30268eb6488eSEric Joyner 	 */
30278eb6488eSEric Joyner 	if (hw->phy.type == ixgbe_phy_none) {
30288eb6488eSEric Joyner 		err = hw->phy.ops.identify(hw);
30298eb6488eSEric Joyner 		if (err == IXGBE_ERR_SFP_NOT_SUPPORTED) {
30308eb6488eSEric Joyner 			device_printf(dev,
30318eb6488eSEric Joyner 			    "Unsupported SFP+ module type was detected.\n");
30328eb6488eSEric Joyner 			return;
30338eb6488eSEric Joyner 		}
30348eb6488eSEric Joyner 	}
30358eb6488eSEric Joyner 
30368eb6488eSEric Joyner 	/* Set moderation on the Link interrupt */
30378eb6488eSEric Joyner 	IXGBE_WRITE_REG(hw, IXGBE_EITR(adapter->vector), IXGBE_LINK_ITR);
30388eb6488eSEric Joyner 
30398eb6488eSEric Joyner 	/* Config/Enable Link */
30408eb6488eSEric Joyner 	ixgbe_config_link(adapter);
30418eb6488eSEric Joyner 
30428eb6488eSEric Joyner 	/* Hardware Packet Buffer & Flow Control setup */
30438eb6488eSEric Joyner 	ixgbe_config_delay_values(adapter);
30448eb6488eSEric Joyner 
30458eb6488eSEric Joyner 	/* Initialize the FC settings */
30468eb6488eSEric Joyner 	ixgbe_start_hw(hw);
30478eb6488eSEric Joyner 
30488eb6488eSEric Joyner 	/* Set up VLAN support and filter */
30498eb6488eSEric Joyner 	ixgbe_setup_vlan_hw_support(adapter);
30508eb6488eSEric Joyner 
30518eb6488eSEric Joyner 	/* Setup DMA Coalescing */
30528eb6488eSEric Joyner 	ixgbe_config_dmac(adapter);
30538eb6488eSEric Joyner 
30548eb6488eSEric Joyner 	/* And now turn on interrupts */
30558eb6488eSEric Joyner 	ixgbe_enable_intr(adapter);
30568eb6488eSEric Joyner 
30578eb6488eSEric Joyner 	/* Enable the use of the MBX by the VF's */
30588eb6488eSEric Joyner 	if (adapter->feat_en & IXGBE_FEATURE_SRIOV) {
30598eb6488eSEric Joyner 		ctrl_ext = IXGBE_READ_REG(hw, IXGBE_CTRL_EXT);
30608eb6488eSEric Joyner 		ctrl_ext |= IXGBE_CTRL_EXT_PFRSTD;
30618eb6488eSEric Joyner 		IXGBE_WRITE_REG(hw, IXGBE_CTRL_EXT, ctrl_ext);
30628eb6488eSEric Joyner 	}
30638eb6488eSEric Joyner 
30648eb6488eSEric Joyner 	/* Now inform the stack we're ready */
30658eb6488eSEric Joyner 	ifp->if_drv_flags |= IFF_DRV_RUNNING;
30668eb6488eSEric Joyner 
30678eb6488eSEric Joyner 	return;
30688eb6488eSEric Joyner } /* ixgbe_init_locked */
30698eb6488eSEric Joyner 
30708eb6488eSEric Joyner /************************************************************************
30718eb6488eSEric Joyner  * ixgbe_init
30728eb6488eSEric Joyner  ************************************************************************/
30738eb6488eSEric Joyner static void
30748eb6488eSEric Joyner ixgbe_init(void *arg)
30758eb6488eSEric Joyner {
30768eb6488eSEric Joyner 	struct adapter *adapter = arg;
30778eb6488eSEric Joyner 
30788eb6488eSEric Joyner 	IXGBE_CORE_LOCK(adapter);
30798eb6488eSEric Joyner 	ixgbe_init_locked(adapter);
30808eb6488eSEric Joyner 	IXGBE_CORE_UNLOCK(adapter);
30818eb6488eSEric Joyner 
30828eb6488eSEric Joyner 	return;
30838eb6488eSEric Joyner } /* ixgbe_init */
30848eb6488eSEric Joyner 
30858eb6488eSEric Joyner /************************************************************************
30868eb6488eSEric Joyner  * ixgbe_set_ivar
30878eb6488eSEric Joyner  *
30888eb6488eSEric Joyner  *   Setup the correct IVAR register for a particular MSI-X interrupt
30898eb6488eSEric Joyner  *     (yes this is all very magic and confusing :)
30908eb6488eSEric Joyner  *    - entry is the register array entry
30918eb6488eSEric Joyner  *    - vector is the MSI-X vector for this queue
30928eb6488eSEric Joyner  *    - type is RX/TX/MISC
30938eb6488eSEric Joyner  ************************************************************************/
30948eb6488eSEric Joyner static void
30958eb6488eSEric Joyner ixgbe_set_ivar(struct adapter *adapter, u8 entry, u8 vector, s8 type)
30968eb6488eSEric Joyner {
30978eb6488eSEric Joyner 	struct ixgbe_hw *hw = &adapter->hw;
30988eb6488eSEric Joyner 	u32 ivar, index;
30998eb6488eSEric Joyner 
31008eb6488eSEric Joyner 	vector |= IXGBE_IVAR_ALLOC_VAL;
31018eb6488eSEric Joyner 
31028eb6488eSEric Joyner 	switch (hw->mac.type) {
31038eb6488eSEric Joyner 
31048eb6488eSEric Joyner 	case ixgbe_mac_82598EB:
31058eb6488eSEric Joyner 		if (type == -1)
31068eb6488eSEric Joyner 			entry = IXGBE_IVAR_OTHER_CAUSES_INDEX;
31078eb6488eSEric Joyner 		else
31088eb6488eSEric Joyner 			entry += (type * 64);
31098eb6488eSEric Joyner 		index = (entry >> 2) & 0x1F;
31108eb6488eSEric Joyner 		ivar = IXGBE_READ_REG(hw, IXGBE_IVAR(index));
31118eb6488eSEric Joyner 		ivar &= ~(0xFF << (8 * (entry & 0x3)));
31128eb6488eSEric Joyner 		ivar |= (vector << (8 * (entry & 0x3)));
31138eb6488eSEric Joyner 		IXGBE_WRITE_REG(&adapter->hw, IXGBE_IVAR(index), ivar);
31148eb6488eSEric Joyner 		break;
31158eb6488eSEric Joyner 
31168eb6488eSEric Joyner 	case ixgbe_mac_82599EB:
31178eb6488eSEric Joyner 	case ixgbe_mac_X540:
31188eb6488eSEric Joyner 	case ixgbe_mac_X550:
31198eb6488eSEric Joyner 	case ixgbe_mac_X550EM_x:
31208eb6488eSEric Joyner 	case ixgbe_mac_X550EM_a:
31218eb6488eSEric Joyner 		if (type == -1) { /* MISC IVAR */
31228eb6488eSEric Joyner 			index = (entry & 1) * 8;
31238eb6488eSEric Joyner 			ivar = IXGBE_READ_REG(hw, IXGBE_IVAR_MISC);
31248eb6488eSEric Joyner 			ivar &= ~(0xFF << index);
31258eb6488eSEric Joyner 			ivar |= (vector << index);
31268eb6488eSEric Joyner 			IXGBE_WRITE_REG(hw, IXGBE_IVAR_MISC, ivar);
31278eb6488eSEric Joyner 		} else {          /* RX/TX IVARS */
31288eb6488eSEric Joyner 			index = (16 * (entry & 1)) + (8 * type);
31298eb6488eSEric Joyner 			ivar = IXGBE_READ_REG(hw, IXGBE_IVAR(entry >> 1));
31308eb6488eSEric Joyner 			ivar &= ~(0xFF << index);
31318eb6488eSEric Joyner 			ivar |= (vector << index);
31328eb6488eSEric Joyner 			IXGBE_WRITE_REG(hw, IXGBE_IVAR(entry >> 1), ivar);
31338eb6488eSEric Joyner 		}
31348eb6488eSEric Joyner 
31358eb6488eSEric Joyner 	default:
31368eb6488eSEric Joyner 		break;
31378eb6488eSEric Joyner 	}
31388eb6488eSEric Joyner } /* ixgbe_set_ivar */
31398eb6488eSEric Joyner 
31408eb6488eSEric Joyner /************************************************************************
31418eb6488eSEric Joyner  * ixgbe_configure_ivars
31428eb6488eSEric Joyner  ************************************************************************/
31438eb6488eSEric Joyner static void
31448eb6488eSEric Joyner ixgbe_configure_ivars(struct adapter *adapter)
31458eb6488eSEric Joyner {
31468eb6488eSEric Joyner 	struct ix_queue *que = adapter->queues;
31478eb6488eSEric Joyner 	u32             newitr;
31488eb6488eSEric Joyner 
31498eb6488eSEric Joyner 	if (ixgbe_max_interrupt_rate > 0)
31508eb6488eSEric Joyner 		newitr = (4000000 / ixgbe_max_interrupt_rate) & 0x0FF8;
31518eb6488eSEric Joyner 	else {
31528eb6488eSEric Joyner 		/*
31538eb6488eSEric Joyner 		 * Disable DMA coalescing if interrupt moderation is
31548eb6488eSEric Joyner 		 * disabled.
31558eb6488eSEric Joyner 		 */
31568eb6488eSEric Joyner 		adapter->dmac = 0;
31578eb6488eSEric Joyner 		newitr = 0;
31588eb6488eSEric Joyner 	}
31598eb6488eSEric Joyner 
31608eb6488eSEric Joyner 	for (int i = 0; i < adapter->num_queues; i++, que++) {
31618eb6488eSEric Joyner 		struct rx_ring *rxr = &adapter->rx_rings[i];
31628eb6488eSEric Joyner 		struct tx_ring *txr = &adapter->tx_rings[i];
31638eb6488eSEric Joyner 		/* First the RX queue entry */
31648eb6488eSEric Joyner 		ixgbe_set_ivar(adapter, rxr->me, que->msix, 0);
31658eb6488eSEric Joyner 		/* ... and the TX */
31668eb6488eSEric Joyner 		ixgbe_set_ivar(adapter, txr->me, que->msix, 1);
31678eb6488eSEric Joyner 		/* Set an Initial EITR value */
31688eb6488eSEric Joyner 		IXGBE_WRITE_REG(&adapter->hw, IXGBE_EITR(que->msix), newitr);
31698eb6488eSEric Joyner 	}
31708eb6488eSEric Joyner 
31718eb6488eSEric Joyner 	/* For the Link interrupt */
31728eb6488eSEric Joyner 	ixgbe_set_ivar(adapter, 1, adapter->vector, -1);
31738eb6488eSEric Joyner } /* ixgbe_configure_ivars */
31748eb6488eSEric Joyner 
31758eb6488eSEric Joyner /************************************************************************
31768eb6488eSEric Joyner  * ixgbe_config_gpie
31778eb6488eSEric Joyner  ************************************************************************/
31788eb6488eSEric Joyner static void
31798eb6488eSEric Joyner ixgbe_config_gpie(struct adapter *adapter)
31808eb6488eSEric Joyner {
31818eb6488eSEric Joyner 	struct ixgbe_hw *hw = &adapter->hw;
31828eb6488eSEric Joyner 	u32             gpie;
31838eb6488eSEric Joyner 
31848eb6488eSEric Joyner 	gpie = IXGBE_READ_REG(hw, IXGBE_GPIE);
31858eb6488eSEric Joyner 
31868eb6488eSEric Joyner 	if (adapter->feat_en & IXGBE_FEATURE_MSIX) {
31878eb6488eSEric Joyner 		/* Enable Enhanced MSI-X mode */
31888eb6488eSEric Joyner 		gpie |= IXGBE_GPIE_MSIX_MODE
31898eb6488eSEric Joyner 		     |  IXGBE_GPIE_EIAME
31908eb6488eSEric Joyner 		     |  IXGBE_GPIE_PBA_SUPPORT
31918eb6488eSEric Joyner 		     |  IXGBE_GPIE_OCD;
31928eb6488eSEric Joyner 	}
31938eb6488eSEric Joyner 
31948eb6488eSEric Joyner 	/* Fan Failure Interrupt */
31958eb6488eSEric Joyner 	if (adapter->feat_en & IXGBE_FEATURE_FAN_FAIL)
31968eb6488eSEric Joyner 		gpie |= IXGBE_SDP1_GPIEN;
31978eb6488eSEric Joyner 
31988eb6488eSEric Joyner 	/* Thermal Sensor Interrupt */
31998eb6488eSEric Joyner 	if (adapter->feat_en & IXGBE_FEATURE_TEMP_SENSOR)
32008eb6488eSEric Joyner 		gpie |= IXGBE_SDP0_GPIEN_X540;
32018eb6488eSEric Joyner 
32028eb6488eSEric Joyner 	/* Link detection */
32038eb6488eSEric Joyner 	switch (hw->mac.type) {
32048eb6488eSEric Joyner 	case ixgbe_mac_82599EB:
32058eb6488eSEric Joyner 		gpie |= IXGBE_SDP1_GPIEN | IXGBE_SDP2_GPIEN;
32068eb6488eSEric Joyner 		break;
32078eb6488eSEric Joyner 	case ixgbe_mac_X550EM_x:
32088eb6488eSEric Joyner 	case ixgbe_mac_X550EM_a:
32098eb6488eSEric Joyner 		gpie |= IXGBE_SDP0_GPIEN_X540;
32108eb6488eSEric Joyner 		break;
32118eb6488eSEric Joyner 	default:
32128eb6488eSEric Joyner 		break;
32138eb6488eSEric Joyner 	}
32148eb6488eSEric Joyner 
32158eb6488eSEric Joyner 	IXGBE_WRITE_REG(hw, IXGBE_GPIE, gpie);
32168eb6488eSEric Joyner 
32178eb6488eSEric Joyner 	return;
32188eb6488eSEric Joyner } /* ixgbe_config_gpie */
32198eb6488eSEric Joyner 
32208eb6488eSEric Joyner /************************************************************************
32218eb6488eSEric Joyner  * ixgbe_config_delay_values
32228eb6488eSEric Joyner  *
32238eb6488eSEric Joyner  *   Requires adapter->max_frame_size to be set.
32248eb6488eSEric Joyner  ************************************************************************/
32258eb6488eSEric Joyner static void
32268eb6488eSEric Joyner ixgbe_config_delay_values(struct adapter *adapter)
32278eb6488eSEric Joyner {
32288eb6488eSEric Joyner 	struct ixgbe_hw *hw = &adapter->hw;
32298eb6488eSEric Joyner 	u32             rxpb, frame, size, tmp;
32308eb6488eSEric Joyner 
32318eb6488eSEric Joyner 	frame = adapter->max_frame_size;
32328eb6488eSEric Joyner 
32338eb6488eSEric Joyner 	/* Calculate High Water */
32348eb6488eSEric Joyner 	switch (hw->mac.type) {
32358eb6488eSEric Joyner 	case ixgbe_mac_X540:
32368eb6488eSEric Joyner 	case ixgbe_mac_X550:
32378eb6488eSEric Joyner 	case ixgbe_mac_X550EM_x:
32388eb6488eSEric Joyner 	case ixgbe_mac_X550EM_a:
32398eb6488eSEric Joyner 		tmp = IXGBE_DV_X540(frame, frame);
32408eb6488eSEric Joyner 		break;
32418eb6488eSEric Joyner 	default:
32428eb6488eSEric Joyner 		tmp = IXGBE_DV(frame, frame);
32438eb6488eSEric Joyner 		break;
32448eb6488eSEric Joyner 	}
32458eb6488eSEric Joyner 	size = IXGBE_BT2KB(tmp);
32468eb6488eSEric Joyner 	rxpb = IXGBE_READ_REG(hw, IXGBE_RXPBSIZE(0)) >> 10;
32478eb6488eSEric Joyner 	hw->fc.high_water[0] = rxpb - size;
32488eb6488eSEric Joyner 
32498eb6488eSEric Joyner 	/* Now calculate Low Water */
32508eb6488eSEric Joyner 	switch (hw->mac.type) {
32518eb6488eSEric Joyner 	case ixgbe_mac_X540:
32528eb6488eSEric Joyner 	case ixgbe_mac_X550:
32538eb6488eSEric Joyner 	case ixgbe_mac_X550EM_x:
32548eb6488eSEric Joyner 	case ixgbe_mac_X550EM_a:
32558eb6488eSEric Joyner 		tmp = IXGBE_LOW_DV_X540(frame);
32568eb6488eSEric Joyner 		break;
32578eb6488eSEric Joyner 	default:
32588eb6488eSEric Joyner 		tmp = IXGBE_LOW_DV(frame);
32598eb6488eSEric Joyner 		break;
32608eb6488eSEric Joyner 	}
32618eb6488eSEric Joyner 	hw->fc.low_water[0] = IXGBE_BT2KB(tmp);
32628eb6488eSEric Joyner 
32638eb6488eSEric Joyner 	hw->fc.pause_time = IXGBE_FC_PAUSE;
32648eb6488eSEric Joyner 	hw->fc.send_xon = TRUE;
32658eb6488eSEric Joyner } /* ixgbe_config_delay_values */
32668eb6488eSEric Joyner 
32678eb6488eSEric Joyner /************************************************************************
32688eb6488eSEric Joyner  * ixgbe_set_multi - Multicast Update
32698eb6488eSEric Joyner  *
32708eb6488eSEric Joyner  *   Called whenever multicast address list is updated.
32718eb6488eSEric Joyner  ************************************************************************/
32728eb6488eSEric Joyner static void
32738eb6488eSEric Joyner ixgbe_set_multi(struct adapter *adapter)
32748eb6488eSEric Joyner {
32758eb6488eSEric Joyner 	struct ifmultiaddr   *ifma;
32768eb6488eSEric Joyner 	struct ixgbe_mc_addr *mta;
32778eb6488eSEric Joyner 	struct ifnet         *ifp = adapter->ifp;
32788eb6488eSEric Joyner 	u8                   *update_ptr;
32798eb6488eSEric Joyner 	int                  mcnt = 0;
32808eb6488eSEric Joyner 	u32                  fctrl;
32818eb6488eSEric Joyner 
32828eb6488eSEric Joyner 	IOCTL_DEBUGOUT("ixgbe_set_multi: begin");
32838eb6488eSEric Joyner 
32848eb6488eSEric Joyner 	mta = adapter->mta;
32858eb6488eSEric Joyner 	bzero(mta, sizeof(*mta) * MAX_NUM_MULTICAST_ADDRESSES);
32868eb6488eSEric Joyner 
32878eb6488eSEric Joyner #if __FreeBSD_version < 800000
32888eb6488eSEric Joyner 	IF_ADDR_LOCK(ifp);
32898eb6488eSEric Joyner #else
32908eb6488eSEric Joyner 	if_maddr_rlock(ifp);
32918eb6488eSEric Joyner #endif
32928eb6488eSEric Joyner 	TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
32938eb6488eSEric Joyner 		if (ifma->ifma_addr->sa_family != AF_LINK)
32948eb6488eSEric Joyner 			continue;
32958eb6488eSEric Joyner 		if (mcnt == MAX_NUM_MULTICAST_ADDRESSES)
32968eb6488eSEric Joyner 			break;
32978eb6488eSEric Joyner 		bcopy(LLADDR((struct sockaddr_dl *) ifma->ifma_addr),
32988eb6488eSEric Joyner 		    mta[mcnt].addr, IXGBE_ETH_LENGTH_OF_ADDRESS);
32998eb6488eSEric Joyner 		mta[mcnt].vmdq = adapter->pool;
33008eb6488eSEric Joyner 		mcnt++;
33018eb6488eSEric Joyner 	}
33028eb6488eSEric Joyner #if __FreeBSD_version < 800000
33038eb6488eSEric Joyner 	IF_ADDR_UNLOCK(ifp);
33048eb6488eSEric Joyner #else
33058eb6488eSEric Joyner 	if_maddr_runlock(ifp);
33068eb6488eSEric Joyner #endif
33078eb6488eSEric Joyner 
33088eb6488eSEric Joyner 	fctrl = IXGBE_READ_REG(&adapter->hw, IXGBE_FCTRL);
33098eb6488eSEric Joyner 	fctrl |= (IXGBE_FCTRL_UPE | IXGBE_FCTRL_MPE);
33108eb6488eSEric Joyner 	if (ifp->if_flags & IFF_PROMISC)
33118eb6488eSEric Joyner 		fctrl |= (IXGBE_FCTRL_UPE | IXGBE_FCTRL_MPE);
33128eb6488eSEric Joyner 	else if (mcnt >= MAX_NUM_MULTICAST_ADDRESSES ||
33138eb6488eSEric Joyner 	    ifp->if_flags & IFF_ALLMULTI) {
33148eb6488eSEric Joyner 		fctrl |= IXGBE_FCTRL_MPE;
33158eb6488eSEric Joyner 		fctrl &= ~IXGBE_FCTRL_UPE;
33168eb6488eSEric Joyner 	} else
33178eb6488eSEric Joyner 		fctrl &= ~(IXGBE_FCTRL_UPE | IXGBE_FCTRL_MPE);
33188eb6488eSEric Joyner 
33198eb6488eSEric Joyner 	IXGBE_WRITE_REG(&adapter->hw, IXGBE_FCTRL, fctrl);
33208eb6488eSEric Joyner 
33218eb6488eSEric Joyner 	if (mcnt < MAX_NUM_MULTICAST_ADDRESSES) {
33228eb6488eSEric Joyner 		update_ptr = (u8 *)mta;
33238eb6488eSEric Joyner 		ixgbe_update_mc_addr_list(&adapter->hw, update_ptr, mcnt,
33248eb6488eSEric Joyner 		    ixgbe_mc_array_itr, TRUE);
33258eb6488eSEric Joyner 	}
33268eb6488eSEric Joyner 
33278eb6488eSEric Joyner 	return;
33288eb6488eSEric Joyner } /* ixgbe_set_multi */
33298eb6488eSEric Joyner 
33308eb6488eSEric Joyner /************************************************************************
33318eb6488eSEric Joyner  * ixgbe_mc_array_itr
33328eb6488eSEric Joyner  *
33338eb6488eSEric Joyner  *   An iterator function needed by the multicast shared code.
33348eb6488eSEric Joyner  *   It feeds the shared code routine the addresses in the
33358eb6488eSEric Joyner  *   array of ixgbe_set_multi() one by one.
33368eb6488eSEric Joyner  ************************************************************************/
33378eb6488eSEric Joyner static u8 *
33388eb6488eSEric Joyner ixgbe_mc_array_itr(struct ixgbe_hw *hw, u8 **update_ptr, u32 *vmdq)
33398eb6488eSEric Joyner {
33408eb6488eSEric Joyner 	struct ixgbe_mc_addr *mta;
33418eb6488eSEric Joyner 
33428eb6488eSEric Joyner 	mta = (struct ixgbe_mc_addr *)*update_ptr;
33438eb6488eSEric Joyner 	*vmdq = mta->vmdq;
33448eb6488eSEric Joyner 
33458eb6488eSEric Joyner 	*update_ptr = (u8*)(mta + 1);
33468eb6488eSEric Joyner 
33478eb6488eSEric Joyner 	return (mta->addr);
33488eb6488eSEric Joyner } /* ixgbe_mc_array_itr */
33498eb6488eSEric Joyner 
33508eb6488eSEric Joyner /************************************************************************
33518eb6488eSEric Joyner  * ixgbe_local_timer - Timer routine
33528eb6488eSEric Joyner  *
33538eb6488eSEric Joyner  *   Checks for link status, updates statistics,
33548eb6488eSEric Joyner  *   and runs the watchdog check.
33558eb6488eSEric Joyner  ************************************************************************/
33568eb6488eSEric Joyner static void
33578eb6488eSEric Joyner ixgbe_local_timer(void *arg)
33588eb6488eSEric Joyner {
33598eb6488eSEric Joyner 	struct adapter  *adapter = arg;
33608eb6488eSEric Joyner 	device_t        dev = adapter->dev;
33618eb6488eSEric Joyner 	struct ix_queue *que = adapter->queues;
33628eb6488eSEric Joyner 	u64             queues = 0;
33638eb6488eSEric Joyner 	int             hung = 0;
33648eb6488eSEric Joyner 
33658eb6488eSEric Joyner 	mtx_assert(&adapter->core_mtx, MA_OWNED);
33668eb6488eSEric Joyner 
33678eb6488eSEric Joyner 	/* Check for pluggable optics */
33688eb6488eSEric Joyner 	if (adapter->sfp_probe)
33698eb6488eSEric Joyner 		if (!ixgbe_sfp_probe(adapter))
33708eb6488eSEric Joyner 			goto out; /* Nothing to do */
33718eb6488eSEric Joyner 
33728eb6488eSEric Joyner 	ixgbe_update_link_status(adapter);
33738eb6488eSEric Joyner 	ixgbe_update_stats_counters(adapter);
33748eb6488eSEric Joyner 
33758eb6488eSEric Joyner 	/*
33768eb6488eSEric Joyner 	 * Check the TX queues status
33778eb6488eSEric Joyner 	 *      - mark hung queues so we don't schedule on them
33788eb6488eSEric Joyner 	 *      - watchdog only if all queues show hung
33798eb6488eSEric Joyner 	 */
33808eb6488eSEric Joyner 	for (int i = 0; i < adapter->num_queues; i++, que++) {
33818eb6488eSEric Joyner 		/* Keep track of queues with work for soft irq */
33828eb6488eSEric Joyner 		if (que->txr->busy)
33838eb6488eSEric Joyner 			queues |= ((u64)1 << que->me);
33848eb6488eSEric Joyner 		/*
33858eb6488eSEric Joyner 		 * Each time txeof runs without cleaning, but there
33868eb6488eSEric Joyner 		 * are uncleaned descriptors it increments busy. If
33878eb6488eSEric Joyner 		 * we get to the MAX we declare it hung.
33888eb6488eSEric Joyner 		 */
33898eb6488eSEric Joyner 		if (que->busy == IXGBE_QUEUE_HUNG) {
33908eb6488eSEric Joyner 			++hung;
33918eb6488eSEric Joyner 			/* Mark the queue as inactive */
33928eb6488eSEric Joyner 			adapter->active_queues &= ~((u64)1 << que->me);
33938eb6488eSEric Joyner 			continue;
33948eb6488eSEric Joyner 		} else {
33958eb6488eSEric Joyner 			/* Check if we've come back from hung */
33968eb6488eSEric Joyner 			if ((adapter->active_queues & ((u64)1 << que->me)) == 0)
33978eb6488eSEric Joyner 				adapter->active_queues |= ((u64)1 << que->me);
33988eb6488eSEric Joyner 		}
33998eb6488eSEric Joyner 		if (que->busy >= IXGBE_MAX_TX_BUSY) {
34008eb6488eSEric Joyner 			device_printf(dev,
34018eb6488eSEric Joyner 			    "Warning queue %d appears to be hung!\n", i);
34028eb6488eSEric Joyner 			que->txr->busy = IXGBE_QUEUE_HUNG;
34038eb6488eSEric Joyner 			++hung;
34048eb6488eSEric Joyner 		}
34058eb6488eSEric Joyner 	}
34068eb6488eSEric Joyner 
34078eb6488eSEric Joyner 	/* Only truly watchdog if all queues show hung */
34088eb6488eSEric Joyner 	if (hung == adapter->num_queues)
34098eb6488eSEric Joyner 		goto watchdog;
34108eb6488eSEric Joyner 	else if (queues != 0) { /* Force an IRQ on queues with work */
34118eb6488eSEric Joyner 		ixgbe_rearm_queues(adapter, queues);
34128eb6488eSEric Joyner 	}
34138eb6488eSEric Joyner 
34148eb6488eSEric Joyner out:
34158eb6488eSEric Joyner 	callout_reset(&adapter->timer, hz, ixgbe_local_timer, adapter);
34168eb6488eSEric Joyner 	return;
34178eb6488eSEric Joyner 
34188eb6488eSEric Joyner watchdog:
34198eb6488eSEric Joyner 	device_printf(adapter->dev, "Watchdog timeout -- resetting\n");
34208eb6488eSEric Joyner 	adapter->ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
34218eb6488eSEric Joyner 	adapter->watchdog_events++;
34228eb6488eSEric Joyner 	ixgbe_init_locked(adapter);
34238eb6488eSEric Joyner } /* ixgbe_local_timer */
34248eb6488eSEric Joyner 
34258eb6488eSEric Joyner /************************************************************************
34268eb6488eSEric Joyner  * ixgbe_sfp_probe
34278eb6488eSEric Joyner  *
34288eb6488eSEric Joyner  *   Determine if a port had optics inserted.
34298eb6488eSEric Joyner  ************************************************************************/
34308eb6488eSEric Joyner static bool
34318eb6488eSEric Joyner ixgbe_sfp_probe(struct adapter *adapter)
34328eb6488eSEric Joyner {
34338eb6488eSEric Joyner 	struct ixgbe_hw *hw = &adapter->hw;
34348eb6488eSEric Joyner 	device_t        dev = adapter->dev;
34358eb6488eSEric Joyner 	bool            result = FALSE;
34368eb6488eSEric Joyner 
34378eb6488eSEric Joyner 	if ((hw->phy.type == ixgbe_phy_nl) &&
34388eb6488eSEric Joyner 	    (hw->phy.sfp_type == ixgbe_sfp_type_not_present)) {
34398eb6488eSEric Joyner 		s32 ret = hw->phy.ops.identify_sfp(hw);
34408eb6488eSEric Joyner 		if (ret)
34418eb6488eSEric Joyner 			goto out;
34428eb6488eSEric Joyner 		ret = hw->phy.ops.reset(hw);
34438eb6488eSEric Joyner 		adapter->sfp_probe = FALSE;
34448eb6488eSEric Joyner 		if (ret == IXGBE_ERR_SFP_NOT_SUPPORTED) {
34458eb6488eSEric Joyner 			device_printf(dev, "Unsupported SFP+ module detected!");
34468eb6488eSEric Joyner 			device_printf(dev,
34478eb6488eSEric Joyner 			    "Reload driver with supported module.\n");
34488eb6488eSEric Joyner 			goto out;
34498eb6488eSEric Joyner 		} else
34508eb6488eSEric Joyner 			device_printf(dev, "SFP+ module detected!\n");
34518eb6488eSEric Joyner 		/* We now have supported optics */
34528eb6488eSEric Joyner 		result = TRUE;
34538eb6488eSEric Joyner 	}
34548eb6488eSEric Joyner out:
34558eb6488eSEric Joyner 
34568eb6488eSEric Joyner 	return (result);
34578eb6488eSEric Joyner } /* ixgbe_sfp_probe */
34588eb6488eSEric Joyner 
34598eb6488eSEric Joyner /************************************************************************
34608eb6488eSEric Joyner  * ixgbe_handle_mod - Tasklet for SFP module interrupts
34618eb6488eSEric Joyner  ************************************************************************/
34628eb6488eSEric Joyner static void
34638eb6488eSEric Joyner ixgbe_handle_mod(void *context, int pending)
34648eb6488eSEric Joyner {
34658eb6488eSEric Joyner 	struct adapter  *adapter = context;
34668eb6488eSEric Joyner 	struct ixgbe_hw *hw = &adapter->hw;
34678eb6488eSEric Joyner 	device_t        dev = adapter->dev;
34688eb6488eSEric Joyner 	u32             err, cage_full = 0;
34698eb6488eSEric Joyner 
34708eb6488eSEric Joyner 	if (adapter->hw.need_crosstalk_fix) {
34718eb6488eSEric Joyner 		switch (hw->mac.type) {
34728eb6488eSEric Joyner 		case ixgbe_mac_82599EB:
34738eb6488eSEric Joyner 			cage_full = IXGBE_READ_REG(hw, IXGBE_ESDP) &
34748eb6488eSEric Joyner 			    IXGBE_ESDP_SDP2;
34758eb6488eSEric Joyner 			break;
34768eb6488eSEric Joyner 		case ixgbe_mac_X550EM_x:
34778eb6488eSEric Joyner 		case ixgbe_mac_X550EM_a:
34788eb6488eSEric Joyner 			cage_full = IXGBE_READ_REG(hw, IXGBE_ESDP) &
34798eb6488eSEric Joyner 			    IXGBE_ESDP_SDP0;
34808eb6488eSEric Joyner 			break;
34818eb6488eSEric Joyner 		default:
34828eb6488eSEric Joyner 			break;
34838eb6488eSEric Joyner 		}
34848eb6488eSEric Joyner 
34858eb6488eSEric Joyner 		if (!cage_full)
34868eb6488eSEric Joyner 			return;
34878eb6488eSEric Joyner 	}
34888eb6488eSEric Joyner 
34898eb6488eSEric Joyner 	err = hw->phy.ops.identify_sfp(hw);
34908eb6488eSEric Joyner 	if (err == IXGBE_ERR_SFP_NOT_SUPPORTED) {
34918eb6488eSEric Joyner 		device_printf(dev,
34928eb6488eSEric Joyner 		    "Unsupported SFP+ module type was detected.\n");
34938eb6488eSEric Joyner 		return;
34948eb6488eSEric Joyner 	}
34958eb6488eSEric Joyner 
34968eb6488eSEric Joyner 	err = hw->mac.ops.setup_sfp(hw);
34978eb6488eSEric Joyner 	if (err == IXGBE_ERR_SFP_NOT_SUPPORTED) {
34988eb6488eSEric Joyner 		device_printf(dev,
34998eb6488eSEric Joyner 		    "Setup failure - unsupported SFP+ module type.\n");
35008eb6488eSEric Joyner 		return;
35018eb6488eSEric Joyner 	}
35028eb6488eSEric Joyner 	taskqueue_enqueue(adapter->tq, &adapter->msf_task);
35038eb6488eSEric Joyner } /* ixgbe_handle_mod */
35048eb6488eSEric Joyner 
35058eb6488eSEric Joyner 
35068eb6488eSEric Joyner /************************************************************************
35078eb6488eSEric Joyner  * ixgbe_handle_msf - Tasklet for MSF (multispeed fiber) interrupts
35088eb6488eSEric Joyner  ************************************************************************/
35098eb6488eSEric Joyner static void
35108eb6488eSEric Joyner ixgbe_handle_msf(void *context, int pending)
35118eb6488eSEric Joyner {
35128eb6488eSEric Joyner 	struct adapter  *adapter = context;
35138eb6488eSEric Joyner 	struct ixgbe_hw *hw = &adapter->hw;
35148eb6488eSEric Joyner 	u32             autoneg;
35158eb6488eSEric Joyner 	bool            negotiate;
35168eb6488eSEric Joyner 
35178eb6488eSEric Joyner 	/* get_supported_phy_layer will call hw->phy.ops.identify_sfp() */
35188eb6488eSEric Joyner 	adapter->phy_layer = ixgbe_get_supported_physical_layer(hw);
35198eb6488eSEric Joyner 
35208eb6488eSEric Joyner 	autoneg = hw->phy.autoneg_advertised;
35218eb6488eSEric Joyner 	if ((!autoneg) && (hw->mac.ops.get_link_capabilities))
35228eb6488eSEric Joyner 		hw->mac.ops.get_link_capabilities(hw, &autoneg, &negotiate);
35238eb6488eSEric Joyner 	if (hw->mac.ops.setup_link)
35248eb6488eSEric Joyner 		hw->mac.ops.setup_link(hw, autoneg, TRUE);
35258eb6488eSEric Joyner 
35268eb6488eSEric Joyner 	/* Adjust media types shown in ifconfig */
35278eb6488eSEric Joyner 	ifmedia_removeall(&adapter->media);
35288eb6488eSEric Joyner 	ixgbe_add_media_types(adapter);
35298eb6488eSEric Joyner 	ifmedia_set(&adapter->media, IFM_ETHER | IFM_AUTO);
35308eb6488eSEric Joyner } /* ixgbe_handle_msf */
35318eb6488eSEric Joyner 
35328eb6488eSEric Joyner /************************************************************************
35338eb6488eSEric Joyner  * ixgbe_handle_phy - Tasklet for external PHY interrupts
35348eb6488eSEric Joyner  ************************************************************************/
35358eb6488eSEric Joyner static void
35368eb6488eSEric Joyner ixgbe_handle_phy(void *context, int pending)
35378eb6488eSEric Joyner {
35388eb6488eSEric Joyner 	struct adapter  *adapter = context;
35398eb6488eSEric Joyner 	struct ixgbe_hw *hw = &adapter->hw;
35408eb6488eSEric Joyner 	int             error;
35418eb6488eSEric Joyner 
35428eb6488eSEric Joyner 	error = hw->phy.ops.handle_lasi(hw);
35438eb6488eSEric Joyner 	if (error == IXGBE_ERR_OVERTEMP)
35448eb6488eSEric Joyner 		device_printf(adapter->dev, "CRITICAL: EXTERNAL PHY OVER TEMP!!  PHY will downshift to lower power state!\n");
35458eb6488eSEric Joyner 	else if (error)
35468eb6488eSEric Joyner 		device_printf(adapter->dev,
35478eb6488eSEric Joyner 		    "Error handling LASI interrupt: %d\n", error);
35488eb6488eSEric Joyner } /* ixgbe_handle_phy */
35498eb6488eSEric Joyner 
35508eb6488eSEric Joyner /************************************************************************
35518eb6488eSEric Joyner  * ixgbe_stop - Stop the hardware
35528eb6488eSEric Joyner  *
35538eb6488eSEric Joyner  *   Disables all traffic on the adapter by issuing a
35548eb6488eSEric Joyner  *   global reset on the MAC and deallocates TX/RX buffers.
35558eb6488eSEric Joyner  ************************************************************************/
35568eb6488eSEric Joyner static void
35578eb6488eSEric Joyner ixgbe_stop(void *arg)
35588eb6488eSEric Joyner {
35598eb6488eSEric Joyner 	struct ifnet    *ifp;
35608eb6488eSEric Joyner 	struct adapter  *adapter = arg;
35618eb6488eSEric Joyner 	struct ixgbe_hw *hw = &adapter->hw;
35628eb6488eSEric Joyner 
35638eb6488eSEric Joyner 	ifp = adapter->ifp;
35648eb6488eSEric Joyner 
35658eb6488eSEric Joyner 	mtx_assert(&adapter->core_mtx, MA_OWNED);
35668eb6488eSEric Joyner 
35678eb6488eSEric Joyner 	INIT_DEBUGOUT("ixgbe_stop: begin\n");
35688eb6488eSEric Joyner 	ixgbe_disable_intr(adapter);
35698eb6488eSEric Joyner 	callout_stop(&adapter->timer);
35708eb6488eSEric Joyner 
35718eb6488eSEric Joyner 	/* Let the stack know...*/
35728eb6488eSEric Joyner 	ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
35738eb6488eSEric Joyner 
35748eb6488eSEric Joyner 	ixgbe_reset_hw(hw);
35758eb6488eSEric Joyner 	hw->adapter_stopped = FALSE;
35768eb6488eSEric Joyner 	ixgbe_stop_adapter(hw);
35778eb6488eSEric Joyner 	if (hw->mac.type == ixgbe_mac_82599EB)
35788eb6488eSEric Joyner 		ixgbe_stop_mac_link_on_d3_82599(hw);
35798eb6488eSEric Joyner 	/* Turn off the laser - noop with no optics */
35808eb6488eSEric Joyner 	ixgbe_disable_tx_laser(hw);
35818eb6488eSEric Joyner 
35828eb6488eSEric Joyner 	/* Update the stack */
35838eb6488eSEric Joyner 	adapter->link_up = FALSE;
35848eb6488eSEric Joyner 	ixgbe_update_link_status(adapter);
35858eb6488eSEric Joyner 
35868eb6488eSEric Joyner 	/* reprogram the RAR[0] in case user changed it. */
35878eb6488eSEric Joyner 	ixgbe_set_rar(&adapter->hw, 0, adapter->hw.mac.addr, 0, IXGBE_RAH_AV);
35888eb6488eSEric Joyner 
35898eb6488eSEric Joyner 	return;
35908eb6488eSEric Joyner } /* ixgbe_stop */
35918eb6488eSEric Joyner 
35928eb6488eSEric Joyner /************************************************************************
35938eb6488eSEric Joyner  * ixgbe_update_link_status - Update OS on link state
35948eb6488eSEric Joyner  *
35958eb6488eSEric Joyner  * Note: Only updates the OS on the cached link state.
35968eb6488eSEric Joyner  *       The real check of the hardware only happens with
35978eb6488eSEric Joyner  *       a link interrupt.
35988eb6488eSEric Joyner  ************************************************************************/
35998eb6488eSEric Joyner static void
36008eb6488eSEric Joyner ixgbe_update_link_status(struct adapter *adapter)
36018eb6488eSEric Joyner {
36028eb6488eSEric Joyner 	struct ifnet *ifp = adapter->ifp;
36038eb6488eSEric Joyner 	device_t     dev = adapter->dev;
36048eb6488eSEric Joyner 
36058eb6488eSEric Joyner 	if (adapter->link_up) {
36068eb6488eSEric Joyner 		if (adapter->link_active == FALSE) {
36078eb6488eSEric Joyner 			if (bootverbose)
36088eb6488eSEric Joyner 				device_printf(dev, "Link is up %d Gbps %s \n",
36098eb6488eSEric Joyner 				    ((adapter->link_speed == 128) ? 10 : 1),
36108eb6488eSEric Joyner 				    "Full Duplex");
36118eb6488eSEric Joyner 			adapter->link_active = TRUE;
36128eb6488eSEric Joyner 			/* Update any Flow Control changes */
36138eb6488eSEric Joyner 			ixgbe_fc_enable(&adapter->hw);
36148eb6488eSEric Joyner 			/* Update DMA coalescing config */
36158eb6488eSEric Joyner 			ixgbe_config_dmac(adapter);
36168eb6488eSEric Joyner 			if_link_state_change(ifp, LINK_STATE_UP);
36178eb6488eSEric Joyner 			if (adapter->feat_en & IXGBE_FEATURE_SRIOV)
36188eb6488eSEric Joyner 				ixgbe_ping_all_vfs(adapter);
36198eb6488eSEric Joyner 		}
36208eb6488eSEric Joyner 	} else { /* Link down */
36218eb6488eSEric Joyner 		if (adapter->link_active == TRUE) {
36228eb6488eSEric Joyner 			if (bootverbose)
36238eb6488eSEric Joyner 				device_printf(dev, "Link is Down\n");
36248eb6488eSEric Joyner 			if_link_state_change(ifp, LINK_STATE_DOWN);
36258eb6488eSEric Joyner 			adapter->link_active = FALSE;
36268eb6488eSEric Joyner 			if (adapter->feat_en & IXGBE_FEATURE_SRIOV)
36278eb6488eSEric Joyner 				ixgbe_ping_all_vfs(adapter);
36288eb6488eSEric Joyner 		}
36298eb6488eSEric Joyner 	}
36308eb6488eSEric Joyner 
36318eb6488eSEric Joyner 	return;
36328eb6488eSEric Joyner } /* ixgbe_update_link_status */
36338eb6488eSEric Joyner 
36348eb6488eSEric Joyner /************************************************************************
36358eb6488eSEric Joyner  * ixgbe_config_dmac - Configure DMA Coalescing
36368eb6488eSEric Joyner  ************************************************************************/
36378eb6488eSEric Joyner static void
36388eb6488eSEric Joyner ixgbe_config_dmac(struct adapter *adapter)
36398eb6488eSEric Joyner {
36408eb6488eSEric Joyner 	struct ixgbe_hw          *hw = &adapter->hw;
36418eb6488eSEric Joyner 	struct ixgbe_dmac_config *dcfg = &hw->mac.dmac_config;
36428eb6488eSEric Joyner 
36438eb6488eSEric Joyner 	if (hw->mac.type < ixgbe_mac_X550 || !hw->mac.ops.dmac_config)
36448eb6488eSEric Joyner 		return;
36458eb6488eSEric Joyner 
36468eb6488eSEric Joyner 	if (dcfg->watchdog_timer ^ adapter->dmac ||
36478eb6488eSEric Joyner 	    dcfg->link_speed ^ adapter->link_speed) {
36488eb6488eSEric Joyner 		dcfg->watchdog_timer = adapter->dmac;
36498eb6488eSEric Joyner 		dcfg->fcoe_en = false;
36508eb6488eSEric Joyner 		dcfg->link_speed = adapter->link_speed;
36518eb6488eSEric Joyner 		dcfg->num_tcs = 1;
36528eb6488eSEric Joyner 
36538eb6488eSEric Joyner 		INIT_DEBUGOUT2("dmac settings: watchdog %d, link speed %d\n",
36548eb6488eSEric Joyner 		    dcfg->watchdog_timer, dcfg->link_speed);
36558eb6488eSEric Joyner 
36568eb6488eSEric Joyner 		hw->mac.ops.dmac_config(hw);
36578eb6488eSEric Joyner 	}
36588eb6488eSEric Joyner } /* ixgbe_config_dmac */
36598eb6488eSEric Joyner 
36608eb6488eSEric Joyner /************************************************************************
36618eb6488eSEric Joyner  * ixgbe_enable_intr
36628eb6488eSEric Joyner  ************************************************************************/
36638eb6488eSEric Joyner static void
36648eb6488eSEric Joyner ixgbe_enable_intr(struct adapter *adapter)
36658eb6488eSEric Joyner {
36668eb6488eSEric Joyner 	struct ixgbe_hw *hw = &adapter->hw;
36678eb6488eSEric Joyner 	struct ix_queue *que = adapter->queues;
36688eb6488eSEric Joyner 	u32             mask, fwsm;
36698eb6488eSEric Joyner 
36708eb6488eSEric Joyner 	mask = (IXGBE_EIMS_ENABLE_MASK & ~IXGBE_EIMS_RTX_QUEUE);
36718eb6488eSEric Joyner 
36728eb6488eSEric Joyner 	switch (adapter->hw.mac.type) {
36738eb6488eSEric Joyner 	case ixgbe_mac_82599EB:
36748eb6488eSEric Joyner 		mask |= IXGBE_EIMS_ECC;
36758eb6488eSEric Joyner 		/* Temperature sensor on some adapters */
36768eb6488eSEric Joyner 		mask |= IXGBE_EIMS_GPI_SDP0;
36778eb6488eSEric Joyner 		/* SFP+ (RX_LOS_N & MOD_ABS_N) */
36788eb6488eSEric Joyner 		mask |= IXGBE_EIMS_GPI_SDP1;
36798eb6488eSEric Joyner 		mask |= IXGBE_EIMS_GPI_SDP2;
36808eb6488eSEric Joyner 		break;
36818eb6488eSEric Joyner 	case ixgbe_mac_X540:
36828eb6488eSEric Joyner 		/* Detect if Thermal Sensor is enabled */
36838eb6488eSEric Joyner 		fwsm = IXGBE_READ_REG(hw, IXGBE_FWSM);
36848eb6488eSEric Joyner 		if (fwsm & IXGBE_FWSM_TS_ENABLED)
36858eb6488eSEric Joyner 			mask |= IXGBE_EIMS_TS;
36868eb6488eSEric Joyner 		mask |= IXGBE_EIMS_ECC;
36878eb6488eSEric Joyner 		break;
36888eb6488eSEric Joyner 	case ixgbe_mac_X550:
36898eb6488eSEric Joyner 		/* MAC thermal sensor is automatically enabled */
36908eb6488eSEric Joyner 		mask |= IXGBE_EIMS_TS;
36918eb6488eSEric Joyner 		mask |= IXGBE_EIMS_ECC;
36928eb6488eSEric Joyner 		break;
36938eb6488eSEric Joyner 	case ixgbe_mac_X550EM_x:
36948eb6488eSEric Joyner 	case ixgbe_mac_X550EM_a:
36958eb6488eSEric Joyner 		/* Some devices use SDP0 for important information */
36968eb6488eSEric Joyner 		if (hw->device_id == IXGBE_DEV_ID_X550EM_X_SFP ||
36978eb6488eSEric Joyner 		    hw->device_id == IXGBE_DEV_ID_X550EM_A_SFP ||
36988eb6488eSEric Joyner 		    hw->device_id == IXGBE_DEV_ID_X550EM_A_SFP_N ||
36998eb6488eSEric Joyner 		    hw->device_id == IXGBE_DEV_ID_X550EM_X_10G_T)
37008eb6488eSEric Joyner 			mask |= IXGBE_EIMS_GPI_SDP0_BY_MAC(hw);
37018eb6488eSEric Joyner 		if (hw->phy.type == ixgbe_phy_x550em_ext_t)
37028eb6488eSEric Joyner 			mask |= IXGBE_EICR_GPI_SDP0_X540;
37038eb6488eSEric Joyner 		mask |= IXGBE_EIMS_ECC;
37048eb6488eSEric Joyner 		break;
37058eb6488eSEric Joyner 	default:
37068eb6488eSEric Joyner 		break;
37078eb6488eSEric Joyner 	}
37088eb6488eSEric Joyner 
37098eb6488eSEric Joyner 	/* Enable Fan Failure detection */
37108eb6488eSEric Joyner 	if (adapter->feat_en & IXGBE_FEATURE_FAN_FAIL)
37118eb6488eSEric Joyner 		mask |= IXGBE_EIMS_GPI_SDP1;
37128eb6488eSEric Joyner 	/* Enable SR-IOV */
37138eb6488eSEric Joyner 	if (adapter->feat_en & IXGBE_FEATURE_SRIOV)
37148eb6488eSEric Joyner 		mask |= IXGBE_EIMS_MAILBOX;
37158eb6488eSEric Joyner 	/* Enable Flow Director */
37168eb6488eSEric Joyner 	if (adapter->feat_en & IXGBE_FEATURE_FDIR)
37178eb6488eSEric Joyner 		mask |= IXGBE_EIMS_FLOW_DIR;
37188eb6488eSEric Joyner 
37198eb6488eSEric Joyner 	IXGBE_WRITE_REG(hw, IXGBE_EIMS, mask);
37208eb6488eSEric Joyner 
37218eb6488eSEric Joyner 	/* With MSI-X we use auto clear */
37228eb6488eSEric Joyner 	if (adapter->msix_mem) {
37238eb6488eSEric Joyner 		mask = IXGBE_EIMS_ENABLE_MASK;
37248eb6488eSEric Joyner 		/* Don't autoclear Link */
37258eb6488eSEric Joyner 		mask &= ~IXGBE_EIMS_OTHER;
37268eb6488eSEric Joyner 		mask &= ~IXGBE_EIMS_LSC;
37278eb6488eSEric Joyner 		if (adapter->feat_cap & IXGBE_FEATURE_SRIOV)
37288eb6488eSEric Joyner 			mask &= ~IXGBE_EIMS_MAILBOX;
37298eb6488eSEric Joyner 		IXGBE_WRITE_REG(hw, IXGBE_EIAC, mask);
37306f37f232SEric Joyner 	}
37316f37f232SEric Joyner 
3732758cc3dcSJack F Vogel 	/*
37338eb6488eSEric Joyner 	 * Now enable all queues, this is done separately to
37348eb6488eSEric Joyner 	 * allow for handling the extended (beyond 32) MSI-X
37358eb6488eSEric Joyner 	 * vectors that can be used by 82599
3736758cc3dcSJack F Vogel 	 */
37378eb6488eSEric Joyner 	for (int i = 0; i < adapter->num_queues; i++, que++)
37388eb6488eSEric Joyner 		ixgbe_enable_queue(adapter, que->msix);
37398eb6488eSEric Joyner 
37408eb6488eSEric Joyner 	IXGBE_WRITE_FLUSH(hw);
37418eb6488eSEric Joyner 
37428eb6488eSEric Joyner 	return;
37438eb6488eSEric Joyner } /* ixgbe_enable_intr */
37448eb6488eSEric Joyner 
37458eb6488eSEric Joyner /************************************************************************
37468eb6488eSEric Joyner  * ixgbe_disable_intr
37478eb6488eSEric Joyner  ************************************************************************/
3748758cc3dcSJack F Vogel static void
37498eb6488eSEric Joyner ixgbe_disable_intr(struct adapter *adapter)
3750758cc3dcSJack F Vogel {
37518eb6488eSEric Joyner 	if (adapter->msix_mem)
37528eb6488eSEric Joyner 		IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIAC, 0);
37538eb6488eSEric Joyner 	if (adapter->hw.mac.type == ixgbe_mac_82598EB) {
37548eb6488eSEric Joyner 		IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMC, ~0);
37558eb6488eSEric Joyner 	} else {
37568eb6488eSEric Joyner 		IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMC, 0xFFFF0000);
37578eb6488eSEric Joyner 		IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMC_EX(0), ~0);
37588eb6488eSEric Joyner 		IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMC_EX(1), ~0);
37598eb6488eSEric Joyner 	}
37608eb6488eSEric Joyner 	IXGBE_WRITE_FLUSH(&adapter->hw);
3761758cc3dcSJack F Vogel 
37628eb6488eSEric Joyner 	return;
37638eb6488eSEric Joyner } /* ixgbe_disable_intr */
37648eb6488eSEric Joyner 
37658eb6488eSEric Joyner /************************************************************************
37668eb6488eSEric Joyner  * ixgbe_legacy_irq - Legacy Interrupt Service routine
37678eb6488eSEric Joyner  ************************************************************************/
37688eb6488eSEric Joyner static void
37698eb6488eSEric Joyner ixgbe_legacy_irq(void *arg)
37708eb6488eSEric Joyner {
37718eb6488eSEric Joyner 	struct ix_queue *que = arg;
37728eb6488eSEric Joyner 	struct adapter  *adapter = que->adapter;
37738eb6488eSEric Joyner 	struct ixgbe_hw *hw = &adapter->hw;
37748eb6488eSEric Joyner 	struct ifnet    *ifp = adapter->ifp;
3775758cc3dcSJack F Vogel 	struct tx_ring  *txr = adapter->tx_rings;
37768eb6488eSEric Joyner 	bool            more = false;
37778eb6488eSEric Joyner 	u32             eicr, eicr_mask;
3778758cc3dcSJack F Vogel 
37798eb6488eSEric Joyner 	/* Silicon errata #26 on 82598 */
37808eb6488eSEric Joyner 	IXGBE_WRITE_REG(hw, IXGBE_EIMC, IXGBE_IRQ_CLEAR_MASK);
3781758cc3dcSJack F Vogel 
37828eb6488eSEric Joyner 	eicr = IXGBE_READ_REG(hw, IXGBE_EICR);
3783758cc3dcSJack F Vogel 
37848eb6488eSEric Joyner 	++que->irqs;
37858eb6488eSEric Joyner 	if (eicr == 0) {
37868eb6488eSEric Joyner 		ixgbe_enable_intr(adapter);
37878eb6488eSEric Joyner 		return;
3788758cc3dcSJack F Vogel 	}
3789758cc3dcSJack F Vogel 
37908eb6488eSEric Joyner 	if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
37918eb6488eSEric Joyner 		more = ixgbe_rxeof(que);
3792758cc3dcSJack F Vogel 
37938eb6488eSEric Joyner 		IXGBE_TX_LOCK(txr);
37948eb6488eSEric Joyner 		ixgbe_txeof(txr);
37958eb6488eSEric Joyner 		if (!ixgbe_ring_empty(ifp, txr->br))
37968eb6488eSEric Joyner 			ixgbe_start_locked(ifp, txr);
37978eb6488eSEric Joyner 		IXGBE_TX_UNLOCK(txr);
3798758cc3dcSJack F Vogel 	}
3799758cc3dcSJack F Vogel 
38008eb6488eSEric Joyner 	/* Check for fan failure */
38018eb6488eSEric Joyner 	if (adapter->feat_en & IXGBE_FEATURE_FAN_FAIL) {
38028eb6488eSEric Joyner 		ixgbe_check_fan_failure(adapter, eicr, true);
38038eb6488eSEric Joyner 		IXGBE_WRITE_REG(hw, IXGBE_EIMS, IXGBE_EICR_GPI_SDP1_BY_MAC(hw));
3804758cc3dcSJack F Vogel 	}
3805758cc3dcSJack F Vogel 
38068eb6488eSEric Joyner 	/* Link status change */
38078eb6488eSEric Joyner 	if (eicr & IXGBE_EICR_LSC)
38088eb6488eSEric Joyner 		taskqueue_enqueue(adapter->tq, &adapter->link_task);
38098eb6488eSEric Joyner 
38108eb6488eSEric Joyner 	if (ixgbe_is_sfp(hw)) {
38118eb6488eSEric Joyner 		/* Pluggable optics-related interrupt */
38128eb6488eSEric Joyner 		if (hw->mac.type >= ixgbe_mac_X540)
38138eb6488eSEric Joyner 			eicr_mask = IXGBE_EICR_GPI_SDP0_X540;
38148eb6488eSEric Joyner 		else
38158eb6488eSEric Joyner 			eicr_mask = IXGBE_EICR_GPI_SDP2_BY_MAC(hw);
38168eb6488eSEric Joyner 
38178eb6488eSEric Joyner 		if (eicr & eicr_mask) {
38188eb6488eSEric Joyner 			IXGBE_WRITE_REG(hw, IXGBE_EICR, eicr_mask);
38198eb6488eSEric Joyner 			taskqueue_enqueue(adapter->tq, &adapter->mod_task);
38208eb6488eSEric Joyner 		}
38218eb6488eSEric Joyner 
38228eb6488eSEric Joyner 		if ((hw->mac.type == ixgbe_mac_82599EB) &&
38238eb6488eSEric Joyner 		    (eicr & IXGBE_EICR_GPI_SDP1_BY_MAC(hw))) {
38248eb6488eSEric Joyner 			IXGBE_WRITE_REG(hw, IXGBE_EICR,
38258eb6488eSEric Joyner 			    IXGBE_EICR_GPI_SDP1_BY_MAC(hw));
38268eb6488eSEric Joyner 			taskqueue_enqueue(adapter->tq, &adapter->msf_task);
38278eb6488eSEric Joyner 		}
38288eb6488eSEric Joyner 	}
38298eb6488eSEric Joyner 
38308eb6488eSEric Joyner 	/* External PHY interrupt */
38318eb6488eSEric Joyner 	if ((hw->phy.type == ixgbe_phy_x550em_ext_t) &&
38328eb6488eSEric Joyner 	    (eicr & IXGBE_EICR_GPI_SDP0_X540))
38338eb6488eSEric Joyner 		taskqueue_enqueue(adapter->tq, &adapter->phy_task);
38348eb6488eSEric Joyner 
38358eb6488eSEric Joyner 	if (more)
38368eb6488eSEric Joyner 		taskqueue_enqueue(que->tq, &que->que_task);
38378eb6488eSEric Joyner 	else
38388eb6488eSEric Joyner 		ixgbe_enable_intr(adapter);
38398eb6488eSEric Joyner 
38408eb6488eSEric Joyner 	return;
38418eb6488eSEric Joyner } /* ixgbe_legacy_irq */
38428eb6488eSEric Joyner 
38438eb6488eSEric Joyner /************************************************************************
38448eb6488eSEric Joyner  * ixgbe_free_pci_resources
38458eb6488eSEric Joyner  ************************************************************************/
38468eb6488eSEric Joyner static void
38478eb6488eSEric Joyner ixgbe_free_pci_resources(struct adapter *adapter)
38488eb6488eSEric Joyner {
38498eb6488eSEric Joyner 	struct ix_queue *que = adapter->queues;
38508eb6488eSEric Joyner 	device_t        dev = adapter->dev;
38518eb6488eSEric Joyner 	int             rid, memrid;
38528eb6488eSEric Joyner 
38538eb6488eSEric Joyner 	if (adapter->hw.mac.type == ixgbe_mac_82598EB)
38548eb6488eSEric Joyner 		memrid = PCIR_BAR(MSIX_82598_BAR);
38558eb6488eSEric Joyner 	else
38568eb6488eSEric Joyner 		memrid = PCIR_BAR(MSIX_82599_BAR);
38578eb6488eSEric Joyner 
38588eb6488eSEric Joyner 	/*
38598eb6488eSEric Joyner 	 * There is a slight possibility of a failure mode
38608eb6488eSEric Joyner 	 * in attach that will result in entering this function
38618eb6488eSEric Joyner 	 * before interrupt resources have been initialized, and
38628eb6488eSEric Joyner 	 * in that case we do not want to execute the loops below
38638eb6488eSEric Joyner 	 * We can detect this reliably by the state of the adapter
38648eb6488eSEric Joyner 	 * res pointer.
38658eb6488eSEric Joyner 	 */
38668eb6488eSEric Joyner 	if (adapter->res == NULL)
38678eb6488eSEric Joyner 		goto mem;
38688eb6488eSEric Joyner 
38698eb6488eSEric Joyner 	/*
38708eb6488eSEric Joyner 	 * Release all msix queue resources:
38718eb6488eSEric Joyner 	 */
38728eb6488eSEric Joyner 	for (int i = 0; i < adapter->num_queues; i++, que++) {
38738eb6488eSEric Joyner 		rid = que->msix + 1;
38748eb6488eSEric Joyner 		if (que->tag != NULL) {
38758eb6488eSEric Joyner 			bus_teardown_intr(dev, que->res, que->tag);
38768eb6488eSEric Joyner 			que->tag = NULL;
38778eb6488eSEric Joyner 		}
38788eb6488eSEric Joyner 		if (que->res != NULL)
38798eb6488eSEric Joyner 			bus_release_resource(dev, SYS_RES_IRQ, rid, que->res);
38808eb6488eSEric Joyner 	}
38818eb6488eSEric Joyner 
38828eb6488eSEric Joyner 
38838eb6488eSEric Joyner 	if (adapter->tag != NULL) {
38848eb6488eSEric Joyner 		bus_teardown_intr(dev, adapter->res, adapter->tag);
38858eb6488eSEric Joyner 		adapter->tag = NULL;
38868eb6488eSEric Joyner 	}
38878eb6488eSEric Joyner 
38888eb6488eSEric Joyner 	/* Clean the Legacy or Link interrupt last */
38898eb6488eSEric Joyner 	if (adapter->res != NULL)
38908eb6488eSEric Joyner 		bus_release_resource(dev, SYS_RES_IRQ, adapter->link_rid,
38918eb6488eSEric Joyner 		    adapter->res);
38928eb6488eSEric Joyner 
38938eb6488eSEric Joyner mem:
38948eb6488eSEric Joyner 	if ((adapter->feat_en & IXGBE_FEATURE_MSI) ||
38958eb6488eSEric Joyner 	    (adapter->feat_en & IXGBE_FEATURE_MSIX))
38968eb6488eSEric Joyner 		pci_release_msi(dev);
38978eb6488eSEric Joyner 
38988eb6488eSEric Joyner 	if (adapter->msix_mem != NULL)
38998eb6488eSEric Joyner 		bus_release_resource(dev, SYS_RES_MEMORY, memrid,
39008eb6488eSEric Joyner 		    adapter->msix_mem);
39018eb6488eSEric Joyner 
39028eb6488eSEric Joyner 	if (adapter->pci_mem != NULL)
39038eb6488eSEric Joyner 		bus_release_resource(dev, SYS_RES_MEMORY, PCIR_BAR(0),
39048eb6488eSEric Joyner 		    adapter->pci_mem);
39058eb6488eSEric Joyner 
39068eb6488eSEric Joyner 	return;
39078eb6488eSEric Joyner } /* ixgbe_free_pci_resources */
39088eb6488eSEric Joyner 
39098eb6488eSEric Joyner /************************************************************************
39108eb6488eSEric Joyner  * ixgbe_set_sysctl_value
39118eb6488eSEric Joyner  ************************************************************************/
3912b0c041f8SSean Bruno static void
3913b0c041f8SSean Bruno ixgbe_set_sysctl_value(struct adapter *adapter, const char *name,
3914b0c041f8SSean Bruno     const char *description, int *limit, int value)
3915b0c041f8SSean Bruno {
3916b0c041f8SSean Bruno 	*limit = value;
3917b0c041f8SSean Bruno 	SYSCTL_ADD_INT(device_get_sysctl_ctx(adapter->dev),
3918b0c041f8SSean Bruno 	    SYSCTL_CHILDREN(device_get_sysctl_tree(adapter->dev)),
3919b0c041f8SSean Bruno 	    OID_AUTO, name, CTLFLAG_RW, limit, value, description);
39208eb6488eSEric Joyner } /* ixgbe_set_sysctl_value */
3921b0c041f8SSean Bruno 
39228eb6488eSEric Joyner /************************************************************************
39238eb6488eSEric Joyner  * ixgbe_sysctl_flowcntl
39248eb6488eSEric Joyner  *
39258eb6488eSEric Joyner  *   SYSCTL wrapper around setting Flow Control
39268eb6488eSEric Joyner  ************************************************************************/
3927758cc3dcSJack F Vogel static int
3928f2c4db54SSteven Hartland ixgbe_sysctl_flowcntl(SYSCTL_HANDLER_ARGS)
3929758cc3dcSJack F Vogel {
3930f2c4db54SSteven Hartland 	struct adapter *adapter;
39318eb6488eSEric Joyner 	int            error, fc;
3932758cc3dcSJack F Vogel 
3933f2c4db54SSteven Hartland 	adapter = (struct adapter *)arg1;
39348eb6488eSEric Joyner 	fc = adapter->hw.fc.current_mode;
3935f2c4db54SSteven Hartland 
3936f2c4db54SSteven Hartland 	error = sysctl_handle_int(oidp, &fc, 0, req);
3937758cc3dcSJack F Vogel 	if ((error) || (req->newptr == NULL))
3938758cc3dcSJack F Vogel 		return (error);
3939758cc3dcSJack F Vogel 
3940758cc3dcSJack F Vogel 	/* Don't bother if it's not changed */
39418eb6488eSEric Joyner 	if (fc == adapter->hw.fc.current_mode)
3942758cc3dcSJack F Vogel 		return (0);
3943758cc3dcSJack F Vogel 
3944f2c4db54SSteven Hartland 	return ixgbe_set_flowcntl(adapter, fc);
39458eb6488eSEric Joyner } /* ixgbe_sysctl_flowcntl */
3946f2c4db54SSteven Hartland 
39478eb6488eSEric Joyner /************************************************************************
39488eb6488eSEric Joyner  * ixgbe_set_flowcntl - Set flow control
39498eb6488eSEric Joyner  *
39508eb6488eSEric Joyner  *   Flow control values:
39518eb6488eSEric Joyner  *     0 - off
39528eb6488eSEric Joyner  *     1 - rx pause
39538eb6488eSEric Joyner  *     2 - tx pause
39548eb6488eSEric Joyner  *     3 - full
39558eb6488eSEric Joyner  ************************************************************************/
3956f2c4db54SSteven Hartland static int
3957f2c4db54SSteven Hartland ixgbe_set_flowcntl(struct adapter *adapter, int fc)
3958f2c4db54SSteven Hartland {
3959f2c4db54SSteven Hartland 	switch (fc) {
3960758cc3dcSJack F Vogel 	case ixgbe_fc_rx_pause:
3961758cc3dcSJack F Vogel 	case ixgbe_fc_tx_pause:
3962758cc3dcSJack F Vogel 	case ixgbe_fc_full:
39638eb6488eSEric Joyner 		adapter->hw.fc.requested_mode = fc;
3964758cc3dcSJack F Vogel 		if (adapter->num_queues > 1)
3965758cc3dcSJack F Vogel 			ixgbe_disable_rx_drop(adapter);
3966758cc3dcSJack F Vogel 		break;
3967758cc3dcSJack F Vogel 	case ixgbe_fc_none:
3968758cc3dcSJack F Vogel 		adapter->hw.fc.requested_mode = ixgbe_fc_none;
3969758cc3dcSJack F Vogel 		if (adapter->num_queues > 1)
3970758cc3dcSJack F Vogel 			ixgbe_enable_rx_drop(adapter);
3971758cc3dcSJack F Vogel 		break;
3972758cc3dcSJack F Vogel 	default:
3973758cc3dcSJack F Vogel 		return (EINVAL);
3974758cc3dcSJack F Vogel 	}
39758eb6488eSEric Joyner 
3976758cc3dcSJack F Vogel 	/* Don't autoneg if forcing a value */
3977758cc3dcSJack F Vogel 	adapter->hw.fc.disable_fc_autoneg = TRUE;
3978758cc3dcSJack F Vogel 	ixgbe_fc_enable(&adapter->hw);
39798eb6488eSEric Joyner 
3980f2c4db54SSteven Hartland 	return (0);
39818eb6488eSEric Joyner } /* ixgbe_set_flowcntl */
39828eb6488eSEric Joyner 
39838eb6488eSEric Joyner /************************************************************************
39848eb6488eSEric Joyner  * ixgbe_enable_rx_drop
39858eb6488eSEric Joyner  *
39868eb6488eSEric Joyner  *   Enable the hardware to drop packets when the buffer is
39878eb6488eSEric Joyner  *   full. This is useful with multiqueue, so that no single
39888eb6488eSEric Joyner  *   queue being full stalls the entire RX engine. We only
39898eb6488eSEric Joyner  *   enable this when Multiqueue is enabled AND Flow Control
39908eb6488eSEric Joyner  *   is disabled.
39918eb6488eSEric Joyner  ************************************************************************/
39928eb6488eSEric Joyner static void
39938eb6488eSEric Joyner ixgbe_enable_rx_drop(struct adapter *adapter)
39948eb6488eSEric Joyner {
39958eb6488eSEric Joyner 	struct ixgbe_hw *hw = &adapter->hw;
39968eb6488eSEric Joyner 	struct rx_ring  *rxr;
39978eb6488eSEric Joyner 	u32             srrctl;
39988eb6488eSEric Joyner 
39998eb6488eSEric Joyner 	for (int i = 0; i < adapter->num_queues; i++) {
40008eb6488eSEric Joyner 		rxr = &adapter->rx_rings[i];
40018eb6488eSEric Joyner 		srrctl = IXGBE_READ_REG(hw, IXGBE_SRRCTL(rxr->me));
40028eb6488eSEric Joyner 		srrctl |= IXGBE_SRRCTL_DROP_EN;
40038eb6488eSEric Joyner 		IXGBE_WRITE_REG(hw, IXGBE_SRRCTL(rxr->me), srrctl);
4004758cc3dcSJack F Vogel 	}
4005758cc3dcSJack F Vogel 
40068eb6488eSEric Joyner 	/* enable drop for each vf */
40078eb6488eSEric Joyner 	for (int i = 0; i < adapter->num_vfs; i++) {
40088eb6488eSEric Joyner 		IXGBE_WRITE_REG(hw, IXGBE_QDE,
40098eb6488eSEric Joyner 		    (IXGBE_QDE_WRITE | (i << IXGBE_QDE_IDX_SHIFT) |
40108eb6488eSEric Joyner 		    IXGBE_QDE_ENABLE));
40118eb6488eSEric Joyner 	}
40128eb6488eSEric Joyner } /* ixgbe_enable_rx_drop */
40138eb6488eSEric Joyner 
40148eb6488eSEric Joyner /************************************************************************
40158eb6488eSEric Joyner  * ixgbe_disable_rx_drop
40168eb6488eSEric Joyner  ************************************************************************/
40178eb6488eSEric Joyner static void
40188eb6488eSEric Joyner ixgbe_disable_rx_drop(struct adapter *adapter)
40198eb6488eSEric Joyner {
40208eb6488eSEric Joyner 	struct ixgbe_hw *hw = &adapter->hw;
40218eb6488eSEric Joyner 	struct rx_ring  *rxr;
40228eb6488eSEric Joyner 	u32             srrctl;
40238eb6488eSEric Joyner 
40248eb6488eSEric Joyner 	for (int i = 0; i < adapter->num_queues; i++) {
40258eb6488eSEric Joyner 		rxr = &adapter->rx_rings[i];
40268eb6488eSEric Joyner 		srrctl = IXGBE_READ_REG(hw, IXGBE_SRRCTL(rxr->me));
40278eb6488eSEric Joyner 		srrctl &= ~IXGBE_SRRCTL_DROP_EN;
40288eb6488eSEric Joyner 		IXGBE_WRITE_REG(hw, IXGBE_SRRCTL(rxr->me), srrctl);
40298eb6488eSEric Joyner 	}
40308eb6488eSEric Joyner 
40318eb6488eSEric Joyner 	/* disable drop for each vf */
40328eb6488eSEric Joyner 	for (int i = 0; i < adapter->num_vfs; i++) {
40338eb6488eSEric Joyner 		IXGBE_WRITE_REG(hw, IXGBE_QDE,
40348eb6488eSEric Joyner 		    (IXGBE_QDE_WRITE | (i << IXGBE_QDE_IDX_SHIFT)));
40358eb6488eSEric Joyner 	}
40368eb6488eSEric Joyner } /* ixgbe_disable_rx_drop */
40378eb6488eSEric Joyner 
40388eb6488eSEric Joyner /************************************************************************
40398eb6488eSEric Joyner  * ixgbe_sysctl_advertise
40408eb6488eSEric Joyner  *
40418eb6488eSEric Joyner  *   SYSCTL wrapper around setting advertised speed
40428eb6488eSEric Joyner  ************************************************************************/
4043758cc3dcSJack F Vogel static int
4044f2c4db54SSteven Hartland ixgbe_sysctl_advertise(SYSCTL_HANDLER_ARGS)
4045758cc3dcSJack F Vogel {
4046758cc3dcSJack F Vogel 	struct adapter *adapter;
40478eb6488eSEric Joyner 	int            error, advertise;
4048758cc3dcSJack F Vogel 
4049758cc3dcSJack F Vogel 	adapter = (struct adapter *)arg1;
4050f2c4db54SSteven Hartland 	advertise = adapter->advertise;
4051758cc3dcSJack F Vogel 
4052f2c4db54SSteven Hartland 	error = sysctl_handle_int(oidp, &advertise, 0, req);
4053758cc3dcSJack F Vogel 	if ((error) || (req->newptr == NULL))
4054758cc3dcSJack F Vogel 		return (error);
4055758cc3dcSJack F Vogel 
4056f2c4db54SSteven Hartland 	return ixgbe_set_advertise(adapter, advertise);
40578eb6488eSEric Joyner } /* ixgbe_sysctl_advertise */
4058f2c4db54SSteven Hartland 
40598eb6488eSEric Joyner /************************************************************************
40608eb6488eSEric Joyner  * ixgbe_set_advertise - Control advertised link speed
40618eb6488eSEric Joyner  *
40628eb6488eSEric Joyner  *   Flags:
40638eb6488eSEric Joyner  *     0x1 - advertise 100 Mb
40648eb6488eSEric Joyner  *     0x2 - advertise 1G
40658eb6488eSEric Joyner  *     0x4 - advertise 10G
40668eb6488eSEric Joyner  *     0x8 - advertise 10 Mb (yes, Mb)
40678eb6488eSEric Joyner  ************************************************************************/
4068f2c4db54SSteven Hartland static int
4069f2c4db54SSteven Hartland ixgbe_set_advertise(struct adapter *adapter, int advertise)
4070f2c4db54SSteven Hartland {
4071f2c4db54SSteven Hartland 	device_t         dev;
4072f2c4db54SSteven Hartland 	struct ixgbe_hw  *hw;
40738eb6488eSEric Joyner 	ixgbe_link_speed speed = 0;
40748eb6488eSEric Joyner 	ixgbe_link_speed link_caps = 0;
40758eb6488eSEric Joyner 	s32              err = IXGBE_NOT_IMPLEMENTED;
40768eb6488eSEric Joyner 	bool             negotiate = FALSE;
4077f2c4db54SSteven Hartland 
4078d775d23aSSteven Hartland 	/* Checks to validate new value */
4079d775d23aSSteven Hartland 	if (adapter->advertise == advertise) /* no change */
4080d775d23aSSteven Hartland 		return (0);
4081d775d23aSSteven Hartland 
4082f2c4db54SSteven Hartland 	dev = adapter->dev;
40838eb6488eSEric Joyner 	hw = &adapter->hw;
4084f2c4db54SSteven Hartland 
4085a9ca1c79SSean Bruno 	/* No speed changes for backplane media */
4086a9ca1c79SSean Bruno 	if (hw->phy.media_type == ixgbe_media_type_backplane)
4087a9ca1c79SSean Bruno 		return (ENODEV);
4088a9ca1c79SSean Bruno 
4089758cc3dcSJack F Vogel 	if (!((hw->phy.media_type == ixgbe_media_type_copper) ||
4090758cc3dcSJack F Vogel 	      (hw->phy.multispeed_fiber))) {
40918eb6488eSEric Joyner 		device_printf(dev, "Advertised speed can only be set on copper or multispeed fiber media types.\n");
4092758cc3dcSJack F Vogel 		return (EINVAL);
4093758cc3dcSJack F Vogel 	}
4094758cc3dcSJack F Vogel 
40958eb6488eSEric Joyner 	if (advertise < 0x1 || advertise > 0xF) {
40968eb6488eSEric Joyner 		device_printf(dev, "Invalid advertised speed; valid modes are 0x1 through 0xF\n");
4097758cc3dcSJack F Vogel 		return (EINVAL);
4098758cc3dcSJack F Vogel 	}
4099758cc3dcSJack F Vogel 
41008eb6488eSEric Joyner 	if (hw->mac.ops.get_link_capabilities) {
41018eb6488eSEric Joyner 		err = hw->mac.ops.get_link_capabilities(hw, &link_caps,
41028eb6488eSEric Joyner 		    &negotiate);
41038eb6488eSEric Joyner 		if (err != IXGBE_SUCCESS) {
41048eb6488eSEric Joyner 			device_printf(dev, "Unable to determine supported advertise speeds\n");
41058eb6488eSEric Joyner 			return (ENODEV);
41068eb6488eSEric Joyner 		}
4107758cc3dcSJack F Vogel 	}
4108758cc3dcSJack F Vogel 
4109758cc3dcSJack F Vogel 	/* Set new value and report new advertised mode */
41108eb6488eSEric Joyner 	if (advertise & 0x1) {
41118eb6488eSEric Joyner 		if (!(link_caps & IXGBE_LINK_SPEED_100_FULL)) {
41128eb6488eSEric Joyner 			device_printf(dev, "Interface does not support 100Mb advertised speed\n");
41138eb6488eSEric Joyner 			return (EINVAL);
41148eb6488eSEric Joyner 		}
4115758cc3dcSJack F Vogel 		speed |= IXGBE_LINK_SPEED_100_FULL;
41168eb6488eSEric Joyner 	}
41178eb6488eSEric Joyner 	if (advertise & 0x2) {
41188eb6488eSEric Joyner 		if (!(link_caps & IXGBE_LINK_SPEED_1GB_FULL)) {
41198eb6488eSEric Joyner 			device_printf(dev, "Interface does not support 1Gb advertised speed\n");
41208eb6488eSEric Joyner 			return (EINVAL);
41218eb6488eSEric Joyner 		}
4122758cc3dcSJack F Vogel 		speed |= IXGBE_LINK_SPEED_1GB_FULL;
41238eb6488eSEric Joyner 	}
41248eb6488eSEric Joyner 	if (advertise & 0x4) {
41258eb6488eSEric Joyner 		if (!(link_caps & IXGBE_LINK_SPEED_10GB_FULL)) {
41268eb6488eSEric Joyner 			device_printf(dev, "Interface does not support 10Gb advertised speed\n");
41278eb6488eSEric Joyner 			return (EINVAL);
41288eb6488eSEric Joyner 		}
4129758cc3dcSJack F Vogel 		speed |= IXGBE_LINK_SPEED_10GB_FULL;
41308eb6488eSEric Joyner 	}
41318eb6488eSEric Joyner 	if (advertise & 0x8) {
41328eb6488eSEric Joyner 		if (!(link_caps & IXGBE_LINK_SPEED_10_FULL)) {
41338eb6488eSEric Joyner 			device_printf(dev, "Interface does not support 10Mb advertised speed\n");
41348eb6488eSEric Joyner 			return (EINVAL);
41358eb6488eSEric Joyner 		}
41368eb6488eSEric Joyner 		speed |= IXGBE_LINK_SPEED_10_FULL;
41378eb6488eSEric Joyner 	}
4138758cc3dcSJack F Vogel 
4139758cc3dcSJack F Vogel 	hw->mac.autotry_restart = TRUE;
4140758cc3dcSJack F Vogel 	hw->mac.ops.setup_link(hw, speed, TRUE);
41418eb6488eSEric Joyner 	adapter->advertise = advertise;
4142758cc3dcSJack F Vogel 
4143f2c4db54SSteven Hartland 	return (0);
41448eb6488eSEric Joyner } /* ixgbe_set_advertise */
41458eb6488eSEric Joyner 
41468eb6488eSEric Joyner /************************************************************************
41478eb6488eSEric Joyner  * ixgbe_get_advertise - Get current advertised speed settings
41488eb6488eSEric Joyner  *
41498eb6488eSEric Joyner  *   Formatted for sysctl usage.
41508eb6488eSEric Joyner  *   Flags:
41518eb6488eSEric Joyner  *     0x1 - advertise 100 Mb
41528eb6488eSEric Joyner  *     0x2 - advertise 1G
41538eb6488eSEric Joyner  *     0x4 - advertise 10G
41548eb6488eSEric Joyner  *     0x8 - advertise 10 Mb (yes, Mb)
41558eb6488eSEric Joyner  ************************************************************************/
41568eb6488eSEric Joyner static int
41578eb6488eSEric Joyner ixgbe_get_advertise(struct adapter *adapter)
41588eb6488eSEric Joyner {
41598eb6488eSEric Joyner 	struct ixgbe_hw  *hw = &adapter->hw;
41608eb6488eSEric Joyner 	int              speed;
41618eb6488eSEric Joyner 	ixgbe_link_speed link_caps = 0;
41628eb6488eSEric Joyner 	s32              err;
41638eb6488eSEric Joyner 	bool             negotiate = FALSE;
4164758cc3dcSJack F Vogel 
4165758cc3dcSJack F Vogel 	/*
41668eb6488eSEric Joyner 	 * Advertised speed means nothing unless it's copper or
41678eb6488eSEric Joyner 	 * multi-speed fiber
4168758cc3dcSJack F Vogel 	 */
41698eb6488eSEric Joyner 	if (!(hw->phy.media_type == ixgbe_media_type_copper) &&
41708eb6488eSEric Joyner 	    !(hw->phy.multispeed_fiber))
4171758cc3dcSJack F Vogel 		return (0);
4172758cc3dcSJack F Vogel 
41738eb6488eSEric Joyner 	err = hw->mac.ops.get_link_capabilities(hw, &link_caps, &negotiate);
41748eb6488eSEric Joyner 	if (err != IXGBE_SUCCESS)
41758eb6488eSEric Joyner 		return (0);
41768eb6488eSEric Joyner 
41778eb6488eSEric Joyner 	speed =
41788eb6488eSEric Joyner 	    ((link_caps & IXGBE_LINK_SPEED_10GB_FULL) ? 4 : 0) |
41798eb6488eSEric Joyner 	    ((link_caps & IXGBE_LINK_SPEED_1GB_FULL)  ? 2 : 0) |
41808eb6488eSEric Joyner 	    ((link_caps & IXGBE_LINK_SPEED_100_FULL)  ? 1 : 0) |
41818eb6488eSEric Joyner 	    ((link_caps & IXGBE_LINK_SPEED_10_FULL)   ? 8 : 0);
41828eb6488eSEric Joyner 
41838eb6488eSEric Joyner 	return speed;
41848eb6488eSEric Joyner } /* ixgbe_get_advertise */
41858eb6488eSEric Joyner 
41868eb6488eSEric Joyner /************************************************************************
41878eb6488eSEric Joyner  * ixgbe_sysctl_dmac - Manage DMA Coalescing
41888eb6488eSEric Joyner  *
41898eb6488eSEric Joyner  *   Control values:
41908eb6488eSEric Joyner  *     0/1 - off / on (use default value of 1000)
41918eb6488eSEric Joyner  *
41928eb6488eSEric Joyner  *     Legal timer values are:
41938eb6488eSEric Joyner  *     50,100,250,500,1000,2000,5000,10000
41948eb6488eSEric Joyner  *
41958eb6488eSEric Joyner  *     Turning off interrupt moderation will also turn this off.
41968eb6488eSEric Joyner  ************************************************************************/
41976f37f232SEric Joyner static int
41986f37f232SEric Joyner ixgbe_sysctl_dmac(SYSCTL_HANDLER_ARGS)
41996f37f232SEric Joyner {
42006f37f232SEric Joyner 	struct adapter *adapter = (struct adapter *)arg1;
42016f37f232SEric Joyner 	struct ifnet   *ifp = adapter->ifp;
42026f37f232SEric Joyner 	int            error;
4203a9ca1c79SSean Bruno 	u32            newval;
42046f37f232SEric Joyner 
4205a9ca1c79SSean Bruno 	newval = adapter->dmac;
4206a9ca1c79SSean Bruno 	error = sysctl_handle_int(oidp, &newval, 0, req);
42076f37f232SEric Joyner 	if ((error) || (req->newptr == NULL))
42086f37f232SEric Joyner 		return (error);
42096f37f232SEric Joyner 
4210a9ca1c79SSean Bruno 	switch (newval) {
42116f37f232SEric Joyner 	case 0:
42126f37f232SEric Joyner 		/* Disabled */
4213a9ca1c79SSean Bruno 		adapter->dmac = 0;
42146f37f232SEric Joyner 		break;
4215a9ca1c79SSean Bruno 	case 1:
4216a9ca1c79SSean Bruno 		/* Enable and use default */
42176f37f232SEric Joyner 		adapter->dmac = 1000;
42186f37f232SEric Joyner 		break;
42196f37f232SEric Joyner 	case 50:
42206f37f232SEric Joyner 	case 100:
42216f37f232SEric Joyner 	case 250:
42226f37f232SEric Joyner 	case 500:
42236f37f232SEric Joyner 	case 1000:
42246f37f232SEric Joyner 	case 2000:
42256f37f232SEric Joyner 	case 5000:
42266f37f232SEric Joyner 	case 10000:
42276f37f232SEric Joyner 		/* Legal values - allow */
4228a9ca1c79SSean Bruno 		adapter->dmac = newval;
42296f37f232SEric Joyner 		break;
42306f37f232SEric Joyner 	default:
42316f37f232SEric Joyner 		/* Do nothing, illegal value */
42326f37f232SEric Joyner 		return (EINVAL);
42336f37f232SEric Joyner 	}
42346f37f232SEric Joyner 
42356f37f232SEric Joyner 	/* Re-initialize hardware if it's already running */
42366f37f232SEric Joyner 	if (ifp->if_drv_flags & IFF_DRV_RUNNING)
42376f37f232SEric Joyner 		ixgbe_init(adapter);
42386f37f232SEric Joyner 
42396f37f232SEric Joyner 	return (0);
42408eb6488eSEric Joyner } /* ixgbe_sysctl_dmac */
42416f37f232SEric Joyner 
4242a9ca1c79SSean Bruno #ifdef IXGBE_DEBUG
42438eb6488eSEric Joyner /************************************************************************
42448eb6488eSEric Joyner  * ixgbe_sysctl_power_state
42458eb6488eSEric Joyner  *
4246a9ca1c79SSean Bruno  *   Sysctl to test power states
4247a9ca1c79SSean Bruno  *   Values:
4248a9ca1c79SSean Bruno  *     0      - set device to D0
4249a9ca1c79SSean Bruno  *     3      - set device to D3
4250a9ca1c79SSean Bruno  *     (none) - get current device power state
42518eb6488eSEric Joyner  ************************************************************************/
4252a9ca1c79SSean Bruno static int
4253a9ca1c79SSean Bruno ixgbe_sysctl_power_state(SYSCTL_HANDLER_ARGS)
4254a9ca1c79SSean Bruno {
4255a9ca1c79SSean Bruno 	struct adapter *adapter = (struct adapter *)arg1;
4256a9ca1c79SSean Bruno 	device_t       dev = adapter->dev;
4257a9ca1c79SSean Bruno 	int            curr_ps, new_ps, error = 0;
4258a9ca1c79SSean Bruno 
4259a9ca1c79SSean Bruno 	curr_ps = new_ps = pci_get_powerstate(dev);
4260a9ca1c79SSean Bruno 
4261a9ca1c79SSean Bruno 	error = sysctl_handle_int(oidp, &new_ps, 0, req);
4262a9ca1c79SSean Bruno 	if ((error) || (req->newptr == NULL))
4263a9ca1c79SSean Bruno 		return (error);
4264a9ca1c79SSean Bruno 
4265a9ca1c79SSean Bruno 	if (new_ps == curr_ps)
4266a9ca1c79SSean Bruno 		return (0);
4267a9ca1c79SSean Bruno 
4268a9ca1c79SSean Bruno 	if (new_ps == 3 && curr_ps == 0)
4269a9ca1c79SSean Bruno 		error = DEVICE_SUSPEND(dev);
4270a9ca1c79SSean Bruno 	else if (new_ps == 0 && curr_ps == 3)
4271a9ca1c79SSean Bruno 		error = DEVICE_RESUME(dev);
4272a9ca1c79SSean Bruno 	else
4273a9ca1c79SSean Bruno 		return (EINVAL);
4274a9ca1c79SSean Bruno 
4275a9ca1c79SSean Bruno 	device_printf(dev, "New state: %d\n", pci_get_powerstate(dev));
4276a9ca1c79SSean Bruno 
4277a9ca1c79SSean Bruno 	return (error);
42788eb6488eSEric Joyner } /* ixgbe_sysctl_power_state */
4279a9ca1c79SSean Bruno #endif
42808eb6488eSEric Joyner 
42818eb6488eSEric Joyner /************************************************************************
42828eb6488eSEric Joyner  * ixgbe_sysctl_wol_enable
42838eb6488eSEric Joyner  *
42848eb6488eSEric Joyner  *   Sysctl to enable/disable the WoL capability,
42858eb6488eSEric Joyner  *   if supported by the adapter.
42868eb6488eSEric Joyner  *
42876f37f232SEric Joyner  *   Values:
42886f37f232SEric Joyner  *     0 - disabled
42896f37f232SEric Joyner  *     1 - enabled
42908eb6488eSEric Joyner  ************************************************************************/
42916f37f232SEric Joyner static int
42926f37f232SEric Joyner ixgbe_sysctl_wol_enable(SYSCTL_HANDLER_ARGS)
42936f37f232SEric Joyner {
42946f37f232SEric Joyner 	struct adapter  *adapter = (struct adapter *)arg1;
42956f37f232SEric Joyner 	struct ixgbe_hw *hw = &adapter->hw;
42966f37f232SEric Joyner 	int             new_wol_enabled;
42976f37f232SEric Joyner 	int             error = 0;
42986f37f232SEric Joyner 
42996f37f232SEric Joyner 	new_wol_enabled = hw->wol_enabled;
43006f37f232SEric Joyner 	error = sysctl_handle_int(oidp, &new_wol_enabled, 0, req);
43016f37f232SEric Joyner 	if ((error) || (req->newptr == NULL))
43026f37f232SEric Joyner 		return (error);
4303a9ca1c79SSean Bruno 	new_wol_enabled = !!(new_wol_enabled);
43046f37f232SEric Joyner 	if (new_wol_enabled == hw->wol_enabled)
43056f37f232SEric Joyner 		return (0);
43066f37f232SEric Joyner 
43076f37f232SEric Joyner 	if (new_wol_enabled > 0 && !adapter->wol_support)
43086f37f232SEric Joyner 		return (ENODEV);
43096f37f232SEric Joyner 	else
4310a9ca1c79SSean Bruno 		hw->wol_enabled = new_wol_enabled;
43116f37f232SEric Joyner 
43126f37f232SEric Joyner 	return (0);
43138eb6488eSEric Joyner } /* ixgbe_sysctl_wol_enable */
43146f37f232SEric Joyner 
43158eb6488eSEric Joyner /************************************************************************
43168eb6488eSEric Joyner  * ixgbe_sysctl_wufc - Wake Up Filter Control
43178eb6488eSEric Joyner  *
43186f37f232SEric Joyner  *   Sysctl to enable/disable the types of packets that the
43196f37f232SEric Joyner  *   adapter will wake up on upon receipt.
43206f37f232SEric Joyner  *   Flags:
43216f37f232SEric Joyner  *     0x1  - Link Status Change
43226f37f232SEric Joyner  *     0x2  - Magic Packet
43236f37f232SEric Joyner  *     0x4  - Direct Exact
43246f37f232SEric Joyner  *     0x8  - Directed Multicast
43256f37f232SEric Joyner  *     0x10 - Broadcast
43266f37f232SEric Joyner  *     0x20 - ARP/IPv4 Request Packet
43276f37f232SEric Joyner  *     0x40 - Direct IPv4 Packet
43286f37f232SEric Joyner  *     0x80 - Direct IPv6 Packet
43296f37f232SEric Joyner  *
43308eb6488eSEric Joyner  *   Settings not listed above will cause the sysctl to return an error.
43318eb6488eSEric Joyner  ************************************************************************/
43326f37f232SEric Joyner static int
43336f37f232SEric Joyner ixgbe_sysctl_wufc(SYSCTL_HANDLER_ARGS)
43346f37f232SEric Joyner {
43356f37f232SEric Joyner 	struct adapter *adapter = (struct adapter *)arg1;
43366f37f232SEric Joyner 	int            error = 0;
43376f37f232SEric Joyner 	u32            new_wufc;
43386f37f232SEric Joyner 
43396f37f232SEric Joyner 	new_wufc = adapter->wufc;
43406f37f232SEric Joyner 
43416f37f232SEric Joyner 	error = sysctl_handle_int(oidp, &new_wufc, 0, req);
43426f37f232SEric Joyner 	if ((error) || (req->newptr == NULL))
43436f37f232SEric Joyner 		return (error);
43446f37f232SEric Joyner 	if (new_wufc == adapter->wufc)
43456f37f232SEric Joyner 		return (0);
43466f37f232SEric Joyner 
43476f37f232SEric Joyner 	if (new_wufc & 0xffffff00)
43486f37f232SEric Joyner 		return (EINVAL);
43498eb6488eSEric Joyner 
43506f37f232SEric Joyner 	new_wufc &= 0xff;
43516f37f232SEric Joyner 	new_wufc |= (0xffffff & adapter->wufc);
43526f37f232SEric Joyner 	adapter->wufc = new_wufc;
43536f37f232SEric Joyner 
43546f37f232SEric Joyner 	return (0);
43558eb6488eSEric Joyner } /* ixgbe_sysctl_wufc */
43566f37f232SEric Joyner 
4357a9ca1c79SSean Bruno #ifdef IXGBE_DEBUG
43588eb6488eSEric Joyner /************************************************************************
43598eb6488eSEric Joyner  * ixgbe_sysctl_print_rss_config
43608eb6488eSEric Joyner  ************************************************************************/
4361a9ca1c79SSean Bruno static int
4362a9ca1c79SSean Bruno ixgbe_sysctl_print_rss_config(SYSCTL_HANDLER_ARGS)
4363a9ca1c79SSean Bruno {
4364a9ca1c79SSean Bruno 	struct adapter  *adapter = (struct adapter *)arg1;
4365a9ca1c79SSean Bruno 	struct ixgbe_hw *hw = &adapter->hw;
4366a9ca1c79SSean Bruno 	device_t        dev = adapter->dev;
4367a9ca1c79SSean Bruno 	struct sbuf     *buf;
43688eb6488eSEric Joyner 	int             error = 0, reta_size;
4369a9ca1c79SSean Bruno 	u32             reg;
4370a9ca1c79SSean Bruno 
4371a9ca1c79SSean Bruno 	buf = sbuf_new_for_sysctl(NULL, NULL, 128, req);
4372a9ca1c79SSean Bruno 	if (!buf) {
4373a9ca1c79SSean Bruno 		device_printf(dev, "Could not allocate sbuf for output.\n");
4374a9ca1c79SSean Bruno 		return (ENOMEM);
4375a9ca1c79SSean Bruno 	}
4376a9ca1c79SSean Bruno 
4377a9ca1c79SSean Bruno 	// TODO: use sbufs to make a string to print out
4378a9ca1c79SSean Bruno 	/* Set multiplier for RETA setup and table size based on MAC */
4379a9ca1c79SSean Bruno 	switch (adapter->hw.mac.type) {
4380a9ca1c79SSean Bruno 	case ixgbe_mac_X550:
4381a9ca1c79SSean Bruno 	case ixgbe_mac_X550EM_x:
43828eb6488eSEric Joyner 	case ixgbe_mac_X550EM_a:
4383a9ca1c79SSean Bruno 		reta_size = 128;
4384a9ca1c79SSean Bruno 		break;
4385a9ca1c79SSean Bruno 	default:
4386a9ca1c79SSean Bruno 		reta_size = 32;
4387a9ca1c79SSean Bruno 		break;
4388a9ca1c79SSean Bruno 	}
4389a9ca1c79SSean Bruno 
4390a9ca1c79SSean Bruno 	/* Print out the redirection table */
4391a9ca1c79SSean Bruno 	sbuf_cat(buf, "\n");
4392a9ca1c79SSean Bruno 	for (int i = 0; i < reta_size; i++) {
4393a9ca1c79SSean Bruno 		if (i < 32) {
4394a9ca1c79SSean Bruno 			reg = IXGBE_READ_REG(hw, IXGBE_RETA(i));
4395a9ca1c79SSean Bruno 			sbuf_printf(buf, "RETA(%2d): 0x%08x\n", i, reg);
4396a9ca1c79SSean Bruno 		} else {
4397a9ca1c79SSean Bruno 			reg = IXGBE_READ_REG(hw, IXGBE_ERETA(i - 32));
4398a9ca1c79SSean Bruno 			sbuf_printf(buf, "ERETA(%2d): 0x%08x\n", i - 32, reg);
4399a9ca1c79SSean Bruno 		}
4400a9ca1c79SSean Bruno 	}
4401a9ca1c79SSean Bruno 
4402a9ca1c79SSean Bruno 	// TODO: print more config
4403a9ca1c79SSean Bruno 
4404a9ca1c79SSean Bruno 	error = sbuf_finish(buf);
4405a9ca1c79SSean Bruno 	if (error)
4406a9ca1c79SSean Bruno 		device_printf(dev, "Error finishing sbuf: %d\n", error);
4407a9ca1c79SSean Bruno 
4408a9ca1c79SSean Bruno 	sbuf_delete(buf);
44098eb6488eSEric Joyner 
4410a9ca1c79SSean Bruno 	return (0);
44118eb6488eSEric Joyner } /* ixgbe_sysctl_print_rss_config */
4412a9ca1c79SSean Bruno #endif /* IXGBE_DEBUG */
4413a9ca1c79SSean Bruno 
44148eb6488eSEric Joyner /************************************************************************
44158eb6488eSEric Joyner  * ixgbe_sysctl_phy_temp - Retrieve temperature of PHY
44168eb6488eSEric Joyner  *
44178eb6488eSEric Joyner  *   For X552/X557-AT devices using an external PHY
44188eb6488eSEric Joyner  ************************************************************************/
44198eb6488eSEric Joyner static int
44208eb6488eSEric Joyner ixgbe_sysctl_phy_temp(SYSCTL_HANDLER_ARGS)
44218eb6488eSEric Joyner {
44228eb6488eSEric Joyner 	struct adapter  *adapter = (struct adapter *)arg1;
44238eb6488eSEric Joyner 	struct ixgbe_hw *hw = &adapter->hw;
44248eb6488eSEric Joyner 	u16             reg;
44258eb6488eSEric Joyner 
44268eb6488eSEric Joyner 	if (hw->device_id != IXGBE_DEV_ID_X550EM_X_10G_T) {
44278eb6488eSEric Joyner 		device_printf(adapter->dev,
44288eb6488eSEric Joyner 		    "Device has no supported external thermal sensor.\n");
44298eb6488eSEric Joyner 		return (ENODEV);
44308eb6488eSEric Joyner 	}
44318eb6488eSEric Joyner 
44328eb6488eSEric Joyner 	if (hw->phy.ops.read_reg(hw, IXGBE_PHY_CURRENT_TEMP,
44338eb6488eSEric Joyner 	    IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE, &reg)) {
44348eb6488eSEric Joyner 		device_printf(adapter->dev,
44358eb6488eSEric Joyner 		    "Error reading from PHY's current temperature register\n");
44368eb6488eSEric Joyner 		return (EAGAIN);
44378eb6488eSEric Joyner 	}
44388eb6488eSEric Joyner 
44398eb6488eSEric Joyner 	/* Shift temp for output */
44408eb6488eSEric Joyner 	reg = reg >> 8;
44418eb6488eSEric Joyner 
44428eb6488eSEric Joyner 	return (sysctl_handle_int(oidp, NULL, reg, req));
44438eb6488eSEric Joyner } /* ixgbe_sysctl_phy_temp */
44448eb6488eSEric Joyner 
44458eb6488eSEric Joyner /************************************************************************
44468eb6488eSEric Joyner  * ixgbe_sysctl_phy_overtemp_occurred
44478eb6488eSEric Joyner  *
44488eb6488eSEric Joyner  *   Reports (directly from the PHY) whether the current PHY
44498eb6488eSEric Joyner  *   temperature is over the overtemp threshold.
44508eb6488eSEric Joyner  ************************************************************************/
44518eb6488eSEric Joyner static int
44528eb6488eSEric Joyner ixgbe_sysctl_phy_overtemp_occurred(SYSCTL_HANDLER_ARGS)
44538eb6488eSEric Joyner {
44548eb6488eSEric Joyner 	struct adapter  *adapter = (struct adapter *)arg1;
44558eb6488eSEric Joyner 	struct ixgbe_hw *hw = &adapter->hw;
44568eb6488eSEric Joyner 	u16             reg;
44578eb6488eSEric Joyner 
44588eb6488eSEric Joyner 	if (hw->device_id != IXGBE_DEV_ID_X550EM_X_10G_T) {
44598eb6488eSEric Joyner 		device_printf(adapter->dev,
44608eb6488eSEric Joyner 		    "Device has no supported external thermal sensor.\n");
44618eb6488eSEric Joyner 		return (ENODEV);
44628eb6488eSEric Joyner 	}
44638eb6488eSEric Joyner 
44648eb6488eSEric Joyner 	if (hw->phy.ops.read_reg(hw, IXGBE_PHY_OVERTEMP_STATUS,
44658eb6488eSEric Joyner 	    IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE, &reg)) {
44668eb6488eSEric Joyner 		device_printf(adapter->dev,
44678eb6488eSEric Joyner 		    "Error reading from PHY's temperature status register\n");
44688eb6488eSEric Joyner 		return (EAGAIN);
44698eb6488eSEric Joyner 	}
44708eb6488eSEric Joyner 
44718eb6488eSEric Joyner 	/* Get occurrence bit */
44728eb6488eSEric Joyner 	reg = !!(reg & 0x4000);
44738eb6488eSEric Joyner 
44748eb6488eSEric Joyner 	return (sysctl_handle_int(oidp, 0, reg, req));
44758eb6488eSEric Joyner } /* ixgbe_sysctl_phy_overtemp_occurred */
44768eb6488eSEric Joyner 
44778eb6488eSEric Joyner /************************************************************************
44788eb6488eSEric Joyner  * ixgbe_sysctl_eee_state
44798eb6488eSEric Joyner  *
44808eb6488eSEric Joyner  *   Sysctl to set EEE power saving feature
44818eb6488eSEric Joyner  *   Values:
44828eb6488eSEric Joyner  *     0      - disable EEE
44838eb6488eSEric Joyner  *     1      - enable EEE
44848eb6488eSEric Joyner  *     (none) - get current device EEE state
44858eb6488eSEric Joyner  ************************************************************************/
44868eb6488eSEric Joyner static int
44878eb6488eSEric Joyner ixgbe_sysctl_eee_state(SYSCTL_HANDLER_ARGS)
44888eb6488eSEric Joyner {
44898eb6488eSEric Joyner 	struct adapter *adapter = (struct adapter *)arg1;
44908eb6488eSEric Joyner 	device_t       dev = adapter->dev;
44918eb6488eSEric Joyner 	int            curr_eee, new_eee, error = 0;
44928eb6488eSEric Joyner 	s32            retval;
44938eb6488eSEric Joyner 
44948eb6488eSEric Joyner 	curr_eee = new_eee = !!(adapter->feat_en & IXGBE_FEATURE_EEE);
44958eb6488eSEric Joyner 
44968eb6488eSEric Joyner 	error = sysctl_handle_int(oidp, &new_eee, 0, req);
44978eb6488eSEric Joyner 	if ((error) || (req->newptr == NULL))
44988eb6488eSEric Joyner 		return (error);
44998eb6488eSEric Joyner 
45008eb6488eSEric Joyner 	/* Nothing to do */
45018eb6488eSEric Joyner 	if (new_eee == curr_eee)
45028eb6488eSEric Joyner 		return (0);
45038eb6488eSEric Joyner 
45048eb6488eSEric Joyner 	/* Not supported */
45058eb6488eSEric Joyner 	if (!(adapter->feat_cap & IXGBE_FEATURE_EEE))
45068eb6488eSEric Joyner 		return (EINVAL);
45078eb6488eSEric Joyner 
45088eb6488eSEric Joyner 	/* Bounds checking */
45098eb6488eSEric Joyner 	if ((new_eee < 0) || (new_eee > 1))
45108eb6488eSEric Joyner 		return (EINVAL);
45118eb6488eSEric Joyner 
45128eb6488eSEric Joyner 	retval = adapter->hw.mac.ops.setup_eee(&adapter->hw, new_eee);
45138eb6488eSEric Joyner 	if (retval) {
45148eb6488eSEric Joyner 		device_printf(dev, "Error in EEE setup: 0x%08X\n", retval);
45158eb6488eSEric Joyner 		return (EINVAL);
45168eb6488eSEric Joyner 	}
45178eb6488eSEric Joyner 
45188eb6488eSEric Joyner 	/* Restart auto-neg */
45198eb6488eSEric Joyner 	ixgbe_init(adapter);
45208eb6488eSEric Joyner 
45218eb6488eSEric Joyner 	device_printf(dev, "New EEE state: %d\n", new_eee);
45228eb6488eSEric Joyner 
45238eb6488eSEric Joyner 	/* Cache new value */
45248eb6488eSEric Joyner 	if (new_eee)
45258eb6488eSEric Joyner 		adapter->feat_en |= IXGBE_FEATURE_EEE;
45268eb6488eSEric Joyner 	else
45278eb6488eSEric Joyner 		adapter->feat_en &= ~IXGBE_FEATURE_EEE;
45288eb6488eSEric Joyner 
45298eb6488eSEric Joyner 	return (error);
45308eb6488eSEric Joyner } /* ixgbe_sysctl_eee_state */
45318eb6488eSEric Joyner 
45328eb6488eSEric Joyner /************************************************************************
45338eb6488eSEric Joyner  * ixgbe_init_device_features
45348eb6488eSEric Joyner  ************************************************************************/
45358eb6488eSEric Joyner static void
45368eb6488eSEric Joyner ixgbe_init_device_features(struct adapter *adapter)
45378eb6488eSEric Joyner {
45388eb6488eSEric Joyner 	adapter->feat_cap = IXGBE_FEATURE_NETMAP
45398eb6488eSEric Joyner 	                  | IXGBE_FEATURE_RSS
45408eb6488eSEric Joyner 	                  | IXGBE_FEATURE_MSI
45418eb6488eSEric Joyner 	                  | IXGBE_FEATURE_MSIX
45428eb6488eSEric Joyner 	                  | IXGBE_FEATURE_LEGACY_IRQ
45438eb6488eSEric Joyner 	                  | IXGBE_FEATURE_LEGACY_TX;
45448eb6488eSEric Joyner 
45458eb6488eSEric Joyner 	/* Set capabilities first... */
45468eb6488eSEric Joyner 	switch (adapter->hw.mac.type) {
45478eb6488eSEric Joyner 	case ixgbe_mac_82598EB:
45488eb6488eSEric Joyner 		if (adapter->hw.device_id == IXGBE_DEV_ID_82598AT)
45498eb6488eSEric Joyner 			adapter->feat_cap |= IXGBE_FEATURE_FAN_FAIL;
45508eb6488eSEric Joyner 		break;
45518eb6488eSEric Joyner 	case ixgbe_mac_X540:
45528eb6488eSEric Joyner 		adapter->feat_cap |= IXGBE_FEATURE_SRIOV;
45538eb6488eSEric Joyner 		adapter->feat_cap |= IXGBE_FEATURE_FDIR;
45548eb6488eSEric Joyner 		if ((adapter->hw.device_id == IXGBE_DEV_ID_X540_BYPASS) &&
45558eb6488eSEric Joyner 		    (adapter->hw.bus.func == 0))
45568eb6488eSEric Joyner 			adapter->feat_cap |= IXGBE_FEATURE_BYPASS;
45578eb6488eSEric Joyner 		break;
45588eb6488eSEric Joyner 	case ixgbe_mac_X550:
45598eb6488eSEric Joyner 		adapter->feat_cap |= IXGBE_FEATURE_TEMP_SENSOR;
45608eb6488eSEric Joyner 		adapter->feat_cap |= IXGBE_FEATURE_SRIOV;
45618eb6488eSEric Joyner 		adapter->feat_cap |= IXGBE_FEATURE_FDIR;
45628eb6488eSEric Joyner 		break;
45638eb6488eSEric Joyner 	case ixgbe_mac_X550EM_x:
45648eb6488eSEric Joyner 		adapter->feat_cap |= IXGBE_FEATURE_SRIOV;
45658eb6488eSEric Joyner 		adapter->feat_cap |= IXGBE_FEATURE_FDIR;
45668eb6488eSEric Joyner 		if (adapter->hw.device_id == IXGBE_DEV_ID_X550EM_X_KR)
45678eb6488eSEric Joyner 			adapter->feat_cap |= IXGBE_FEATURE_EEE;
45688eb6488eSEric Joyner 		break;
45698eb6488eSEric Joyner 	case ixgbe_mac_X550EM_a:
45708eb6488eSEric Joyner 		adapter->feat_cap |= IXGBE_FEATURE_SRIOV;
45718eb6488eSEric Joyner 		adapter->feat_cap |= IXGBE_FEATURE_FDIR;
45728eb6488eSEric Joyner 		adapter->feat_cap &= ~IXGBE_FEATURE_LEGACY_IRQ;
45738eb6488eSEric Joyner 		if ((adapter->hw.device_id == IXGBE_DEV_ID_X550EM_A_1G_T) ||
45748eb6488eSEric Joyner 		    (adapter->hw.device_id == IXGBE_DEV_ID_X550EM_A_1G_T_L)) {
45758eb6488eSEric Joyner 			adapter->feat_cap |= IXGBE_FEATURE_TEMP_SENSOR;
45768eb6488eSEric Joyner 			adapter->feat_cap |= IXGBE_FEATURE_EEE;
45778eb6488eSEric Joyner 		}
45788eb6488eSEric Joyner 		break;
45798eb6488eSEric Joyner 	case ixgbe_mac_82599EB:
45808eb6488eSEric Joyner 		adapter->feat_cap |= IXGBE_FEATURE_SRIOV;
45818eb6488eSEric Joyner 		adapter->feat_cap |= IXGBE_FEATURE_FDIR;
45828eb6488eSEric Joyner 		if ((adapter->hw.device_id == IXGBE_DEV_ID_82599_BYPASS) &&
45838eb6488eSEric Joyner 		    (adapter->hw.bus.func == 0))
45848eb6488eSEric Joyner 			adapter->feat_cap |= IXGBE_FEATURE_BYPASS;
45858eb6488eSEric Joyner 		if (adapter->hw.device_id == IXGBE_DEV_ID_82599_QSFP_SF_QP)
45868eb6488eSEric Joyner 			adapter->feat_cap &= ~IXGBE_FEATURE_LEGACY_IRQ;
45878eb6488eSEric Joyner 		break;
45888eb6488eSEric Joyner 	default:
45898eb6488eSEric Joyner 		break;
45908eb6488eSEric Joyner 	}
45918eb6488eSEric Joyner 
45928eb6488eSEric Joyner 	/* Enabled by default... */
45938eb6488eSEric Joyner 	/* Fan failure detection */
45948eb6488eSEric Joyner 	if (adapter->feat_cap & IXGBE_FEATURE_FAN_FAIL)
45958eb6488eSEric Joyner 		adapter->feat_en |= IXGBE_FEATURE_FAN_FAIL;
45968eb6488eSEric Joyner 	/* Netmap */
45978eb6488eSEric Joyner 	if (adapter->feat_cap & IXGBE_FEATURE_NETMAP)
45988eb6488eSEric Joyner 		adapter->feat_en |= IXGBE_FEATURE_NETMAP;
45998eb6488eSEric Joyner 	/* EEE */
46008eb6488eSEric Joyner 	if (adapter->feat_cap & IXGBE_FEATURE_EEE)
46018eb6488eSEric Joyner 		adapter->feat_en |= IXGBE_FEATURE_EEE;
46028eb6488eSEric Joyner 	/* Thermal Sensor */
46038eb6488eSEric Joyner 	if (adapter->feat_cap & IXGBE_FEATURE_TEMP_SENSOR)
46048eb6488eSEric Joyner 		adapter->feat_en |= IXGBE_FEATURE_TEMP_SENSOR;
46058eb6488eSEric Joyner 
46068eb6488eSEric Joyner 	/* Enabled via global sysctl... */
46078eb6488eSEric Joyner 	/* Flow Director */
46088eb6488eSEric Joyner 	if (ixgbe_enable_fdir) {
46098eb6488eSEric Joyner 		if (adapter->feat_cap & IXGBE_FEATURE_FDIR)
46108eb6488eSEric Joyner 			adapter->feat_en |= IXGBE_FEATURE_FDIR;
46118eb6488eSEric Joyner 		else
46128eb6488eSEric Joyner 			device_printf(adapter->dev, "Device does not support Flow Director. Leaving disabled.");
46138eb6488eSEric Joyner 	}
46148eb6488eSEric Joyner 	/* Legacy (single queue) transmit */
46158eb6488eSEric Joyner 	if ((adapter->feat_cap & IXGBE_FEATURE_LEGACY_TX) &&
46168eb6488eSEric Joyner 	    ixgbe_enable_legacy_tx)
46178eb6488eSEric Joyner 		adapter->feat_en |= IXGBE_FEATURE_LEGACY_TX;
46186f37f232SEric Joyner 	/*
46198eb6488eSEric Joyner 	 * Message Signal Interrupts - Extended (MSI-X)
46208eb6488eSEric Joyner 	 * Normal MSI is only enabled if MSI-X calls fail.
4621758cc3dcSJack F Vogel 	 */
46228eb6488eSEric Joyner 	if (!ixgbe_enable_msix)
46238eb6488eSEric Joyner 		adapter->feat_cap &= ~IXGBE_FEATURE_MSIX;
46248eb6488eSEric Joyner 	/* Receive-Side Scaling (RSS) */
46258eb6488eSEric Joyner 	if ((adapter->feat_cap & IXGBE_FEATURE_RSS) && ixgbe_enable_rss)
46268eb6488eSEric Joyner 		adapter->feat_en |= IXGBE_FEATURE_RSS;
46278eb6488eSEric Joyner 
46288eb6488eSEric Joyner 	/* Disable features with unmet dependencies... */
46298eb6488eSEric Joyner 	/* No MSI-X */
46308eb6488eSEric Joyner 	if (!(adapter->feat_cap & IXGBE_FEATURE_MSIX)) {
46318eb6488eSEric Joyner 		adapter->feat_cap &= ~IXGBE_FEATURE_RSS;
46328eb6488eSEric Joyner 		adapter->feat_cap &= ~IXGBE_FEATURE_SRIOV;
46338eb6488eSEric Joyner 		adapter->feat_en &= ~IXGBE_FEATURE_RSS;
46348eb6488eSEric Joyner 		adapter->feat_en &= ~IXGBE_FEATURE_SRIOV;
46358eb6488eSEric Joyner 	}
46368eb6488eSEric Joyner } /* ixgbe_init_device_features */
46378eb6488eSEric Joyner 
46388eb6488eSEric Joyner /************************************************************************
46398eb6488eSEric Joyner  * ixgbe_probe - Device identification routine
46408eb6488eSEric Joyner  *
46418eb6488eSEric Joyner  *   Determines if the driver should be loaded on
46428eb6488eSEric Joyner  *   adapter based on its PCI vendor/device ID.
46438eb6488eSEric Joyner  *
46448eb6488eSEric Joyner  *   return BUS_PROBE_DEFAULT on success, positive on failure
46458eb6488eSEric Joyner  ************************************************************************/
46468eb6488eSEric Joyner static int
46478eb6488eSEric Joyner ixgbe_probe(device_t dev)
46488eb6488eSEric Joyner {
46498eb6488eSEric Joyner 	ixgbe_vendor_info_t *ent;
46508eb6488eSEric Joyner 
46518eb6488eSEric Joyner 	u16  pci_vendor_id = 0;
46528eb6488eSEric Joyner 	u16  pci_device_id = 0;
46538eb6488eSEric Joyner 	u16  pci_subvendor_id = 0;
46548eb6488eSEric Joyner 	u16  pci_subdevice_id = 0;
46558eb6488eSEric Joyner 	char adapter_name[256];
46568eb6488eSEric Joyner 
46578eb6488eSEric Joyner 	INIT_DEBUGOUT("ixgbe_probe: begin");
46588eb6488eSEric Joyner 
46598eb6488eSEric Joyner 	pci_vendor_id = pci_get_vendor(dev);
46608eb6488eSEric Joyner 	if (pci_vendor_id != IXGBE_INTEL_VENDOR_ID)
46618eb6488eSEric Joyner 		return (ENXIO);
46628eb6488eSEric Joyner 
46638eb6488eSEric Joyner 	pci_device_id = pci_get_device(dev);
46648eb6488eSEric Joyner 	pci_subvendor_id = pci_get_subvendor(dev);
46658eb6488eSEric Joyner 	pci_subdevice_id = pci_get_subdevice(dev);
46668eb6488eSEric Joyner 
46678eb6488eSEric Joyner 	ent = ixgbe_vendor_info_array;
46688eb6488eSEric Joyner 	while (ent->vendor_id != 0) {
46698eb6488eSEric Joyner 		if ((pci_vendor_id == ent->vendor_id) &&
46708eb6488eSEric Joyner 		    (pci_device_id == ent->device_id) &&
46718eb6488eSEric Joyner 		    ((pci_subvendor_id == ent->subvendor_id) ||
46728eb6488eSEric Joyner 		     (ent->subvendor_id == 0)) &&
46738eb6488eSEric Joyner 		    ((pci_subdevice_id == ent->subdevice_id) ||
46748eb6488eSEric Joyner 		     (ent->subdevice_id == 0))) {
46758eb6488eSEric Joyner 			sprintf(adapter_name, "%s, Version - %s",
46768eb6488eSEric Joyner 				ixgbe_strings[ent->index],
46778eb6488eSEric Joyner 				ixgbe_driver_version);
46788eb6488eSEric Joyner 			device_set_desc_copy(dev, adapter_name);
46798eb6488eSEric Joyner 			++ixgbe_total_ports;
46808eb6488eSEric Joyner 			return (BUS_PROBE_DEFAULT);
46818eb6488eSEric Joyner 		}
46828eb6488eSEric Joyner 		ent++;
46838eb6488eSEric Joyner 	}
46848eb6488eSEric Joyner 
46858eb6488eSEric Joyner 	return (ENXIO);
46868eb6488eSEric Joyner } /* ixgbe_probe */
46878eb6488eSEric Joyner 
46888eb6488eSEric Joyner 
46898eb6488eSEric Joyner /************************************************************************
46908eb6488eSEric Joyner  * ixgbe_ioctl - Ioctl entry point
46918eb6488eSEric Joyner  *
46928eb6488eSEric Joyner  *   Called when the user wants to configure the interface.
46938eb6488eSEric Joyner  *
46948eb6488eSEric Joyner  *   return 0 on success, positive on failure
46958eb6488eSEric Joyner  ************************************************************************/
46968eb6488eSEric Joyner static int
46978eb6488eSEric Joyner ixgbe_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
46988eb6488eSEric Joyner {
46998eb6488eSEric Joyner 	struct adapter *adapter = ifp->if_softc;
47008eb6488eSEric Joyner 	struct ifreq   *ifr = (struct ifreq *) data;
47018eb6488eSEric Joyner #if defined(INET) || defined(INET6)
47028eb6488eSEric Joyner 	struct ifaddr  *ifa = (struct ifaddr *)data;
47038eb6488eSEric Joyner #endif
47048eb6488eSEric Joyner 	int            error = 0;
47058eb6488eSEric Joyner 	bool           avoid_reset = FALSE;
47068eb6488eSEric Joyner 
47078eb6488eSEric Joyner 	switch (command) {
47088eb6488eSEric Joyner 	case SIOCSIFADDR:
47098eb6488eSEric Joyner #ifdef INET
47108eb6488eSEric Joyner 		if (ifa->ifa_addr->sa_family == AF_INET)
47118eb6488eSEric Joyner 			avoid_reset = TRUE;
47128eb6488eSEric Joyner #endif
47138eb6488eSEric Joyner #ifdef INET6
47148eb6488eSEric Joyner 		if (ifa->ifa_addr->sa_family == AF_INET6)
47158eb6488eSEric Joyner 			avoid_reset = TRUE;
47168eb6488eSEric Joyner #endif
47178eb6488eSEric Joyner 		/*
47188eb6488eSEric Joyner 		 * Calling init results in link renegotiation,
47198eb6488eSEric Joyner 		 * so we avoid doing it when possible.
47208eb6488eSEric Joyner 		 */
47218eb6488eSEric Joyner 		if (avoid_reset) {
47228eb6488eSEric Joyner 			ifp->if_flags |= IFF_UP;
47238eb6488eSEric Joyner 			if (!(ifp->if_drv_flags & IFF_DRV_RUNNING))
47248eb6488eSEric Joyner 				ixgbe_init(adapter);
47258eb6488eSEric Joyner #ifdef INET
47268eb6488eSEric Joyner 			if (!(ifp->if_flags & IFF_NOARP))
47278eb6488eSEric Joyner 				arp_ifinit(ifp, ifa);
47288eb6488eSEric Joyner #endif
47298eb6488eSEric Joyner 		} else
47308eb6488eSEric Joyner 			error = ether_ioctl(ifp, command, data);
47318eb6488eSEric Joyner 		break;
47328eb6488eSEric Joyner 	case SIOCSIFMTU:
47338eb6488eSEric Joyner 		IOCTL_DEBUGOUT("ioctl: SIOCSIFMTU (Set Interface MTU)");
47348eb6488eSEric Joyner 		if (ifr->ifr_mtu > IXGBE_MAX_MTU) {
47358eb6488eSEric Joyner 			error = EINVAL;
47368eb6488eSEric Joyner 		} else {
47378eb6488eSEric Joyner 			IXGBE_CORE_LOCK(adapter);
47388eb6488eSEric Joyner 			ifp->if_mtu = ifr->ifr_mtu;
47398eb6488eSEric Joyner 			adapter->max_frame_size = ifp->if_mtu + IXGBE_MTU_HDR;
47408eb6488eSEric Joyner 			if (ifp->if_drv_flags & IFF_DRV_RUNNING)
47418eb6488eSEric Joyner 				ixgbe_init_locked(adapter);
47428eb6488eSEric Joyner 			ixgbe_recalculate_max_frame(adapter);
47438eb6488eSEric Joyner 			IXGBE_CORE_UNLOCK(adapter);
47448eb6488eSEric Joyner 		}
47458eb6488eSEric Joyner 		break;
47468eb6488eSEric Joyner 	case SIOCSIFFLAGS:
47478eb6488eSEric Joyner 		IOCTL_DEBUGOUT("ioctl: SIOCSIFFLAGS (Set Interface Flags)");
47488eb6488eSEric Joyner 		IXGBE_CORE_LOCK(adapter);
47498eb6488eSEric Joyner 		if (ifp->if_flags & IFF_UP) {
47508eb6488eSEric Joyner 			if ((ifp->if_drv_flags & IFF_DRV_RUNNING)) {
47518eb6488eSEric Joyner 				if ((ifp->if_flags ^ adapter->if_flags) &
47528eb6488eSEric Joyner 				    (IFF_PROMISC | IFF_ALLMULTI)) {
47538eb6488eSEric Joyner 					ixgbe_set_promisc(adapter);
47548eb6488eSEric Joyner 				}
47558eb6488eSEric Joyner 			} else
47568eb6488eSEric Joyner 				ixgbe_init_locked(adapter);
47578eb6488eSEric Joyner 		} else
47588eb6488eSEric Joyner 			if (ifp->if_drv_flags & IFF_DRV_RUNNING)
47598eb6488eSEric Joyner 				ixgbe_stop(adapter);
47608eb6488eSEric Joyner 		adapter->if_flags = ifp->if_flags;
47618eb6488eSEric Joyner 		IXGBE_CORE_UNLOCK(adapter);
47628eb6488eSEric Joyner 		break;
47638eb6488eSEric Joyner 	case SIOCADDMULTI:
47648eb6488eSEric Joyner 	case SIOCDELMULTI:
47658eb6488eSEric Joyner 		IOCTL_DEBUGOUT("ioctl: SIOC(ADD|DEL)MULTI");
47668eb6488eSEric Joyner 		if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
47678eb6488eSEric Joyner 			IXGBE_CORE_LOCK(adapter);
47688eb6488eSEric Joyner 			ixgbe_disable_intr(adapter);
47698eb6488eSEric Joyner 			ixgbe_set_multi(adapter);
47708eb6488eSEric Joyner 			ixgbe_enable_intr(adapter);
47718eb6488eSEric Joyner 			IXGBE_CORE_UNLOCK(adapter);
47728eb6488eSEric Joyner 		}
47738eb6488eSEric Joyner 		break;
47748eb6488eSEric Joyner 	case SIOCSIFMEDIA:
47758eb6488eSEric Joyner 	case SIOCGIFMEDIA:
47768eb6488eSEric Joyner 		IOCTL_DEBUGOUT("ioctl: SIOCxIFMEDIA (Get/Set Interface Media)");
47778eb6488eSEric Joyner 		error = ifmedia_ioctl(ifp, ifr, &adapter->media, command);
47788eb6488eSEric Joyner 		break;
47798eb6488eSEric Joyner 	case SIOCSIFCAP:
47808eb6488eSEric Joyner 	{
47818eb6488eSEric Joyner 		IOCTL_DEBUGOUT("ioctl: SIOCSIFCAP (Set Capabilities)");
47828eb6488eSEric Joyner 
47838eb6488eSEric Joyner 		int mask = ifr->ifr_reqcap ^ ifp->if_capenable;
47848eb6488eSEric Joyner 
47858eb6488eSEric Joyner 		if (!mask)
47868eb6488eSEric Joyner 			break;
47878eb6488eSEric Joyner 
47888eb6488eSEric Joyner 		/* HW cannot turn these on/off separately */
47898eb6488eSEric Joyner 		if (mask & (IFCAP_RXCSUM | IFCAP_RXCSUM_IPV6)) {
47908eb6488eSEric Joyner 			ifp->if_capenable ^= IFCAP_RXCSUM;
47918eb6488eSEric Joyner 			ifp->if_capenable ^= IFCAP_RXCSUM_IPV6;
47928eb6488eSEric Joyner 		}
47938eb6488eSEric Joyner 		if (mask & IFCAP_TXCSUM)
47948eb6488eSEric Joyner 			ifp->if_capenable ^= IFCAP_TXCSUM;
47958eb6488eSEric Joyner 		if (mask & IFCAP_TXCSUM_IPV6)
47968eb6488eSEric Joyner 			ifp->if_capenable ^= IFCAP_TXCSUM_IPV6;
47978eb6488eSEric Joyner 		if (mask & IFCAP_TSO4)
47988eb6488eSEric Joyner 			ifp->if_capenable ^= IFCAP_TSO4;
47998eb6488eSEric Joyner 		if (mask & IFCAP_TSO6)
48008eb6488eSEric Joyner 			ifp->if_capenable ^= IFCAP_TSO6;
48018eb6488eSEric Joyner 		if (mask & IFCAP_LRO)
48028eb6488eSEric Joyner 			ifp->if_capenable ^= IFCAP_LRO;
48038eb6488eSEric Joyner 		if (mask & IFCAP_VLAN_HWTAGGING)
48048eb6488eSEric Joyner 			ifp->if_capenable ^= IFCAP_VLAN_HWTAGGING;
48058eb6488eSEric Joyner 		if (mask & IFCAP_VLAN_HWFILTER)
48068eb6488eSEric Joyner 			ifp->if_capenable ^= IFCAP_VLAN_HWFILTER;
48078eb6488eSEric Joyner 		if (mask & IFCAP_VLAN_HWTSO)
48088eb6488eSEric Joyner 			ifp->if_capenable ^= IFCAP_VLAN_HWTSO;
48098eb6488eSEric Joyner 
48108eb6488eSEric Joyner 		if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
48118eb6488eSEric Joyner 			IXGBE_CORE_LOCK(adapter);
48128eb6488eSEric Joyner 			ixgbe_init_locked(adapter);
48138eb6488eSEric Joyner 			IXGBE_CORE_UNLOCK(adapter);
48148eb6488eSEric Joyner 		}
48158eb6488eSEric Joyner 		VLAN_CAPABILITIES(ifp);
48168eb6488eSEric Joyner 		break;
48178eb6488eSEric Joyner 	}
48188eb6488eSEric Joyner #if __FreeBSD_version >= 1100036
48198eb6488eSEric Joyner 	case SIOCGI2C:
4820758cc3dcSJack F Vogel 	{
4821758cc3dcSJack F Vogel 		struct ixgbe_hw *hw = &adapter->hw;
48228eb6488eSEric Joyner 		struct ifi2creq i2c;
48238eb6488eSEric Joyner 		int i;
4824758cc3dcSJack F Vogel 
48258eb6488eSEric Joyner 		IOCTL_DEBUGOUT("ioctl: SIOCGI2C (Get I2C Data)");
48268eb6488eSEric Joyner 		error = copyin(ifr->ifr_data, &i2c, sizeof(i2c));
48278eb6488eSEric Joyner 		if (error != 0)
48288eb6488eSEric Joyner 			break;
48298eb6488eSEric Joyner 		if (i2c.dev_addr != 0xA0 && i2c.dev_addr != 0xA2) {
48308eb6488eSEric Joyner 			error = EINVAL;
48318eb6488eSEric Joyner 			break;
4832758cc3dcSJack F Vogel 		}
48338eb6488eSEric Joyner 		if (i2c.len > sizeof(i2c.data)) {
48348eb6488eSEric Joyner 			error = EINVAL;
48358eb6488eSEric Joyner 			break;
483648056c88SJack F Vogel 		}
48378eb6488eSEric Joyner 
48388eb6488eSEric Joyner 		for (i = 0; i < i2c.len; i++)
48398eb6488eSEric Joyner 			hw->phy.ops.read_i2c_byte(hw, i2c.offset + i,
48408eb6488eSEric Joyner 			    i2c.dev_addr, &i2c.data[i]);
48418eb6488eSEric Joyner 		error = copyout(&i2c, ifr->ifr_data, sizeof(i2c));
48428eb6488eSEric Joyner 		break;
48438eb6488eSEric Joyner 	}
48448eb6488eSEric Joyner #endif
48458eb6488eSEric Joyner 	default:
48468eb6488eSEric Joyner 		IOCTL_DEBUGOUT1("ioctl: UNKNOWN (0x%X)\n", (int)command);
48478eb6488eSEric Joyner 		error = ether_ioctl(ifp, command, data);
48488eb6488eSEric Joyner 		break;
48498eb6488eSEric Joyner 	}
48508eb6488eSEric Joyner 
48518eb6488eSEric Joyner 	return (error);
48528eb6488eSEric Joyner } /* ixgbe_ioctl */
48538eb6488eSEric Joyner 
48548eb6488eSEric Joyner /************************************************************************
48558eb6488eSEric Joyner  * ixgbe_check_fan_failure
48568eb6488eSEric Joyner  ************************************************************************/
48578eb6488eSEric Joyner static void
48588eb6488eSEric Joyner ixgbe_check_fan_failure(struct adapter *adapter, u32 reg, bool in_interrupt)
48598eb6488eSEric Joyner {
48608eb6488eSEric Joyner 	u32 mask;
48618eb6488eSEric Joyner 
48628eb6488eSEric Joyner 	mask = (in_interrupt) ? IXGBE_EICR_GPI_SDP1_BY_MAC(&adapter->hw) :
48638eb6488eSEric Joyner 	    IXGBE_ESDP_SDP1;
48648eb6488eSEric Joyner 
48658eb6488eSEric Joyner 	if (reg & mask)
48668eb6488eSEric Joyner 		device_printf(adapter->dev, "\nCRITICAL: FAN FAILURE!! REPLACE IMMEDIATELY!!\n");
48678eb6488eSEric Joyner } /* ixgbe_check_fan_failure */
48688eb6488eSEric Joyner 
48698eb6488eSEric Joyner /************************************************************************
48708eb6488eSEric Joyner  * ixgbe_handle_que
48718eb6488eSEric Joyner  ************************************************************************/
48728eb6488eSEric Joyner static void
48738eb6488eSEric Joyner ixgbe_handle_que(void *context, int pending)
48748eb6488eSEric Joyner {
48758eb6488eSEric Joyner 	struct ix_queue *que = context;
48768eb6488eSEric Joyner 	struct adapter  *adapter = que->adapter;
48778eb6488eSEric Joyner 	struct tx_ring  *txr = que->txr;
48788eb6488eSEric Joyner 	struct ifnet    *ifp = adapter->ifp;
48798eb6488eSEric Joyner 
48808eb6488eSEric Joyner 	if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
48818eb6488eSEric Joyner 		ixgbe_rxeof(que);
48828eb6488eSEric Joyner 		IXGBE_TX_LOCK(txr);
48838eb6488eSEric Joyner 		ixgbe_txeof(txr);
48848eb6488eSEric Joyner 		if (!ixgbe_ring_empty(ifp, txr->br))
48858eb6488eSEric Joyner 			ixgbe_start_locked(ifp, txr);
48868eb6488eSEric Joyner 		IXGBE_TX_UNLOCK(txr);
48878eb6488eSEric Joyner 	}
48888eb6488eSEric Joyner 
48898eb6488eSEric Joyner 	/* Re-enable this interrupt */
48908eb6488eSEric Joyner 	if (que->res != NULL)
48918eb6488eSEric Joyner 		ixgbe_enable_queue(adapter, que->msix);
48928eb6488eSEric Joyner 	else
48938eb6488eSEric Joyner 		ixgbe_enable_intr(adapter);
48948eb6488eSEric Joyner 
48958eb6488eSEric Joyner 	return;
48968eb6488eSEric Joyner } /* ixgbe_handle_que */
48978eb6488eSEric Joyner 
48988eb6488eSEric Joyner 
48998eb6488eSEric Joyner 
49008eb6488eSEric Joyner /************************************************************************
49018eb6488eSEric Joyner  * ixgbe_allocate_legacy - Setup the Legacy or MSI Interrupt handler
49028eb6488eSEric Joyner  ************************************************************************/
49038eb6488eSEric Joyner static int
49048eb6488eSEric Joyner ixgbe_allocate_legacy(struct adapter *adapter)
49058eb6488eSEric Joyner {
49068eb6488eSEric Joyner 	device_t        dev = adapter->dev;
49078eb6488eSEric Joyner 	struct ix_queue *que = adapter->queues;
49088eb6488eSEric Joyner 	struct tx_ring  *txr = adapter->tx_rings;
49098eb6488eSEric Joyner 	int             error;
49108eb6488eSEric Joyner 
49118eb6488eSEric Joyner 	/* We allocate a single interrupt resource */
49128eb6488eSEric Joyner 	adapter->res = bus_alloc_resource_any(dev, SYS_RES_IRQ,
49138eb6488eSEric Joyner 	    &adapter->link_rid, RF_SHAREABLE | RF_ACTIVE);
49148eb6488eSEric Joyner 	if (adapter->res == NULL) {
49158eb6488eSEric Joyner 		device_printf(dev,
49168eb6488eSEric Joyner 		    "Unable to allocate bus resource: interrupt\n");
49178eb6488eSEric Joyner 		return (ENXIO);
49188eb6488eSEric Joyner 	}
49198eb6488eSEric Joyner 
49208eb6488eSEric Joyner 	/*
49218eb6488eSEric Joyner 	 * Try allocating a fast interrupt and the associated deferred
49228eb6488eSEric Joyner 	 * processing contexts.
49238eb6488eSEric Joyner 	 */
49248eb6488eSEric Joyner 	if (!(adapter->feat_en & IXGBE_FEATURE_LEGACY_TX))
49258eb6488eSEric Joyner 		TASK_INIT(&txr->txq_task, 0, ixgbe_deferred_mq_start, txr);
49268eb6488eSEric Joyner 	TASK_INIT(&que->que_task, 0, ixgbe_handle_que, que);
49278eb6488eSEric Joyner 	que->tq = taskqueue_create_fast("ixgbe_que", M_NOWAIT,
49288eb6488eSEric Joyner 	    taskqueue_thread_enqueue, &que->tq);
49298eb6488eSEric Joyner 	taskqueue_start_threads(&que->tq, 1, PI_NET, "%s ixq",
49308eb6488eSEric Joyner 	    device_get_nameunit(adapter->dev));
49318eb6488eSEric Joyner 
49328eb6488eSEric Joyner 	/* Tasklets for Link, SFP and Multispeed Fiber */
49338eb6488eSEric Joyner 	TASK_INIT(&adapter->link_task, 0, ixgbe_handle_link, adapter);
49348eb6488eSEric Joyner 	TASK_INIT(&adapter->mod_task, 0, ixgbe_handle_mod, adapter);
49358eb6488eSEric Joyner 	TASK_INIT(&adapter->msf_task, 0, ixgbe_handle_msf, adapter);
49368eb6488eSEric Joyner 	TASK_INIT(&adapter->phy_task, 0, ixgbe_handle_phy, adapter);
49378eb6488eSEric Joyner 	if (adapter->feat_en & IXGBE_FEATURE_FDIR)
49388eb6488eSEric Joyner 		TASK_INIT(&adapter->fdir_task, 0, ixgbe_reinit_fdir, adapter);
49398eb6488eSEric Joyner 	adapter->tq = taskqueue_create_fast("ixgbe_link", M_NOWAIT,
49408eb6488eSEric Joyner 	    taskqueue_thread_enqueue, &adapter->tq);
49418eb6488eSEric Joyner 	taskqueue_start_threads(&adapter->tq, 1, PI_NET, "%s linkq",
49428eb6488eSEric Joyner 	    device_get_nameunit(adapter->dev));
49438eb6488eSEric Joyner 
49448eb6488eSEric Joyner 	if ((error = bus_setup_intr(dev, adapter->res,
49458eb6488eSEric Joyner 	    INTR_TYPE_NET | INTR_MPSAFE, NULL, ixgbe_legacy_irq, que,
49468eb6488eSEric Joyner 	    &adapter->tag)) != 0) {
49478eb6488eSEric Joyner 		device_printf(dev,
49488eb6488eSEric Joyner 		    "Failed to register fast interrupt handler: %d\n", error);
49498eb6488eSEric Joyner 		taskqueue_free(que->tq);
49508eb6488eSEric Joyner 		taskqueue_free(adapter->tq);
49518eb6488eSEric Joyner 		que->tq = NULL;
49528eb6488eSEric Joyner 		adapter->tq = NULL;
49538eb6488eSEric Joyner 
49548eb6488eSEric Joyner 		return (error);
49558eb6488eSEric Joyner 	}
49568eb6488eSEric Joyner 	/* For simplicity in the handlers */
49578eb6488eSEric Joyner 	adapter->active_queues = IXGBE_EIMS_ENABLE_MASK;
49588eb6488eSEric Joyner 
49598eb6488eSEric Joyner 	return (0);
49608eb6488eSEric Joyner } /* ixgbe_allocate_legacy */
49618eb6488eSEric Joyner 
49628eb6488eSEric Joyner 
49638eb6488eSEric Joyner /************************************************************************
49648eb6488eSEric Joyner  * ixgbe_allocate_msix - Setup MSI-X Interrupt resources and handlers
49658eb6488eSEric Joyner  ************************************************************************/
49668eb6488eSEric Joyner static int
49678eb6488eSEric Joyner ixgbe_allocate_msix(struct adapter *adapter)
49688eb6488eSEric Joyner {
49698eb6488eSEric Joyner 	device_t        dev = adapter->dev;
49708eb6488eSEric Joyner 	struct ix_queue *que = adapter->queues;
49718eb6488eSEric Joyner 	struct tx_ring  *txr = adapter->tx_rings;
49728eb6488eSEric Joyner 	int             error, rid, vector = 0;
49738eb6488eSEric Joyner 	int             cpu_id = 0;
49748eb6488eSEric Joyner 	unsigned int    rss_buckets = 0;
49758eb6488eSEric Joyner 	cpuset_t        cpu_mask;
49768eb6488eSEric Joyner 
49778eb6488eSEric Joyner 	/*
49788eb6488eSEric Joyner 	 * If we're doing RSS, the number of queues needs to
49798eb6488eSEric Joyner 	 * match the number of RSS buckets that are configured.
49808eb6488eSEric Joyner 	 *
49818eb6488eSEric Joyner 	 * + If there's more queues than RSS buckets, we'll end
49828eb6488eSEric Joyner 	 *   up with queues that get no traffic.
49838eb6488eSEric Joyner 	 *
49848eb6488eSEric Joyner 	 * + If there's more RSS buckets than queues, we'll end
49858eb6488eSEric Joyner 	 *   up having multiple RSS buckets map to the same queue,
49868eb6488eSEric Joyner 	 *   so there'll be some contention.
49878eb6488eSEric Joyner 	 */
49888eb6488eSEric Joyner 	rss_buckets = rss_getnumbuckets();
49898eb6488eSEric Joyner 	if ((adapter->feat_en & IXGBE_FEATURE_RSS) &&
49908eb6488eSEric Joyner 	    (adapter->num_queues != rss_buckets)) {
49918eb6488eSEric Joyner 		device_printf(dev, "%s: number of queues (%d) != number of RSS buckets (%d); performance will be impacted.\n",
49928eb6488eSEric Joyner 		    __func__, adapter->num_queues, rss_buckets);
49938eb6488eSEric Joyner 	}
49948eb6488eSEric Joyner 
49958eb6488eSEric Joyner 	for (int i = 0; i < adapter->num_queues; i++, vector++, que++, txr++) {
49968eb6488eSEric Joyner 		rid = vector + 1;
49978eb6488eSEric Joyner 		que->res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid,
49988eb6488eSEric Joyner 		    RF_SHAREABLE | RF_ACTIVE);
49998eb6488eSEric Joyner 		if (que->res == NULL) {
50008eb6488eSEric Joyner 			device_printf(dev, "Unable to allocate bus resource: que interrupt [%d]\n",
50018eb6488eSEric Joyner 			    vector);
50028eb6488eSEric Joyner 			return (ENXIO);
50038eb6488eSEric Joyner 		}
50048eb6488eSEric Joyner 		/* Set the handler function */
50058eb6488eSEric Joyner 		error = bus_setup_intr(dev, que->res,
50068eb6488eSEric Joyner 		    INTR_TYPE_NET | INTR_MPSAFE, NULL, ixgbe_msix_que, que,
50078eb6488eSEric Joyner 		    &que->tag);
50088eb6488eSEric Joyner 		if (error) {
50098eb6488eSEric Joyner 			que->res = NULL;
50108eb6488eSEric Joyner 			device_printf(dev, "Failed to register QUE handler");
50118eb6488eSEric Joyner 			return (error);
50128eb6488eSEric Joyner 		}
50138eb6488eSEric Joyner #if __FreeBSD_version >= 800504
50148eb6488eSEric Joyner 		bus_describe_intr(dev, que->res, que->tag, "q%d", i);
50158eb6488eSEric Joyner #endif
50168eb6488eSEric Joyner 		que->msix = vector;
50178eb6488eSEric Joyner 		adapter->active_queues |= (u64)(1 << que->msix);
50188eb6488eSEric Joyner 
50198eb6488eSEric Joyner 		if (adapter->feat_en & IXGBE_FEATURE_RSS) {
50208eb6488eSEric Joyner 			/*
50218eb6488eSEric Joyner 			 * The queue ID is used as the RSS layer bucket ID.
50228eb6488eSEric Joyner 			 * We look up the queue ID -> RSS CPU ID and select
50238eb6488eSEric Joyner 			 * that.
50248eb6488eSEric Joyner 			 */
50258eb6488eSEric Joyner 			cpu_id = rss_getcpu(i % rss_buckets);
50268eb6488eSEric Joyner 			CPU_SETOF(cpu_id, &cpu_mask);
50278eb6488eSEric Joyner 		} else {
50288eb6488eSEric Joyner 			/*
50298eb6488eSEric Joyner 			 * Bind the MSI-X vector, and thus the
50308eb6488eSEric Joyner 			 * rings to the corresponding CPU.
50318eb6488eSEric Joyner 			 *
50328eb6488eSEric Joyner 			 * This just happens to match the default RSS
50338eb6488eSEric Joyner 			 * round-robin bucket -> queue -> CPU allocation.
50348eb6488eSEric Joyner 			 */
50358eb6488eSEric Joyner 			if (adapter->num_queues > 1)
50368eb6488eSEric Joyner 				cpu_id = i;
50378eb6488eSEric Joyner 		}
50388eb6488eSEric Joyner 		if (adapter->num_queues > 1)
50398eb6488eSEric Joyner 			bus_bind_intr(dev, que->res, cpu_id);
50408eb6488eSEric Joyner #ifdef IXGBE_DEBUG
50418eb6488eSEric Joyner 		if (adapter->feat_en & IXGBE_FEATURE_RSS)
50428eb6488eSEric Joyner 			device_printf(dev, "Bound RSS bucket %d to CPU %d\n", i,
50438eb6488eSEric Joyner 			    cpu_id);
50448eb6488eSEric Joyner 		else
50458eb6488eSEric Joyner 			device_printf(dev, "Bound queue %d to cpu %d\n", i,
50468eb6488eSEric Joyner 			    cpu_id);
50478eb6488eSEric Joyner #endif /* IXGBE_DEBUG */
50488eb6488eSEric Joyner 
50498eb6488eSEric Joyner 
50508eb6488eSEric Joyner 		if (!(adapter->feat_en & IXGBE_FEATURE_LEGACY_TX))
50518eb6488eSEric Joyner 			TASK_INIT(&txr->txq_task, 0, ixgbe_deferred_mq_start,
50528eb6488eSEric Joyner 			    txr);
50538eb6488eSEric Joyner 		TASK_INIT(&que->que_task, 0, ixgbe_handle_que, que);
50548eb6488eSEric Joyner 		que->tq = taskqueue_create_fast("ixgbe_que", M_NOWAIT,
50558eb6488eSEric Joyner 		    taskqueue_thread_enqueue, &que->tq);
50568eb6488eSEric Joyner #if __FreeBSD_version < 1100000
50578eb6488eSEric Joyner 		taskqueue_start_threads(&que->tq, 1, PI_NET, "%s:q%d",
50588eb6488eSEric Joyner 		    device_get_nameunit(adapter->dev), i);
50598eb6488eSEric Joyner #else
50608eb6488eSEric Joyner 		if (adapter->feat_en & IXGBE_FEATURE_RSS)
50618eb6488eSEric Joyner 			taskqueue_start_threads_cpuset(&que->tq, 1, PI_NET,
50628eb6488eSEric Joyner 			    &cpu_mask, "%s (bucket %d)",
50638eb6488eSEric Joyner 			    device_get_nameunit(adapter->dev), cpu_id);
50648eb6488eSEric Joyner 		else
50658eb6488eSEric Joyner 			taskqueue_start_threads_cpuset(&que->tq, 1, PI_NET,
50668eb6488eSEric Joyner 			    NULL, "%s:q%d", device_get_nameunit(adapter->dev),
50678eb6488eSEric Joyner 			    i);
506848056c88SJack F Vogel #endif
5069758cc3dcSJack F Vogel 	}
5070758cc3dcSJack F Vogel 
50718eb6488eSEric Joyner 	/* and Link */
50728eb6488eSEric Joyner 	adapter->link_rid = vector + 1;
50738eb6488eSEric Joyner 	adapter->res = bus_alloc_resource_any(dev, SYS_RES_IRQ,
50748eb6488eSEric Joyner 	    &adapter->link_rid, RF_SHAREABLE | RF_ACTIVE);
50758eb6488eSEric Joyner 	if (!adapter->res) {
50768eb6488eSEric Joyner 		device_printf(dev,
50778eb6488eSEric Joyner 		    "Unable to allocate bus resource: Link interrupt [%d]\n",
50788eb6488eSEric Joyner 		    adapter->link_rid);
50798eb6488eSEric Joyner 		return (ENXIO);
50808eb6488eSEric Joyner 	}
50818eb6488eSEric Joyner 	/* Set the link handler function */
50828eb6488eSEric Joyner 	error = bus_setup_intr(dev, adapter->res, INTR_TYPE_NET | INTR_MPSAFE,
50838eb6488eSEric Joyner 	    NULL, ixgbe_msix_link, adapter, &adapter->tag);
50848eb6488eSEric Joyner 	if (error) {
50858eb6488eSEric Joyner 		adapter->res = NULL;
50868eb6488eSEric Joyner 		device_printf(dev, "Failed to register LINK handler");
50878eb6488eSEric Joyner 		return (error);
50888eb6488eSEric Joyner 	}
50898eb6488eSEric Joyner #if __FreeBSD_version >= 800504
50908eb6488eSEric Joyner 	bus_describe_intr(dev, adapter->res, adapter->tag, "link");
50918eb6488eSEric Joyner #endif
50928eb6488eSEric Joyner 	adapter->vector = vector;
50938eb6488eSEric Joyner 	/* Tasklets for Link, SFP and Multispeed Fiber */
50948eb6488eSEric Joyner 	TASK_INIT(&adapter->link_task, 0, ixgbe_handle_link, adapter);
50958eb6488eSEric Joyner 	TASK_INIT(&adapter->mod_task, 0, ixgbe_handle_mod, adapter);
50968eb6488eSEric Joyner 	TASK_INIT(&adapter->msf_task, 0, ixgbe_handle_msf, adapter);
50978eb6488eSEric Joyner 	if (adapter->feat_cap & IXGBE_FEATURE_SRIOV)
50988eb6488eSEric Joyner 		TASK_INIT(&adapter->mbx_task, 0, ixgbe_handle_mbx, adapter);
50998eb6488eSEric Joyner 	TASK_INIT(&adapter->phy_task, 0, ixgbe_handle_phy, adapter);
51008eb6488eSEric Joyner 	if (adapter->feat_en & IXGBE_FEATURE_FDIR)
51018eb6488eSEric Joyner 		TASK_INIT(&adapter->fdir_task, 0, ixgbe_reinit_fdir, adapter);
51028eb6488eSEric Joyner 	adapter->tq = taskqueue_create_fast("ixgbe_link", M_NOWAIT,
51038eb6488eSEric Joyner 	    taskqueue_thread_enqueue, &adapter->tq);
51048eb6488eSEric Joyner 	taskqueue_start_threads(&adapter->tq, 1, PI_NET, "%s linkq",
51058eb6488eSEric Joyner 	    device_get_nameunit(adapter->dev));
51068eb6488eSEric Joyner 
51078eb6488eSEric Joyner 	return (0);
51088eb6488eSEric Joyner } /* ixgbe_allocate_msix */
51098eb6488eSEric Joyner 
51108eb6488eSEric Joyner /************************************************************************
51118eb6488eSEric Joyner  * ixgbe_configure_interrupts
51128eb6488eSEric Joyner  *
51138eb6488eSEric Joyner  *   Setup MSI-X, MSI, or legacy interrupts (in that order).
51148eb6488eSEric Joyner  *   This will also depend on user settings.
51158eb6488eSEric Joyner  ************************************************************************/
51168eb6488eSEric Joyner static int
51178eb6488eSEric Joyner ixgbe_configure_interrupts(struct adapter *adapter)
5118758cc3dcSJack F Vogel {
51198eb6488eSEric Joyner 	device_t dev = adapter->dev;
51208eb6488eSEric Joyner 	int      rid, want, queues, msgs;
51218eb6488eSEric Joyner 
51228eb6488eSEric Joyner 	/* Default to 1 queue if MSI-X setup fails */
51238eb6488eSEric Joyner 	adapter->num_queues = 1;
51248eb6488eSEric Joyner 
51258eb6488eSEric Joyner 	/* Override by tuneable */
51268eb6488eSEric Joyner 	if (!(adapter->feat_cap & IXGBE_FEATURE_MSIX))
51278eb6488eSEric Joyner 		goto msi;
51288eb6488eSEric Joyner 
51298eb6488eSEric Joyner 	/* First try MSI-X */
51308eb6488eSEric Joyner 	msgs = pci_msix_count(dev);
51318eb6488eSEric Joyner 	if (msgs == 0)
51328eb6488eSEric Joyner 		goto msi;
51338eb6488eSEric Joyner 	rid = PCIR_BAR(MSIX_82598_BAR);
51348eb6488eSEric Joyner 	adapter->msix_mem = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
51358eb6488eSEric Joyner 	    RF_ACTIVE);
51368eb6488eSEric Joyner 	if (adapter->msix_mem == NULL) {
51378eb6488eSEric Joyner 		rid += 4;  /* 82599 maps in higher BAR */
51388eb6488eSEric Joyner 		adapter->msix_mem = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
51398eb6488eSEric Joyner 		    &rid, RF_ACTIVE);
51408eb6488eSEric Joyner 	}
51418eb6488eSEric Joyner 	if (adapter->msix_mem == NULL) {
51428eb6488eSEric Joyner 		/* May not be enabled */
51438eb6488eSEric Joyner 		device_printf(adapter->dev, "Unable to map MSI-X table.\n");
51448eb6488eSEric Joyner 		goto msi;
51458eb6488eSEric Joyner 	}
51468eb6488eSEric Joyner 
51478eb6488eSEric Joyner 	/* Figure out a reasonable auto config value */
51488eb6488eSEric Joyner 	queues = min(mp_ncpus, msgs - 1);
51498eb6488eSEric Joyner 	/* If we're doing RSS, clamp at the number of RSS buckets */
51508eb6488eSEric Joyner 	if (adapter->feat_en & IXGBE_FEATURE_RSS)
51518eb6488eSEric Joyner 		queues = min(queues, rss_getnumbuckets());
51528eb6488eSEric Joyner 	if (ixgbe_num_queues > queues) {
51538eb6488eSEric Joyner 		device_printf(adapter->dev, "ixgbe_num_queues (%d) is too large, using reduced amount (%d).\n", ixgbe_num_queues, queues);
51548eb6488eSEric Joyner 		ixgbe_num_queues = queues;
51558eb6488eSEric Joyner 	}
51568eb6488eSEric Joyner 
51578eb6488eSEric Joyner 	if (ixgbe_num_queues != 0)
51588eb6488eSEric Joyner 		queues = ixgbe_num_queues;
51598eb6488eSEric Joyner 	/* Set max queues to 8 when autoconfiguring */
51608eb6488eSEric Joyner 	else
51618eb6488eSEric Joyner 		queues = min(queues, 8);
51628eb6488eSEric Joyner 
51638eb6488eSEric Joyner 	/* reflect correct sysctl value */
51648eb6488eSEric Joyner 	ixgbe_num_queues = queues;
51658eb6488eSEric Joyner 
51668eb6488eSEric Joyner 	/*
51678eb6488eSEric Joyner 	 * Want one vector (RX/TX pair) per queue
51688eb6488eSEric Joyner 	 * plus an additional for Link.
51698eb6488eSEric Joyner 	 */
51708eb6488eSEric Joyner 	want = queues + 1;
51718eb6488eSEric Joyner 	if (msgs >= want)
51728eb6488eSEric Joyner 		msgs = want;
51738eb6488eSEric Joyner 	else {
51748eb6488eSEric Joyner 		device_printf(adapter->dev, "MSI-X Configuration Problem, %d vectors but %d queues wanted!\n",
51758eb6488eSEric Joyner 		    msgs, want);
51768eb6488eSEric Joyner 		goto msi;
51778eb6488eSEric Joyner 	}
51788eb6488eSEric Joyner 	if ((pci_alloc_msix(dev, &msgs) == 0) && (msgs == want)) {
51798eb6488eSEric Joyner 		device_printf(adapter->dev,
51808eb6488eSEric Joyner 		    "Using MSI-X interrupts with %d vectors\n", msgs);
51818eb6488eSEric Joyner 		adapter->num_queues = queues;
51828eb6488eSEric Joyner 		adapter->feat_en |= IXGBE_FEATURE_MSIX;
51838eb6488eSEric Joyner 		return (0);
51848eb6488eSEric Joyner 	}
51858eb6488eSEric Joyner 	/*
51868eb6488eSEric Joyner 	 * MSI-X allocation failed or provided us with
51878eb6488eSEric Joyner 	 * less vectors than needed. Free MSI-X resources
51888eb6488eSEric Joyner 	 * and we'll try enabling MSI.
51898eb6488eSEric Joyner 	 */
51908eb6488eSEric Joyner 	pci_release_msi(dev);
51918eb6488eSEric Joyner 
51928eb6488eSEric Joyner msi:
51938eb6488eSEric Joyner 	/* Without MSI-X, some features are no longer supported */
51948eb6488eSEric Joyner 	adapter->feat_cap &= ~IXGBE_FEATURE_RSS;
51958eb6488eSEric Joyner 	adapter->feat_en  &= ~IXGBE_FEATURE_RSS;
51968eb6488eSEric Joyner 	adapter->feat_cap &= ~IXGBE_FEATURE_SRIOV;
51978eb6488eSEric Joyner 	adapter->feat_en  &= ~IXGBE_FEATURE_SRIOV;
51988eb6488eSEric Joyner 
51998eb6488eSEric Joyner 	if (adapter->msix_mem != NULL) {
52008eb6488eSEric Joyner 		bus_release_resource(dev, SYS_RES_MEMORY, rid,
52018eb6488eSEric Joyner 		    adapter->msix_mem);
52028eb6488eSEric Joyner 		adapter->msix_mem = NULL;
52038eb6488eSEric Joyner 	}
52048eb6488eSEric Joyner 	msgs = 1;
52058eb6488eSEric Joyner 	if (pci_alloc_msi(dev, &msgs) == 0) {
52068eb6488eSEric Joyner 		adapter->feat_en |= IXGBE_FEATURE_MSI;
52078eb6488eSEric Joyner 		adapter->link_rid = 1;
52088eb6488eSEric Joyner 		device_printf(adapter->dev, "Using an MSI interrupt\n");
52098eb6488eSEric Joyner 		return (0);
52108eb6488eSEric Joyner 	}
52118eb6488eSEric Joyner 
52128eb6488eSEric Joyner 	if (!(adapter->feat_cap & IXGBE_FEATURE_LEGACY_IRQ)) {
52138eb6488eSEric Joyner 		device_printf(adapter->dev,
52148eb6488eSEric Joyner 		    "Device does not support legacy interrupts.\n");
52158eb6488eSEric Joyner 		return 1;
52168eb6488eSEric Joyner 	}
52178eb6488eSEric Joyner 
52188eb6488eSEric Joyner 	adapter->feat_en |= IXGBE_FEATURE_LEGACY_IRQ;
52198eb6488eSEric Joyner 	adapter->link_rid = 0;
52208eb6488eSEric Joyner 	device_printf(adapter->dev, "Using a Legacy interrupt\n");
52218eb6488eSEric Joyner 
52228eb6488eSEric Joyner 	return (0);
52238eb6488eSEric Joyner } /* ixgbe_configure_interrupts */
52248eb6488eSEric Joyner 
52258eb6488eSEric Joyner 
52268eb6488eSEric Joyner /************************************************************************
52278eb6488eSEric Joyner  * ixgbe_handle_link - Tasklet for MSI-X Link interrupts
52288eb6488eSEric Joyner  *
52298eb6488eSEric Joyner  *   Done outside of interrupt context since the driver might sleep
52308eb6488eSEric Joyner  ************************************************************************/
52318eb6488eSEric Joyner static void
52328eb6488eSEric Joyner ixgbe_handle_link(void *context, int pending)
52338eb6488eSEric Joyner {
52348eb6488eSEric Joyner 	struct adapter  *adapter = context;
5235758cc3dcSJack F Vogel 	struct ixgbe_hw *hw = &adapter->hw;
5236758cc3dcSJack F Vogel 
52378eb6488eSEric Joyner 	ixgbe_check_link(hw, &adapter->link_speed, &adapter->link_up, 0);
52388eb6488eSEric Joyner 	ixgbe_update_link_status(adapter);
5239758cc3dcSJack F Vogel 
52408eb6488eSEric Joyner 	/* Re-enable link interrupts */
52418eb6488eSEric Joyner 	IXGBE_WRITE_REG(hw, IXGBE_EIMS, IXGBE_EIMS_LSC);
52428eb6488eSEric Joyner } /* ixgbe_handle_link */
52438eb6488eSEric Joyner 
52448eb6488eSEric Joyner /************************************************************************
52458eb6488eSEric Joyner  * ixgbe_rearm_queues
52468eb6488eSEric Joyner  ************************************************************************/
5247758cc3dcSJack F Vogel static void
5248758cc3dcSJack F Vogel ixgbe_rearm_queues(struct adapter *adapter, u64 queues)
5249758cc3dcSJack F Vogel {
5250758cc3dcSJack F Vogel 	u32 mask;
5251758cc3dcSJack F Vogel 
5252758cc3dcSJack F Vogel 	switch (adapter->hw.mac.type) {
5253758cc3dcSJack F Vogel 	case ixgbe_mac_82598EB:
5254758cc3dcSJack F Vogel 		mask = (IXGBE_EIMS_RTX_QUEUE & queues);
5255758cc3dcSJack F Vogel 		IXGBE_WRITE_REG(&adapter->hw, IXGBE_EICS, mask);
5256758cc3dcSJack F Vogel 		break;
5257758cc3dcSJack F Vogel 	case ixgbe_mac_82599EB:
5258758cc3dcSJack F Vogel 	case ixgbe_mac_X540:
5259758cc3dcSJack F Vogel 	case ixgbe_mac_X550:
52606f37f232SEric Joyner 	case ixgbe_mac_X550EM_x:
52618eb6488eSEric Joyner 	case ixgbe_mac_X550EM_a:
5262758cc3dcSJack F Vogel 		mask = (queues & 0xFFFFFFFF);
5263758cc3dcSJack F Vogel 		IXGBE_WRITE_REG(&adapter->hw, IXGBE_EICS_EX(0), mask);
5264758cc3dcSJack F Vogel 		mask = (queues >> 32);
5265758cc3dcSJack F Vogel 		IXGBE_WRITE_REG(&adapter->hw, IXGBE_EICS_EX(1), mask);
5266758cc3dcSJack F Vogel 		break;
5267758cc3dcSJack F Vogel 	default:
5268758cc3dcSJack F Vogel 		break;
5269758cc3dcSJack F Vogel 	}
52708eb6488eSEric Joyner } /* ixgbe_rearm_queues */
5271758cc3dcSJack F Vogel 
5272