xref: /freebsd/sys/dev/ixgbe/if_ix.c (revision afb1aa4e6df245d38fd2ba683fa521d5dabe8392)
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 #include "opt_inet.h"
37758cc3dcSJack F Vogel #include "opt_inet6.h"
38758cc3dcSJack F Vogel #include "opt_rss.h"
39758cc3dcSJack F Vogel 
40758cc3dcSJack F Vogel #include "ixgbe.h"
41c19c7afeSEric Joyner #include "ixgbe_sriov.h"
42c19c7afeSEric Joyner #include "ifdi_if.h"
43c19c7afeSEric Joyner 
44c19c7afeSEric Joyner #include <net/netmap.h>
45c19c7afeSEric Joyner #include <dev/netmap/netmap_kern.h>
46758cc3dcSJack F Vogel 
478eb6488eSEric Joyner /************************************************************************
48758cc3dcSJack F Vogel  * Driver version
498eb6488eSEric Joyner  ************************************************************************/
507d48aa4cSEric Joyner char ixgbe_driver_version[] = "4.0.1-k";
51a9ca1c79SSean Bruno 
52758cc3dcSJack F Vogel 
538eb6488eSEric Joyner /************************************************************************
54758cc3dcSJack F Vogel  * PCI Device ID Table
55758cc3dcSJack F Vogel  *
56758cc3dcSJack F Vogel  *   Used by probe to select devices to load on
57758cc3dcSJack F Vogel  *   Last field stores an index into ixgbe_strings
58758cc3dcSJack F Vogel  *   Last entry must be all 0s
59758cc3dcSJack F Vogel  *
60758cc3dcSJack F Vogel  *   { Vendor ID, Device ID, SubVendor ID, SubDevice ID, String Index }
618eb6488eSEric Joyner  ************************************************************************/
62c19c7afeSEric Joyner static pci_vendor_info_t ixgbe_vendor_info_array[] =
63758cc3dcSJack F Vogel {
64c19c7afeSEric Joyner   PVID(IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82598AF_DUAL_PORT,  "Intel(R) PRO/10GbE PCI-Express Network Driver"),
65c19c7afeSEric Joyner   PVID(IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82598AF_SINGLE_PORT,  "Intel(R) PRO/10GbE PCI-Express Network Driver"),
66c19c7afeSEric Joyner   PVID(IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82598EB_CX4,  "Intel(R) PRO/10GbE PCI-Express Network Driver"),
67c19c7afeSEric Joyner   PVID(IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82598AT,  "Intel(R) PRO/10GbE PCI-Express Network Driver"),
68c19c7afeSEric Joyner   PVID(IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82598AT2,  "Intel(R) PRO/10GbE PCI-Express Network Driver"),
69c19c7afeSEric Joyner   PVID(IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82598,  "Intel(R) PRO/10GbE PCI-Express Network Driver"),
70c19c7afeSEric Joyner   PVID(IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82598_DA_DUAL_PORT,  "Intel(R) PRO/10GbE PCI-Express Network Driver"),
71c19c7afeSEric Joyner   PVID(IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82598_CX4_DUAL_PORT,  "Intel(R) PRO/10GbE PCI-Express Network Driver"),
72c19c7afeSEric Joyner   PVID(IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82598EB_XF_LR,  "Intel(R) PRO/10GbE PCI-Express Network Driver"),
73c19c7afeSEric Joyner   PVID(IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82598_SR_DUAL_PORT_EM,  "Intel(R) PRO/10GbE PCI-Express Network Driver"),
74c19c7afeSEric Joyner   PVID(IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82598EB_SFP_LOM,  "Intel(R) PRO/10GbE PCI-Express Network Driver"),
75c19c7afeSEric Joyner   PVID(IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82599_KX4,  "Intel(R) PRO/10GbE PCI-Express Network Driver"),
76c19c7afeSEric Joyner   PVID(IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82599_KX4_MEZZ,  "Intel(R) PRO/10GbE PCI-Express Network Driver"),
77c19c7afeSEric Joyner   PVID(IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82599_SFP,  "Intel(R) PRO/10GbE PCI-Express Network Driver"),
78c19c7afeSEric Joyner   PVID(IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82599_XAUI_LOM,  "Intel(R) PRO/10GbE PCI-Express Network Driver"),
79c19c7afeSEric Joyner   PVID(IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82599_CX4,  "Intel(R) PRO/10GbE PCI-Express Network Driver"),
80c19c7afeSEric Joyner   PVID(IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82599_T3_LOM,  "Intel(R) PRO/10GbE PCI-Express Network Driver"),
81c19c7afeSEric Joyner   PVID(IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82599_COMBO_BACKPLANE,  "Intel(R) PRO/10GbE PCI-Express Network Driver"),
82c19c7afeSEric Joyner   PVID(IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82599_BACKPLANE_FCOE,  "Intel(R) PRO/10GbE PCI-Express Network Driver"),
83c19c7afeSEric Joyner   PVID(IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82599_SFP_SF2,  "Intel(R) PRO/10GbE PCI-Express Network Driver"),
84c19c7afeSEric Joyner   PVID(IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82599_SFP_FCOE,  "Intel(R) PRO/10GbE PCI-Express Network Driver"),
85c19c7afeSEric Joyner   PVID(IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82599EN_SFP,  "Intel(R) PRO/10GbE PCI-Express Network Driver"),
86c19c7afeSEric Joyner   PVID(IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82599_SFP_SF_QP,  "Intel(R) PRO/10GbE PCI-Express Network Driver"),
87c19c7afeSEric Joyner   PVID(IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82599_QSFP_SF_QP,  "Intel(R) PRO/10GbE PCI-Express Network Driver"),
88c19c7afeSEric Joyner   PVID(IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X540T,  "Intel(R) PRO/10GbE PCI-Express Network Driver"),
89c19c7afeSEric Joyner   PVID(IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X540T1,  "Intel(R) PRO/10GbE PCI-Express Network Driver"),
90c19c7afeSEric Joyner   PVID(IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X550T,  "Intel(R) PRO/10GbE PCI-Express Network Driver"),
91c19c7afeSEric Joyner   PVID(IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X550T1, "Intel(R) PRO/10GbE PCI-Express Network Driver"),
92c19c7afeSEric Joyner   PVID(IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X550EM_X_KR,  "Intel(R) PRO/10GbE PCI-Express Network Driver"),
93c19c7afeSEric Joyner   PVID(IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X550EM_X_KX4,  "Intel(R) PRO/10GbE PCI-Express Network Driver"),
94c19c7afeSEric Joyner   PVID(IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X550EM_X_10G_T,  "Intel(R) PRO/10GbE PCI-Express Network Driver"),
957d48aa4cSEric Joyner   PVID(IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X550EM_X_1G_T,  "Intel(R) PRO/10GbE PCI-Express Network Driver"),
96c19c7afeSEric Joyner   PVID(IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X550EM_X_SFP, "Intel(R) PRO/10GbE PCI-Express Network Driver"),
97c19c7afeSEric Joyner   PVID(IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X550EM_A_KR, "Intel(R) PRO/10GbE PCI-Express Network Driver"),
98c19c7afeSEric Joyner   PVID(IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X550EM_A_KR_L, "Intel(R) PRO/10GbE PCI-Express Network Driver"),
99c19c7afeSEric Joyner   PVID(IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X550EM_A_SFP, "Intel(R) PRO/10GbE PCI-Express Network Driver"),
100c19c7afeSEric Joyner   PVID(IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X550EM_A_SFP_N, "Intel(R) PRO/10GbE PCI-Express Network Driver"),
101c19c7afeSEric Joyner   PVID(IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X550EM_A_SGMII, "Intel(R) PRO/10GbE PCI-Express Network Driver"),
102c19c7afeSEric Joyner   PVID(IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X550EM_A_SGMII_L, "Intel(R) PRO/10GbE PCI-Express Network Driver"),
103c19c7afeSEric Joyner   PVID(IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X550EM_A_10G_T, "Intel(R) PRO/10GbE PCI-Express Network Driver"),
104c19c7afeSEric Joyner   PVID(IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X550EM_A_1G_T, "Intel(R) PRO/10GbE PCI-Express Network Driver"),
105c19c7afeSEric Joyner   PVID(IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X550EM_A_1G_T_L, "Intel(R) PRO/10GbE PCI-Express Network Driver"),
106c19c7afeSEric Joyner   PVID(IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X540_BYPASS, "Intel(R) PRO/10GbE PCI-Express Network Driver"),
107c19c7afeSEric Joyner   PVID(IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82599_BYPASS, "Intel(R) PRO/10GbE PCI-Express Network Driver"),
108758cc3dcSJack F Vogel 	/* required last entry */
109c19c7afeSEric Joyner   PVID_END
110758cc3dcSJack F Vogel };
111758cc3dcSJack F Vogel 
112c19c7afeSEric Joyner static void *ixgbe_register(device_t dev);
113c19c7afeSEric Joyner static int  ixgbe_if_attach_pre(if_ctx_t ctx);
114c19c7afeSEric Joyner static int  ixgbe_if_attach_post(if_ctx_t ctx);
115c19c7afeSEric Joyner static int  ixgbe_if_detach(if_ctx_t ctx);
116c19c7afeSEric Joyner static int  ixgbe_if_shutdown(if_ctx_t ctx);
117c19c7afeSEric Joyner static int  ixgbe_if_suspend(if_ctx_t ctx);
118c19c7afeSEric Joyner static int  ixgbe_if_resume(if_ctx_t ctx);
119c19c7afeSEric Joyner 
120c19c7afeSEric Joyner static void ixgbe_if_stop(if_ctx_t ctx);
121c19c7afeSEric Joyner void ixgbe_if_enable_intr(if_ctx_t ctx);
122c19c7afeSEric Joyner static void ixgbe_if_disable_intr(if_ctx_t ctx);
123b2c1e8e6SEric Joyner static void ixgbe_link_intr_enable(if_ctx_t ctx);
124c19c7afeSEric Joyner static int  ixgbe_if_rx_queue_intr_enable(if_ctx_t ctx, uint16_t qid);
125c19c7afeSEric Joyner static void ixgbe_if_media_status(if_ctx_t ctx, struct ifmediareq * ifmr);
126c19c7afeSEric Joyner static int  ixgbe_if_media_change(if_ctx_t ctx);
127c19c7afeSEric Joyner static int  ixgbe_if_msix_intr_assign(if_ctx_t, int);
128c19c7afeSEric Joyner static int  ixgbe_if_mtu_set(if_ctx_t ctx, uint32_t mtu);
129c19c7afeSEric Joyner static void ixgbe_if_crcstrip_set(if_ctx_t ctx, int onoff, int strip);
130c19c7afeSEric Joyner static void ixgbe_if_multi_set(if_ctx_t ctx);
131c19c7afeSEric Joyner static int  ixgbe_if_promisc_set(if_ctx_t ctx, int flags);
132c19c7afeSEric Joyner static int  ixgbe_if_tx_queues_alloc(if_ctx_t ctx, caddr_t *vaddrs,
133c19c7afeSEric Joyner                                      uint64_t *paddrs, int nrxqs, int nrxqsets);
134c19c7afeSEric Joyner static int  ixgbe_if_rx_queues_alloc(if_ctx_t ctx, caddr_t *vaddrs,
135c19c7afeSEric Joyner                                      uint64_t *paddrs, int nrxqs, int nrxqsets);
136c19c7afeSEric Joyner static void ixgbe_if_queues_free(if_ctx_t ctx);
137c19c7afeSEric Joyner static void ixgbe_if_timer(if_ctx_t ctx, uint16_t);
138c19c7afeSEric Joyner static void ixgbe_if_update_admin_status(if_ctx_t ctx);
139c19c7afeSEric Joyner static void ixgbe_if_vlan_register(if_ctx_t ctx, u16 vtag);
140c19c7afeSEric Joyner static void ixgbe_if_vlan_unregister(if_ctx_t ctx, u16 vtag);
141bca38080SAndrew Gallatin static int  ixgbe_if_i2c_req(if_ctx_t ctx, struct ifi2creq *req);
142cf150917SEric Joyner static bool ixgbe_if_needs_restart(if_ctx_t ctx, enum iflib_restart_event event);
143c19c7afeSEric Joyner int ixgbe_intr(void *arg);
144758cc3dcSJack F Vogel 
1458eb6488eSEric Joyner /************************************************************************
146758cc3dcSJack F Vogel  * Function prototypes
1478eb6488eSEric Joyner  ************************************************************************/
148758cc3dcSJack F Vogel #if __FreeBSD_version >= 1100036
149c19c7afeSEric Joyner static uint64_t ixgbe_if_get_counter(if_ctx_t, ift_counter);
150758cc3dcSJack F Vogel #endif
151758cc3dcSJack F Vogel 
152c19c7afeSEric Joyner static void ixgbe_enable_queue(struct adapter *adapter, u32 vector);
153c19c7afeSEric Joyner static void ixgbe_disable_queue(struct adapter *adapter, u32 vector);
154c19c7afeSEric Joyner static void ixgbe_add_device_sysctls(if_ctx_t ctx);
155c19c7afeSEric Joyner static int  ixgbe_allocate_pci_resources(if_ctx_t ctx);
156c19c7afeSEric Joyner static int  ixgbe_setup_low_power_mode(if_ctx_t ctx);
157c19c7afeSEric Joyner 
158c19c7afeSEric Joyner static void ixgbe_config_dmac(struct adapter *adapter);
159c19c7afeSEric Joyner static void ixgbe_configure_ivars(struct adapter *adapter);
160c19c7afeSEric Joyner static void ixgbe_set_ivar(struct adapter *adapter, u8 entry, u8 vector,
161c19c7afeSEric Joyner                            s8 type);
162c19c7afeSEric Joyner static u8   *ixgbe_mc_array_itr(struct ixgbe_hw *, u8 **, u32 *);
163c19c7afeSEric Joyner static bool ixgbe_sfp_probe(if_ctx_t ctx);
164c19c7afeSEric Joyner 
165c19c7afeSEric Joyner static void ixgbe_free_pci_resources(if_ctx_t ctx);
166c19c7afeSEric Joyner 
167c19c7afeSEric Joyner static int  ixgbe_msix_link(void *arg);
168c19c7afeSEric Joyner static int  ixgbe_msix_que(void *arg);
169c19c7afeSEric Joyner static void ixgbe_initialize_rss_mapping(struct adapter *adapter);
170c19c7afeSEric Joyner static void ixgbe_initialize_receive_units(if_ctx_t ctx);
171c19c7afeSEric Joyner static void ixgbe_initialize_transmit_units(if_ctx_t ctx);
172c19c7afeSEric Joyner 
173c19c7afeSEric Joyner static int  ixgbe_setup_interface(if_ctx_t ctx);
174c19c7afeSEric Joyner static void ixgbe_init_device_features(struct adapter *adapter);
175c19c7afeSEric Joyner static void ixgbe_check_fan_failure(struct adapter *, u32, bool);
176c19c7afeSEric Joyner static void ixgbe_add_media_types(if_ctx_t ctx);
177c19c7afeSEric Joyner static void ixgbe_update_stats_counters(struct adapter *adapter);
178b2c1e8e6SEric Joyner static void ixgbe_config_link(if_ctx_t ctx);
179c19c7afeSEric Joyner static void ixgbe_get_slot_info(struct adapter *);
180c19c7afeSEric Joyner static void ixgbe_check_wol_support(struct adapter *adapter);
181758cc3dcSJack F Vogel static void ixgbe_enable_rx_drop(struct adapter *);
182758cc3dcSJack F Vogel static void ixgbe_disable_rx_drop(struct adapter *);
183758cc3dcSJack F Vogel 
184c19c7afeSEric Joyner static void ixgbe_add_hw_stats(struct adapter *adapter);
185f2c4db54SSteven Hartland static int  ixgbe_set_flowcntl(struct adapter *, int);
186f2c4db54SSteven Hartland static int  ixgbe_set_advertise(struct adapter *, int);
1878eb6488eSEric Joyner static int  ixgbe_get_advertise(struct adapter *);
188c19c7afeSEric Joyner static void ixgbe_setup_vlan_hw_support(if_ctx_t ctx);
189c19c7afeSEric Joyner static void ixgbe_config_gpie(struct adapter *adapter);
190c19c7afeSEric Joyner static void ixgbe_config_delay_values(struct adapter *adapter);
1916f37f232SEric Joyner 
1926f37f232SEric Joyner /* Sysctl handlers */
193f2c4db54SSteven Hartland static int  ixgbe_sysctl_flowcntl(SYSCTL_HANDLER_ARGS);
194f2c4db54SSteven Hartland static int  ixgbe_sysctl_advertise(SYSCTL_HANDLER_ARGS);
1958eb6488eSEric Joyner static int  ixgbe_sysctl_interrupt_rate_handler(SYSCTL_HANDLER_ARGS);
1966f37f232SEric Joyner static int  ixgbe_sysctl_dmac(SYSCTL_HANDLER_ARGS);
1976f37f232SEric Joyner static int  ixgbe_sysctl_phy_temp(SYSCTL_HANDLER_ARGS);
1986f37f232SEric Joyner static int  ixgbe_sysctl_phy_overtemp_occurred(SYSCTL_HANDLER_ARGS);
199a9ca1c79SSean Bruno #ifdef IXGBE_DEBUG
200a9ca1c79SSean Bruno static int  ixgbe_sysctl_power_state(SYSCTL_HANDLER_ARGS);
201a9ca1c79SSean Bruno static int  ixgbe_sysctl_print_rss_config(SYSCTL_HANDLER_ARGS);
202a9ca1c79SSean Bruno #endif
2038eb6488eSEric Joyner static int  ixgbe_sysctl_rdh_handler(SYSCTL_HANDLER_ARGS);
2048eb6488eSEric Joyner static int  ixgbe_sysctl_rdt_handler(SYSCTL_HANDLER_ARGS);
2058eb6488eSEric Joyner static int  ixgbe_sysctl_tdt_handler(SYSCTL_HANDLER_ARGS);
2068eb6488eSEric Joyner static int  ixgbe_sysctl_tdh_handler(SYSCTL_HANDLER_ARGS);
2078eb6488eSEric Joyner static int  ixgbe_sysctl_eee_state(SYSCTL_HANDLER_ARGS);
2086f37f232SEric Joyner static int  ixgbe_sysctl_wol_enable(SYSCTL_HANDLER_ARGS);
2096f37f232SEric Joyner static int  ixgbe_sysctl_wufc(SYSCTL_HANDLER_ARGS);
210758cc3dcSJack F Vogel 
211758cc3dcSJack F Vogel /* Deferred interrupt tasklets */
212c19c7afeSEric Joyner static void ixgbe_handle_msf(void *);
213c19c7afeSEric Joyner static void ixgbe_handle_mod(void *);
214c19c7afeSEric Joyner static void ixgbe_handle_phy(void *);
215758cc3dcSJack F Vogel 
2168eb6488eSEric Joyner /************************************************************************
217758cc3dcSJack F Vogel  *  FreeBSD Device Interface Entry Points
2188eb6488eSEric Joyner  ************************************************************************/
219a1edda90SAdrian Chadd static device_method_t ix_methods[] = {
220758cc3dcSJack F Vogel 	/* Device interface */
221c19c7afeSEric Joyner 	DEVMETHOD(device_register, ixgbe_register),
222c19c7afeSEric Joyner 	DEVMETHOD(device_probe, iflib_device_probe),
223c19c7afeSEric Joyner 	DEVMETHOD(device_attach, iflib_device_attach),
224c19c7afeSEric Joyner 	DEVMETHOD(device_detach, iflib_device_detach),
225c19c7afeSEric Joyner 	DEVMETHOD(device_shutdown, iflib_device_shutdown),
226c19c7afeSEric Joyner 	DEVMETHOD(device_suspend, iflib_device_suspend),
227c19c7afeSEric Joyner 	DEVMETHOD(device_resume, iflib_device_resume),
22848056c88SJack F Vogel #ifdef PCI_IOV
229c19c7afeSEric Joyner 	DEVMETHOD(pci_iov_init, iflib_device_iov_init),
230c19c7afeSEric Joyner 	DEVMETHOD(pci_iov_uninit, iflib_device_iov_uninit),
231c19c7afeSEric Joyner 	DEVMETHOD(pci_iov_add_vf, iflib_device_iov_add_vf),
23248056c88SJack F Vogel #endif /* PCI_IOV */
233758cc3dcSJack F Vogel 	DEVMETHOD_END
234758cc3dcSJack F Vogel };
235758cc3dcSJack F Vogel 
236a1edda90SAdrian Chadd static driver_t ix_driver = {
237a1edda90SAdrian Chadd 	"ix", ix_methods, sizeof(struct adapter),
238758cc3dcSJack F Vogel };
239758cc3dcSJack F Vogel 
240a1edda90SAdrian Chadd devclass_t ix_devclass;
241a1edda90SAdrian Chadd DRIVER_MODULE(ix, pci, ix_driver, ix_devclass, 0, 0);
242937b0f25SYuri Pankov IFLIB_PNP_INFO(pci, ix_driver, ixgbe_vendor_info_array);
243a1edda90SAdrian Chadd MODULE_DEPEND(ix, pci, 1, 1, 1);
244a1edda90SAdrian Chadd MODULE_DEPEND(ix, ether, 1, 1, 1);
245c19c7afeSEric Joyner MODULE_DEPEND(ix, iflib, 1, 1, 1);
246c19c7afeSEric Joyner 
247c19c7afeSEric Joyner static device_method_t ixgbe_if_methods[] = {
248c19c7afeSEric Joyner 	DEVMETHOD(ifdi_attach_pre, ixgbe_if_attach_pre),
249c19c7afeSEric Joyner 	DEVMETHOD(ifdi_attach_post, ixgbe_if_attach_post),
250c19c7afeSEric Joyner 	DEVMETHOD(ifdi_detach, ixgbe_if_detach),
251c19c7afeSEric Joyner 	DEVMETHOD(ifdi_shutdown, ixgbe_if_shutdown),
252c19c7afeSEric Joyner 	DEVMETHOD(ifdi_suspend, ixgbe_if_suspend),
253c19c7afeSEric Joyner 	DEVMETHOD(ifdi_resume, ixgbe_if_resume),
254c19c7afeSEric Joyner 	DEVMETHOD(ifdi_init, ixgbe_if_init),
255c19c7afeSEric Joyner 	DEVMETHOD(ifdi_stop, ixgbe_if_stop),
256c19c7afeSEric Joyner 	DEVMETHOD(ifdi_msix_intr_assign, ixgbe_if_msix_intr_assign),
257c19c7afeSEric Joyner 	DEVMETHOD(ifdi_intr_enable, ixgbe_if_enable_intr),
258c19c7afeSEric Joyner 	DEVMETHOD(ifdi_intr_disable, ixgbe_if_disable_intr),
259b2c1e8e6SEric Joyner 	DEVMETHOD(ifdi_link_intr_enable, ixgbe_link_intr_enable),
260c19c7afeSEric Joyner 	DEVMETHOD(ifdi_tx_queue_intr_enable, ixgbe_if_rx_queue_intr_enable),
261c19c7afeSEric Joyner 	DEVMETHOD(ifdi_rx_queue_intr_enable, ixgbe_if_rx_queue_intr_enable),
262c19c7afeSEric Joyner 	DEVMETHOD(ifdi_tx_queues_alloc, ixgbe_if_tx_queues_alloc),
263c19c7afeSEric Joyner 	DEVMETHOD(ifdi_rx_queues_alloc, ixgbe_if_rx_queues_alloc),
264c19c7afeSEric Joyner 	DEVMETHOD(ifdi_queues_free, ixgbe_if_queues_free),
265c19c7afeSEric Joyner 	DEVMETHOD(ifdi_update_admin_status, ixgbe_if_update_admin_status),
266c19c7afeSEric Joyner 	DEVMETHOD(ifdi_multi_set, ixgbe_if_multi_set),
267c19c7afeSEric Joyner 	DEVMETHOD(ifdi_mtu_set, ixgbe_if_mtu_set),
268c19c7afeSEric Joyner 	DEVMETHOD(ifdi_crcstrip_set, ixgbe_if_crcstrip_set),
269c19c7afeSEric Joyner 	DEVMETHOD(ifdi_media_status, ixgbe_if_media_status),
270c19c7afeSEric Joyner 	DEVMETHOD(ifdi_media_change, ixgbe_if_media_change),
271c19c7afeSEric Joyner 	DEVMETHOD(ifdi_promisc_set, ixgbe_if_promisc_set),
272c19c7afeSEric Joyner 	DEVMETHOD(ifdi_timer, ixgbe_if_timer),
273c19c7afeSEric Joyner 	DEVMETHOD(ifdi_vlan_register, ixgbe_if_vlan_register),
274c19c7afeSEric Joyner 	DEVMETHOD(ifdi_vlan_unregister, ixgbe_if_vlan_unregister),
275c19c7afeSEric Joyner 	DEVMETHOD(ifdi_get_counter, ixgbe_if_get_counter),
276bca38080SAndrew Gallatin 	DEVMETHOD(ifdi_i2c_req, ixgbe_if_i2c_req),
277cf150917SEric Joyner 	DEVMETHOD(ifdi_needs_restart, ixgbe_if_needs_restart),
278c19c7afeSEric Joyner #ifdef PCI_IOV
279c19c7afeSEric Joyner 	DEVMETHOD(ifdi_iov_init, ixgbe_if_iov_init),
280c19c7afeSEric Joyner 	DEVMETHOD(ifdi_iov_uninit, ixgbe_if_iov_uninit),
281c19c7afeSEric Joyner 	DEVMETHOD(ifdi_iov_vf_add, ixgbe_if_iov_vf_add),
282c19c7afeSEric Joyner #endif /* PCI_IOV */
283c19c7afeSEric Joyner 	DEVMETHOD_END
284c19c7afeSEric Joyner };
285758cc3dcSJack F Vogel 
286758cc3dcSJack F Vogel /*
2878eb6488eSEric Joyner  * TUNEABLE PARAMETERS:
288758cc3dcSJack F Vogel  */
289758cc3dcSJack F Vogel 
29020b91f0aSPawel Biernacki static SYSCTL_NODE(_hw, OID_AUTO, ix, CTLFLAG_RD | CTLFLAG_MPSAFE, 0,
29120b91f0aSPawel Biernacki     "IXGBE driver parameters");
292c19c7afeSEric Joyner static driver_t ixgbe_if_driver = {
293c19c7afeSEric Joyner   "ixgbe_if", ixgbe_if_methods, sizeof(struct adapter)
294c19c7afeSEric Joyner };
295758cc3dcSJack F Vogel 
296758cc3dcSJack F Vogel static int ixgbe_max_interrupt_rate = (4000000 / IXGBE_LOW_LATENCY);
297758cc3dcSJack F Vogel SYSCTL_INT(_hw_ix, OID_AUTO, max_interrupt_rate, CTLFLAG_RDTUN,
298758cc3dcSJack F Vogel     &ixgbe_max_interrupt_rate, 0, "Maximum interrupts per second");
299758cc3dcSJack F Vogel 
300f2c4db54SSteven Hartland /* Flow control setting, default to full */
301f2c4db54SSteven Hartland static int ixgbe_flow_control = ixgbe_fc_full;
302f2c4db54SSteven Hartland SYSCTL_INT(_hw_ix, OID_AUTO, flow_control, CTLFLAG_RDTUN,
303f2c4db54SSteven Hartland     &ixgbe_flow_control, 0, "Default flow control used for all adapters");
304f2c4db54SSteven Hartland 
305f2c4db54SSteven Hartland /* Advertise Speed, default to 0 (auto) */
306f2c4db54SSteven Hartland static int ixgbe_advertise_speed = 0;
307f2c4db54SSteven Hartland SYSCTL_INT(_hw_ix, OID_AUTO, advertise_speed, CTLFLAG_RDTUN,
308f2c4db54SSteven Hartland     &ixgbe_advertise_speed, 0, "Default advertised speed for all adapters");
309f2c4db54SSteven Hartland 
310758cc3dcSJack F Vogel /*
3118eb6488eSEric Joyner  * Smart speed setting, default to on
3128eb6488eSEric Joyner  * this only works as a compile option
3138eb6488eSEric Joyner  * right now as its during attach, set
3148eb6488eSEric Joyner  * this to 'ixgbe_smart_speed_off' to
3158eb6488eSEric Joyner  * disable.
316758cc3dcSJack F Vogel  */
317758cc3dcSJack F Vogel static int ixgbe_smart_speed = ixgbe_smart_speed_on;
318758cc3dcSJack F Vogel 
319758cc3dcSJack F Vogel /*
3208eb6488eSEric Joyner  * MSI-X should be the default for best performance,
321758cc3dcSJack F Vogel  * but this allows it to be forced off for testing.
322758cc3dcSJack F Vogel  */
323758cc3dcSJack F Vogel static int ixgbe_enable_msix = 1;
324758cc3dcSJack F Vogel SYSCTL_INT(_hw_ix, OID_AUTO, enable_msix, CTLFLAG_RDTUN, &ixgbe_enable_msix, 0,
325758cc3dcSJack F Vogel     "Enable MSI-X interrupts");
326758cc3dcSJack F Vogel 
327758cc3dcSJack F Vogel /*
3288eb6488eSEric Joyner  * Defining this on will allow the use
3298eb6488eSEric Joyner  * of unsupported SFP+ modules, note that
3308eb6488eSEric Joyner  * doing so you are on your own :)
331758cc3dcSJack F Vogel  */
332758cc3dcSJack F Vogel static int allow_unsupported_sfp = FALSE;
333fb6aa95dSSean Bruno SYSCTL_INT(_hw_ix, OID_AUTO, unsupported_sfp, CTLFLAG_RDTUN,
3348eb6488eSEric Joyner     &allow_unsupported_sfp, 0,
3358eb6488eSEric Joyner     "Allow unsupported SFP modules...use at your own risk");
3368eb6488eSEric Joyner 
3378eb6488eSEric Joyner /*
3388eb6488eSEric Joyner  * Not sure if Flow Director is fully baked,
3398eb6488eSEric Joyner  * so we'll default to turning it off.
3408eb6488eSEric Joyner  */
3418eb6488eSEric Joyner static int ixgbe_enable_fdir = 0;
3428eb6488eSEric Joyner SYSCTL_INT(_hw_ix, OID_AUTO, enable_fdir, CTLFLAG_RDTUN, &ixgbe_enable_fdir, 0,
3438eb6488eSEric Joyner     "Enable Flow Director");
3448eb6488eSEric Joyner 
3458eb6488eSEric Joyner /* Receive-Side Scaling */
3468eb6488eSEric Joyner static int ixgbe_enable_rss = 1;
3478eb6488eSEric Joyner SYSCTL_INT(_hw_ix, OID_AUTO, enable_rss, CTLFLAG_RDTUN, &ixgbe_enable_rss, 0,
3488eb6488eSEric Joyner     "Enable Receive-Side Scaling (RSS)");
349758cc3dcSJack F Vogel 
350c19c7afeSEric Joyner #if 0
351758cc3dcSJack F Vogel /* Keep running tab on them for sanity check */
352758cc3dcSJack F Vogel static int ixgbe_total_ports;
353c19c7afeSEric Joyner #endif
354758cc3dcSJack F Vogel 
3558eb6488eSEric Joyner MALLOC_DEFINE(M_IXGBE, "ix", "ix driver allocations");
356758cc3dcSJack F Vogel 
357c19c7afeSEric Joyner /*
358c19c7afeSEric Joyner  * For Flow Director: this is the number of TX packets we sample
359c19c7afeSEric Joyner  * for the filter pool, this means every 20th packet will be probed.
360c19c7afeSEric Joyner  *
361c19c7afeSEric Joyner  * This feature can be disabled by setting this to 0.
362c19c7afeSEric Joyner  */
363c19c7afeSEric Joyner static int atr_sample_rate = 20;
364c19c7afeSEric Joyner 
365c19c7afeSEric Joyner extern struct if_txrx ixgbe_txrx;
366c19c7afeSEric Joyner 
367c19c7afeSEric Joyner static struct if_shared_ctx ixgbe_sctx_init = {
368c19c7afeSEric Joyner 	.isc_magic = IFLIB_MAGIC,
369c19c7afeSEric Joyner 	.isc_q_align = PAGE_SIZE,/* max(DBA_ALIGN, PAGE_SIZE) */
3707f87c040SMarius Strobl 	.isc_tx_maxsize = IXGBE_TSO_SIZE + sizeof(struct ether_vlan_header),
371c19c7afeSEric Joyner 	.isc_tx_maxsegsize = PAGE_SIZE,
3727f87c040SMarius Strobl 	.isc_tso_maxsize = IXGBE_TSO_SIZE + sizeof(struct ether_vlan_header),
3737f87c040SMarius Strobl 	.isc_tso_maxsegsize = PAGE_SIZE,
374c19c7afeSEric Joyner 	.isc_rx_maxsize = PAGE_SIZE*4,
375c19c7afeSEric Joyner 	.isc_rx_nsegments = 1,
376c19c7afeSEric Joyner 	.isc_rx_maxsegsize = PAGE_SIZE*4,
377c19c7afeSEric Joyner 	.isc_nfl = 1,
378c19c7afeSEric Joyner 	.isc_ntxqs = 1,
379c19c7afeSEric Joyner 	.isc_nrxqs = 1,
380c19c7afeSEric Joyner 
381c19c7afeSEric Joyner 	.isc_admin_intrcnt = 1,
382c19c7afeSEric Joyner 	.isc_vendor_info = ixgbe_vendor_info_array,
383c19c7afeSEric Joyner 	.isc_driver_version = ixgbe_driver_version,
384c19c7afeSEric Joyner 	.isc_driver = &ixgbe_if_driver,
3857aad1f4eSEric Joyner 	.isc_flags = IFLIB_TSO_INIT_IP,
386c19c7afeSEric Joyner 
387c19c7afeSEric Joyner 	.isc_nrxd_min = {MIN_RXD},
388c19c7afeSEric Joyner 	.isc_ntxd_min = {MIN_TXD},
389c19c7afeSEric Joyner 	.isc_nrxd_max = {MAX_RXD},
390c19c7afeSEric Joyner 	.isc_ntxd_max = {MAX_TXD},
391c19c7afeSEric Joyner 	.isc_nrxd_default = {DEFAULT_RXD},
392c19c7afeSEric Joyner 	.isc_ntxd_default = {DEFAULT_TXD},
393c19c7afeSEric Joyner };
394c19c7afeSEric Joyner 
395c19c7afeSEric Joyner if_shared_ctx_t ixgbe_sctx = &ixgbe_sctx_init;
396c19c7afeSEric Joyner 
397c19c7afeSEric Joyner /************************************************************************
398c19c7afeSEric Joyner  * ixgbe_if_tx_queues_alloc
399c19c7afeSEric Joyner  ************************************************************************/
400c19c7afeSEric Joyner static int
401c19c7afeSEric Joyner ixgbe_if_tx_queues_alloc(if_ctx_t ctx, caddr_t *vaddrs, uint64_t *paddrs,
402c19c7afeSEric Joyner                          int ntxqs, int ntxqsets)
403c19c7afeSEric Joyner {
404c19c7afeSEric Joyner 	struct adapter     *adapter = iflib_get_softc(ctx);
405c19c7afeSEric Joyner 	if_softc_ctx_t     scctx = adapter->shared;
406c19c7afeSEric Joyner 	struct ix_tx_queue *que;
407c19c7afeSEric Joyner 	int                i, j, error;
408c19c7afeSEric Joyner 
409c19c7afeSEric Joyner 	MPASS(adapter->num_tx_queues > 0);
410c19c7afeSEric Joyner 	MPASS(adapter->num_tx_queues == ntxqsets);
411c19c7afeSEric Joyner 	MPASS(ntxqs == 1);
412c19c7afeSEric Joyner 
413c19c7afeSEric Joyner 	/* Allocate queue structure memory */
414c19c7afeSEric Joyner 	adapter->tx_queues =
415c19c7afeSEric Joyner 	    (struct ix_tx_queue *)malloc(sizeof(struct ix_tx_queue) * ntxqsets,
416c19c7afeSEric Joyner 	                                 M_IXGBE, M_NOWAIT | M_ZERO);
417c19c7afeSEric Joyner 	if (!adapter->tx_queues) {
418c19c7afeSEric Joyner 		device_printf(iflib_get_dev(ctx),
419c19c7afeSEric Joyner 		    "Unable to allocate TX ring memory\n");
420c19c7afeSEric Joyner 		return (ENOMEM);
421c19c7afeSEric Joyner 	}
422c19c7afeSEric Joyner 
423c19c7afeSEric Joyner 	for (i = 0, que = adapter->tx_queues; i < ntxqsets; i++, que++) {
424c19c7afeSEric Joyner 		struct tx_ring *txr = &que->txr;
425c19c7afeSEric Joyner 
426c19c7afeSEric Joyner 		/* In case SR-IOV is enabled, align the index properly */
427c19c7afeSEric Joyner 		txr->me = ixgbe_vf_que_index(adapter->iov_mode, adapter->pool,
428c19c7afeSEric Joyner 		    i);
429c19c7afeSEric Joyner 
430c19c7afeSEric Joyner 		txr->adapter = que->adapter = adapter;
431c19c7afeSEric Joyner 
432c19c7afeSEric Joyner 		/* Allocate report status array */
433c19c7afeSEric Joyner 		txr->tx_rsq = (qidx_t *)malloc(sizeof(qidx_t) * scctx->isc_ntxd[0], M_IXGBE, M_NOWAIT | M_ZERO);
434c19c7afeSEric Joyner 		if (txr->tx_rsq == NULL) {
435c19c7afeSEric Joyner 			error = ENOMEM;
436c19c7afeSEric Joyner 			goto fail;
437c19c7afeSEric Joyner 		}
438c19c7afeSEric Joyner 		for (j = 0; j < scctx->isc_ntxd[0]; j++)
439c19c7afeSEric Joyner 			txr->tx_rsq[j] = QIDX_INVALID;
440c19c7afeSEric Joyner 		/* get the virtual and physical address of the hardware queues */
441c19c7afeSEric Joyner 		txr->tail = IXGBE_TDT(txr->me);
442c19c7afeSEric Joyner 		txr->tx_base = (union ixgbe_adv_tx_desc *)vaddrs[i];
443c19c7afeSEric Joyner 		txr->tx_paddr = paddrs[i];
444c19c7afeSEric Joyner 
445c19c7afeSEric Joyner 		txr->bytes = 0;
446c19c7afeSEric Joyner 		txr->total_packets = 0;
447c19c7afeSEric Joyner 
448c19c7afeSEric Joyner 		/* Set the rate at which we sample packets */
449c19c7afeSEric Joyner 		if (adapter->feat_en & IXGBE_FEATURE_FDIR)
450c19c7afeSEric Joyner 			txr->atr_sample = atr_sample_rate;
451c19c7afeSEric Joyner 
452c19c7afeSEric Joyner 	}
453c19c7afeSEric Joyner 
454c19c7afeSEric Joyner 	device_printf(iflib_get_dev(ctx), "allocated for %d queues\n",
455c19c7afeSEric Joyner 	    adapter->num_tx_queues);
456c19c7afeSEric Joyner 
457c19c7afeSEric Joyner 	return (0);
458c19c7afeSEric Joyner 
459c19c7afeSEric Joyner fail:
460c19c7afeSEric Joyner 	ixgbe_if_queues_free(ctx);
461c19c7afeSEric Joyner 
462c19c7afeSEric Joyner 	return (error);
463c19c7afeSEric Joyner } /* ixgbe_if_tx_queues_alloc */
464c19c7afeSEric Joyner 
465c19c7afeSEric Joyner /************************************************************************
466c19c7afeSEric Joyner  * ixgbe_if_rx_queues_alloc
467c19c7afeSEric Joyner  ************************************************************************/
468c19c7afeSEric Joyner static int
469c19c7afeSEric Joyner ixgbe_if_rx_queues_alloc(if_ctx_t ctx, caddr_t *vaddrs, uint64_t *paddrs,
470c19c7afeSEric Joyner                          int nrxqs, int nrxqsets)
471c19c7afeSEric Joyner {
472c19c7afeSEric Joyner 	struct adapter     *adapter = iflib_get_softc(ctx);
473c19c7afeSEric Joyner 	struct ix_rx_queue *que;
474c19c7afeSEric Joyner 	int                i;
475c19c7afeSEric Joyner 
476c19c7afeSEric Joyner 	MPASS(adapter->num_rx_queues > 0);
477c19c7afeSEric Joyner 	MPASS(adapter->num_rx_queues == nrxqsets);
478c19c7afeSEric Joyner 	MPASS(nrxqs == 1);
479c19c7afeSEric Joyner 
480c19c7afeSEric Joyner 	/* Allocate queue structure memory */
481c19c7afeSEric Joyner 	adapter->rx_queues =
482c19c7afeSEric Joyner 	    (struct ix_rx_queue *)malloc(sizeof(struct ix_rx_queue)*nrxqsets,
483c19c7afeSEric Joyner 	                                 M_IXGBE, M_NOWAIT | M_ZERO);
484c19c7afeSEric Joyner 	if (!adapter->rx_queues) {
485c19c7afeSEric Joyner 		device_printf(iflib_get_dev(ctx),
486c19c7afeSEric Joyner 		    "Unable to allocate TX ring memory\n");
487c19c7afeSEric Joyner 		return (ENOMEM);
488c19c7afeSEric Joyner 	}
489c19c7afeSEric Joyner 
490c19c7afeSEric Joyner 	for (i = 0, que = adapter->rx_queues; i < nrxqsets; i++, que++) {
491c19c7afeSEric Joyner 		struct rx_ring *rxr = &que->rxr;
492c19c7afeSEric Joyner 
493c19c7afeSEric Joyner 		/* In case SR-IOV is enabled, align the index properly */
494c19c7afeSEric Joyner 		rxr->me = ixgbe_vf_que_index(adapter->iov_mode, adapter->pool,
495c19c7afeSEric Joyner 		    i);
496c19c7afeSEric Joyner 
497c19c7afeSEric Joyner 		rxr->adapter = que->adapter = adapter;
498c19c7afeSEric Joyner 
499c19c7afeSEric Joyner 		/* get the virtual and physical address of the hw queues */
500c19c7afeSEric Joyner 		rxr->tail = IXGBE_RDT(rxr->me);
501c19c7afeSEric Joyner 		rxr->rx_base = (union ixgbe_adv_rx_desc *)vaddrs[i];
502c19c7afeSEric Joyner 		rxr->rx_paddr = paddrs[i];
503c19c7afeSEric Joyner 		rxr->bytes = 0;
504c19c7afeSEric Joyner 		rxr->que = que;
505c19c7afeSEric Joyner 	}
506c19c7afeSEric Joyner 
507c19c7afeSEric Joyner 	device_printf(iflib_get_dev(ctx), "allocated for %d rx queues\n",
508c19c7afeSEric Joyner 	    adapter->num_rx_queues);
509c19c7afeSEric Joyner 
510c19c7afeSEric Joyner 	return (0);
511c19c7afeSEric Joyner } /* ixgbe_if_rx_queues_alloc */
512c19c7afeSEric Joyner 
513c19c7afeSEric Joyner /************************************************************************
514c19c7afeSEric Joyner  * ixgbe_if_queues_free
515c19c7afeSEric Joyner  ************************************************************************/
516c19c7afeSEric Joyner static void
517c19c7afeSEric Joyner ixgbe_if_queues_free(if_ctx_t ctx)
518c19c7afeSEric Joyner {
519c19c7afeSEric Joyner 	struct adapter     *adapter = iflib_get_softc(ctx);
520c19c7afeSEric Joyner 	struct ix_tx_queue *tx_que = adapter->tx_queues;
521c19c7afeSEric Joyner 	struct ix_rx_queue *rx_que = adapter->rx_queues;
522c19c7afeSEric Joyner 	int                i;
523c19c7afeSEric Joyner 
524c19c7afeSEric Joyner 	if (tx_que != NULL) {
525c19c7afeSEric Joyner 		for (i = 0; i < adapter->num_tx_queues; i++, tx_que++) {
526c19c7afeSEric Joyner 			struct tx_ring *txr = &tx_que->txr;
527c19c7afeSEric Joyner 			if (txr->tx_rsq == NULL)
528c19c7afeSEric Joyner 				break;
529c19c7afeSEric Joyner 
530c19c7afeSEric Joyner 			free(txr->tx_rsq, M_IXGBE);
531c19c7afeSEric Joyner 			txr->tx_rsq = NULL;
532c19c7afeSEric Joyner 		}
533c19c7afeSEric Joyner 
534c19c7afeSEric Joyner 		free(adapter->tx_queues, M_IXGBE);
535c19c7afeSEric Joyner 		adapter->tx_queues = NULL;
536c19c7afeSEric Joyner 	}
537c19c7afeSEric Joyner 	if (rx_que != NULL) {
538c19c7afeSEric Joyner 		free(adapter->rx_queues, M_IXGBE);
539c19c7afeSEric Joyner 		adapter->rx_queues = NULL;
540c19c7afeSEric Joyner 	}
541c19c7afeSEric Joyner } /* ixgbe_if_queues_free */
542c19c7afeSEric Joyner 
5438eb6488eSEric Joyner /************************************************************************
5448eb6488eSEric Joyner  * ixgbe_initialize_rss_mapping
5458eb6488eSEric Joyner  ************************************************************************/
5468eb6488eSEric Joyner static void
5478eb6488eSEric Joyner ixgbe_initialize_rss_mapping(struct adapter *adapter)
548758cc3dcSJack F Vogel {
5496f37f232SEric Joyner 	struct ixgbe_hw *hw = &adapter->hw;
5508eb6488eSEric Joyner 	u32             reta = 0, mrqc, rss_key[10];
5518eb6488eSEric Joyner 	int             queue_id, table_size, index_mult;
5528eb6488eSEric Joyner 	int             i, j;
5538eb6488eSEric Joyner 	u32             rss_hash_config;
5546f37f232SEric Joyner 
5558eb6488eSEric Joyner 	if (adapter->feat_en & IXGBE_FEATURE_RSS) {
5568eb6488eSEric Joyner 		/* Fetch the configured RSS key */
5578eb6488eSEric Joyner 		rss_getkey((uint8_t *)&rss_key);
558758cc3dcSJack F Vogel 	} else {
5598eb6488eSEric Joyner 		/* set up random bits */
5608eb6488eSEric Joyner 		arc4rand(&rss_key, sizeof(rss_key), 0);
561758cc3dcSJack F Vogel 	}
562758cc3dcSJack F Vogel 
5638eb6488eSEric Joyner 	/* Set multiplier for RETA setup and table size based on MAC */
5648eb6488eSEric Joyner 	index_mult = 0x1;
5658eb6488eSEric Joyner 	table_size = 128;
5668eb6488eSEric Joyner 	switch (adapter->hw.mac.type) {
5678eb6488eSEric Joyner 	case ixgbe_mac_82598EB:
5688eb6488eSEric Joyner 		index_mult = 0x11;
569758cc3dcSJack F Vogel 		break;
5708eb6488eSEric Joyner 	case ixgbe_mac_X550:
5718eb6488eSEric Joyner 	case ixgbe_mac_X550EM_x:
5728eb6488eSEric Joyner 	case ixgbe_mac_X550EM_a:
5738eb6488eSEric Joyner 		table_size = 512;
5748eb6488eSEric Joyner 		break;
575758cc3dcSJack F Vogel 	default:
576758cc3dcSJack F Vogel 		break;
577758cc3dcSJack F Vogel 	}
578758cc3dcSJack F Vogel 
5798eb6488eSEric Joyner 	/* Set up the redirection table */
5808eb6488eSEric Joyner 	for (i = 0, j = 0; i < table_size; i++, j++) {
581c19c7afeSEric Joyner 		if (j == adapter->num_rx_queues)
5828eb6488eSEric Joyner 			j = 0;
583758cc3dcSJack F Vogel 
5848eb6488eSEric Joyner 		if (adapter->feat_en & IXGBE_FEATURE_RSS) {
585a9ca1c79SSean Bruno 			/*
5868eb6488eSEric Joyner 			 * Fetch the RSS bucket id for the given indirection
5878eb6488eSEric Joyner 			 * entry. Cap it at the number of configured buckets
588c19c7afeSEric Joyner 			 * (which is num_rx_queues.)
589a9ca1c79SSean Bruno 			 */
5908eb6488eSEric Joyner 			queue_id = rss_get_indirection_to_bucket(i);
591c19c7afeSEric Joyner 			queue_id = queue_id % adapter->num_rx_queues;
592758cc3dcSJack F Vogel 		} else
5938eb6488eSEric Joyner 			queue_id = (j * index_mult);
5948eb6488eSEric Joyner 
5958eb6488eSEric Joyner 		/*
5968eb6488eSEric Joyner 		 * The low 8 bits are for hash value (n+0);
5978eb6488eSEric Joyner 		 * The next 8 bits are for hash value (n+1), etc.
5988eb6488eSEric Joyner 		 */
5998eb6488eSEric Joyner 		reta = reta >> 8;
6008eb6488eSEric Joyner 		reta = reta | (((uint32_t)queue_id) << 24);
6018eb6488eSEric Joyner 		if ((i & 3) == 3) {
6028eb6488eSEric Joyner 			if (i < 128)
6038eb6488eSEric Joyner 				IXGBE_WRITE_REG(hw, IXGBE_RETA(i >> 2), reta);
6048eb6488eSEric Joyner 			else
6058eb6488eSEric Joyner 				IXGBE_WRITE_REG(hw, IXGBE_ERETA((i >> 2) - 32),
6068eb6488eSEric Joyner 				    reta);
6078eb6488eSEric Joyner 			reta = 0;
6088eb6488eSEric Joyner 		}
609758cc3dcSJack F Vogel 	}
610758cc3dcSJack F Vogel 
6118eb6488eSEric Joyner 	/* Now fill our hash function seeds */
6128eb6488eSEric Joyner 	for (i = 0; i < 10; i++)
6138eb6488eSEric Joyner 		IXGBE_WRITE_REG(hw, IXGBE_RSSRK(i), rss_key[i]);
614758cc3dcSJack F Vogel 
6158eb6488eSEric Joyner 	/* Perform hash on these packet types */
6168eb6488eSEric Joyner 	if (adapter->feat_en & IXGBE_FEATURE_RSS)
6178eb6488eSEric Joyner 		rss_hash_config = rss_gethashconfig();
618758cc3dcSJack F Vogel 	else {
619758cc3dcSJack F Vogel 		/*
6208eb6488eSEric Joyner 		 * Disable UDP - IP fragments aren't currently being handled
6218eb6488eSEric Joyner 		 * and so we end up with a mix of 2-tuple and 4-tuple
6228eb6488eSEric Joyner 		 * traffic.
623758cc3dcSJack F Vogel 		 */
6248eb6488eSEric Joyner 		rss_hash_config = RSS_HASHTYPE_RSS_IPV4
6258eb6488eSEric Joyner 		                | RSS_HASHTYPE_RSS_TCP_IPV4
6268eb6488eSEric Joyner 		                | RSS_HASHTYPE_RSS_IPV6
6278eb6488eSEric Joyner 		                | RSS_HASHTYPE_RSS_TCP_IPV6
6288eb6488eSEric Joyner 		                | RSS_HASHTYPE_RSS_IPV6_EX
6298eb6488eSEric Joyner 		                | RSS_HASHTYPE_RSS_TCP_IPV6_EX;
630758cc3dcSJack F Vogel 	}
631758cc3dcSJack F Vogel 
6328eb6488eSEric Joyner 	mrqc = IXGBE_MRQC_RSSEN;
6338eb6488eSEric Joyner 	if (rss_hash_config & RSS_HASHTYPE_RSS_IPV4)
6348eb6488eSEric Joyner 		mrqc |= IXGBE_MRQC_RSS_FIELD_IPV4;
6358eb6488eSEric Joyner 	if (rss_hash_config & RSS_HASHTYPE_RSS_TCP_IPV4)
6368eb6488eSEric Joyner 		mrqc |= IXGBE_MRQC_RSS_FIELD_IPV4_TCP;
6378eb6488eSEric Joyner 	if (rss_hash_config & RSS_HASHTYPE_RSS_IPV6)
6388eb6488eSEric Joyner 		mrqc |= IXGBE_MRQC_RSS_FIELD_IPV6;
6398eb6488eSEric Joyner 	if (rss_hash_config & RSS_HASHTYPE_RSS_TCP_IPV6)
6408eb6488eSEric Joyner 		mrqc |= IXGBE_MRQC_RSS_FIELD_IPV6_TCP;
6418eb6488eSEric Joyner 	if (rss_hash_config & RSS_HASHTYPE_RSS_IPV6_EX)
6428eb6488eSEric Joyner 		mrqc |= IXGBE_MRQC_RSS_FIELD_IPV6_EX;
6438eb6488eSEric Joyner 	if (rss_hash_config & RSS_HASHTYPE_RSS_TCP_IPV6_EX)
6448eb6488eSEric Joyner 		mrqc |= IXGBE_MRQC_RSS_FIELD_IPV6_EX_TCP;
6458eb6488eSEric Joyner 	if (rss_hash_config & RSS_HASHTYPE_RSS_UDP_IPV4)
6468eb6488eSEric Joyner 		mrqc |= IXGBE_MRQC_RSS_FIELD_IPV4_UDP;
6478eb6488eSEric Joyner 	if (rss_hash_config & RSS_HASHTYPE_RSS_UDP_IPV6)
6488eb6488eSEric Joyner 		mrqc |= IXGBE_MRQC_RSS_FIELD_IPV6_UDP;
6498eb6488eSEric Joyner 	if (rss_hash_config & RSS_HASHTYPE_RSS_UDP_IPV6_EX)
6508eb6488eSEric Joyner 		mrqc |= IXGBE_MRQC_RSS_FIELD_IPV6_EX_UDP;
6518eb6488eSEric Joyner 	mrqc |= ixgbe_get_mrqc(adapter->iov_mode);
6528eb6488eSEric Joyner 	IXGBE_WRITE_REG(hw, IXGBE_MRQC, mrqc);
6538eb6488eSEric Joyner } /* ixgbe_initialize_rss_mapping */
654758cc3dcSJack F Vogel 
6558eb6488eSEric Joyner /************************************************************************
6568eb6488eSEric Joyner  * ixgbe_initialize_receive_units - Setup receive registers and features.
6578eb6488eSEric Joyner  ************************************************************************/
6588eb6488eSEric Joyner #define BSIZEPKT_ROUNDUP ((1<<IXGBE_SRRCTL_BSIZEPKT_SHIFT)-1)
659758cc3dcSJack F Vogel 
660758cc3dcSJack F Vogel static void
661c19c7afeSEric Joyner ixgbe_initialize_receive_units(if_ctx_t ctx)
662758cc3dcSJack F Vogel {
663c19c7afeSEric Joyner 	struct adapter     *adapter = iflib_get_softc(ctx);
664c19c7afeSEric Joyner 	if_softc_ctx_t     scctx = adapter->shared;
66548056c88SJack F Vogel 	struct ixgbe_hw    *hw = &adapter->hw;
666c19c7afeSEric Joyner 	struct ifnet       *ifp = iflib_get_ifp(ctx);
667c19c7afeSEric Joyner 	struct ix_rx_queue *que;
6688eb6488eSEric Joyner 	int                i, j;
6698eb6488eSEric Joyner 	u32                bufsz, fctrl, srrctl, rxcsum;
6708eb6488eSEric Joyner 	u32                hlreg;
67148056c88SJack F Vogel 
67248056c88SJack F Vogel 	/*
6738eb6488eSEric Joyner 	 * Make sure receives are disabled while
6748eb6488eSEric Joyner 	 * setting up the descriptor ring
67548056c88SJack F Vogel 	 */
6768eb6488eSEric Joyner 	ixgbe_disable_rx(hw);
6778eb6488eSEric Joyner 
6788eb6488eSEric Joyner 	/* Enable broadcasts */
6798eb6488eSEric Joyner 	fctrl = IXGBE_READ_REG(hw, IXGBE_FCTRL);
6808eb6488eSEric Joyner 	fctrl |= IXGBE_FCTRL_BAM;
6818eb6488eSEric Joyner 	if (adapter->hw.mac.type == ixgbe_mac_82598EB) {
6828eb6488eSEric Joyner 		fctrl |= IXGBE_FCTRL_DPF;
6838eb6488eSEric Joyner 		fctrl |= IXGBE_FCTRL_PMCF;
68448056c88SJack F Vogel 	}
6858eb6488eSEric Joyner 	IXGBE_WRITE_REG(hw, IXGBE_FCTRL, fctrl);
6868eb6488eSEric Joyner 
6878eb6488eSEric Joyner 	/* Set for Jumbo Frames? */
6888eb6488eSEric Joyner 	hlreg = IXGBE_READ_REG(hw, IXGBE_HLREG0);
6898eb6488eSEric Joyner 	if (ifp->if_mtu > ETHERMTU)
6908eb6488eSEric Joyner 		hlreg |= IXGBE_HLREG0_JUMBOEN;
6918eb6488eSEric Joyner 	else
6928eb6488eSEric Joyner 		hlreg &= ~IXGBE_HLREG0_JUMBOEN;
6938eb6488eSEric Joyner 	IXGBE_WRITE_REG(hw, IXGBE_HLREG0, hlreg);
6948eb6488eSEric Joyner 
6958eb6488eSEric Joyner 	bufsz = (adapter->rx_mbuf_sz + BSIZEPKT_ROUNDUP) >>
6968eb6488eSEric Joyner 	    IXGBE_SRRCTL_BSIZEPKT_SHIFT;
6978eb6488eSEric Joyner 
698c19c7afeSEric Joyner 	/* Setup the Base and Length of the Rx Descriptor Ring */
699c19c7afeSEric Joyner 	for (i = 0, que = adapter->rx_queues; i < adapter->num_rx_queues; i++, que++) {
700c19c7afeSEric Joyner 		struct rx_ring *rxr = &que->rxr;
701c19c7afeSEric Joyner 		u64            rdba = rxr->rx_paddr;
702c19c7afeSEric Joyner 
7038eb6488eSEric Joyner 		j = rxr->me;
7048eb6488eSEric Joyner 
7058eb6488eSEric Joyner 		/* Setup the Base and Length of the Rx Descriptor Ring */
7068eb6488eSEric Joyner 		IXGBE_WRITE_REG(hw, IXGBE_RDBAL(j),
7078eb6488eSEric Joyner 		    (rdba & 0x00000000ffffffffULL));
7088eb6488eSEric Joyner 		IXGBE_WRITE_REG(hw, IXGBE_RDBAH(j), (rdba >> 32));
7098eb6488eSEric Joyner 		IXGBE_WRITE_REG(hw, IXGBE_RDLEN(j),
710c19c7afeSEric Joyner 		     scctx->isc_nrxd[0] * sizeof(union ixgbe_adv_rx_desc));
7118eb6488eSEric Joyner 
7128eb6488eSEric Joyner 		/* Set up the SRRCTL register */
7138eb6488eSEric Joyner 		srrctl = IXGBE_READ_REG(hw, IXGBE_SRRCTL(j));
7148eb6488eSEric Joyner 		srrctl &= ~IXGBE_SRRCTL_BSIZEHDR_MASK;
7158eb6488eSEric Joyner 		srrctl &= ~IXGBE_SRRCTL_BSIZEPKT_MASK;
7168eb6488eSEric Joyner 		srrctl |= bufsz;
7178eb6488eSEric Joyner 		srrctl |= IXGBE_SRRCTL_DESCTYPE_ADV_ONEBUF;
71848056c88SJack F Vogel 
71948056c88SJack F Vogel 		/*
7208eb6488eSEric Joyner 		 * Set DROP_EN iff we have no flow control and >1 queue.
7218eb6488eSEric Joyner 		 * Note that srrctl was cleared shortly before during reset,
7228eb6488eSEric Joyner 		 * so we do not need to clear the bit, but do it just in case
7238eb6488eSEric Joyner 		 * this code is moved elsewhere.
72448056c88SJack F Vogel 		 */
725c19c7afeSEric Joyner 		if (adapter->num_rx_queues > 1 &&
7268eb6488eSEric Joyner 		    adapter->hw.fc.requested_mode == ixgbe_fc_none) {
7278eb6488eSEric Joyner 			srrctl |= IXGBE_SRRCTL_DROP_EN;
728758cc3dcSJack F Vogel 		} else {
7298eb6488eSEric Joyner 			srrctl &= ~IXGBE_SRRCTL_DROP_EN;
730758cc3dcSJack F Vogel 		}
731758cc3dcSJack F Vogel 
7328eb6488eSEric Joyner 		IXGBE_WRITE_REG(hw, IXGBE_SRRCTL(j), srrctl);
733758cc3dcSJack F Vogel 
7348eb6488eSEric Joyner 		/* Setup the HW Rx Head and Tail Descriptor Pointers */
7358eb6488eSEric Joyner 		IXGBE_WRITE_REG(hw, IXGBE_RDH(j), 0);
7368eb6488eSEric Joyner 		IXGBE_WRITE_REG(hw, IXGBE_RDT(j), 0);
737758cc3dcSJack F Vogel 
7388eb6488eSEric Joyner 		/* Set the driver rx tail address */
7398eb6488eSEric Joyner 		rxr->tail =  IXGBE_RDT(rxr->me);
740a9ca1c79SSean Bruno 	}
741758cc3dcSJack F Vogel 
742758cc3dcSJack F Vogel 	if (adapter->hw.mac.type != ixgbe_mac_82598EB) {
7438eb6488eSEric Joyner 		u32 psrtype = IXGBE_PSRTYPE_TCPHDR
7448eb6488eSEric Joyner 		            | IXGBE_PSRTYPE_UDPHDR
7458eb6488eSEric Joyner 		            | IXGBE_PSRTYPE_IPV4HDR
7468eb6488eSEric Joyner 		            | IXGBE_PSRTYPE_IPV6HDR;
7478eb6488eSEric Joyner 		IXGBE_WRITE_REG(hw, IXGBE_PSRTYPE(0), psrtype);
7486f37f232SEric Joyner 	}
7496f37f232SEric Joyner 
7508eb6488eSEric Joyner 	rxcsum = IXGBE_READ_REG(hw, IXGBE_RXCSUM);
7518eb6488eSEric Joyner 
7528eb6488eSEric Joyner 	ixgbe_initialize_rss_mapping(adapter);
7538eb6488eSEric Joyner 
754c19c7afeSEric Joyner 	if (adapter->num_rx_queues > 1) {
7558eb6488eSEric Joyner 		/* RSS and RX IPP Checksum are mutually exclusive */
7568eb6488eSEric Joyner 		rxcsum |= IXGBE_RXCSUM_PCSD;
7576f37f232SEric Joyner 	}
7586f37f232SEric Joyner 
7598eb6488eSEric Joyner 	if (ifp->if_capenable & IFCAP_RXCSUM)
7608eb6488eSEric Joyner 		rxcsum |= IXGBE_RXCSUM_PCSD;
761758cc3dcSJack F Vogel 
7628eb6488eSEric Joyner 	/* This is useful for calculating UDP/IP fragment checksums */
7638eb6488eSEric Joyner 	if (!(rxcsum & IXGBE_RXCSUM_PCSD))
7648eb6488eSEric Joyner 		rxcsum |= IXGBE_RXCSUM_IPPCSE;
765758cc3dcSJack F Vogel 
7668eb6488eSEric Joyner 	IXGBE_WRITE_REG(hw, IXGBE_RXCSUM, rxcsum);
767758cc3dcSJack F Vogel 
7688eb6488eSEric Joyner } /* ixgbe_initialize_receive_units */
769758cc3dcSJack F Vogel 
7708eb6488eSEric Joyner /************************************************************************
7718eb6488eSEric Joyner  * ixgbe_initialize_transmit_units - Enable transmit units.
7728eb6488eSEric Joyner  ************************************************************************/
773758cc3dcSJack F Vogel static void
774c19c7afeSEric Joyner ixgbe_initialize_transmit_units(if_ctx_t ctx)
775758cc3dcSJack F Vogel {
776c19c7afeSEric Joyner 	struct adapter     *adapter = iflib_get_softc(ctx);
777758cc3dcSJack F Vogel 	struct ixgbe_hw    *hw = &adapter->hw;
778c19c7afeSEric Joyner 	if_softc_ctx_t     scctx = adapter->shared;
779c19c7afeSEric Joyner 	struct ix_tx_queue *que;
780c19c7afeSEric Joyner 	int i;
781758cc3dcSJack F Vogel 
782758cc3dcSJack F Vogel 	/* Setup the Base and Length of the Tx Descriptor Ring */
783c19c7afeSEric Joyner 	for (i = 0, que = adapter->tx_queues; i < adapter->num_tx_queues;
784c19c7afeSEric Joyner 	    i++, que++) {
785c19c7afeSEric Joyner 		struct tx_ring	   *txr = &que->txr;
786c19c7afeSEric Joyner 		u64 tdba = txr->tx_paddr;
787758cc3dcSJack F Vogel 		u32 txctrl = 0;
78848056c88SJack F Vogel 		int j = txr->me;
789758cc3dcSJack F Vogel 
79048056c88SJack F Vogel 		IXGBE_WRITE_REG(hw, IXGBE_TDBAL(j),
791758cc3dcSJack F Vogel 		    (tdba & 0x00000000ffffffffULL));
79248056c88SJack F Vogel 		IXGBE_WRITE_REG(hw, IXGBE_TDBAH(j), (tdba >> 32));
79348056c88SJack F Vogel 		IXGBE_WRITE_REG(hw, IXGBE_TDLEN(j),
794c19c7afeSEric Joyner 		    scctx->isc_ntxd[0] * sizeof(union ixgbe_adv_tx_desc));
795758cc3dcSJack F Vogel 
796758cc3dcSJack F Vogel 		/* Setup the HW Tx Head and Tail descriptor pointers */
79748056c88SJack F Vogel 		IXGBE_WRITE_REG(hw, IXGBE_TDH(j), 0);
79848056c88SJack F Vogel 		IXGBE_WRITE_REG(hw, IXGBE_TDT(j), 0);
799758cc3dcSJack F Vogel 
800758cc3dcSJack F Vogel 		/* Cache the tail address */
8012dc2d580SEric Joyner 		txr->tail = IXGBE_TDT(txr->me);
8022dc2d580SEric Joyner 
803088a0b27SEric Joyner 		txr->tx_rs_cidx = txr->tx_rs_pidx;
804088a0b27SEric Joyner 		txr->tx_cidx_processed = scctx->isc_ntxd[0] - 1;
805c19c7afeSEric Joyner 		for (int k = 0; k < scctx->isc_ntxd[0]; k++)
806c19c7afeSEric Joyner 			txr->tx_rsq[k] = QIDX_INVALID;
807758cc3dcSJack F Vogel 
808758cc3dcSJack F Vogel 		/* Disable Head Writeback */
809a9ca1c79SSean Bruno 		/*
810a9ca1c79SSean Bruno 		 * Note: for X550 series devices, these registers are actually
811a9ca1c79SSean Bruno 		 * prefixed with TPH_ isntead of DCA_, but the addresses and
812a9ca1c79SSean Bruno 		 * fields remain the same.
813a9ca1c79SSean Bruno 		 */
814758cc3dcSJack F Vogel 		switch (hw->mac.type) {
815758cc3dcSJack F Vogel 		case ixgbe_mac_82598EB:
81648056c88SJack F Vogel 			txctrl = IXGBE_READ_REG(hw, IXGBE_DCA_TXCTRL(j));
817758cc3dcSJack F Vogel 			break;
818758cc3dcSJack F Vogel 		default:
81948056c88SJack F Vogel 			txctrl = IXGBE_READ_REG(hw, IXGBE_DCA_TXCTRL_82599(j));
820758cc3dcSJack F Vogel 			break;
821758cc3dcSJack F Vogel 		}
822758cc3dcSJack F Vogel 		txctrl &= ~IXGBE_DCA_TXCTRL_DESC_WRO_EN;
823758cc3dcSJack F Vogel 		switch (hw->mac.type) {
824758cc3dcSJack F Vogel 		case ixgbe_mac_82598EB:
82548056c88SJack F Vogel 			IXGBE_WRITE_REG(hw, IXGBE_DCA_TXCTRL(j), txctrl);
826758cc3dcSJack F Vogel 			break;
827758cc3dcSJack F Vogel 		default:
82848056c88SJack F Vogel 			IXGBE_WRITE_REG(hw, IXGBE_DCA_TXCTRL_82599(j), txctrl);
829758cc3dcSJack F Vogel 			break;
830758cc3dcSJack F Vogel 		}
831758cc3dcSJack F Vogel 
832758cc3dcSJack F Vogel 	}
833758cc3dcSJack F Vogel 
834758cc3dcSJack F Vogel 	if (hw->mac.type != ixgbe_mac_82598EB) {
835758cc3dcSJack F Vogel 		u32 dmatxctl, rttdcs;
8368eb6488eSEric Joyner 
837758cc3dcSJack F Vogel 		dmatxctl = IXGBE_READ_REG(hw, IXGBE_DMATXCTL);
838758cc3dcSJack F Vogel 		dmatxctl |= IXGBE_DMATXCTL_TE;
839758cc3dcSJack F Vogel 		IXGBE_WRITE_REG(hw, IXGBE_DMATXCTL, dmatxctl);
840758cc3dcSJack F Vogel 		/* Disable arbiter to set MTQC */
841758cc3dcSJack F Vogel 		rttdcs = IXGBE_READ_REG(hw, IXGBE_RTTDCS);
842758cc3dcSJack F Vogel 		rttdcs |= IXGBE_RTTDCS_ARBDIS;
843758cc3dcSJack F Vogel 		IXGBE_WRITE_REG(hw, IXGBE_RTTDCS, rttdcs);
8448eb6488eSEric Joyner 		IXGBE_WRITE_REG(hw, IXGBE_MTQC,
8458eb6488eSEric Joyner 		    ixgbe_get_mtqc(adapter->iov_mode));
846758cc3dcSJack F Vogel 		rttdcs &= ~IXGBE_RTTDCS_ARBDIS;
847758cc3dcSJack F Vogel 		IXGBE_WRITE_REG(hw, IXGBE_RTTDCS, rttdcs);
848758cc3dcSJack F Vogel 	}
849758cc3dcSJack F Vogel 
8508eb6488eSEric Joyner } /* ixgbe_initialize_transmit_units */
851758cc3dcSJack F Vogel 
8528eb6488eSEric Joyner /************************************************************************
853c19c7afeSEric Joyner  * ixgbe_register
854c19c7afeSEric Joyner  ************************************************************************/
855c19c7afeSEric Joyner static void *
856c19c7afeSEric Joyner ixgbe_register(device_t dev)
857c19c7afeSEric Joyner {
858c19c7afeSEric Joyner 	return (ixgbe_sctx);
859c19c7afeSEric Joyner } /* ixgbe_register */
860c19c7afeSEric Joyner 
861c19c7afeSEric Joyner /************************************************************************
862c19c7afeSEric Joyner  * ixgbe_if_attach_pre - Device initialization routine, part 1
863758cc3dcSJack F Vogel  *
8648eb6488eSEric Joyner  *   Called when the driver is being loaded.
865c19c7afeSEric Joyner  *   Identifies the type of hardware, initializes the hardware,
866c19c7afeSEric Joyner  *   and initializes iflib structures.
867758cc3dcSJack F Vogel  *
8688eb6488eSEric Joyner  *   return 0 on success, positive on failure
8698eb6488eSEric Joyner  ************************************************************************/
8708eb6488eSEric Joyner static int
871c19c7afeSEric Joyner ixgbe_if_attach_pre(if_ctx_t ctx)
872758cc3dcSJack F Vogel {
8738eb6488eSEric Joyner 	struct adapter  *adapter;
874c19c7afeSEric Joyner 	device_t        dev;
875c19c7afeSEric Joyner 	if_softc_ctx_t  scctx;
8768eb6488eSEric Joyner 	struct ixgbe_hw *hw;
8778eb6488eSEric Joyner 	int             error = 0;
8788eb6488eSEric Joyner 	u32             ctrl_ext;
8798eb6488eSEric Joyner 
8808eb6488eSEric Joyner 	INIT_DEBUGOUT("ixgbe_attach: begin");
8818eb6488eSEric Joyner 
8828eb6488eSEric Joyner 	/* Allocate, clear, and link in our adapter structure */
883c19c7afeSEric Joyner 	dev = iflib_get_dev(ctx);
884c19c7afeSEric Joyner 	adapter = iflib_get_softc(ctx);
8858eb6488eSEric Joyner 	adapter->hw.back = adapter;
886c19c7afeSEric Joyner 	adapter->ctx = ctx;
8878eb6488eSEric Joyner 	adapter->dev = dev;
888c19c7afeSEric Joyner 	scctx = adapter->shared = iflib_get_softc_ctx(ctx);
889c19c7afeSEric Joyner 	adapter->media = iflib_get_media(ctx);
8908eb6488eSEric Joyner 	hw = &adapter->hw;
8918eb6488eSEric Joyner 
8928eb6488eSEric Joyner 	/* Determine hardware revision */
8938eb6488eSEric Joyner 	hw->vendor_id = pci_get_vendor(dev);
8948eb6488eSEric Joyner 	hw->device_id = pci_get_device(dev);
8958eb6488eSEric Joyner 	hw->revision_id = pci_get_revid(dev);
8968eb6488eSEric Joyner 	hw->subsystem_vendor_id = pci_get_subvendor(dev);
8978eb6488eSEric Joyner 	hw->subsystem_device_id = pci_get_subdevice(dev);
898758cc3dcSJack F Vogel 
8998eb6488eSEric Joyner 	/* Do base PCI setup - map BAR0 */
900c19c7afeSEric Joyner 	if (ixgbe_allocate_pci_resources(ctx)) {
9018eb6488eSEric Joyner 		device_printf(dev, "Allocation of PCI resources failed\n");
902c19c7afeSEric Joyner 		return (ENXIO);
9036f37f232SEric Joyner 	}
904758cc3dcSJack F Vogel 
9058eb6488eSEric Joyner 	/* let hardware know driver is loaded */
9068eb6488eSEric Joyner 	ctrl_ext = IXGBE_READ_REG(hw, IXGBE_CTRL_EXT);
9078eb6488eSEric Joyner 	ctrl_ext |= IXGBE_CTRL_EXT_DRV_LOAD;
9088eb6488eSEric Joyner 	IXGBE_WRITE_REG(hw, IXGBE_CTRL_EXT, ctrl_ext);
909758cc3dcSJack F Vogel 
910758cc3dcSJack F Vogel 	/*
9118eb6488eSEric Joyner 	 * Initialize the shared code
912758cc3dcSJack F Vogel 	 */
913c19c7afeSEric Joyner 	if (ixgbe_init_shared_code(hw) != 0) {
9148eb6488eSEric Joyner 		device_printf(dev, "Unable to initialize the shared code\n");
9158eb6488eSEric Joyner 		error = ENXIO;
916c19c7afeSEric Joyner 		goto err_pci;
91730126537SJack F Vogel 	}
918758cc3dcSJack F Vogel 
9198eb6488eSEric Joyner 	if (hw->mbx.ops.init_params)
9208eb6488eSEric Joyner 		hw->mbx.ops.init_params(hw);
921758cc3dcSJack F Vogel 
9228eb6488eSEric Joyner 	hw->allow_unsupported_sfp = allow_unsupported_sfp;
923758cc3dcSJack F Vogel 
924c19c7afeSEric Joyner 	if (hw->mac.type != ixgbe_mac_82598EB)
9258eb6488eSEric Joyner 		hw->phy.smart_speed = ixgbe_smart_speed;
9268eb6488eSEric Joyner 
9278eb6488eSEric Joyner 	ixgbe_init_device_features(adapter);
9288eb6488eSEric Joyner 
9298eb6488eSEric Joyner 	/* Enable WoL (if supported) */
9308eb6488eSEric Joyner 	ixgbe_check_wol_support(adapter);
9318eb6488eSEric Joyner 
9328eb6488eSEric Joyner 	/* Verify adapter fan is still functional (if applicable) */
9338eb6488eSEric Joyner 	if (adapter->feat_en & IXGBE_FEATURE_FAN_FAIL) {
9348eb6488eSEric Joyner 		u32 esdp = IXGBE_READ_REG(hw, IXGBE_ESDP);
9358eb6488eSEric Joyner 		ixgbe_check_fan_failure(adapter, esdp, FALSE);
9368eb6488eSEric Joyner 	}
9378eb6488eSEric Joyner 
9388eb6488eSEric Joyner 	/* Ensure SW/FW semaphore is free */
9398eb6488eSEric Joyner 	ixgbe_init_swfw_semaphore(hw);
9408eb6488eSEric Joyner 
9418eb6488eSEric Joyner 	/* Set an initial default flow control value */
9428eb6488eSEric Joyner 	hw->fc.requested_mode = ixgbe_flow_control;
9438eb6488eSEric Joyner 
9448eb6488eSEric Joyner 	hw->phy.reset_if_overtemp = TRUE;
9458eb6488eSEric Joyner 	error = ixgbe_reset_hw(hw);
9468eb6488eSEric Joyner 	hw->phy.reset_if_overtemp = FALSE;
9478eb6488eSEric Joyner 	if (error == IXGBE_ERR_SFP_NOT_PRESENT) {
948758cc3dcSJack F Vogel 		/*
9498eb6488eSEric Joyner 		 * No optics in this port, set up
9508eb6488eSEric Joyner 		 * so the timer routine will probe
9518eb6488eSEric Joyner 		 * for later insertion.
952758cc3dcSJack F Vogel 		 */
9538eb6488eSEric Joyner 		adapter->sfp_probe = TRUE;
954c19c7afeSEric Joyner 		error = 0;
9558eb6488eSEric Joyner 	} else if (error == IXGBE_ERR_SFP_NOT_SUPPORTED) {
9568eb6488eSEric Joyner 		device_printf(dev, "Unsupported SFP+ module detected!\n");
9578eb6488eSEric Joyner 		error = EIO;
958c19c7afeSEric Joyner 		goto err_pci;
9598eb6488eSEric Joyner 	} else if (error) {
9608eb6488eSEric Joyner 		device_printf(dev, "Hardware initialization failed\n");
9618eb6488eSEric Joyner 		error = EIO;
962c19c7afeSEric Joyner 		goto err_pci;
96397f9586eSSean Bruno 	}
96497f9586eSSean Bruno 
9658eb6488eSEric Joyner 	/* Make sure we have a good EEPROM before we read from it */
9668eb6488eSEric Joyner 	if (ixgbe_validate_eeprom_checksum(&adapter->hw, NULL) < 0) {
9678eb6488eSEric Joyner 		device_printf(dev, "The EEPROM Checksum Is Not Valid\n");
9688eb6488eSEric Joyner 		error = EIO;
969c19c7afeSEric Joyner 		goto err_pci;
97097f9586eSSean Bruno 	}
97197f9586eSSean Bruno 
9728eb6488eSEric Joyner 	error = ixgbe_start_hw(hw);
9738eb6488eSEric Joyner 	switch (error) {
9748eb6488eSEric Joyner 	case IXGBE_ERR_EEPROM_VERSION:
9758eb6488eSEric 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");
97697f9586eSSean Bruno 		break;
9778eb6488eSEric Joyner 	case IXGBE_ERR_SFP_NOT_SUPPORTED:
9788eb6488eSEric Joyner 		device_printf(dev, "Unsupported SFP+ Module\n");
9798eb6488eSEric Joyner 		error = EIO;
980c19c7afeSEric Joyner 		goto err_pci;
9818eb6488eSEric Joyner 	case IXGBE_ERR_SFP_NOT_PRESENT:
9828eb6488eSEric Joyner 		device_printf(dev, "No SFP+ Module found\n");
9838eb6488eSEric Joyner 		/* falls thru */
98497f9586eSSean Bruno 	default:
98597f9586eSSean Bruno 		break;
98697f9586eSSean Bruno 	}
98797f9586eSSean Bruno 
988c19c7afeSEric Joyner 	/* Most of the iflib initialization... */
989c19c7afeSEric Joyner 
990c19c7afeSEric Joyner 	iflib_set_mac(ctx, hw->mac.addr);
991c19c7afeSEric Joyner 	switch (adapter->hw.mac.type) {
992c19c7afeSEric Joyner 	case ixgbe_mac_X550:
993c19c7afeSEric Joyner 	case ixgbe_mac_X550EM_x:
994c19c7afeSEric Joyner 	case ixgbe_mac_X550EM_a:
995c19c7afeSEric Joyner 		scctx->isc_rss_table_size = 512;
996c19c7afeSEric Joyner 		scctx->isc_ntxqsets_max = scctx->isc_nrxqsets_max = 64;
997c19c7afeSEric Joyner 		break;
998c19c7afeSEric Joyner 	default:
999c19c7afeSEric Joyner 		scctx->isc_rss_table_size = 128;
1000c19c7afeSEric Joyner 		scctx->isc_ntxqsets_max = scctx->isc_nrxqsets_max = 16;
1001c19c7afeSEric Joyner 	}
1002c19c7afeSEric Joyner 
1003c19c7afeSEric Joyner 	/* Allow legacy interrupts */
1004c19c7afeSEric Joyner 	ixgbe_txrx.ift_legacy_intr = ixgbe_intr;
1005c19c7afeSEric Joyner 
1006c19c7afeSEric Joyner 	scctx->isc_txqsizes[0] =
1007c19c7afeSEric Joyner 	    roundup2(scctx->isc_ntxd[0] * sizeof(union ixgbe_adv_tx_desc) +
1008c19c7afeSEric Joyner 	    sizeof(u32), DBA_ALIGN),
1009c19c7afeSEric Joyner 	scctx->isc_rxqsizes[0] =
1010c19c7afeSEric Joyner 	    roundup2(scctx->isc_nrxd[0] * sizeof(union ixgbe_adv_rx_desc),
1011c19c7afeSEric Joyner 	    DBA_ALIGN);
1012c19c7afeSEric Joyner 
1013c19c7afeSEric Joyner 	/* XXX */
1014c19c7afeSEric Joyner 	scctx->isc_tx_csum_flags = CSUM_IP | CSUM_TCP | CSUM_UDP | CSUM_TSO |
1015c19c7afeSEric Joyner 	    CSUM_IP6_TCP | CSUM_IP6_UDP | CSUM_IP6_TSO;
1016c19c7afeSEric Joyner 	if (adapter->hw.mac.type == ixgbe_mac_82598EB) {
1017c19c7afeSEric Joyner 		scctx->isc_tx_nsegments = IXGBE_82598_SCATTER;
1018c19c7afeSEric Joyner 	} else {
1019c19c7afeSEric Joyner 		scctx->isc_tx_csum_flags |= CSUM_SCTP |CSUM_IP6_SCTP;
1020c19c7afeSEric Joyner 		scctx->isc_tx_nsegments = IXGBE_82599_SCATTER;
1021c19c7afeSEric Joyner 	}
1022749597dcSEric Joyner 
1023749597dcSEric Joyner 	scctx->isc_msix_bar = pci_msix_table_bar(dev);
1024749597dcSEric Joyner 
1025c19c7afeSEric Joyner 	scctx->isc_tx_tso_segments_max = scctx->isc_tx_nsegments;
1026c19c7afeSEric Joyner 	scctx->isc_tx_tso_size_max = IXGBE_TSO_SIZE;
1027c19c7afeSEric Joyner 	scctx->isc_tx_tso_segsize_max = PAGE_SIZE;
1028c19c7afeSEric Joyner 
1029c19c7afeSEric Joyner 	scctx->isc_txrx = &ixgbe_txrx;
1030c19c7afeSEric Joyner 
10317f87c040SMarius Strobl 	scctx->isc_capabilities = scctx->isc_capenable = IXGBE_CAPS;
1032c19c7afeSEric Joyner 
1033c19c7afeSEric Joyner 	return (0);
1034c19c7afeSEric Joyner 
1035c19c7afeSEric Joyner err_pci:
1036c19c7afeSEric Joyner 	ctrl_ext = IXGBE_READ_REG(&adapter->hw, IXGBE_CTRL_EXT);
1037c19c7afeSEric Joyner 	ctrl_ext &= ~IXGBE_CTRL_EXT_DRV_LOAD;
1038c19c7afeSEric Joyner 	IXGBE_WRITE_REG(&adapter->hw, IXGBE_CTRL_EXT, ctrl_ext);
1039c19c7afeSEric Joyner 	ixgbe_free_pci_resources(ctx);
1040c19c7afeSEric Joyner 
1041c19c7afeSEric Joyner 	return (error);
1042c19c7afeSEric Joyner } /* ixgbe_if_attach_pre */
1043c19c7afeSEric Joyner 
1044c19c7afeSEric Joyner  /*********************************************************************
1045c19c7afeSEric Joyner  * ixgbe_if_attach_post - Device initialization routine, part 2
1046c19c7afeSEric Joyner  *
1047c19c7afeSEric Joyner  *   Called during driver load, but after interrupts and
1048c19c7afeSEric Joyner  *   resources have been allocated and configured.
1049c19c7afeSEric Joyner  *   Sets up some data structures not relevant to iflib.
1050c19c7afeSEric Joyner  *
1051c19c7afeSEric Joyner  *   return 0 on success, positive on failure
1052c19c7afeSEric Joyner  *********************************************************************/
1053c19c7afeSEric Joyner static int
1054c19c7afeSEric Joyner ixgbe_if_attach_post(if_ctx_t ctx)
1055c19c7afeSEric Joyner {
1056c19c7afeSEric Joyner 	device_t dev;
1057c19c7afeSEric Joyner 	struct adapter  *adapter;
1058c19c7afeSEric Joyner 	struct ixgbe_hw *hw;
1059c19c7afeSEric Joyner 	int             error = 0;
1060c19c7afeSEric Joyner 
1061c19c7afeSEric Joyner 	dev = iflib_get_dev(ctx);
1062c19c7afeSEric Joyner 	adapter = iflib_get_softc(ctx);
1063c19c7afeSEric Joyner 	hw = &adapter->hw;
1064c19c7afeSEric Joyner 
1065c19c7afeSEric Joyner 
1066c19c7afeSEric Joyner 	if (adapter->intr_type == IFLIB_INTR_LEGACY &&
1067c19c7afeSEric Joyner 		(adapter->feat_cap & IXGBE_FEATURE_LEGACY_IRQ) == 0) {
1068c19c7afeSEric Joyner 		device_printf(dev, "Device does not support legacy interrupts");
1069c19c7afeSEric Joyner 		error = ENXIO;
1070c19c7afeSEric Joyner 		goto err;
1071c19c7afeSEric Joyner 	}
1072c19c7afeSEric Joyner 
1073c19c7afeSEric Joyner 	/* Allocate multicast array memory. */
1074c19c7afeSEric Joyner 	adapter->mta = malloc(sizeof(*adapter->mta) *
1075c19c7afeSEric Joyner 	                      MAX_NUM_MULTICAST_ADDRESSES, M_IXGBE, M_NOWAIT);
1076c19c7afeSEric Joyner 	if (adapter->mta == NULL) {
1077c19c7afeSEric Joyner 		device_printf(dev, "Can not allocate multicast setup array\n");
1078c19c7afeSEric Joyner 		error = ENOMEM;
1079c19c7afeSEric Joyner 		goto err;
1080c19c7afeSEric Joyner 	}
1081c19c7afeSEric Joyner 
1082c19c7afeSEric Joyner 	/* hw.ix defaults init */
1083c19c7afeSEric Joyner 	ixgbe_set_advertise(adapter, ixgbe_advertise_speed);
1084c19c7afeSEric Joyner 
10858eb6488eSEric Joyner 	/* Enable the optics for 82599 SFP+ fiber */
10868eb6488eSEric Joyner 	ixgbe_enable_tx_laser(hw);
1087758cc3dcSJack F Vogel 
10888eb6488eSEric Joyner 	/* Enable power to the phy. */
10898eb6488eSEric Joyner 	ixgbe_set_phy_power(hw, TRUE);
10908eb6488eSEric Joyner 
1091c19c7afeSEric Joyner 	ixgbe_initialize_iov(adapter);
1092c19c7afeSEric Joyner 
1093c19c7afeSEric Joyner 	error = ixgbe_setup_interface(ctx);
1094c19c7afeSEric Joyner 	if (error) {
1095c19c7afeSEric Joyner 		device_printf(dev, "Interface setup failed: %d\n", error);
1096c19c7afeSEric Joyner 		goto err;
1097c19c7afeSEric Joyner 	}
1098c19c7afeSEric Joyner 
1099c19c7afeSEric Joyner 	ixgbe_if_update_admin_status(ctx);
1100c19c7afeSEric Joyner 
11018eb6488eSEric Joyner 	/* Initialize statistics */
11028eb6488eSEric Joyner 	ixgbe_update_stats_counters(adapter);
1103c19c7afeSEric Joyner 	ixgbe_add_hw_stats(adapter);
11048eb6488eSEric Joyner 
11058eb6488eSEric Joyner 	/* Check PCIE slot type/speed/width */
11068eb6488eSEric Joyner 	ixgbe_get_slot_info(adapter);
1107758cc3dcSJack F Vogel 
1108758cc3dcSJack F Vogel 	/*
11098eb6488eSEric Joyner 	 * Do time init and sysctl init here, but
11108eb6488eSEric Joyner 	 * only on the first port of a bypass adapter.
1111758cc3dcSJack F Vogel 	 */
11128eb6488eSEric Joyner 	ixgbe_bypass_init(adapter);
1113758cc3dcSJack F Vogel 
11148eb6488eSEric Joyner 	/* Set an initial dmac value */
11158eb6488eSEric Joyner 	adapter->dmac = 0;
11168eb6488eSEric Joyner 	/* Set initial advertised speeds (if applicable) */
11178eb6488eSEric Joyner 	adapter->advertise = ixgbe_get_advertise(adapter);
1118758cc3dcSJack F Vogel 
11198eb6488eSEric Joyner 	if (adapter->feat_cap & IXGBE_FEATURE_SRIOV)
11208eb6488eSEric Joyner 		ixgbe_define_iov_schemas(dev, &error);
1121758cc3dcSJack F Vogel 
11228eb6488eSEric Joyner 	/* Add sysctls */
1123c19c7afeSEric Joyner 	ixgbe_add_device_sysctls(ctx);
1124758cc3dcSJack F Vogel 
11258eb6488eSEric Joyner 	return (0);
1126c19c7afeSEric Joyner err:
11278eb6488eSEric Joyner 	return (error);
1128c19c7afeSEric Joyner } /* ixgbe_if_attach_post */
11298eb6488eSEric Joyner 
11308eb6488eSEric Joyner /************************************************************************
11318eb6488eSEric Joyner  * ixgbe_check_wol_support
11326f37f232SEric Joyner  *
11336f37f232SEric Joyner  *   Checks whether the adapter's ports are capable of
11346f37f232SEric Joyner  *   Wake On LAN by reading the adapter's NVM.
11356f37f232SEric Joyner  *
11366f37f232SEric Joyner  *   Sets each port's hw->wol_enabled value depending
11376f37f232SEric Joyner  *   on the value read here.
11388eb6488eSEric Joyner  ************************************************************************/
11396f37f232SEric Joyner static void
11406f37f232SEric Joyner ixgbe_check_wol_support(struct adapter *adapter)
11416f37f232SEric Joyner {
11426f37f232SEric Joyner 	struct ixgbe_hw *hw = &adapter->hw;
11436f37f232SEric Joyner 	u16             dev_caps = 0;
11446f37f232SEric Joyner 
11456f37f232SEric Joyner 	/* Find out WoL support for port */
11466f37f232SEric Joyner 	adapter->wol_support = hw->wol_enabled = 0;
11476f37f232SEric Joyner 	ixgbe_get_device_caps(hw, &dev_caps);
11486f37f232SEric Joyner 	if ((dev_caps & IXGBE_DEVICE_CAPS_WOL_PORT0_1) ||
11496f37f232SEric Joyner 	    ((dev_caps & IXGBE_DEVICE_CAPS_WOL_PORT0) &&
11506f37f232SEric Joyner 	     hw->bus.func == 0))
11516f37f232SEric Joyner 		adapter->wol_support = hw->wol_enabled = 1;
11526f37f232SEric Joyner 
11536f37f232SEric Joyner 	/* Save initial wake up filter configuration */
11546f37f232SEric Joyner 	adapter->wufc = IXGBE_READ_REG(hw, IXGBE_WUFC);
11556f37f232SEric Joyner 
11566f37f232SEric Joyner 	return;
11578eb6488eSEric Joyner } /* ixgbe_check_wol_support */
11586f37f232SEric Joyner 
11598eb6488eSEric Joyner /************************************************************************
11608eb6488eSEric Joyner  * ixgbe_setup_interface
11618eb6488eSEric Joyner  *
11628eb6488eSEric Joyner  *   Setup networking device structure and register an interface.
11638eb6488eSEric Joyner  ************************************************************************/
11646f37f232SEric Joyner static int
1165c19c7afeSEric Joyner ixgbe_setup_interface(if_ctx_t ctx)
11666f37f232SEric Joyner {
1167c19c7afeSEric Joyner 	struct ifnet   *ifp = iflib_get_ifp(ctx);
1168c19c7afeSEric Joyner 	struct adapter *adapter = iflib_get_softc(ctx);
11696f37f232SEric Joyner 
11708eb6488eSEric Joyner 	INIT_DEBUGOUT("ixgbe_setup_interface: begin");
11716f37f232SEric Joyner 
1172c19c7afeSEric Joyner 	if_setbaudrate(ifp, IF_Gbps(10));
11736f37f232SEric Joyner 
11748eb6488eSEric Joyner 	adapter->max_frame_size = ifp->if_mtu + ETHER_HDR_LEN + ETHER_CRC_LEN;
1175758cc3dcSJack F Vogel 
11768eb6488eSEric Joyner 	adapter->phy_layer = ixgbe_get_supported_physical_layer(&adapter->hw);
11778eb6488eSEric Joyner 
1178c19c7afeSEric Joyner 	ixgbe_add_media_types(ctx);
1179c19c7afeSEric Joyner 
1180c19c7afeSEric Joyner 	/* Autoselect media by default */
1181c19c7afeSEric Joyner 	ifmedia_set(adapter->media, IFM_ETHER | IFM_AUTO);
11828eb6488eSEric Joyner 
11838eb6488eSEric Joyner 	return (0);
11848eb6488eSEric Joyner } /* ixgbe_setup_interface */
1185758cc3dcSJack F Vogel 
11868eb6488eSEric Joyner /************************************************************************
1187c19c7afeSEric Joyner  * ixgbe_if_get_counter
11888eb6488eSEric Joyner  ************************************************************************/
1189758cc3dcSJack F Vogel static uint64_t
1190c19c7afeSEric Joyner ixgbe_if_get_counter(if_ctx_t ctx, ift_counter cnt)
1191758cc3dcSJack F Vogel {
1192c19c7afeSEric Joyner 	struct adapter *adapter = iflib_get_softc(ctx);
1193c19c7afeSEric Joyner 	if_t           ifp = iflib_get_ifp(ctx);
1194758cc3dcSJack F Vogel 
1195758cc3dcSJack F Vogel 	switch (cnt) {
1196758cc3dcSJack F Vogel 	case IFCOUNTER_IPACKETS:
1197758cc3dcSJack F Vogel 		return (adapter->ipackets);
1198758cc3dcSJack F Vogel 	case IFCOUNTER_OPACKETS:
1199758cc3dcSJack F Vogel 		return (adapter->opackets);
1200758cc3dcSJack F Vogel 	case IFCOUNTER_IBYTES:
1201758cc3dcSJack F Vogel 		return (adapter->ibytes);
1202758cc3dcSJack F Vogel 	case IFCOUNTER_OBYTES:
1203758cc3dcSJack F Vogel 		return (adapter->obytes);
1204758cc3dcSJack F Vogel 	case IFCOUNTER_IMCASTS:
1205758cc3dcSJack F Vogel 		return (adapter->imcasts);
1206758cc3dcSJack F Vogel 	case IFCOUNTER_OMCASTS:
1207758cc3dcSJack F Vogel 		return (adapter->omcasts);
1208758cc3dcSJack F Vogel 	case IFCOUNTER_COLLISIONS:
1209758cc3dcSJack F Vogel 		return (0);
1210758cc3dcSJack F Vogel 	case IFCOUNTER_IQDROPS:
1211758cc3dcSJack F Vogel 		return (adapter->iqdrops);
1212625d12c6SJohn Baldwin 	case IFCOUNTER_OQDROPS:
1213c19c7afeSEric Joyner 		return (0);
1214758cc3dcSJack F Vogel 	case IFCOUNTER_IERRORS:
1215758cc3dcSJack F Vogel 		return (adapter->ierrors);
1216758cc3dcSJack F Vogel 	default:
1217758cc3dcSJack F Vogel 		return (if_get_counter_default(ifp, cnt));
1218758cc3dcSJack F Vogel 	}
1219c19c7afeSEric Joyner } /* ixgbe_if_get_counter */
1220758cc3dcSJack F Vogel 
12218eb6488eSEric Joyner /************************************************************************
1222bca38080SAndrew Gallatin  * ixgbe_if_i2c_req
1223bca38080SAndrew Gallatin  ************************************************************************/
1224bca38080SAndrew Gallatin static int
1225bca38080SAndrew Gallatin ixgbe_if_i2c_req(if_ctx_t ctx, struct ifi2creq *req)
1226bca38080SAndrew Gallatin {
1227bca38080SAndrew Gallatin 	struct adapter		*adapter = iflib_get_softc(ctx);
1228bca38080SAndrew Gallatin 	struct ixgbe_hw 	*hw = &adapter->hw;
1229bca38080SAndrew Gallatin 	int 			i;
1230bca38080SAndrew Gallatin 
1231bca38080SAndrew Gallatin 
1232bca38080SAndrew Gallatin 	if (hw->phy.ops.read_i2c_byte == NULL)
1233bca38080SAndrew Gallatin 		return (ENXIO);
1234bca38080SAndrew Gallatin 	for (i = 0; i < req->len; i++)
1235bca38080SAndrew Gallatin 		hw->phy.ops.read_i2c_byte(hw, req->offset + i,
1236bca38080SAndrew Gallatin 		    req->dev_addr, &req->data[i]);
1237bca38080SAndrew Gallatin 	return (0);
1238bca38080SAndrew Gallatin } /* ixgbe_if_i2c_req */
1239bca38080SAndrew Gallatin 
1240cf150917SEric Joyner /* ixgbe_if_needs_restart - Tell iflib when the driver needs to be reinitialized
1241cf150917SEric Joyner  * @ctx: iflib context
1242cf150917SEric Joyner  * @event: event code to check
1243cf150917SEric Joyner  *
1244cf150917SEric Joyner  * Defaults to returning true for unknown events.
1245cf150917SEric Joyner  *
1246cf150917SEric Joyner  * @returns true if iflib needs to reinit the interface
1247cf150917SEric Joyner  */
1248cf150917SEric Joyner static bool
1249cf150917SEric Joyner ixgbe_if_needs_restart(if_ctx_t ctx __unused, enum iflib_restart_event event)
1250cf150917SEric Joyner {
1251cf150917SEric Joyner 	switch (event) {
1252cf150917SEric Joyner 	case IFLIB_RESTART_VLAN_CONFIG:
1253cf150917SEric Joyner 		return (false);
1254cf150917SEric Joyner 	default:
1255cf150917SEric Joyner 		return (true);
1256cf150917SEric Joyner 	}
1257cf150917SEric Joyner }
1258cf150917SEric Joyner 
1259bca38080SAndrew Gallatin /************************************************************************
12608eb6488eSEric Joyner  * ixgbe_add_media_types
12618eb6488eSEric Joyner  ************************************************************************/
12628eb6488eSEric Joyner static void
1263c19c7afeSEric Joyner ixgbe_add_media_types(if_ctx_t ctx)
12648eb6488eSEric Joyner {
1265c19c7afeSEric Joyner 	struct adapter  *adapter = iflib_get_softc(ctx);
12668eb6488eSEric Joyner 	struct ixgbe_hw *hw = &adapter->hw;
1267c19c7afeSEric Joyner 	device_t        dev = iflib_get_dev(ctx);
12688eb6488eSEric Joyner 	u64             layer;
12698eb6488eSEric Joyner 
1270c19c7afeSEric Joyner 	layer = adapter->phy_layer = ixgbe_get_supported_physical_layer(hw);
12718eb6488eSEric Joyner 
12728eb6488eSEric Joyner 	/* Media types with matching FreeBSD media defines */
12738eb6488eSEric Joyner 	if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_T)
1274c19c7afeSEric Joyner 		ifmedia_add(adapter->media, IFM_ETHER | IFM_10G_T, 0, NULL);
12758eb6488eSEric Joyner 	if (layer & IXGBE_PHYSICAL_LAYER_1000BASE_T)
1276c19c7afeSEric Joyner 		ifmedia_add(adapter->media, IFM_ETHER | IFM_1000_T, 0, NULL);
12778eb6488eSEric Joyner 	if (layer & IXGBE_PHYSICAL_LAYER_100BASE_TX)
1278c19c7afeSEric Joyner 		ifmedia_add(adapter->media, IFM_ETHER | IFM_100_TX, 0, NULL);
12798eb6488eSEric Joyner 	if (layer & IXGBE_PHYSICAL_LAYER_10BASE_T)
1280c19c7afeSEric Joyner 		ifmedia_add(adapter->media, IFM_ETHER | IFM_10_T, 0, NULL);
12818eb6488eSEric Joyner 
12828eb6488eSEric Joyner 	if (layer & IXGBE_PHYSICAL_LAYER_SFP_PLUS_CU ||
12838eb6488eSEric Joyner 	    layer & IXGBE_PHYSICAL_LAYER_SFP_ACTIVE_DA)
1284c19c7afeSEric Joyner 		ifmedia_add(adapter->media, IFM_ETHER | IFM_10G_TWINAX, 0,
12858eb6488eSEric Joyner 		    NULL);
12868eb6488eSEric Joyner 
12878eb6488eSEric Joyner 	if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_LR) {
1288c19c7afeSEric Joyner 		ifmedia_add(adapter->media, IFM_ETHER | IFM_10G_LR, 0, NULL);
12898eb6488eSEric Joyner 		if (hw->phy.multispeed_fiber)
1290c19c7afeSEric Joyner 			ifmedia_add(adapter->media, IFM_ETHER | IFM_1000_LX, 0,
12918eb6488eSEric Joyner 			    NULL);
12928eb6488eSEric Joyner 	}
12938eb6488eSEric Joyner 	if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_SR) {
1294c19c7afeSEric Joyner 		ifmedia_add(adapter->media, IFM_ETHER | IFM_10G_SR, 0, NULL);
12958eb6488eSEric Joyner 		if (hw->phy.multispeed_fiber)
1296c19c7afeSEric Joyner 			ifmedia_add(adapter->media, IFM_ETHER | IFM_1000_SX, 0,
12978eb6488eSEric Joyner 			    NULL);
12988eb6488eSEric Joyner 	} else if (layer & IXGBE_PHYSICAL_LAYER_1000BASE_SX)
1299c19c7afeSEric Joyner 		ifmedia_add(adapter->media, IFM_ETHER | IFM_1000_SX, 0, NULL);
13008eb6488eSEric Joyner 	if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_CX4)
1301c19c7afeSEric Joyner 		ifmedia_add(adapter->media, IFM_ETHER | IFM_10G_CX4, 0, NULL);
13028eb6488eSEric Joyner 
13038eb6488eSEric Joyner #ifdef IFM_ETH_XTYPE
13048eb6488eSEric Joyner 	if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_KR)
1305c19c7afeSEric Joyner 		ifmedia_add(adapter->media, IFM_ETHER | IFM_10G_KR, 0, NULL);
13068eb6488eSEric Joyner 	if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_KX4)
1307c19c7afeSEric Joyner 		ifmedia_add( adapter->media, IFM_ETHER | IFM_10G_KX4, 0, NULL);
13088eb6488eSEric Joyner 	if (layer & IXGBE_PHYSICAL_LAYER_1000BASE_KX)
1309c19c7afeSEric Joyner 		ifmedia_add(adapter->media, IFM_ETHER | IFM_1000_KX, 0, NULL);
13108eb6488eSEric Joyner 	if (layer & IXGBE_PHYSICAL_LAYER_2500BASE_KX)
1311c19c7afeSEric Joyner 		ifmedia_add(adapter->media, IFM_ETHER | IFM_2500_KX, 0, NULL);
13128eb6488eSEric Joyner #else
13138eb6488eSEric Joyner 	if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_KR) {
13148eb6488eSEric Joyner 		device_printf(dev, "Media supported: 10GbaseKR\n");
13158eb6488eSEric Joyner 		device_printf(dev, "10GbaseKR mapped to 10GbaseSR\n");
1316c19c7afeSEric Joyner 		ifmedia_add(adapter->media, IFM_ETHER | IFM_10G_SR, 0, NULL);
13178eb6488eSEric Joyner 	}
13188eb6488eSEric Joyner 	if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_KX4) {
13198eb6488eSEric Joyner 		device_printf(dev, "Media supported: 10GbaseKX4\n");
13208eb6488eSEric Joyner 		device_printf(dev, "10GbaseKX4 mapped to 10GbaseCX4\n");
1321c19c7afeSEric Joyner 		ifmedia_add(adapter->media, IFM_ETHER | IFM_10G_CX4, 0, NULL);
13228eb6488eSEric Joyner 	}
13238eb6488eSEric Joyner 	if (layer & IXGBE_PHYSICAL_LAYER_1000BASE_KX) {
13248eb6488eSEric Joyner 		device_printf(dev, "Media supported: 1000baseKX\n");
13258eb6488eSEric Joyner 		device_printf(dev, "1000baseKX mapped to 1000baseCX\n");
1326c19c7afeSEric Joyner 		ifmedia_add(adapter->media, IFM_ETHER | IFM_1000_CX, 0, NULL);
13278eb6488eSEric Joyner 	}
13288eb6488eSEric Joyner 	if (layer & IXGBE_PHYSICAL_LAYER_2500BASE_KX) {
13298eb6488eSEric Joyner 		device_printf(dev, "Media supported: 2500baseKX\n");
13308eb6488eSEric Joyner 		device_printf(dev, "2500baseKX mapped to 2500baseSX\n");
1331c19c7afeSEric Joyner 		ifmedia_add(adapter->media, IFM_ETHER | IFM_2500_SX, 0, NULL);
13328eb6488eSEric Joyner 	}
13338eb6488eSEric Joyner #endif
13348eb6488eSEric Joyner 	if (layer & IXGBE_PHYSICAL_LAYER_1000BASE_BX)
13358eb6488eSEric Joyner 		device_printf(dev, "Media supported: 1000baseBX\n");
13368eb6488eSEric Joyner 
13378eb6488eSEric Joyner 	if (hw->device_id == IXGBE_DEV_ID_82598AT) {
1338c19c7afeSEric Joyner 		ifmedia_add(adapter->media, IFM_ETHER | IFM_1000_T | IFM_FDX,
13398eb6488eSEric Joyner 		    0, NULL);
1340c19c7afeSEric Joyner 		ifmedia_add(adapter->media, IFM_ETHER | IFM_1000_T, 0, NULL);
13418eb6488eSEric Joyner 	}
13428eb6488eSEric Joyner 
1343c19c7afeSEric Joyner 	ifmedia_add(adapter->media, IFM_ETHER | IFM_AUTO, 0, NULL);
13448eb6488eSEric Joyner } /* ixgbe_add_media_types */
13458eb6488eSEric Joyner 
13468eb6488eSEric Joyner /************************************************************************
13478eb6488eSEric Joyner  * ixgbe_is_sfp
13488eb6488eSEric Joyner  ************************************************************************/
13498eb6488eSEric Joyner static inline bool
13508eb6488eSEric Joyner ixgbe_is_sfp(struct ixgbe_hw *hw)
13518eb6488eSEric Joyner {
13528eb6488eSEric Joyner 	switch (hw->mac.type) {
13538eb6488eSEric Joyner 	case ixgbe_mac_82598EB:
13548eb6488eSEric Joyner 		if (hw->phy.type == ixgbe_phy_nl)
1355c19c7afeSEric Joyner 			return (TRUE);
1356c19c7afeSEric Joyner 		return (FALSE);
13578eb6488eSEric Joyner 	case ixgbe_mac_82599EB:
13588eb6488eSEric Joyner 		switch (hw->mac.ops.get_media_type(hw)) {
13598eb6488eSEric Joyner 		case ixgbe_media_type_fiber:
13608eb6488eSEric Joyner 		case ixgbe_media_type_fiber_qsfp:
1361c19c7afeSEric Joyner 			return (TRUE);
13628eb6488eSEric Joyner 		default:
1363c19c7afeSEric Joyner 			return (FALSE);
13648eb6488eSEric Joyner 		}
13658eb6488eSEric Joyner 	case ixgbe_mac_X550EM_x:
13668eb6488eSEric Joyner 	case ixgbe_mac_X550EM_a:
13678eb6488eSEric Joyner 		if (hw->mac.ops.get_media_type(hw) == ixgbe_media_type_fiber)
1368c19c7afeSEric Joyner 			return (TRUE);
1369c19c7afeSEric Joyner 		return (FALSE);
13708eb6488eSEric Joyner 	default:
1371c19c7afeSEric Joyner 		return (FALSE);
13728eb6488eSEric Joyner 	}
13738eb6488eSEric Joyner } /* ixgbe_is_sfp */
13748eb6488eSEric Joyner 
13758eb6488eSEric Joyner /************************************************************************
13768eb6488eSEric Joyner  * ixgbe_config_link
13778eb6488eSEric Joyner  ************************************************************************/
13788eb6488eSEric Joyner static void
1379b2c1e8e6SEric Joyner ixgbe_config_link(if_ctx_t ctx)
13808eb6488eSEric Joyner {
1381b2c1e8e6SEric Joyner 	struct adapter  *adapter = iflib_get_softc(ctx);
13828eb6488eSEric Joyner 	struct ixgbe_hw *hw = &adapter->hw;
13838eb6488eSEric Joyner 	u32             autoneg, err = 0;
13848eb6488eSEric Joyner 	bool            sfp, negotiate;
13858eb6488eSEric Joyner 
13868eb6488eSEric Joyner 	sfp = ixgbe_is_sfp(hw);
13878eb6488eSEric Joyner 
13888eb6488eSEric Joyner 	if (sfp) {
1389b2c1e8e6SEric Joyner 		adapter->task_requests |= IXGBE_REQUEST_TASK_MOD;
1390b2c1e8e6SEric Joyner 		iflib_admin_intr_deferred(ctx);
13918eb6488eSEric Joyner 	} else {
13928eb6488eSEric Joyner 		if (hw->mac.ops.check_link)
13938eb6488eSEric Joyner 			err = ixgbe_check_link(hw, &adapter->link_speed,
13948eb6488eSEric Joyner 			    &adapter->link_up, FALSE);
13958eb6488eSEric Joyner 		if (err)
1396c19c7afeSEric Joyner 			return;
13978eb6488eSEric Joyner 		autoneg = hw->phy.autoneg_advertised;
13988eb6488eSEric Joyner 		if ((!autoneg) && (hw->mac.ops.get_link_capabilities))
13998eb6488eSEric Joyner 			err = hw->mac.ops.get_link_capabilities(hw, &autoneg,
14008eb6488eSEric Joyner 			    &negotiate);
14018eb6488eSEric Joyner 		if (err)
1402c19c7afeSEric Joyner 			return;
14038eb6488eSEric Joyner 		if (hw->mac.ops.setup_link)
14048eb6488eSEric Joyner 			err = hw->mac.ops.setup_link(hw, autoneg,
14058eb6488eSEric Joyner 			    adapter->link_up);
14068eb6488eSEric Joyner 	}
14078eb6488eSEric Joyner } /* ixgbe_config_link */
14088eb6488eSEric Joyner 
14098eb6488eSEric Joyner /************************************************************************
14108eb6488eSEric Joyner  * ixgbe_update_stats_counters - Update board statistics counters.
14118eb6488eSEric Joyner  ************************************************************************/
14128eb6488eSEric Joyner static void
14138eb6488eSEric Joyner ixgbe_update_stats_counters(struct adapter *adapter)
14148eb6488eSEric Joyner {
14158eb6488eSEric Joyner 	struct ixgbe_hw       *hw = &adapter->hw;
14168eb6488eSEric Joyner 	struct ixgbe_hw_stats *stats = &adapter->stats.pf;
14178eb6488eSEric Joyner 	u32                   missed_rx = 0, bprc, lxon, lxoff, total;
1418e37d3dc1SEric Joyner 	u32                   lxoffrxc;
14198eb6488eSEric Joyner 	u64                   total_missed_rx = 0;
14208eb6488eSEric Joyner 
14218eb6488eSEric Joyner 	stats->crcerrs += IXGBE_READ_REG(hw, IXGBE_CRCERRS);
14228eb6488eSEric Joyner 	stats->illerrc += IXGBE_READ_REG(hw, IXGBE_ILLERRC);
14238eb6488eSEric Joyner 	stats->errbc += IXGBE_READ_REG(hw, IXGBE_ERRBC);
14248eb6488eSEric Joyner 	stats->mspdc += IXGBE_READ_REG(hw, IXGBE_MSPDC);
14258eb6488eSEric Joyner 	stats->mpc[0] += IXGBE_READ_REG(hw, IXGBE_MPC(0));
14268eb6488eSEric Joyner 
14278eb6488eSEric Joyner 	for (int i = 0; i < 16; i++) {
14288eb6488eSEric Joyner 		stats->qprc[i] += IXGBE_READ_REG(hw, IXGBE_QPRC(i));
14298eb6488eSEric Joyner 		stats->qptc[i] += IXGBE_READ_REG(hw, IXGBE_QPTC(i));
14308eb6488eSEric Joyner 		stats->qprdc[i] += IXGBE_READ_REG(hw, IXGBE_QPRDC(i));
14318eb6488eSEric Joyner 	}
14328eb6488eSEric Joyner 	stats->mlfc += IXGBE_READ_REG(hw, IXGBE_MLFC);
14338eb6488eSEric Joyner 	stats->mrfc += IXGBE_READ_REG(hw, IXGBE_MRFC);
14348eb6488eSEric Joyner 	stats->rlec += IXGBE_READ_REG(hw, IXGBE_RLEC);
14358eb6488eSEric Joyner 
14368eb6488eSEric Joyner 	/* Hardware workaround, gprc counts missed packets */
14378eb6488eSEric Joyner 	stats->gprc += IXGBE_READ_REG(hw, IXGBE_GPRC);
14388eb6488eSEric Joyner 	stats->gprc -= missed_rx;
14398eb6488eSEric Joyner 
14408eb6488eSEric Joyner 	if (hw->mac.type != ixgbe_mac_82598EB) {
14418eb6488eSEric Joyner 		stats->gorc += IXGBE_READ_REG(hw, IXGBE_GORCL) +
14428eb6488eSEric Joyner 		    ((u64)IXGBE_READ_REG(hw, IXGBE_GORCH) << 32);
14438eb6488eSEric Joyner 		stats->gotc += IXGBE_READ_REG(hw, IXGBE_GOTCL) +
14448eb6488eSEric Joyner 		    ((u64)IXGBE_READ_REG(hw, IXGBE_GOTCH) << 32);
14458eb6488eSEric Joyner 		stats->tor += IXGBE_READ_REG(hw, IXGBE_TORL) +
14468eb6488eSEric Joyner 		    ((u64)IXGBE_READ_REG(hw, IXGBE_TORH) << 32);
14478eb6488eSEric Joyner 		stats->lxonrxc += IXGBE_READ_REG(hw, IXGBE_LXONRXCNT);
1448e37d3dc1SEric Joyner 		lxoffrxc = IXGBE_READ_REG(hw, IXGBE_LXOFFRXCNT);
1449e37d3dc1SEric Joyner 		stats->lxoffrxc += lxoffrxc;
14508eb6488eSEric Joyner 	} else {
14518eb6488eSEric Joyner 		stats->lxonrxc += IXGBE_READ_REG(hw, IXGBE_LXONRXC);
1452e37d3dc1SEric Joyner 		lxoffrxc = IXGBE_READ_REG(hw, IXGBE_LXOFFRXC);
1453e37d3dc1SEric Joyner 		stats->lxoffrxc += lxoffrxc;
14548eb6488eSEric Joyner 		/* 82598 only has a counter in the high register */
14558eb6488eSEric Joyner 		stats->gorc += IXGBE_READ_REG(hw, IXGBE_GORCH);
14568eb6488eSEric Joyner 		stats->gotc += IXGBE_READ_REG(hw, IXGBE_GOTCH);
14578eb6488eSEric Joyner 		stats->tor += IXGBE_READ_REG(hw, IXGBE_TORH);
14588eb6488eSEric Joyner 	}
14598eb6488eSEric Joyner 
14608eb6488eSEric Joyner 	/*
1461e37d3dc1SEric Joyner 	 * For watchdog management we need to know if we have been paused
1462e37d3dc1SEric Joyner 	 * during the last interval, so capture that here.
1463e37d3dc1SEric Joyner 	*/
1464e37d3dc1SEric Joyner 	if (lxoffrxc)
1465e37d3dc1SEric Joyner 		adapter->shared->isc_pause_frames = 1;
1466e37d3dc1SEric Joyner 
1467e37d3dc1SEric Joyner 	/*
14688eb6488eSEric Joyner 	 * Workaround: mprc hardware is incorrectly counting
14698eb6488eSEric Joyner 	 * broadcasts, so for now we subtract those.
1470758cc3dcSJack F Vogel 	 */
14718eb6488eSEric Joyner 	bprc = IXGBE_READ_REG(hw, IXGBE_BPRC);
14728eb6488eSEric Joyner 	stats->bprc += bprc;
14738eb6488eSEric Joyner 	stats->mprc += IXGBE_READ_REG(hw, IXGBE_MPRC);
14748eb6488eSEric Joyner 	if (hw->mac.type == ixgbe_mac_82598EB)
14758eb6488eSEric Joyner 		stats->mprc -= bprc;
14768eb6488eSEric Joyner 
14778eb6488eSEric Joyner 	stats->prc64 += IXGBE_READ_REG(hw, IXGBE_PRC64);
14788eb6488eSEric Joyner 	stats->prc127 += IXGBE_READ_REG(hw, IXGBE_PRC127);
14798eb6488eSEric Joyner 	stats->prc255 += IXGBE_READ_REG(hw, IXGBE_PRC255);
14808eb6488eSEric Joyner 	stats->prc511 += IXGBE_READ_REG(hw, IXGBE_PRC511);
14818eb6488eSEric Joyner 	stats->prc1023 += IXGBE_READ_REG(hw, IXGBE_PRC1023);
14828eb6488eSEric Joyner 	stats->prc1522 += IXGBE_READ_REG(hw, IXGBE_PRC1522);
14838eb6488eSEric Joyner 
14848eb6488eSEric Joyner 	lxon = IXGBE_READ_REG(hw, IXGBE_LXONTXC);
14858eb6488eSEric Joyner 	stats->lxontxc += lxon;
14868eb6488eSEric Joyner 	lxoff = IXGBE_READ_REG(hw, IXGBE_LXOFFTXC);
14878eb6488eSEric Joyner 	stats->lxofftxc += lxoff;
14888eb6488eSEric Joyner 	total = lxon + lxoff;
14898eb6488eSEric Joyner 
14908eb6488eSEric Joyner 	stats->gptc += IXGBE_READ_REG(hw, IXGBE_GPTC);
14918eb6488eSEric Joyner 	stats->mptc += IXGBE_READ_REG(hw, IXGBE_MPTC);
14928eb6488eSEric Joyner 	stats->ptc64 += IXGBE_READ_REG(hw, IXGBE_PTC64);
14938eb6488eSEric Joyner 	stats->gptc -= total;
14948eb6488eSEric Joyner 	stats->mptc -= total;
14958eb6488eSEric Joyner 	stats->ptc64 -= total;
14968eb6488eSEric Joyner 	stats->gotc -= total * ETHER_MIN_LEN;
14978eb6488eSEric Joyner 
14988eb6488eSEric Joyner 	stats->ruc += IXGBE_READ_REG(hw, IXGBE_RUC);
14998eb6488eSEric Joyner 	stats->rfc += IXGBE_READ_REG(hw, IXGBE_RFC);
15008eb6488eSEric Joyner 	stats->roc += IXGBE_READ_REG(hw, IXGBE_ROC);
15018eb6488eSEric Joyner 	stats->rjc += IXGBE_READ_REG(hw, IXGBE_RJC);
15028eb6488eSEric Joyner 	stats->mngprc += IXGBE_READ_REG(hw, IXGBE_MNGPRC);
15038eb6488eSEric Joyner 	stats->mngpdc += IXGBE_READ_REG(hw, IXGBE_MNGPDC);
15048eb6488eSEric Joyner 	stats->mngptc += IXGBE_READ_REG(hw, IXGBE_MNGPTC);
15058eb6488eSEric Joyner 	stats->tpr += IXGBE_READ_REG(hw, IXGBE_TPR);
15068eb6488eSEric Joyner 	stats->tpt += IXGBE_READ_REG(hw, IXGBE_TPT);
15078eb6488eSEric Joyner 	stats->ptc127 += IXGBE_READ_REG(hw, IXGBE_PTC127);
15088eb6488eSEric Joyner 	stats->ptc255 += IXGBE_READ_REG(hw, IXGBE_PTC255);
15098eb6488eSEric Joyner 	stats->ptc511 += IXGBE_READ_REG(hw, IXGBE_PTC511);
15108eb6488eSEric Joyner 	stats->ptc1023 += IXGBE_READ_REG(hw, IXGBE_PTC1023);
15118eb6488eSEric Joyner 	stats->ptc1522 += IXGBE_READ_REG(hw, IXGBE_PTC1522);
15128eb6488eSEric Joyner 	stats->bptc += IXGBE_READ_REG(hw, IXGBE_BPTC);
15138eb6488eSEric Joyner 	stats->xec += IXGBE_READ_REG(hw, IXGBE_XEC);
15148eb6488eSEric Joyner 	stats->fccrc += IXGBE_READ_REG(hw, IXGBE_FCCRC);
15158eb6488eSEric Joyner 	stats->fclast += IXGBE_READ_REG(hw, IXGBE_FCLAST);
15168eb6488eSEric Joyner 	/* Only read FCOE on 82599 */
15178eb6488eSEric Joyner 	if (hw->mac.type != ixgbe_mac_82598EB) {
15188eb6488eSEric Joyner 		stats->fcoerpdc += IXGBE_READ_REG(hw, IXGBE_FCOERPDC);
15198eb6488eSEric Joyner 		stats->fcoeprc += IXGBE_READ_REG(hw, IXGBE_FCOEPRC);
15208eb6488eSEric Joyner 		stats->fcoeptc += IXGBE_READ_REG(hw, IXGBE_FCOEPTC);
15218eb6488eSEric Joyner 		stats->fcoedwrc += IXGBE_READ_REG(hw, IXGBE_FCOEDWRC);
15228eb6488eSEric Joyner 		stats->fcoedwtc += IXGBE_READ_REG(hw, IXGBE_FCOEDWTC);
15238eb6488eSEric Joyner 	}
15248eb6488eSEric Joyner 
15258eb6488eSEric Joyner 	/* Fill out the OS statistics structure */
15268eb6488eSEric Joyner 	IXGBE_SET_IPACKETS(adapter, stats->gprc);
15278eb6488eSEric Joyner 	IXGBE_SET_OPACKETS(adapter, stats->gptc);
15288eb6488eSEric Joyner 	IXGBE_SET_IBYTES(adapter, stats->gorc);
15298eb6488eSEric Joyner 	IXGBE_SET_OBYTES(adapter, stats->gotc);
15308eb6488eSEric Joyner 	IXGBE_SET_IMCASTS(adapter, stats->mprc);
15318eb6488eSEric Joyner 	IXGBE_SET_OMCASTS(adapter, stats->mptc);
15328eb6488eSEric Joyner 	IXGBE_SET_COLLISIONS(adapter, 0);
15338eb6488eSEric Joyner 	IXGBE_SET_IQDROPS(adapter, total_missed_rx);
1534*afb1aa4eSPiotr Pietruszewski 
1535*afb1aa4eSPiotr Pietruszewski 	/*
1536*afb1aa4eSPiotr Pietruszewski 	 * Aggregate following types of errors as RX errors:
1537*afb1aa4eSPiotr Pietruszewski 	 * - CRC error count,
1538*afb1aa4eSPiotr Pietruszewski 	 * - illegal byte error count,
1539*afb1aa4eSPiotr Pietruszewski 	 * - checksum error count,
1540*afb1aa4eSPiotr Pietruszewski 	 * - missed packets count,
1541*afb1aa4eSPiotr Pietruszewski 	 * - length error count,
1542*afb1aa4eSPiotr Pietruszewski 	 * - undersized packets count,
1543*afb1aa4eSPiotr Pietruszewski 	 * - fragmented packets count,
1544*afb1aa4eSPiotr Pietruszewski 	 * - oversized packets count,
1545*afb1aa4eSPiotr Pietruszewski 	 * - jabber count.
1546*afb1aa4eSPiotr Pietruszewski 	 */
1547*afb1aa4eSPiotr Pietruszewski 	IXGBE_SET_IERRORS(adapter, stats->crcerrs + stats->illerrc + stats->xec +
1548*afb1aa4eSPiotr Pietruszewski 	    stats->mpc[0] + stats->rlec + stats->ruc + stats->rfc + stats->roc +
1549*afb1aa4eSPiotr Pietruszewski 	    stats->rjc);
15508eb6488eSEric Joyner } /* ixgbe_update_stats_counters */
15518eb6488eSEric Joyner 
15528eb6488eSEric Joyner /************************************************************************
15538eb6488eSEric Joyner  * ixgbe_add_hw_stats
15548eb6488eSEric Joyner  *
15558eb6488eSEric Joyner  *   Add sysctl variables, one per statistic, to the system.
15568eb6488eSEric Joyner  ************************************************************************/
15578eb6488eSEric Joyner static void
15588eb6488eSEric Joyner ixgbe_add_hw_stats(struct adapter *adapter)
15598eb6488eSEric Joyner {
1560c19c7afeSEric Joyner 	device_t               dev = iflib_get_dev(adapter->ctx);
1561c19c7afeSEric Joyner 	struct ix_rx_queue     *rx_que;
1562c19c7afeSEric Joyner 	struct ix_tx_queue     *tx_que;
15638eb6488eSEric Joyner 	struct sysctl_ctx_list *ctx = device_get_sysctl_ctx(dev);
15648eb6488eSEric Joyner 	struct sysctl_oid      *tree = device_get_sysctl_tree(dev);
15658eb6488eSEric Joyner 	struct sysctl_oid_list *child = SYSCTL_CHILDREN(tree);
15668eb6488eSEric Joyner 	struct ixgbe_hw_stats  *stats = &adapter->stats.pf;
15678eb6488eSEric Joyner 	struct sysctl_oid      *stat_node, *queue_node;
15688eb6488eSEric Joyner 	struct sysctl_oid_list *stat_list, *queue_list;
1569c19c7afeSEric Joyner 	int                    i;
15708eb6488eSEric Joyner 
15718eb6488eSEric Joyner #define QUEUE_NAME_LEN 32
15728eb6488eSEric Joyner 	char                   namebuf[QUEUE_NAME_LEN];
15738eb6488eSEric Joyner 
15748eb6488eSEric Joyner 	/* Driver Statistics */
15758eb6488eSEric Joyner 	SYSCTL_ADD_ULONG(ctx, child, OID_AUTO, "dropped",
15768eb6488eSEric Joyner 	    CTLFLAG_RD, &adapter->dropped_pkts, "Driver dropped packets");
15778eb6488eSEric Joyner 	SYSCTL_ADD_ULONG(ctx, child, OID_AUTO, "watchdog_events",
15788eb6488eSEric Joyner 	    CTLFLAG_RD, &adapter->watchdog_events, "Watchdog timeouts");
15798eb6488eSEric Joyner 	SYSCTL_ADD_ULONG(ctx, child, OID_AUTO, "link_irq",
15808eb6488eSEric Joyner 	    CTLFLAG_RD, &adapter->link_irq, "Link MSI-X IRQ Handled");
15818eb6488eSEric Joyner 
1582c19c7afeSEric Joyner 	for (i = 0, tx_que = adapter->tx_queues; i < adapter->num_tx_queues; i++, tx_que++) {
1583c19c7afeSEric Joyner 		struct tx_ring *txr = &tx_que->txr;
15848eb6488eSEric Joyner 		snprintf(namebuf, QUEUE_NAME_LEN, "queue%d", i);
15858eb6488eSEric Joyner 		queue_node = SYSCTL_ADD_NODE(ctx, child, OID_AUTO, namebuf,
158620b91f0aSPawel Biernacki 		    CTLFLAG_RD | CTLFLAG_MPSAFE, NULL, "Queue Name");
15878eb6488eSEric Joyner 		queue_list = SYSCTL_CHILDREN(queue_node);
15888eb6488eSEric Joyner 
15898eb6488eSEric Joyner 		SYSCTL_ADD_PROC(ctx, queue_list, OID_AUTO, "txd_head",
159020b91f0aSPawel Biernacki 		    CTLTYPE_UINT | CTLFLAG_RD | CTLFLAG_NEEDGIANT, txr, 0,
15918eb6488eSEric Joyner 		    ixgbe_sysctl_tdh_handler, "IU", "Transmit Descriptor Head");
15928eb6488eSEric Joyner 		SYSCTL_ADD_PROC(ctx, queue_list, OID_AUTO, "txd_tail",
159320b91f0aSPawel Biernacki 		    CTLTYPE_UINT | CTLFLAG_RD | CTLFLAG_NEEDGIANT, txr, 0,
15948eb6488eSEric Joyner 		    ixgbe_sysctl_tdt_handler, "IU", "Transmit Descriptor Tail");
15958eb6488eSEric Joyner 		SYSCTL_ADD_UQUAD(ctx, queue_list, OID_AUTO, "tso_tx",
15968eb6488eSEric Joyner 		    CTLFLAG_RD, &txr->tso_tx, "TSO");
15978eb6488eSEric Joyner 		SYSCTL_ADD_UQUAD(ctx, queue_list, OID_AUTO, "tx_packets",
15988eb6488eSEric Joyner 		    CTLFLAG_RD, &txr->total_packets,
15998eb6488eSEric Joyner 		    "Queue Packets Transmitted");
16008eb6488eSEric Joyner 	}
16018eb6488eSEric Joyner 
1602c19c7afeSEric Joyner 	for (i = 0, rx_que = adapter->rx_queues; i < adapter->num_rx_queues; i++, rx_que++) {
1603c19c7afeSEric Joyner 		struct rx_ring *rxr = &rx_que->rxr;
16048eb6488eSEric Joyner 		snprintf(namebuf, QUEUE_NAME_LEN, "queue%d", i);
16058eb6488eSEric Joyner 		queue_node = SYSCTL_ADD_NODE(ctx, child, OID_AUTO, namebuf,
160620b91f0aSPawel Biernacki 		    CTLFLAG_RD | CTLFLAG_MPSAFE, NULL, "Queue Name");
16078eb6488eSEric Joyner 		queue_list = SYSCTL_CHILDREN(queue_node);
16088eb6488eSEric Joyner 
1609c19c7afeSEric Joyner 		SYSCTL_ADD_PROC(ctx, queue_list, OID_AUTO, "interrupt_rate",
161020b91f0aSPawel Biernacki 		    CTLTYPE_UINT | CTLFLAG_RW | CTLFLAG_NEEDGIANT,
161120b91f0aSPawel Biernacki 		    &adapter->rx_queues[i], 0,
1612c19c7afeSEric Joyner 		    ixgbe_sysctl_interrupt_rate_handler, "IU",
1613c19c7afeSEric Joyner 		    "Interrupt Rate");
1614c19c7afeSEric Joyner 		SYSCTL_ADD_UQUAD(ctx, queue_list, OID_AUTO, "irqs",
1615c19c7afeSEric Joyner 		    CTLFLAG_RD, &(adapter->rx_queues[i].irqs),
1616c19c7afeSEric Joyner 		    "irqs on this queue");
16178eb6488eSEric Joyner 		SYSCTL_ADD_PROC(ctx, queue_list, OID_AUTO, "rxd_head",
161820b91f0aSPawel Biernacki 		    CTLTYPE_UINT | CTLFLAG_RD | CTLFLAG_NEEDGIANT, rxr, 0,
16198eb6488eSEric Joyner 		    ixgbe_sysctl_rdh_handler, "IU", "Receive Descriptor Head");
16208eb6488eSEric Joyner 		SYSCTL_ADD_PROC(ctx, queue_list, OID_AUTO, "rxd_tail",
162120b91f0aSPawel Biernacki 		    CTLTYPE_UINT | CTLFLAG_RD | CTLFLAG_NEEDGIANT, rxr, 0,
16228eb6488eSEric Joyner 		    ixgbe_sysctl_rdt_handler, "IU", "Receive Descriptor Tail");
16238eb6488eSEric Joyner 		SYSCTL_ADD_UQUAD(ctx, queue_list, OID_AUTO, "rx_packets",
16248eb6488eSEric Joyner 		    CTLFLAG_RD, &rxr->rx_packets, "Queue Packets Received");
16258eb6488eSEric Joyner 		SYSCTL_ADD_UQUAD(ctx, queue_list, OID_AUTO, "rx_bytes",
16268eb6488eSEric Joyner 		    CTLFLAG_RD, &rxr->rx_bytes, "Queue Bytes Received");
16278eb6488eSEric Joyner 		SYSCTL_ADD_UQUAD(ctx, queue_list, OID_AUTO, "rx_copies",
16288eb6488eSEric Joyner 		    CTLFLAG_RD, &rxr->rx_copies, "Copied RX Frames");
16298eb6488eSEric Joyner 		SYSCTL_ADD_UQUAD(ctx, queue_list, OID_AUTO, "rx_discarded",
16308eb6488eSEric Joyner 		    CTLFLAG_RD, &rxr->rx_discarded, "Discarded RX packets");
16318eb6488eSEric Joyner 	}
16328eb6488eSEric Joyner 
16338eb6488eSEric Joyner 	/* MAC stats get their own sub node */
16348eb6488eSEric Joyner 
16358eb6488eSEric Joyner 	stat_node = SYSCTL_ADD_NODE(ctx, child, OID_AUTO, "mac_stats",
163620b91f0aSPawel Biernacki 	    CTLFLAG_RD | CTLFLAG_MPSAFE, NULL, "MAC Statistics");
16378eb6488eSEric Joyner 	stat_list = SYSCTL_CHILDREN(stat_node);
16388eb6488eSEric Joyner 
1639*afb1aa4eSPiotr Pietruszewski 	SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "rx_errs",
1640*afb1aa4eSPiotr Pietruszewski 	    CTLFLAG_RD, &adapter->ierrors, IXGBE_SYSCTL_DESC_RX_ERRS);
16418eb6488eSEric Joyner 	SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "crc_errs",
16428eb6488eSEric Joyner 	    CTLFLAG_RD, &stats->crcerrs, "CRC Errors");
16438eb6488eSEric Joyner 	SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "ill_errs",
16448eb6488eSEric Joyner 	    CTLFLAG_RD, &stats->illerrc, "Illegal Byte Errors");
16458eb6488eSEric Joyner 	SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "byte_errs",
16468eb6488eSEric Joyner 	    CTLFLAG_RD, &stats->errbc, "Byte Errors");
16478eb6488eSEric Joyner 	SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "short_discards",
16488eb6488eSEric Joyner 	    CTLFLAG_RD, &stats->mspdc, "MAC Short Packets Discarded");
16498eb6488eSEric Joyner 	SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "local_faults",
16508eb6488eSEric Joyner 	    CTLFLAG_RD, &stats->mlfc, "MAC Local Faults");
16518eb6488eSEric Joyner 	SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "remote_faults",
16528eb6488eSEric Joyner 	    CTLFLAG_RD, &stats->mrfc, "MAC Remote Faults");
16538eb6488eSEric Joyner 	SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "rec_len_errs",
16548eb6488eSEric Joyner 	    CTLFLAG_RD, &stats->rlec, "Receive Length Errors");
16558eb6488eSEric Joyner 	SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "rx_missed_packets",
16568eb6488eSEric Joyner 	    CTLFLAG_RD, &stats->mpc[0], "RX Missed Packet Count");
16578eb6488eSEric Joyner 
16588eb6488eSEric Joyner 	/* Flow Control stats */
16598eb6488eSEric Joyner 	SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "xon_txd",
16608eb6488eSEric Joyner 	    CTLFLAG_RD, &stats->lxontxc, "Link XON Transmitted");
16618eb6488eSEric Joyner 	SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "xon_recvd",
16628eb6488eSEric Joyner 	    CTLFLAG_RD, &stats->lxonrxc, "Link XON Received");
16638eb6488eSEric Joyner 	SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "xoff_txd",
16648eb6488eSEric Joyner 	    CTLFLAG_RD, &stats->lxofftxc, "Link XOFF Transmitted");
16658eb6488eSEric Joyner 	SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "xoff_recvd",
16668eb6488eSEric Joyner 	    CTLFLAG_RD, &stats->lxoffrxc, "Link XOFF Received");
16678eb6488eSEric Joyner 
16688eb6488eSEric Joyner 	/* Packet Reception Stats */
16698eb6488eSEric Joyner 	SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "total_octets_rcvd",
16708eb6488eSEric Joyner 	    CTLFLAG_RD, &stats->tor, "Total Octets Received");
16718eb6488eSEric Joyner 	SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "good_octets_rcvd",
16728eb6488eSEric Joyner 	    CTLFLAG_RD, &stats->gorc, "Good Octets Received");
16738eb6488eSEric Joyner 	SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "total_pkts_rcvd",
16748eb6488eSEric Joyner 	    CTLFLAG_RD, &stats->tpr, "Total Packets Received");
16758eb6488eSEric Joyner 	SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "good_pkts_rcvd",
16768eb6488eSEric Joyner 	    CTLFLAG_RD, &stats->gprc, "Good Packets Received");
16778eb6488eSEric Joyner 	SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "mcast_pkts_rcvd",
16788eb6488eSEric Joyner 	    CTLFLAG_RD, &stats->mprc, "Multicast Packets Received");
16798eb6488eSEric Joyner 	SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "bcast_pkts_rcvd",
16808eb6488eSEric Joyner 	    CTLFLAG_RD, &stats->bprc, "Broadcast Packets Received");
16818eb6488eSEric Joyner 	SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "rx_frames_64",
16828eb6488eSEric Joyner 	    CTLFLAG_RD, &stats->prc64, "64 byte frames received ");
16838eb6488eSEric Joyner 	SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "rx_frames_65_127",
16848eb6488eSEric Joyner 	    CTLFLAG_RD, &stats->prc127, "65-127 byte frames received");
16858eb6488eSEric Joyner 	SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "rx_frames_128_255",
16868eb6488eSEric Joyner 	    CTLFLAG_RD, &stats->prc255, "128-255 byte frames received");
16878eb6488eSEric Joyner 	SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "rx_frames_256_511",
16888eb6488eSEric Joyner 	    CTLFLAG_RD, &stats->prc511, "256-511 byte frames received");
16898eb6488eSEric Joyner 	SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "rx_frames_512_1023",
16908eb6488eSEric Joyner 	    CTLFLAG_RD, &stats->prc1023, "512-1023 byte frames received");
16918eb6488eSEric Joyner 	SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "rx_frames_1024_1522",
16928eb6488eSEric Joyner 	    CTLFLAG_RD, &stats->prc1522, "1023-1522 byte frames received");
16938eb6488eSEric Joyner 	SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "recv_undersized",
16948eb6488eSEric Joyner 	    CTLFLAG_RD, &stats->ruc, "Receive Undersized");
16958eb6488eSEric Joyner 	SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "recv_fragmented",
16968eb6488eSEric Joyner 	    CTLFLAG_RD, &stats->rfc, "Fragmented Packets Received ");
16978eb6488eSEric Joyner 	SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "recv_oversized",
16988eb6488eSEric Joyner 	    CTLFLAG_RD, &stats->roc, "Oversized Packets Received");
16998eb6488eSEric Joyner 	SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "recv_jabberd",
17008eb6488eSEric Joyner 	    CTLFLAG_RD, &stats->rjc, "Received Jabber");
17018eb6488eSEric Joyner 	SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "management_pkts_rcvd",
17028eb6488eSEric Joyner 	    CTLFLAG_RD, &stats->mngprc, "Management Packets Received");
17038eb6488eSEric Joyner 	SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "management_pkts_drpd",
17048eb6488eSEric Joyner 	    CTLFLAG_RD, &stats->mngptc, "Management Packets Dropped");
17058eb6488eSEric Joyner 	SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "checksum_errs",
17068eb6488eSEric Joyner 	    CTLFLAG_RD, &stats->xec, "Checksum Errors");
17078eb6488eSEric Joyner 
17088eb6488eSEric Joyner 	/* Packet Transmission Stats */
17098eb6488eSEric Joyner 	SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "good_octets_txd",
17108eb6488eSEric Joyner 	    CTLFLAG_RD, &stats->gotc, "Good Octets Transmitted");
17118eb6488eSEric Joyner 	SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "total_pkts_txd",
17128eb6488eSEric Joyner 	    CTLFLAG_RD, &stats->tpt, "Total Packets Transmitted");
17138eb6488eSEric Joyner 	SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "good_pkts_txd",
17148eb6488eSEric Joyner 	    CTLFLAG_RD, &stats->gptc, "Good Packets Transmitted");
17158eb6488eSEric Joyner 	SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "bcast_pkts_txd",
17168eb6488eSEric Joyner 	    CTLFLAG_RD, &stats->bptc, "Broadcast Packets Transmitted");
17178eb6488eSEric Joyner 	SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "mcast_pkts_txd",
17188eb6488eSEric Joyner 	    CTLFLAG_RD, &stats->mptc, "Multicast Packets Transmitted");
17198eb6488eSEric Joyner 	SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "management_pkts_txd",
17208eb6488eSEric Joyner 	    CTLFLAG_RD, &stats->mngptc, "Management Packets Transmitted");
17218eb6488eSEric Joyner 	SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "tx_frames_64",
17228eb6488eSEric Joyner 	    CTLFLAG_RD, &stats->ptc64, "64 byte frames transmitted ");
17238eb6488eSEric Joyner 	SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "tx_frames_65_127",
17248eb6488eSEric Joyner 	    CTLFLAG_RD, &stats->ptc127, "65-127 byte frames transmitted");
17258eb6488eSEric Joyner 	SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "tx_frames_128_255",
17268eb6488eSEric Joyner 	    CTLFLAG_RD, &stats->ptc255, "128-255 byte frames transmitted");
17278eb6488eSEric Joyner 	SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "tx_frames_256_511",
17288eb6488eSEric Joyner 	    CTLFLAG_RD, &stats->ptc511, "256-511 byte frames transmitted");
17298eb6488eSEric Joyner 	SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "tx_frames_512_1023",
17308eb6488eSEric Joyner 	    CTLFLAG_RD, &stats->ptc1023, "512-1023 byte frames transmitted");
17318eb6488eSEric Joyner 	SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "tx_frames_1024_1522",
17328eb6488eSEric Joyner 	    CTLFLAG_RD, &stats->ptc1522, "1024-1522 byte frames transmitted");
17338eb6488eSEric Joyner } /* ixgbe_add_hw_stats */
17348eb6488eSEric Joyner 
17358eb6488eSEric Joyner /************************************************************************
17368eb6488eSEric Joyner  * ixgbe_sysctl_tdh_handler - Transmit Descriptor Head handler function
17378eb6488eSEric Joyner  *
17388eb6488eSEric Joyner  *   Retrieves the TDH value from the hardware
17398eb6488eSEric Joyner  ************************************************************************/
1740758cc3dcSJack F Vogel static int
1741758cc3dcSJack F Vogel ixgbe_sysctl_tdh_handler(SYSCTL_HANDLER_ARGS)
1742758cc3dcSJack F Vogel {
1743758cc3dcSJack F Vogel 	struct tx_ring *txr = ((struct tx_ring *)oidp->oid_arg1);
17448eb6488eSEric Joyner 	int            error;
17458eb6488eSEric Joyner 	unsigned int   val;
1746758cc3dcSJack F Vogel 
17478eb6488eSEric Joyner 	if (!txr)
17488eb6488eSEric Joyner 		return (0);
17498eb6488eSEric Joyner 
17508eb6488eSEric Joyner 	val = IXGBE_READ_REG(&txr->adapter->hw, IXGBE_TDH(txr->me));
1751758cc3dcSJack F Vogel 	error = sysctl_handle_int(oidp, &val, 0, req);
1752758cc3dcSJack F Vogel 	if (error || !req->newptr)
1753758cc3dcSJack F Vogel 		return error;
1754758cc3dcSJack F Vogel 
17558eb6488eSEric Joyner 	return (0);
17568eb6488eSEric Joyner } /* ixgbe_sysctl_tdh_handler */
17578eb6488eSEric Joyner 
17588eb6488eSEric Joyner /************************************************************************
17598eb6488eSEric Joyner  * ixgbe_sysctl_tdt_handler - Transmit Descriptor Tail handler function
17608eb6488eSEric Joyner  *
1761758cc3dcSJack F Vogel  *   Retrieves the TDT value from the hardware
17628eb6488eSEric Joyner  ************************************************************************/
1763758cc3dcSJack F Vogel static int
1764758cc3dcSJack F Vogel ixgbe_sysctl_tdt_handler(SYSCTL_HANDLER_ARGS)
1765758cc3dcSJack F Vogel {
1766758cc3dcSJack F Vogel 	struct tx_ring *txr = ((struct tx_ring *)oidp->oid_arg1);
17678eb6488eSEric Joyner 	int            error;
17688eb6488eSEric Joyner 	unsigned int   val;
1769758cc3dcSJack F Vogel 
17708eb6488eSEric Joyner 	if (!txr)
17718eb6488eSEric Joyner 		return (0);
17728eb6488eSEric Joyner 
17738eb6488eSEric Joyner 	val = IXGBE_READ_REG(&txr->adapter->hw, IXGBE_TDT(txr->me));
1774758cc3dcSJack F Vogel 	error = sysctl_handle_int(oidp, &val, 0, req);
1775758cc3dcSJack F Vogel 	if (error || !req->newptr)
1776758cc3dcSJack F Vogel 		return error;
1777758cc3dcSJack F Vogel 
17788eb6488eSEric Joyner 	return (0);
17798eb6488eSEric Joyner } /* ixgbe_sysctl_tdt_handler */
17808eb6488eSEric Joyner 
17818eb6488eSEric Joyner /************************************************************************
17828eb6488eSEric Joyner  * ixgbe_sysctl_rdh_handler - Receive Descriptor Head handler function
17838eb6488eSEric Joyner  *
1784758cc3dcSJack F Vogel  *   Retrieves the RDH value from the hardware
17858eb6488eSEric Joyner  ************************************************************************/
1786758cc3dcSJack F Vogel static int
1787758cc3dcSJack F Vogel ixgbe_sysctl_rdh_handler(SYSCTL_HANDLER_ARGS)
1788758cc3dcSJack F Vogel {
1789758cc3dcSJack F Vogel 	struct rx_ring *rxr = ((struct rx_ring *)oidp->oid_arg1);
17908eb6488eSEric Joyner 	int            error;
17918eb6488eSEric Joyner 	unsigned int   val;
1792758cc3dcSJack F Vogel 
17938eb6488eSEric Joyner 	if (!rxr)
17948eb6488eSEric Joyner 		return (0);
17958eb6488eSEric Joyner 
17968eb6488eSEric Joyner 	val = IXGBE_READ_REG(&rxr->adapter->hw, IXGBE_RDH(rxr->me));
1797758cc3dcSJack F Vogel 	error = sysctl_handle_int(oidp, &val, 0, req);
1798758cc3dcSJack F Vogel 	if (error || !req->newptr)
1799758cc3dcSJack F Vogel 		return error;
1800758cc3dcSJack F Vogel 
18018eb6488eSEric Joyner 	return (0);
18028eb6488eSEric Joyner } /* ixgbe_sysctl_rdh_handler */
18038eb6488eSEric Joyner 
18048eb6488eSEric Joyner /************************************************************************
18058eb6488eSEric Joyner  * ixgbe_sysctl_rdt_handler - Receive Descriptor Tail handler function
18068eb6488eSEric Joyner  *
1807758cc3dcSJack F Vogel  *   Retrieves the RDT value from the hardware
18088eb6488eSEric Joyner  ************************************************************************/
1809758cc3dcSJack F Vogel static int
1810758cc3dcSJack F Vogel ixgbe_sysctl_rdt_handler(SYSCTL_HANDLER_ARGS)
1811758cc3dcSJack F Vogel {
1812758cc3dcSJack F Vogel 	struct rx_ring *rxr = ((struct rx_ring *)oidp->oid_arg1);
18138eb6488eSEric Joyner 	int            error;
18148eb6488eSEric Joyner 	unsigned int   val;
1815758cc3dcSJack F Vogel 
18168eb6488eSEric Joyner 	if (!rxr)
18178eb6488eSEric Joyner 		return (0);
18188eb6488eSEric Joyner 
18198eb6488eSEric Joyner 	val = IXGBE_READ_REG(&rxr->adapter->hw, IXGBE_RDT(rxr->me));
1820758cc3dcSJack F Vogel 	error = sysctl_handle_int(oidp, &val, 0, req);
1821758cc3dcSJack F Vogel 	if (error || !req->newptr)
1822758cc3dcSJack F Vogel 		return error;
18238eb6488eSEric Joyner 
18248eb6488eSEric Joyner 	return (0);
18258eb6488eSEric Joyner } /* ixgbe_sysctl_rdt_handler */
18268eb6488eSEric Joyner 
18278eb6488eSEric Joyner /************************************************************************
1828c19c7afeSEric Joyner  * ixgbe_if_vlan_register
18298eb6488eSEric Joyner  *
18308eb6488eSEric Joyner  *   Run via vlan config EVENT, it enables us to use the
18318eb6488eSEric Joyner  *   HW Filter table since we can get the vlan id. This
18328eb6488eSEric Joyner  *   just creates the entry in the soft version of the
18338eb6488eSEric Joyner  *   VFTA, init will repopulate the real table.
18348eb6488eSEric Joyner  ************************************************************************/
18358eb6488eSEric Joyner static void
1836c19c7afeSEric Joyner ixgbe_if_vlan_register(if_ctx_t ctx, u16 vtag)
18378eb6488eSEric Joyner {
1838c19c7afeSEric Joyner 	struct adapter *adapter = iflib_get_softc(ctx);
18398eb6488eSEric Joyner 	u16            index, bit;
18408eb6488eSEric Joyner 
18418eb6488eSEric Joyner 	index = (vtag >> 5) & 0x7F;
18428eb6488eSEric Joyner 	bit = vtag & 0x1F;
18438eb6488eSEric Joyner 	adapter->shadow_vfta[index] |= (1 << bit);
18448eb6488eSEric Joyner 	++adapter->num_vlans;
1845c19c7afeSEric Joyner 	ixgbe_setup_vlan_hw_support(ctx);
1846c19c7afeSEric Joyner } /* ixgbe_if_vlan_register */
18478eb6488eSEric Joyner 
18488eb6488eSEric Joyner /************************************************************************
1849c19c7afeSEric Joyner  * ixgbe_if_vlan_unregister
18508eb6488eSEric Joyner  *
18518eb6488eSEric Joyner  *   Run via vlan unconfig EVENT, remove our entry in the soft vfta.
18528eb6488eSEric Joyner  ************************************************************************/
18538eb6488eSEric Joyner static void
1854c19c7afeSEric Joyner ixgbe_if_vlan_unregister(if_ctx_t ctx, u16 vtag)
18558eb6488eSEric Joyner {
1856c19c7afeSEric Joyner 	struct adapter *adapter = iflib_get_softc(ctx);
18578eb6488eSEric Joyner 	u16            index, bit;
18588eb6488eSEric Joyner 
18598eb6488eSEric Joyner 	index = (vtag >> 5) & 0x7F;
18608eb6488eSEric Joyner 	bit = vtag & 0x1F;
18618eb6488eSEric Joyner 	adapter->shadow_vfta[index] &= ~(1 << bit);
18628eb6488eSEric Joyner 	--adapter->num_vlans;
18638eb6488eSEric Joyner 	/* Re-init to load the changes */
1864c19c7afeSEric Joyner 	ixgbe_setup_vlan_hw_support(ctx);
1865c19c7afeSEric Joyner } /* ixgbe_if_vlan_unregister */
18668eb6488eSEric Joyner 
18678eb6488eSEric Joyner /************************************************************************
18688eb6488eSEric Joyner  * ixgbe_setup_vlan_hw_support
18698eb6488eSEric Joyner  ************************************************************************/
18708eb6488eSEric Joyner static void
1871c19c7afeSEric Joyner ixgbe_setup_vlan_hw_support(if_ctx_t ctx)
18728eb6488eSEric Joyner {
1873c19c7afeSEric Joyner 	struct ifnet	*ifp = iflib_get_ifp(ctx);
1874c19c7afeSEric Joyner 	struct adapter  *adapter = iflib_get_softc(ctx);
18758eb6488eSEric Joyner 	struct ixgbe_hw *hw = &adapter->hw;
18768eb6488eSEric Joyner 	struct rx_ring  *rxr;
18778eb6488eSEric Joyner 	int             i;
18788eb6488eSEric Joyner 	u32             ctrl;
18798eb6488eSEric Joyner 
18808eb6488eSEric Joyner 
18818eb6488eSEric Joyner 	/*
18828eb6488eSEric Joyner 	 * We get here thru init_locked, meaning
18838eb6488eSEric Joyner 	 * a soft reset, this has already cleared
18848eb6488eSEric Joyner 	 * the VFTA and other state, so if there
18858eb6488eSEric Joyner 	 * have been no vlan's registered do nothing.
18868eb6488eSEric Joyner 	 */
18878eb6488eSEric Joyner 	if (adapter->num_vlans == 0)
18888eb6488eSEric Joyner 		return;
18898eb6488eSEric Joyner 
18908eb6488eSEric Joyner 	/* Setup the queues for vlans */
18919c92bb71SSean Bruno 	if (ifp->if_capenable & IFCAP_VLAN_HWTAGGING) {
1892c19c7afeSEric Joyner 		for (i = 0; i < adapter->num_rx_queues; i++) {
1893c19c7afeSEric Joyner 			rxr = &adapter->rx_queues[i].rxr;
18948eb6488eSEric Joyner 			/* On 82599 the VLAN enable is per/queue in RXDCTL */
18958eb6488eSEric Joyner 			if (hw->mac.type != ixgbe_mac_82598EB) {
18968eb6488eSEric Joyner 				ctrl = IXGBE_READ_REG(hw, IXGBE_RXDCTL(rxr->me));
18978eb6488eSEric Joyner 				ctrl |= IXGBE_RXDCTL_VME;
18988eb6488eSEric Joyner 				IXGBE_WRITE_REG(hw, IXGBE_RXDCTL(rxr->me), ctrl);
18998eb6488eSEric Joyner 			}
19008eb6488eSEric Joyner 			rxr->vtag_strip = TRUE;
1901758cc3dcSJack F Vogel 		}
19029c92bb71SSean Bruno 	}
1903758cc3dcSJack F Vogel 
19048eb6488eSEric Joyner 	if ((ifp->if_capenable & IFCAP_VLAN_HWFILTER) == 0)
19058eb6488eSEric Joyner 		return;
19068eb6488eSEric Joyner 	/*
19078eb6488eSEric Joyner 	 * A soft reset zero's out the VFTA, so
19088eb6488eSEric Joyner 	 * we need to repopulate it now.
19098eb6488eSEric Joyner 	 */
19108eb6488eSEric Joyner 	for (i = 0; i < IXGBE_VFTA_SIZE; i++)
19118eb6488eSEric Joyner 		if (adapter->shadow_vfta[i] != 0)
19128eb6488eSEric Joyner 			IXGBE_WRITE_REG(hw, IXGBE_VFTA(i),
19138eb6488eSEric Joyner 			    adapter->shadow_vfta[i]);
19148eb6488eSEric Joyner 
19158eb6488eSEric Joyner 	ctrl = IXGBE_READ_REG(hw, IXGBE_VLNCTRL);
19168eb6488eSEric Joyner 	/* Enable the Filter Table if enabled */
19178eb6488eSEric Joyner 	if (ifp->if_capenable & IFCAP_VLAN_HWFILTER) {
19188eb6488eSEric Joyner 		ctrl &= ~IXGBE_VLNCTRL_CFIEN;
19198eb6488eSEric Joyner 		ctrl |= IXGBE_VLNCTRL_VFE;
19208eb6488eSEric Joyner 	}
19218eb6488eSEric Joyner 	if (hw->mac.type == ixgbe_mac_82598EB)
19228eb6488eSEric Joyner 		ctrl |= IXGBE_VLNCTRL_VME;
19238eb6488eSEric Joyner 	IXGBE_WRITE_REG(hw, IXGBE_VLNCTRL, ctrl);
19248eb6488eSEric Joyner } /* ixgbe_setup_vlan_hw_support */
19258eb6488eSEric Joyner 
19268eb6488eSEric Joyner /************************************************************************
19278eb6488eSEric Joyner  * ixgbe_get_slot_info
19288eb6488eSEric Joyner  *
19298eb6488eSEric Joyner  *   Get the width and transaction speed of
19308eb6488eSEric Joyner  *   the slot this adapter is plugged into.
19318eb6488eSEric Joyner  ************************************************************************/
19328eb6488eSEric Joyner static void
19338eb6488eSEric Joyner ixgbe_get_slot_info(struct adapter *adapter)
19348eb6488eSEric Joyner {
1935c19c7afeSEric Joyner 	device_t        dev = iflib_get_dev(adapter->ctx);
19368eb6488eSEric Joyner 	struct ixgbe_hw *hw = &adapter->hw;
1937c19c7afeSEric Joyner 	int             bus_info_valid = TRUE;
19388eb6488eSEric Joyner 	u32             offset;
19398eb6488eSEric Joyner 	u16             link;
19408eb6488eSEric Joyner 
19418eb6488eSEric Joyner 	/* Some devices are behind an internal bridge */
19428eb6488eSEric Joyner 	switch (hw->device_id) {
19438eb6488eSEric Joyner 	case IXGBE_DEV_ID_82599_SFP_SF_QP:
19448eb6488eSEric Joyner 	case IXGBE_DEV_ID_82599_QSFP_SF_QP:
19458eb6488eSEric Joyner 		goto get_parent_info;
19468eb6488eSEric Joyner 	default:
19478eb6488eSEric Joyner 		break;
19488eb6488eSEric Joyner 	}
19498eb6488eSEric Joyner 
19508eb6488eSEric Joyner 	ixgbe_get_bus_info(hw);
19518eb6488eSEric Joyner 
19528eb6488eSEric Joyner 	/*
19538eb6488eSEric Joyner 	 * Some devices don't use PCI-E, but there is no need
19548eb6488eSEric Joyner 	 * to display "Unknown" for bus speed and width.
19558eb6488eSEric Joyner 	 */
19568eb6488eSEric Joyner 	switch (hw->mac.type) {
19578eb6488eSEric Joyner 	case ixgbe_mac_X550EM_x:
19588eb6488eSEric Joyner 	case ixgbe_mac_X550EM_a:
19598eb6488eSEric Joyner 		return;
19608eb6488eSEric Joyner 	default:
19618eb6488eSEric Joyner 		goto display;
19628eb6488eSEric Joyner 	}
19638eb6488eSEric Joyner 
19648eb6488eSEric Joyner get_parent_info:
19658eb6488eSEric Joyner 	/*
19668eb6488eSEric Joyner 	 * For the Quad port adapter we need to parse back
19678eb6488eSEric Joyner 	 * up the PCI tree to find the speed of the expansion
19688eb6488eSEric Joyner 	 * slot into which this adapter is plugged. A bit more work.
19698eb6488eSEric Joyner 	 */
19708eb6488eSEric Joyner 	dev = device_get_parent(device_get_parent(dev));
19718eb6488eSEric Joyner #ifdef IXGBE_DEBUG
19728eb6488eSEric Joyner 	device_printf(dev, "parent pcib = %x,%x,%x\n", pci_get_bus(dev),
19738eb6488eSEric Joyner 	    pci_get_slot(dev), pci_get_function(dev));
19748eb6488eSEric Joyner #endif
19758eb6488eSEric Joyner 	dev = device_get_parent(device_get_parent(dev));
19768eb6488eSEric Joyner #ifdef IXGBE_DEBUG
19778eb6488eSEric Joyner 	device_printf(dev, "slot pcib = %x,%x,%x\n", pci_get_bus(dev),
19788eb6488eSEric Joyner 	    pci_get_slot(dev), pci_get_function(dev));
19798eb6488eSEric Joyner #endif
19808eb6488eSEric Joyner 	/* Now get the PCI Express Capabilities offset */
19818eb6488eSEric Joyner 	if (pci_find_cap(dev, PCIY_EXPRESS, &offset)) {
19828eb6488eSEric Joyner 		/*
19838eb6488eSEric Joyner 		 * Hmm...can't get PCI-Express capabilities.
19848eb6488eSEric Joyner 		 * Falling back to default method.
19858eb6488eSEric Joyner 		 */
19868eb6488eSEric Joyner 		bus_info_valid = FALSE;
19878eb6488eSEric Joyner 		ixgbe_get_bus_info(hw);
19888eb6488eSEric Joyner 		goto display;
19898eb6488eSEric Joyner 	}
19908eb6488eSEric Joyner 	/* ...and read the Link Status Register */
19918eb6488eSEric Joyner 	link = pci_read_config(dev, offset + PCIER_LINK_STA, 2);
19928eb6488eSEric Joyner 	ixgbe_set_pci_config_data_generic(hw, link);
19938eb6488eSEric Joyner 
19948eb6488eSEric Joyner display:
19958eb6488eSEric Joyner 	device_printf(dev, "PCI Express Bus: Speed %s %s\n",
19968eb6488eSEric Joyner 	    ((hw->bus.speed == ixgbe_bus_speed_8000)    ? "8.0GT/s"  :
19978eb6488eSEric Joyner 	     (hw->bus.speed == ixgbe_bus_speed_5000)    ? "5.0GT/s"  :
19988eb6488eSEric Joyner 	     (hw->bus.speed == ixgbe_bus_speed_2500)    ? "2.5GT/s"  :
19998eb6488eSEric Joyner 	     "Unknown"),
20008eb6488eSEric Joyner 	    ((hw->bus.width == ixgbe_bus_width_pcie_x8) ? "Width x8" :
20018eb6488eSEric Joyner 	     (hw->bus.width == ixgbe_bus_width_pcie_x4) ? "Width x4" :
20028eb6488eSEric Joyner 	     (hw->bus.width == ixgbe_bus_width_pcie_x1) ? "Width x1" :
20038eb6488eSEric Joyner 	     "Unknown"));
20048eb6488eSEric Joyner 
20058eb6488eSEric Joyner 	if (bus_info_valid) {
20068eb6488eSEric Joyner 		if ((hw->device_id != IXGBE_DEV_ID_82599_SFP_SF_QP) &&
20078eb6488eSEric Joyner 		    ((hw->bus.width <= ixgbe_bus_width_pcie_x4) &&
20088eb6488eSEric Joyner 		    (hw->bus.speed == ixgbe_bus_speed_2500))) {
20098eb6488eSEric Joyner 			device_printf(dev, "PCI-Express bandwidth available for this card\n     is not sufficient for optimal performance.\n");
20108eb6488eSEric Joyner 			device_printf(dev, "For optimal performance a x8 PCIE, or x4 PCIE Gen2 slot is required.\n");
20118eb6488eSEric Joyner 		}
20128eb6488eSEric Joyner 		if ((hw->device_id == IXGBE_DEV_ID_82599_SFP_SF_QP) &&
20138eb6488eSEric Joyner 		    ((hw->bus.width <= ixgbe_bus_width_pcie_x8) &&
20148eb6488eSEric Joyner 		    (hw->bus.speed < ixgbe_bus_speed_8000))) {
20158eb6488eSEric Joyner 			device_printf(dev, "PCI-Express bandwidth available for this card\n     is not sufficient for optimal performance.\n");
20168eb6488eSEric Joyner 			device_printf(dev, "For optimal performance a x8 PCIE Gen3 slot is required.\n");
20178eb6488eSEric Joyner 		}
20188eb6488eSEric Joyner 	} else
20198eb6488eSEric Joyner 		device_printf(dev, "Unable to determine slot speed/width. The speed/width reported are that of the internal switch.\n");
20208eb6488eSEric Joyner 
20218eb6488eSEric Joyner 	return;
20228eb6488eSEric Joyner } /* ixgbe_get_slot_info */
20238eb6488eSEric Joyner 
20248eb6488eSEric Joyner /************************************************************************
2025c19c7afeSEric Joyner  * ixgbe_if_msix_intr_assign
2026c19c7afeSEric Joyner  *
2027c19c7afeSEric Joyner  *   Setup MSI-X Interrupt resources and handlers
20288eb6488eSEric Joyner  ************************************************************************/
2029c19c7afeSEric Joyner static int
2030c19c7afeSEric Joyner ixgbe_if_msix_intr_assign(if_ctx_t ctx, int msix)
20318eb6488eSEric Joyner {
2032c19c7afeSEric Joyner 	struct adapter     *adapter = iflib_get_softc(ctx);
2033c19c7afeSEric Joyner 	struct ix_rx_queue *rx_que = adapter->rx_queues;
2034c19c7afeSEric Joyner 	struct ix_tx_queue *tx_que;
2035c19c7afeSEric Joyner 	int                error, rid, vector = 0;
2036c19c7afeSEric Joyner 	int                cpu_id = 0;
2037c19c7afeSEric Joyner 	char               buf[16];
20388eb6488eSEric Joyner 
2039c19c7afeSEric Joyner 	/* Admin Que is vector 0*/
2040c19c7afeSEric Joyner 	rid = vector + 1;
2041c19c7afeSEric Joyner 	for (int i = 0; i < adapter->num_rx_queues; i++, vector++, rx_que++) {
2042c19c7afeSEric Joyner 		rid = vector + 1;
2043c19c7afeSEric Joyner 
2044c19c7afeSEric Joyner 		snprintf(buf, sizeof(buf), "rxq%d", i);
2045c19c7afeSEric Joyner 		error = iflib_irq_alloc_generic(ctx, &rx_que->que_irq, rid,
204681be6552SMatt Macy 		    IFLIB_INTR_RXTX, ixgbe_msix_que, rx_que, rx_que->rxr.me, buf);
2047c19c7afeSEric Joyner 
2048c19c7afeSEric Joyner 		if (error) {
2049c19c7afeSEric Joyner 			device_printf(iflib_get_dev(ctx),
2050c19c7afeSEric Joyner 			    "Failed to allocate que int %d err: %d", i, error);
2051c19c7afeSEric Joyner 			adapter->num_rx_queues = i + 1;
2052c19c7afeSEric Joyner 			goto fail;
20538eb6488eSEric Joyner 		}
20548eb6488eSEric Joyner 
2055c19c7afeSEric Joyner 		rx_que->msix = vector;
2056c19c7afeSEric Joyner 		if (adapter->feat_en & IXGBE_FEATURE_RSS) {
2057c19c7afeSEric Joyner 			/*
2058c19c7afeSEric Joyner 			 * The queue ID is used as the RSS layer bucket ID.
2059c19c7afeSEric Joyner 			 * We look up the queue ID -> RSS CPU ID and select
2060c19c7afeSEric Joyner 			 * that.
2061c19c7afeSEric Joyner 			 */
2062c19c7afeSEric Joyner 			cpu_id = rss_getcpu(i % rss_getnumbuckets());
20638eb6488eSEric Joyner 		} else {
2064c19c7afeSEric Joyner 			/*
2065b97de13aSMarius Strobl 			 * Bind the MSI-X vector, and thus the
2066c19c7afeSEric Joyner 			 * rings to the corresponding cpu.
2067c19c7afeSEric Joyner 			 *
2068c19c7afeSEric Joyner 			 * This just happens to match the default RSS
2069c19c7afeSEric Joyner 			 * round-robin bucket -> queue -> CPU allocation.
2070c19c7afeSEric Joyner 			 */
2071c19c7afeSEric Joyner 			if (adapter->num_rx_queues > 1)
2072c19c7afeSEric Joyner 				cpu_id = i;
20738eb6488eSEric Joyner 		}
20748eb6488eSEric Joyner 
2075c19c7afeSEric Joyner 	}
2076c19c7afeSEric Joyner 	for (int i = 0; i < adapter->num_tx_queues; i++) {
2077c19c7afeSEric Joyner 		snprintf(buf, sizeof(buf), "txq%d", i);
2078c19c7afeSEric Joyner 		tx_que = &adapter->tx_queues[i];
2079c19c7afeSEric Joyner 		tx_que->msix = i % adapter->num_rx_queues;
2080c19c7afeSEric Joyner 		iflib_softirq_alloc_generic(ctx,
2081c19c7afeSEric Joyner 		    &adapter->rx_queues[tx_que->msix].que_irq,
2082c19c7afeSEric Joyner 		    IFLIB_INTR_TX, tx_que, tx_que->txr.me, buf);
2083c19c7afeSEric Joyner 	}
2084c19c7afeSEric Joyner 	rid = vector + 1;
2085c19c7afeSEric Joyner 	error = iflib_irq_alloc_generic(ctx, &adapter->irq, rid,
2086c19c7afeSEric Joyner 	    IFLIB_INTR_ADMIN, ixgbe_msix_link, adapter, 0, "aq");
2087c19c7afeSEric Joyner 	if (error) {
2088c19c7afeSEric Joyner 		device_printf(iflib_get_dev(ctx),
2089c19c7afeSEric Joyner 		    "Failed to register admin handler");
2090c19c7afeSEric Joyner 		return (error);
2091c19c7afeSEric Joyner 	}
2092c19c7afeSEric Joyner 
2093c19c7afeSEric Joyner 	adapter->vector = vector;
2094c19c7afeSEric Joyner 
2095c19c7afeSEric Joyner 	return (0);
2096c19c7afeSEric Joyner fail:
2097c19c7afeSEric Joyner 	iflib_irq_free(ctx, &adapter->irq);
2098c19c7afeSEric Joyner 	rx_que = adapter->rx_queues;
2099c19c7afeSEric Joyner 	for (int i = 0; i < adapter->num_rx_queues; i++, rx_que++)
2100c19c7afeSEric Joyner 		iflib_irq_free(ctx, &rx_que->que_irq);
2101c19c7afeSEric Joyner 
2102c19c7afeSEric Joyner 	return (error);
2103c19c7afeSEric Joyner } /* ixgbe_if_msix_intr_assign */
2104c19c7afeSEric Joyner 
2105c19c7afeSEric Joyner /*********************************************************************
21068eb6488eSEric Joyner  * ixgbe_msix_que - MSI-X Queue Interrupt Service routine
2107c19c7afeSEric Joyner  **********************************************************************/
2108c19c7afeSEric Joyner static int
21098eb6488eSEric Joyner ixgbe_msix_que(void *arg)
21108eb6488eSEric Joyner {
2111c19c7afeSEric Joyner 	struct ix_rx_queue *que = arg;
21128eb6488eSEric Joyner 	struct adapter     *adapter = que->adapter;
2113c19c7afeSEric Joyner 	struct ifnet       *ifp = iflib_get_ifp(que->adapter->ctx);
21148eb6488eSEric Joyner 
21158eb6488eSEric Joyner 	/* Protect against spurious interrupts */
21168eb6488eSEric Joyner 	if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0)
21176c351041SEric Joyner 		return (FILTER_HANDLED);
21188eb6488eSEric Joyner 
21198eb6488eSEric Joyner 	ixgbe_disable_queue(adapter, que->msix);
21208eb6488eSEric Joyner 	++que->irqs;
21218eb6488eSEric Joyner 
2122c19c7afeSEric Joyner 	return (FILTER_SCHEDULE_THREAD);
21238eb6488eSEric Joyner } /* ixgbe_msix_que */
21248eb6488eSEric Joyner 
21258eb6488eSEric Joyner /************************************************************************
21268eb6488eSEric Joyner  * ixgbe_media_status - Media Ioctl callback
21278eb6488eSEric Joyner  *
21288eb6488eSEric Joyner  *   Called whenever the user queries the status of
21298eb6488eSEric Joyner  *   the interface using ifconfig.
21308eb6488eSEric Joyner  ************************************************************************/
21318eb6488eSEric Joyner static void
2132c19c7afeSEric Joyner ixgbe_if_media_status(if_ctx_t ctx, struct ifmediareq * ifmr)
21338eb6488eSEric Joyner {
2134c19c7afeSEric Joyner 	struct adapter  *adapter = iflib_get_softc(ctx);
21358eb6488eSEric Joyner 	struct ixgbe_hw *hw = &adapter->hw;
21368eb6488eSEric Joyner 	int             layer;
21378eb6488eSEric Joyner 
2138c19c7afeSEric Joyner 	INIT_DEBUGOUT("ixgbe_if_media_status: begin");
2139c19c7afeSEric Joyner 
21408eb6488eSEric Joyner 	ifmr->ifm_status = IFM_AVALID;
21418eb6488eSEric Joyner 	ifmr->ifm_active = IFM_ETHER;
21428eb6488eSEric Joyner 
2143c19c7afeSEric Joyner 	if (!adapter->link_active)
21448eb6488eSEric Joyner 		return;
21458eb6488eSEric Joyner 
21468eb6488eSEric Joyner 	ifmr->ifm_status |= IFM_ACTIVE;
21478eb6488eSEric Joyner 	layer = adapter->phy_layer;
21488eb6488eSEric Joyner 
21498eb6488eSEric Joyner 	if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_T ||
21508eb6488eSEric Joyner 	    layer & IXGBE_PHYSICAL_LAYER_1000BASE_T ||
21518eb6488eSEric Joyner 	    layer & IXGBE_PHYSICAL_LAYER_100BASE_TX ||
21528eb6488eSEric Joyner 	    layer & IXGBE_PHYSICAL_LAYER_10BASE_T)
21538eb6488eSEric Joyner 		switch (adapter->link_speed) {
21548eb6488eSEric Joyner 		case IXGBE_LINK_SPEED_10GB_FULL:
21558eb6488eSEric Joyner 			ifmr->ifm_active |= IFM_10G_T | IFM_FDX;
21568eb6488eSEric Joyner 			break;
21578eb6488eSEric Joyner 		case IXGBE_LINK_SPEED_1GB_FULL:
21588eb6488eSEric Joyner 			ifmr->ifm_active |= IFM_1000_T | IFM_FDX;
21598eb6488eSEric Joyner 			break;
21608eb6488eSEric Joyner 		case IXGBE_LINK_SPEED_100_FULL:
21618eb6488eSEric Joyner 			ifmr->ifm_active |= IFM_100_TX | IFM_FDX;
21628eb6488eSEric Joyner 			break;
21638eb6488eSEric Joyner 		case IXGBE_LINK_SPEED_10_FULL:
21648eb6488eSEric Joyner 			ifmr->ifm_active |= IFM_10_T | IFM_FDX;
21658eb6488eSEric Joyner 			break;
21668eb6488eSEric Joyner 		}
21678eb6488eSEric Joyner 	if (layer & IXGBE_PHYSICAL_LAYER_SFP_PLUS_CU ||
21688eb6488eSEric Joyner 	    layer & IXGBE_PHYSICAL_LAYER_SFP_ACTIVE_DA)
21698eb6488eSEric Joyner 		switch (adapter->link_speed) {
21708eb6488eSEric Joyner 		case IXGBE_LINK_SPEED_10GB_FULL:
21718eb6488eSEric Joyner 			ifmr->ifm_active |= IFM_10G_TWINAX | IFM_FDX;
21728eb6488eSEric Joyner 			break;
21738eb6488eSEric Joyner 		}
21748eb6488eSEric Joyner 	if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_LR)
21758eb6488eSEric Joyner 		switch (adapter->link_speed) {
21768eb6488eSEric Joyner 		case IXGBE_LINK_SPEED_10GB_FULL:
21778eb6488eSEric Joyner 			ifmr->ifm_active |= IFM_10G_LR | IFM_FDX;
21788eb6488eSEric Joyner 			break;
21798eb6488eSEric Joyner 		case IXGBE_LINK_SPEED_1GB_FULL:
21808eb6488eSEric Joyner 			ifmr->ifm_active |= IFM_1000_LX | IFM_FDX;
21818eb6488eSEric Joyner 			break;
21828eb6488eSEric Joyner 		}
21838eb6488eSEric Joyner 	if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_LRM)
21848eb6488eSEric Joyner 		switch (adapter->link_speed) {
21858eb6488eSEric Joyner 		case IXGBE_LINK_SPEED_10GB_FULL:
21868eb6488eSEric Joyner 			ifmr->ifm_active |= IFM_10G_LRM | IFM_FDX;
21878eb6488eSEric Joyner 			break;
21888eb6488eSEric Joyner 		case IXGBE_LINK_SPEED_1GB_FULL:
21898eb6488eSEric Joyner 			ifmr->ifm_active |= IFM_1000_LX | IFM_FDX;
21908eb6488eSEric Joyner 			break;
21918eb6488eSEric Joyner 		}
21928eb6488eSEric Joyner 	if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_SR ||
21938eb6488eSEric Joyner 	    layer & IXGBE_PHYSICAL_LAYER_1000BASE_SX)
21948eb6488eSEric Joyner 		switch (adapter->link_speed) {
21958eb6488eSEric Joyner 		case IXGBE_LINK_SPEED_10GB_FULL:
21968eb6488eSEric Joyner 			ifmr->ifm_active |= IFM_10G_SR | IFM_FDX;
21978eb6488eSEric Joyner 			break;
21988eb6488eSEric Joyner 		case IXGBE_LINK_SPEED_1GB_FULL:
21998eb6488eSEric Joyner 			ifmr->ifm_active |= IFM_1000_SX | IFM_FDX;
22008eb6488eSEric Joyner 			break;
22018eb6488eSEric Joyner 		}
22028eb6488eSEric Joyner 	if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_CX4)
22038eb6488eSEric Joyner 		switch (adapter->link_speed) {
22048eb6488eSEric Joyner 		case IXGBE_LINK_SPEED_10GB_FULL:
22058eb6488eSEric Joyner 			ifmr->ifm_active |= IFM_10G_CX4 | IFM_FDX;
22068eb6488eSEric Joyner 			break;
22078eb6488eSEric Joyner 		}
22088eb6488eSEric Joyner 	/*
22098eb6488eSEric Joyner 	 * XXX: These need to use the proper media types once
22108eb6488eSEric Joyner 	 * they're added.
22118eb6488eSEric Joyner 	 */
22128eb6488eSEric Joyner #ifndef IFM_ETH_XTYPE
22138eb6488eSEric Joyner 	if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_KR)
22148eb6488eSEric Joyner 		switch (adapter->link_speed) {
22158eb6488eSEric Joyner 		case IXGBE_LINK_SPEED_10GB_FULL:
22168eb6488eSEric Joyner 			ifmr->ifm_active |= IFM_10G_SR | IFM_FDX;
22178eb6488eSEric Joyner 			break;
22188eb6488eSEric Joyner 		case IXGBE_LINK_SPEED_2_5GB_FULL:
22198eb6488eSEric Joyner 			ifmr->ifm_active |= IFM_2500_SX | IFM_FDX;
22208eb6488eSEric Joyner 			break;
22218eb6488eSEric Joyner 		case IXGBE_LINK_SPEED_1GB_FULL:
22228eb6488eSEric Joyner 			ifmr->ifm_active |= IFM_1000_CX | IFM_FDX;
22238eb6488eSEric Joyner 			break;
22248eb6488eSEric Joyner 		}
22258eb6488eSEric Joyner 	else if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_KX4 ||
22268eb6488eSEric Joyner 	    layer & IXGBE_PHYSICAL_LAYER_2500BASE_KX ||
22278eb6488eSEric Joyner 	    layer & IXGBE_PHYSICAL_LAYER_1000BASE_KX)
22288eb6488eSEric Joyner 		switch (adapter->link_speed) {
22298eb6488eSEric Joyner 		case IXGBE_LINK_SPEED_10GB_FULL:
22308eb6488eSEric Joyner 			ifmr->ifm_active |= IFM_10G_CX4 | IFM_FDX;
22318eb6488eSEric Joyner 			break;
22328eb6488eSEric Joyner 		case IXGBE_LINK_SPEED_2_5GB_FULL:
22338eb6488eSEric Joyner 			ifmr->ifm_active |= IFM_2500_SX | IFM_FDX;
22348eb6488eSEric Joyner 			break;
22358eb6488eSEric Joyner 		case IXGBE_LINK_SPEED_1GB_FULL:
22368eb6488eSEric Joyner 			ifmr->ifm_active |= IFM_1000_CX | IFM_FDX;
22378eb6488eSEric Joyner 			break;
22388eb6488eSEric Joyner 		}
22398eb6488eSEric Joyner #else
22408eb6488eSEric Joyner 	if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_KR)
22418eb6488eSEric Joyner 		switch (adapter->link_speed) {
22428eb6488eSEric Joyner 		case IXGBE_LINK_SPEED_10GB_FULL:
22438eb6488eSEric Joyner 			ifmr->ifm_active |= IFM_10G_KR | IFM_FDX;
22448eb6488eSEric Joyner 			break;
22458eb6488eSEric Joyner 		case IXGBE_LINK_SPEED_2_5GB_FULL:
22468eb6488eSEric Joyner 			ifmr->ifm_active |= IFM_2500_KX | IFM_FDX;
22478eb6488eSEric Joyner 			break;
22488eb6488eSEric Joyner 		case IXGBE_LINK_SPEED_1GB_FULL:
22498eb6488eSEric Joyner 			ifmr->ifm_active |= IFM_1000_KX | IFM_FDX;
22508eb6488eSEric Joyner 			break;
22518eb6488eSEric Joyner 		}
22528eb6488eSEric Joyner 	else if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_KX4 ||
22538eb6488eSEric Joyner 	    layer & IXGBE_PHYSICAL_LAYER_2500BASE_KX ||
22548eb6488eSEric Joyner 	    layer & IXGBE_PHYSICAL_LAYER_1000BASE_KX)
22558eb6488eSEric Joyner 		switch (adapter->link_speed) {
22568eb6488eSEric Joyner 		case IXGBE_LINK_SPEED_10GB_FULL:
22578eb6488eSEric Joyner 			ifmr->ifm_active |= IFM_10G_KX4 | IFM_FDX;
22588eb6488eSEric Joyner 			break;
22598eb6488eSEric Joyner 		case IXGBE_LINK_SPEED_2_5GB_FULL:
22608eb6488eSEric Joyner 			ifmr->ifm_active |= IFM_2500_KX | IFM_FDX;
22618eb6488eSEric Joyner 			break;
22628eb6488eSEric Joyner 		case IXGBE_LINK_SPEED_1GB_FULL:
22638eb6488eSEric Joyner 			ifmr->ifm_active |= IFM_1000_KX | IFM_FDX;
22648eb6488eSEric Joyner 			break;
22658eb6488eSEric Joyner 		}
22668eb6488eSEric Joyner #endif
22678eb6488eSEric Joyner 
22688eb6488eSEric Joyner 	/* If nothing is recognized... */
22698eb6488eSEric Joyner 	if (IFM_SUBTYPE(ifmr->ifm_active) == 0)
22708eb6488eSEric Joyner 		ifmr->ifm_active |= IFM_UNKNOWN;
22718eb6488eSEric Joyner 
22728eb6488eSEric Joyner 	/* Display current flow control setting used on link */
22738eb6488eSEric Joyner 	if (hw->fc.current_mode == ixgbe_fc_rx_pause ||
22748eb6488eSEric Joyner 	    hw->fc.current_mode == ixgbe_fc_full)
22758eb6488eSEric Joyner 		ifmr->ifm_active |= IFM_ETH_RXPAUSE;
22768eb6488eSEric Joyner 	if (hw->fc.current_mode == ixgbe_fc_tx_pause ||
22778eb6488eSEric Joyner 	    hw->fc.current_mode == ixgbe_fc_full)
22788eb6488eSEric Joyner 		ifmr->ifm_active |= IFM_ETH_TXPAUSE;
22798eb6488eSEric Joyner } /* ixgbe_media_status */
22808eb6488eSEric Joyner 
22818eb6488eSEric Joyner /************************************************************************
22828eb6488eSEric Joyner  * ixgbe_media_change - Media Ioctl callback
22838eb6488eSEric Joyner  *
22848eb6488eSEric Joyner  *   Called when the user changes speed/duplex using
22858eb6488eSEric Joyner  *   media/mediopt option with ifconfig.
22868eb6488eSEric Joyner  ************************************************************************/
22878eb6488eSEric Joyner static int
2288c19c7afeSEric Joyner ixgbe_if_media_change(if_ctx_t ctx)
22898eb6488eSEric Joyner {
2290c19c7afeSEric Joyner 	struct adapter   *adapter = iflib_get_softc(ctx);
2291c19c7afeSEric Joyner 	struct ifmedia   *ifm = iflib_get_media(ctx);
22928eb6488eSEric Joyner 	struct ixgbe_hw  *hw = &adapter->hw;
22938eb6488eSEric Joyner 	ixgbe_link_speed speed = 0;
22948eb6488eSEric Joyner 
2295c19c7afeSEric Joyner 	INIT_DEBUGOUT("ixgbe_if_media_change: begin");
22968eb6488eSEric Joyner 
22978eb6488eSEric Joyner 	if (IFM_TYPE(ifm->ifm_media) != IFM_ETHER)
22988eb6488eSEric Joyner 		return (EINVAL);
22998eb6488eSEric Joyner 
23008eb6488eSEric Joyner 	if (hw->phy.media_type == ixgbe_media_type_backplane)
2301c19c7afeSEric Joyner 		return (EPERM);
23028eb6488eSEric Joyner 
23038eb6488eSEric Joyner 	/*
23048eb6488eSEric Joyner 	 * We don't actually need to check against the supported
23058eb6488eSEric Joyner 	 * media types of the adapter; ifmedia will take care of
23068eb6488eSEric Joyner 	 * that for us.
23078eb6488eSEric Joyner 	 */
23088eb6488eSEric Joyner 	switch (IFM_SUBTYPE(ifm->ifm_media)) {
23098eb6488eSEric Joyner 	case IFM_AUTO:
23108eb6488eSEric Joyner 	case IFM_10G_T:
23118eb6488eSEric Joyner 		speed |= IXGBE_LINK_SPEED_100_FULL;
23128eb6488eSEric Joyner 		speed |= IXGBE_LINK_SPEED_1GB_FULL;
23138eb6488eSEric Joyner 		speed |= IXGBE_LINK_SPEED_10GB_FULL;
23148eb6488eSEric Joyner 		break;
23158eb6488eSEric Joyner 	case IFM_10G_LRM:
23168eb6488eSEric Joyner 	case IFM_10G_LR:
23178eb6488eSEric Joyner #ifndef IFM_ETH_XTYPE
23188eb6488eSEric Joyner 	case IFM_10G_SR: /* KR, too */
23198eb6488eSEric Joyner 	case IFM_10G_CX4: /* KX4 */
23208eb6488eSEric Joyner #else
23218eb6488eSEric Joyner 	case IFM_10G_KR:
23228eb6488eSEric Joyner 	case IFM_10G_KX4:
23238eb6488eSEric Joyner #endif
23248eb6488eSEric Joyner 		speed |= IXGBE_LINK_SPEED_1GB_FULL;
23258eb6488eSEric Joyner 		speed |= IXGBE_LINK_SPEED_10GB_FULL;
23268eb6488eSEric Joyner 		break;
23278eb6488eSEric Joyner #ifndef IFM_ETH_XTYPE
23288eb6488eSEric Joyner 	case IFM_1000_CX: /* KX */
23298eb6488eSEric Joyner #else
23308eb6488eSEric Joyner 	case IFM_1000_KX:
23318eb6488eSEric Joyner #endif
23328eb6488eSEric Joyner 	case IFM_1000_LX:
23338eb6488eSEric Joyner 	case IFM_1000_SX:
23348eb6488eSEric Joyner 		speed |= IXGBE_LINK_SPEED_1GB_FULL;
23358eb6488eSEric Joyner 		break;
23368eb6488eSEric Joyner 	case IFM_1000_T:
23378eb6488eSEric Joyner 		speed |= IXGBE_LINK_SPEED_100_FULL;
23388eb6488eSEric Joyner 		speed |= IXGBE_LINK_SPEED_1GB_FULL;
23398eb6488eSEric Joyner 		break;
23408eb6488eSEric Joyner 	case IFM_10G_TWINAX:
23418eb6488eSEric Joyner 		speed |= IXGBE_LINK_SPEED_10GB_FULL;
23428eb6488eSEric Joyner 		break;
23438eb6488eSEric Joyner 	case IFM_100_TX:
23448eb6488eSEric Joyner 		speed |= IXGBE_LINK_SPEED_100_FULL;
23458eb6488eSEric Joyner 		break;
23468eb6488eSEric Joyner 	case IFM_10_T:
23478eb6488eSEric Joyner 		speed |= IXGBE_LINK_SPEED_10_FULL;
23488eb6488eSEric Joyner 		break;
23498eb6488eSEric Joyner 	default:
23508eb6488eSEric Joyner 		goto invalid;
23518eb6488eSEric Joyner 	}
23528eb6488eSEric Joyner 
23538eb6488eSEric Joyner 	hw->mac.autotry_restart = TRUE;
23548eb6488eSEric Joyner 	hw->mac.ops.setup_link(hw, speed, TRUE);
23558eb6488eSEric Joyner 	adapter->advertise =
23568eb6488eSEric Joyner 	    ((speed & IXGBE_LINK_SPEED_10GB_FULL) ? 4 : 0) |
23578eb6488eSEric Joyner 	    ((speed & IXGBE_LINK_SPEED_1GB_FULL)  ? 2 : 0) |
23588eb6488eSEric Joyner 	    ((speed & IXGBE_LINK_SPEED_100_FULL)  ? 1 : 0) |
23598eb6488eSEric Joyner 	    ((speed & IXGBE_LINK_SPEED_10_FULL)   ? 8 : 0);
23608eb6488eSEric Joyner 
23618eb6488eSEric Joyner 	return (0);
23628eb6488eSEric Joyner 
23638eb6488eSEric Joyner invalid:
2364c19c7afeSEric Joyner 	device_printf(iflib_get_dev(ctx), "Invalid media type!\n");
23658eb6488eSEric Joyner 
23668eb6488eSEric Joyner 	return (EINVAL);
2367c19c7afeSEric Joyner } /* ixgbe_if_media_change */
23688eb6488eSEric Joyner 
23698eb6488eSEric Joyner /************************************************************************
23708eb6488eSEric Joyner  * ixgbe_set_promisc
23718eb6488eSEric Joyner  ************************************************************************/
2372c19c7afeSEric Joyner static int
2373c19c7afeSEric Joyner ixgbe_if_promisc_set(if_ctx_t ctx, int flags)
23748eb6488eSEric Joyner {
2375c19c7afeSEric Joyner 	struct adapter *adapter = iflib_get_softc(ctx);
2376c19c7afeSEric Joyner 	struct ifnet   *ifp = iflib_get_ifp(ctx);
23778eb6488eSEric Joyner 	u32            rctl;
2378c19c7afeSEric Joyner 	int            mcnt = 0;
23798eb6488eSEric Joyner 
23808eb6488eSEric Joyner 	rctl = IXGBE_READ_REG(&adapter->hw, IXGBE_FCTRL);
23818eb6488eSEric Joyner 	rctl &= (~IXGBE_FCTRL_UPE);
23828eb6488eSEric Joyner 	if (ifp->if_flags & IFF_ALLMULTI)
23838eb6488eSEric Joyner 		mcnt = MAX_NUM_MULTICAST_ADDRESSES;
23848eb6488eSEric Joyner 	else {
2385ba76aa63SGleb Smirnoff 		mcnt = min(if_llmaddr_count(ifp), MAX_NUM_MULTICAST_ADDRESSES);
23868eb6488eSEric Joyner 	}
23878eb6488eSEric Joyner 	if (mcnt < MAX_NUM_MULTICAST_ADDRESSES)
23888eb6488eSEric Joyner 		rctl &= (~IXGBE_FCTRL_MPE);
23898eb6488eSEric Joyner 	IXGBE_WRITE_REG(&adapter->hw, IXGBE_FCTRL, rctl);
23908eb6488eSEric Joyner 
23918eb6488eSEric Joyner 	if (ifp->if_flags & IFF_PROMISC) {
23928eb6488eSEric Joyner 		rctl |= (IXGBE_FCTRL_UPE | IXGBE_FCTRL_MPE);
23938eb6488eSEric Joyner 		IXGBE_WRITE_REG(&adapter->hw, IXGBE_FCTRL, rctl);
23948eb6488eSEric Joyner 	} else if (ifp->if_flags & IFF_ALLMULTI) {
23958eb6488eSEric Joyner 		rctl |= IXGBE_FCTRL_MPE;
23968eb6488eSEric Joyner 		rctl &= ~IXGBE_FCTRL_UPE;
23978eb6488eSEric Joyner 		IXGBE_WRITE_REG(&adapter->hw, IXGBE_FCTRL, rctl);
23988eb6488eSEric Joyner 	}
2399c19c7afeSEric Joyner 	return (0);
2400c19c7afeSEric Joyner } /* ixgbe_if_promisc_set */
24018eb6488eSEric Joyner 
24028eb6488eSEric Joyner /************************************************************************
24038eb6488eSEric Joyner  * ixgbe_msix_link - Link status change ISR (MSI/MSI-X)
24048eb6488eSEric Joyner  ************************************************************************/
2405c19c7afeSEric Joyner static int
24068eb6488eSEric Joyner ixgbe_msix_link(void *arg)
24078eb6488eSEric Joyner {
24088eb6488eSEric Joyner 	struct adapter  *adapter = arg;
24098eb6488eSEric Joyner 	struct ixgbe_hw *hw = &adapter->hw;
24108eb6488eSEric Joyner 	u32             eicr, eicr_mask;
24118eb6488eSEric Joyner 	s32             retval;
24128eb6488eSEric Joyner 
24138eb6488eSEric Joyner 	++adapter->link_irq;
24148eb6488eSEric Joyner 
24158eb6488eSEric Joyner 	/* Pause other interrupts */
24168eb6488eSEric Joyner 	IXGBE_WRITE_REG(hw, IXGBE_EIMC, IXGBE_EIMC_OTHER);
24178eb6488eSEric Joyner 
24188eb6488eSEric Joyner 	/* First get the cause */
24198eb6488eSEric Joyner 	eicr = IXGBE_READ_REG(hw, IXGBE_EICS);
24208eb6488eSEric Joyner 	/* Be sure the queue bits are not cleared */
24218eb6488eSEric Joyner 	eicr &= ~IXGBE_EICR_RTX_QUEUE;
24228eb6488eSEric Joyner 	/* Clear interrupt with write */
24238eb6488eSEric Joyner 	IXGBE_WRITE_REG(hw, IXGBE_EICR, eicr);
24248eb6488eSEric Joyner 
24258eb6488eSEric Joyner 	/* Link status change */
24268eb6488eSEric Joyner 	if (eicr & IXGBE_EICR_LSC) {
24278eb6488eSEric Joyner 		IXGBE_WRITE_REG(hw, IXGBE_EIMC, IXGBE_EIMC_LSC);
2428b2c1e8e6SEric Joyner 		adapter->task_requests |= IXGBE_REQUEST_TASK_LSC;
24298eb6488eSEric Joyner 	}
24308eb6488eSEric Joyner 
24318eb6488eSEric Joyner 	if (adapter->hw.mac.type != ixgbe_mac_82598EB) {
24328eb6488eSEric Joyner 		if ((adapter->feat_en & IXGBE_FEATURE_FDIR) &&
24338eb6488eSEric Joyner 		    (eicr & IXGBE_EICR_FLOW_DIR)) {
24348eb6488eSEric Joyner 			/* This is probably overkill :) */
24358eb6488eSEric Joyner 			if (!atomic_cmpset_int(&adapter->fdir_reinit, 0, 1))
2436c19c7afeSEric Joyner 				return (FILTER_HANDLED);
24378eb6488eSEric Joyner 			/* Disable the interrupt */
2438c19c7afeSEric Joyner 			IXGBE_WRITE_REG(hw, IXGBE_EIMC, IXGBE_EICR_FLOW_DIR);
2439b2c1e8e6SEric Joyner 			adapter->task_requests |= IXGBE_REQUEST_TASK_FDIR;
2440c19c7afeSEric Joyner 		} else
24418eb6488eSEric Joyner 			if (eicr & IXGBE_EICR_ECC) {
2442c19c7afeSEric Joyner 				device_printf(iflib_get_dev(adapter->ctx),
2443c19c7afeSEric Joyner 				   "\nCRITICAL: ECC ERROR!! Please Reboot!!\n");
24448eb6488eSEric Joyner 				IXGBE_WRITE_REG(hw, IXGBE_EICR, IXGBE_EICR_ECC);
24458eb6488eSEric Joyner 			}
24468eb6488eSEric Joyner 
24478eb6488eSEric Joyner 		/* Check for over temp condition */
24488eb6488eSEric Joyner 		if (adapter->feat_en & IXGBE_FEATURE_TEMP_SENSOR) {
24498eb6488eSEric Joyner 			switch (adapter->hw.mac.type) {
24508eb6488eSEric Joyner 			case ixgbe_mac_X550EM_a:
24518eb6488eSEric Joyner 				if (!(eicr & IXGBE_EICR_GPI_SDP0_X550EM_a))
24528eb6488eSEric Joyner 					break;
24538eb6488eSEric Joyner 				IXGBE_WRITE_REG(hw, IXGBE_EIMC,
24548eb6488eSEric Joyner 				    IXGBE_EICR_GPI_SDP0_X550EM_a);
24558eb6488eSEric Joyner 				IXGBE_WRITE_REG(hw, IXGBE_EICR,
24568eb6488eSEric Joyner 				    IXGBE_EICR_GPI_SDP0_X550EM_a);
24578eb6488eSEric Joyner 				retval = hw->phy.ops.check_overtemp(hw);
24588eb6488eSEric Joyner 				if (retval != IXGBE_ERR_OVERTEMP)
24598eb6488eSEric Joyner 					break;
2460c19c7afeSEric Joyner 				device_printf(iflib_get_dev(adapter->ctx),
2461c19c7afeSEric Joyner 				    "\nCRITICAL: OVER TEMP!! PHY IS SHUT DOWN!!\n");
2462c19c7afeSEric Joyner 				device_printf(iflib_get_dev(adapter->ctx),
2463c19c7afeSEric Joyner 				    "System shutdown required!\n");
24648eb6488eSEric Joyner 				break;
24658eb6488eSEric Joyner 			default:
24668eb6488eSEric Joyner 				if (!(eicr & IXGBE_EICR_TS))
24678eb6488eSEric Joyner 					break;
24688eb6488eSEric Joyner 				retval = hw->phy.ops.check_overtemp(hw);
24698eb6488eSEric Joyner 				if (retval != IXGBE_ERR_OVERTEMP)
24708eb6488eSEric Joyner 					break;
2471c19c7afeSEric Joyner 				device_printf(iflib_get_dev(adapter->ctx),
2472c19c7afeSEric Joyner 				    "\nCRITICAL: OVER TEMP!! PHY IS SHUT DOWN!!\n");
2473c19c7afeSEric Joyner 				device_printf(iflib_get_dev(adapter->ctx),
2474c19c7afeSEric Joyner 				    "System shutdown required!\n");
24758eb6488eSEric Joyner 				IXGBE_WRITE_REG(hw, IXGBE_EICR, IXGBE_EICR_TS);
24768eb6488eSEric Joyner 				break;
24778eb6488eSEric Joyner 			}
24788eb6488eSEric Joyner 		}
24798eb6488eSEric Joyner 
24808eb6488eSEric Joyner 		/* Check for VF message */
24818eb6488eSEric Joyner 		if ((adapter->feat_en & IXGBE_FEATURE_SRIOV) &&
24828eb6488eSEric Joyner 		    (eicr & IXGBE_EICR_MAILBOX))
2483b2c1e8e6SEric Joyner 			adapter->task_requests |= IXGBE_REQUEST_TASK_MBX;
24848eb6488eSEric Joyner 	}
24858eb6488eSEric Joyner 
24868eb6488eSEric Joyner 	if (ixgbe_is_sfp(hw)) {
24878eb6488eSEric Joyner 		/* Pluggable optics-related interrupt */
24888eb6488eSEric Joyner 		if (hw->mac.type >= ixgbe_mac_X540)
24898eb6488eSEric Joyner 			eicr_mask = IXGBE_EICR_GPI_SDP0_X540;
24908eb6488eSEric Joyner 		else
24918eb6488eSEric Joyner 			eicr_mask = IXGBE_EICR_GPI_SDP2_BY_MAC(hw);
24928eb6488eSEric Joyner 
24938eb6488eSEric Joyner 		if (eicr & eicr_mask) {
24948eb6488eSEric Joyner 			IXGBE_WRITE_REG(hw, IXGBE_EICR, eicr_mask);
2495b2c1e8e6SEric Joyner 			adapter->task_requests |= IXGBE_REQUEST_TASK_MOD;
24968eb6488eSEric Joyner 		}
24978eb6488eSEric Joyner 
24988eb6488eSEric Joyner 		if ((hw->mac.type == ixgbe_mac_82599EB) &&
24998eb6488eSEric Joyner 		    (eicr & IXGBE_EICR_GPI_SDP1_BY_MAC(hw))) {
25008eb6488eSEric Joyner 			IXGBE_WRITE_REG(hw, IXGBE_EICR,
25018eb6488eSEric Joyner 			    IXGBE_EICR_GPI_SDP1_BY_MAC(hw));
2502b2c1e8e6SEric Joyner 			adapter->task_requests |= IXGBE_REQUEST_TASK_MSF;
25038eb6488eSEric Joyner 		}
25048eb6488eSEric Joyner 	}
25058eb6488eSEric Joyner 
25068eb6488eSEric Joyner 	/* Check for fan failure */
25078eb6488eSEric Joyner 	if (adapter->feat_en & IXGBE_FEATURE_FAN_FAIL) {
25088eb6488eSEric Joyner 		ixgbe_check_fan_failure(adapter, eicr, TRUE);
25098eb6488eSEric Joyner 		IXGBE_WRITE_REG(hw, IXGBE_EICR, IXGBE_EICR_GPI_SDP1_BY_MAC(hw));
25108eb6488eSEric Joyner 	}
25118eb6488eSEric Joyner 
25128eb6488eSEric Joyner 	/* External PHY interrupt */
25138eb6488eSEric Joyner 	if ((hw->phy.type == ixgbe_phy_x550em_ext_t) &&
25148eb6488eSEric Joyner 	    (eicr & IXGBE_EICR_GPI_SDP0_X540)) {
25158eb6488eSEric Joyner 		IXGBE_WRITE_REG(hw, IXGBE_EICR, IXGBE_EICR_GPI_SDP0_X540);
2516b2c1e8e6SEric Joyner 		adapter->task_requests |= IXGBE_REQUEST_TASK_PHY;
25178eb6488eSEric Joyner 	}
25188eb6488eSEric Joyner 
2519b2c1e8e6SEric Joyner 	return (adapter->task_requests != 0) ? FILTER_SCHEDULE_THREAD : FILTER_HANDLED;
25208eb6488eSEric Joyner } /* ixgbe_msix_link */
25218eb6488eSEric Joyner 
25228eb6488eSEric Joyner /************************************************************************
25238eb6488eSEric Joyner  * ixgbe_sysctl_interrupt_rate_handler
25248eb6488eSEric Joyner  ************************************************************************/
2525758cc3dcSJack F Vogel static int
2526758cc3dcSJack F Vogel ixgbe_sysctl_interrupt_rate_handler(SYSCTL_HANDLER_ARGS)
2527758cc3dcSJack F Vogel {
2528c19c7afeSEric Joyner 	struct ix_rx_queue *que = ((struct ix_rx_queue *)oidp->oid_arg1);
25298eb6488eSEric Joyner 	int                error;
2530758cc3dcSJack F Vogel 	unsigned int       reg, usec, rate;
2531758cc3dcSJack F Vogel 
2532758cc3dcSJack F Vogel 	reg = IXGBE_READ_REG(&que->adapter->hw, IXGBE_EITR(que->msix));
2533758cc3dcSJack F Vogel 	usec = ((reg & 0x0FF8) >> 3);
2534758cc3dcSJack F Vogel 	if (usec > 0)
2535758cc3dcSJack F Vogel 		rate = 500000 / usec;
2536758cc3dcSJack F Vogel 	else
2537758cc3dcSJack F Vogel 		rate = 0;
2538758cc3dcSJack F Vogel 	error = sysctl_handle_int(oidp, &rate, 0, req);
2539758cc3dcSJack F Vogel 	if (error || !req->newptr)
2540758cc3dcSJack F Vogel 		return error;
2541758cc3dcSJack F Vogel 	reg &= ~0xfff; /* default, no limitation */
2542758cc3dcSJack F Vogel 	ixgbe_max_interrupt_rate = 0;
2543758cc3dcSJack F Vogel 	if (rate > 0 && rate < 500000) {
2544758cc3dcSJack F Vogel 		if (rate < 1000)
2545758cc3dcSJack F Vogel 			rate = 1000;
2546758cc3dcSJack F Vogel 		ixgbe_max_interrupt_rate = rate;
2547758cc3dcSJack F Vogel 		reg |= ((4000000/rate) & 0xff8);
2548758cc3dcSJack F Vogel 	}
2549758cc3dcSJack F Vogel 	IXGBE_WRITE_REG(&que->adapter->hw, IXGBE_EITR(que->msix), reg);
2550758cc3dcSJack F Vogel 
25518eb6488eSEric Joyner 	return (0);
25528eb6488eSEric Joyner } /* ixgbe_sysctl_interrupt_rate_handler */
25538eb6488eSEric Joyner 
25548eb6488eSEric Joyner /************************************************************************
25558eb6488eSEric Joyner  * ixgbe_add_device_sysctls
25568eb6488eSEric Joyner  ************************************************************************/
25576f37f232SEric Joyner static void
2558c19c7afeSEric Joyner ixgbe_add_device_sysctls(if_ctx_t ctx)
25596f37f232SEric Joyner {
2560c19c7afeSEric Joyner 	struct adapter         *adapter = iflib_get_softc(ctx);
2561c19c7afeSEric Joyner 	device_t               dev = iflib_get_dev(ctx);
25626f37f232SEric Joyner 	struct ixgbe_hw        *hw = &adapter->hw;
25636f37f232SEric Joyner 	struct sysctl_oid_list *child;
2564c19c7afeSEric Joyner 	struct sysctl_ctx_list *ctx_list;
25656f37f232SEric Joyner 
2566c19c7afeSEric Joyner 	ctx_list = device_get_sysctl_ctx(dev);
25676f37f232SEric Joyner 	child = SYSCTL_CHILDREN(device_get_sysctl_tree(dev));
25686f37f232SEric Joyner 
25696f37f232SEric Joyner 	/* Sysctls for all devices */
2570c19c7afeSEric Joyner 	SYSCTL_ADD_PROC(ctx_list, child, OID_AUTO, "fc",
257120b91f0aSPawel Biernacki 	    CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_NEEDGIANT,
257220b91f0aSPawel Biernacki 	    adapter, 0, ixgbe_sysctl_flowcntl, "I",
2573c19c7afeSEric Joyner 	    IXGBE_SYSCTL_DESC_SET_FC);
25746f37f232SEric Joyner 
2575c19c7afeSEric Joyner 	SYSCTL_ADD_PROC(ctx_list, child, OID_AUTO, "advertise_speed",
257620b91f0aSPawel Biernacki 	    CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_NEEDGIANT,
257720b91f0aSPawel Biernacki 	    adapter, 0, ixgbe_sysctl_advertise, "I",
25788eb6488eSEric Joyner 	    IXGBE_SYSCTL_DESC_ADV_SPEED);
25796f37f232SEric Joyner 
2580a9ca1c79SSean Bruno #ifdef IXGBE_DEBUG
2581a9ca1c79SSean Bruno 	/* testing sysctls (for all devices) */
2582c19c7afeSEric Joyner 	SYSCTL_ADD_PROC(ctx_list, child, OID_AUTO, "power_state",
258320b91f0aSPawel Biernacki 	    CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_NEEDGIANT,
258420b91f0aSPawel Biernacki 	    adapter, 0, ixgbe_sysctl_power_state,
25858eb6488eSEric Joyner 	    "I", "PCI Power State");
2586a9ca1c79SSean Bruno 
2587c19c7afeSEric Joyner 	SYSCTL_ADD_PROC(ctx_list, child, OID_AUTO, "print_rss_config",
258820b91f0aSPawel Biernacki 	    CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_NEEDGIANT, adapter, 0,
2589a9ca1c79SSean Bruno 	    ixgbe_sysctl_print_rss_config, "A", "Prints RSS Configuration");
2590a9ca1c79SSean Bruno #endif
2591a9ca1c79SSean Bruno 	/* for X550 series devices */
25926f37f232SEric Joyner 	if (hw->mac.type >= ixgbe_mac_X550)
2593c19c7afeSEric Joyner 		SYSCTL_ADD_PROC(ctx_list, child, OID_AUTO, "dmac",
259420b91f0aSPawel Biernacki 		    CTLTYPE_U16 | CTLFLAG_RW | CTLFLAG_NEEDGIANT,
259520b91f0aSPawel Biernacki 		    adapter, 0, ixgbe_sysctl_dmac,
25968eb6488eSEric Joyner 		    "I", "DMA Coalesce");
25976f37f232SEric Joyner 
2598a9ca1c79SSean Bruno 	/* for WoL-capable devices */
2599a9ca1c79SSean Bruno 	if (hw->device_id == IXGBE_DEV_ID_X550EM_X_10G_T) {
2600c19c7afeSEric Joyner 		SYSCTL_ADD_PROC(ctx_list, child, OID_AUTO, "wol_enable",
260120b91f0aSPawel Biernacki 		    CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_NEEDGIANT, adapter, 0,
26028eb6488eSEric Joyner 		    ixgbe_sysctl_wol_enable, "I", "Enable/Disable Wake on LAN");
26036f37f232SEric Joyner 
2604c19c7afeSEric Joyner 		SYSCTL_ADD_PROC(ctx_list, child, OID_AUTO, "wufc",
260520b91f0aSPawel Biernacki 		    CTLTYPE_U32 | CTLFLAG_RW | CTLFLAG_NEEDGIANT,
260620b91f0aSPawel Biernacki 		    adapter, 0, ixgbe_sysctl_wufc,
26078eb6488eSEric Joyner 		    "I", "Enable/Disable Wake Up Filters");
26086f37f232SEric Joyner 	}
26096f37f232SEric Joyner 
2610a9ca1c79SSean Bruno 	/* for X552/X557-AT devices */
26116f37f232SEric Joyner 	if (hw->device_id == IXGBE_DEV_ID_X550EM_X_10G_T) {
26126f37f232SEric Joyner 		struct sysctl_oid *phy_node;
26136f37f232SEric Joyner 		struct sysctl_oid_list *phy_list;
26146f37f232SEric Joyner 
2615c19c7afeSEric Joyner 		phy_node = SYSCTL_ADD_NODE(ctx_list, child, OID_AUTO, "phy",
261620b91f0aSPawel Biernacki 		    CTLFLAG_RD | CTLFLAG_MPSAFE, NULL, "External PHY sysctls");
26176f37f232SEric Joyner 		phy_list = SYSCTL_CHILDREN(phy_node);
26186f37f232SEric Joyner 
2619c19c7afeSEric Joyner 		SYSCTL_ADD_PROC(ctx_list, phy_list, OID_AUTO, "temp",
262020b91f0aSPawel Biernacki 		    CTLTYPE_U16 | CTLFLAG_RD | CTLFLAG_NEEDGIANT,
262120b91f0aSPawel Biernacki 		    adapter, 0, ixgbe_sysctl_phy_temp,
26228eb6488eSEric Joyner 		    "I", "Current External PHY Temperature (Celsius)");
26236f37f232SEric Joyner 
2624c19c7afeSEric Joyner 		SYSCTL_ADD_PROC(ctx_list, phy_list, OID_AUTO,
262520b91f0aSPawel Biernacki 		    "overtemp_occurred",
262620b91f0aSPawel Biernacki 		    CTLTYPE_U16 | CTLFLAG_RD | CTLFLAG_NEEDGIANT, adapter, 0,
26276f37f232SEric Joyner 		    ixgbe_sysctl_phy_overtemp_occurred, "I",
26286f37f232SEric Joyner 		    "External PHY High Temperature Event Occurred");
26296f37f232SEric Joyner 	}
26308eb6488eSEric Joyner 
26318eb6488eSEric Joyner 	if (adapter->feat_cap & IXGBE_FEATURE_EEE) {
2632c19c7afeSEric Joyner 		SYSCTL_ADD_PROC(ctx_list, child, OID_AUTO, "eee_state",
263320b91f0aSPawel Biernacki 		    CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_NEEDGIANT, adapter, 0,
26348eb6488eSEric Joyner 		    ixgbe_sysctl_eee_state, "I", "EEE Power Save State");
26358eb6488eSEric Joyner 	}
26368eb6488eSEric Joyner } /* ixgbe_add_device_sysctls */
26378eb6488eSEric Joyner 
26388eb6488eSEric Joyner /************************************************************************
26398eb6488eSEric Joyner  * ixgbe_allocate_pci_resources
26408eb6488eSEric Joyner  ************************************************************************/
26418eb6488eSEric Joyner static int
2642c19c7afeSEric Joyner ixgbe_allocate_pci_resources(if_ctx_t ctx)
26438eb6488eSEric Joyner {
2644c19c7afeSEric Joyner 	struct adapter *adapter = iflib_get_softc(ctx);
2645c19c7afeSEric Joyner 	device_t        dev = iflib_get_dev(ctx);
26468eb6488eSEric Joyner 	int             rid;
26478eb6488eSEric Joyner 
26488eb6488eSEric Joyner 	rid = PCIR_BAR(0);
26498eb6488eSEric Joyner 	adapter->pci_mem = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
26508eb6488eSEric Joyner 	    RF_ACTIVE);
26518eb6488eSEric Joyner 
26528eb6488eSEric Joyner 	if (!(adapter->pci_mem)) {
26538eb6488eSEric Joyner 		device_printf(dev, "Unable to allocate bus resource: memory\n");
26548eb6488eSEric Joyner 		return (ENXIO);
26558eb6488eSEric Joyner 	}
26568eb6488eSEric Joyner 
26578eb6488eSEric Joyner 	/* Save bus_space values for READ/WRITE_REG macros */
26588eb6488eSEric Joyner 	adapter->osdep.mem_bus_space_tag = rman_get_bustag(adapter->pci_mem);
26598eb6488eSEric Joyner 	adapter->osdep.mem_bus_space_handle =
26608eb6488eSEric Joyner 	    rman_get_bushandle(adapter->pci_mem);
26618eb6488eSEric Joyner 	/* Set hw values for shared code */
26628eb6488eSEric Joyner 	adapter->hw.hw_addr = (u8 *)&adapter->osdep.mem_bus_space_handle;
26638eb6488eSEric Joyner 
26648eb6488eSEric Joyner 	return (0);
26658eb6488eSEric Joyner } /* ixgbe_allocate_pci_resources */
26668eb6488eSEric Joyner 
26678eb6488eSEric Joyner /************************************************************************
26688eb6488eSEric Joyner  * ixgbe_detach - Device removal routine
26698eb6488eSEric Joyner  *
26708eb6488eSEric Joyner  *   Called when the driver is being removed.
26718eb6488eSEric Joyner  *   Stops the adapter and deallocates all the resources
26728eb6488eSEric Joyner  *   that were allocated for driver operation.
26738eb6488eSEric Joyner  *
26748eb6488eSEric Joyner  *   return 0 on success, positive on failure
26758eb6488eSEric Joyner  ************************************************************************/
26768eb6488eSEric Joyner static int
2677c19c7afeSEric Joyner ixgbe_if_detach(if_ctx_t ctx)
26788eb6488eSEric Joyner {
2679c19c7afeSEric Joyner 	struct adapter *adapter = iflib_get_softc(ctx);
2680c19c7afeSEric Joyner 	device_t       dev = iflib_get_dev(ctx);
26818eb6488eSEric Joyner 	u32            ctrl_ext;
26828eb6488eSEric Joyner 
26838eb6488eSEric Joyner 	INIT_DEBUGOUT("ixgbe_detach: begin");
26848eb6488eSEric Joyner 
26858eb6488eSEric Joyner 	if (ixgbe_pci_iov_detach(dev) != 0) {
26868eb6488eSEric Joyner 		device_printf(dev, "SR-IOV in use; detach first.\n");
26878eb6488eSEric Joyner 		return (EBUSY);
26888eb6488eSEric Joyner 	}
26898eb6488eSEric Joyner 
2690c19c7afeSEric Joyner 	ixgbe_setup_low_power_mode(ctx);
26918eb6488eSEric Joyner 
26928eb6488eSEric Joyner 	/* let hardware know driver is unloading */
26938eb6488eSEric Joyner 	ctrl_ext = IXGBE_READ_REG(&adapter->hw, IXGBE_CTRL_EXT);
26948eb6488eSEric Joyner 	ctrl_ext &= ~IXGBE_CTRL_EXT_DRV_LOAD;
26958eb6488eSEric Joyner 	IXGBE_WRITE_REG(&adapter->hw, IXGBE_CTRL_EXT, ctrl_ext);
26968eb6488eSEric Joyner 
2697c19c7afeSEric Joyner 	ixgbe_free_pci_resources(ctx);
26988eb6488eSEric Joyner 	free(adapter->mta, M_IXGBE);
26998eb6488eSEric Joyner 
27008eb6488eSEric Joyner 	return (0);
2701c19c7afeSEric Joyner } /* ixgbe_if_detach */
27028eb6488eSEric Joyner 
27038eb6488eSEric Joyner /************************************************************************
27048eb6488eSEric Joyner  * ixgbe_setup_low_power_mode - LPLU/WoL preparation
27058eb6488eSEric Joyner  *
27068eb6488eSEric Joyner  *   Prepare the adapter/port for LPLU and/or WoL
27078eb6488eSEric Joyner  ************************************************************************/
27088eb6488eSEric Joyner static int
2709c19c7afeSEric Joyner ixgbe_setup_low_power_mode(if_ctx_t ctx)
27108eb6488eSEric Joyner {
2711c19c7afeSEric Joyner 	struct adapter  *adapter = iflib_get_softc(ctx);
27128eb6488eSEric Joyner 	struct ixgbe_hw *hw = &adapter->hw;
2713c19c7afeSEric Joyner 	device_t        dev = iflib_get_dev(ctx);
27148eb6488eSEric Joyner 	s32             error = 0;
27158eb6488eSEric Joyner 
2716c19c7afeSEric Joyner 	if (!hw->wol_enabled)
2717c19c7afeSEric Joyner 		ixgbe_set_phy_power(hw, FALSE);
27188eb6488eSEric Joyner 
27198eb6488eSEric Joyner 	/* Limit power management flow to X550EM baseT */
27208eb6488eSEric Joyner 	if (hw->device_id == IXGBE_DEV_ID_X550EM_X_10G_T &&
27218eb6488eSEric Joyner 	    hw->phy.ops.enter_lplu) {
27228eb6488eSEric Joyner 		/* Turn off support for APM wakeup. (Using ACPI instead) */
27238eb6488eSEric Joyner 		IXGBE_WRITE_REG(hw, IXGBE_GRC,
27248eb6488eSEric Joyner 		    IXGBE_READ_REG(hw, IXGBE_GRC) & ~(u32)2);
27258eb6488eSEric Joyner 
27268eb6488eSEric Joyner 		/*
27278eb6488eSEric Joyner 		 * Clear Wake Up Status register to prevent any previous wakeup
27288eb6488eSEric Joyner 		 * events from waking us up immediately after we suspend.
27298eb6488eSEric Joyner 		 */
27308eb6488eSEric Joyner 		IXGBE_WRITE_REG(hw, IXGBE_WUS, 0xffffffff);
27318eb6488eSEric Joyner 
27328eb6488eSEric Joyner 		/*
27338eb6488eSEric Joyner 		 * Program the Wakeup Filter Control register with user filter
27348eb6488eSEric Joyner 		 * settings
27358eb6488eSEric Joyner 		 */
27368eb6488eSEric Joyner 		IXGBE_WRITE_REG(hw, IXGBE_WUFC, adapter->wufc);
27378eb6488eSEric Joyner 
27388eb6488eSEric Joyner 		/* Enable wakeups and power management in Wakeup Control */
27398eb6488eSEric Joyner 		IXGBE_WRITE_REG(hw, IXGBE_WUC,
27408eb6488eSEric Joyner 		    IXGBE_WUC_WKEN | IXGBE_WUC_PME_EN);
27418eb6488eSEric Joyner 
27428eb6488eSEric Joyner 		/* X550EM baseT adapters need a special LPLU flow */
2743c19c7afeSEric Joyner 		hw->phy.reset_disable = TRUE;
2744c19c7afeSEric Joyner 		ixgbe_if_stop(ctx);
27458eb6488eSEric Joyner 		error = hw->phy.ops.enter_lplu(hw);
27468eb6488eSEric Joyner 		if (error)
27478eb6488eSEric Joyner 			device_printf(dev, "Error entering LPLU: %d\n", error);
2748c19c7afeSEric Joyner 		hw->phy.reset_disable = FALSE;
27498eb6488eSEric Joyner 	} else {
27508eb6488eSEric Joyner 		/* Just stop for other adapters */
2751c19c7afeSEric Joyner 		ixgbe_if_stop(ctx);
27528eb6488eSEric Joyner 	}
27538eb6488eSEric Joyner 
27548eb6488eSEric Joyner 	return error;
27558eb6488eSEric Joyner } /* ixgbe_setup_low_power_mode */
27568eb6488eSEric Joyner 
27578eb6488eSEric Joyner /************************************************************************
27588eb6488eSEric Joyner  * ixgbe_shutdown - Shutdown entry point
27598eb6488eSEric Joyner  ************************************************************************/
27608eb6488eSEric Joyner static int
2761c19c7afeSEric Joyner ixgbe_if_shutdown(if_ctx_t ctx)
27628eb6488eSEric Joyner {
27638eb6488eSEric Joyner 	int error = 0;
27648eb6488eSEric Joyner 
27658eb6488eSEric Joyner 	INIT_DEBUGOUT("ixgbe_shutdown: begin");
27668eb6488eSEric Joyner 
2767c19c7afeSEric Joyner 	error = ixgbe_setup_low_power_mode(ctx);
27688eb6488eSEric Joyner 
27698eb6488eSEric Joyner 	return (error);
2770c19c7afeSEric Joyner } /* ixgbe_if_shutdown */
27718eb6488eSEric Joyner 
27728eb6488eSEric Joyner /************************************************************************
27738eb6488eSEric Joyner  * ixgbe_suspend
27748eb6488eSEric Joyner  *
27758eb6488eSEric Joyner  *   From D0 to D3
27768eb6488eSEric Joyner  ************************************************************************/
27778eb6488eSEric Joyner static int
2778c19c7afeSEric Joyner ixgbe_if_suspend(if_ctx_t ctx)
27798eb6488eSEric Joyner {
27808eb6488eSEric Joyner 	int error = 0;
27818eb6488eSEric Joyner 
27828eb6488eSEric Joyner 	INIT_DEBUGOUT("ixgbe_suspend: begin");
27838eb6488eSEric Joyner 
2784c19c7afeSEric Joyner 	error = ixgbe_setup_low_power_mode(ctx);
27858eb6488eSEric Joyner 
27868eb6488eSEric Joyner 	return (error);
2787c19c7afeSEric Joyner } /* ixgbe_if_suspend */
27888eb6488eSEric Joyner 
27898eb6488eSEric Joyner /************************************************************************
27908eb6488eSEric Joyner  * ixgbe_resume
27918eb6488eSEric Joyner  *
27928eb6488eSEric Joyner  *   From D3 to D0
27938eb6488eSEric Joyner  ************************************************************************/
27948eb6488eSEric Joyner static int
2795c19c7afeSEric Joyner ixgbe_if_resume(if_ctx_t ctx)
27968eb6488eSEric Joyner {
2797c19c7afeSEric Joyner 	struct adapter  *adapter = iflib_get_softc(ctx);
2798c19c7afeSEric Joyner 	device_t        dev = iflib_get_dev(ctx);
2799c19c7afeSEric Joyner 	struct ifnet    *ifp = iflib_get_ifp(ctx);
28008eb6488eSEric Joyner 	struct ixgbe_hw *hw = &adapter->hw;
28018eb6488eSEric Joyner 	u32             wus;
28028eb6488eSEric Joyner 
28038eb6488eSEric Joyner 	INIT_DEBUGOUT("ixgbe_resume: begin");
28048eb6488eSEric Joyner 
28058eb6488eSEric Joyner 	/* Read & clear WUS register */
28068eb6488eSEric Joyner 	wus = IXGBE_READ_REG(hw, IXGBE_WUS);
28078eb6488eSEric Joyner 	if (wus)
28088eb6488eSEric Joyner 		device_printf(dev, "Woken up by (WUS): %#010x\n",
28098eb6488eSEric Joyner 		    IXGBE_READ_REG(hw, IXGBE_WUS));
28108eb6488eSEric Joyner 	IXGBE_WRITE_REG(hw, IXGBE_WUS, 0xffffffff);
28118eb6488eSEric Joyner 	/* And clear WUFC until next low-power transition */
28128eb6488eSEric Joyner 	IXGBE_WRITE_REG(hw, IXGBE_WUFC, 0);
28138eb6488eSEric Joyner 
28148eb6488eSEric Joyner 	/*
28158eb6488eSEric Joyner 	 * Required after D3->D0 transition;
28168eb6488eSEric Joyner 	 * will re-advertise all previous advertised speeds
28178eb6488eSEric Joyner 	 */
28188eb6488eSEric Joyner 	if (ifp->if_flags & IFF_UP)
2819c19c7afeSEric Joyner 		ixgbe_if_init(ctx);
28208eb6488eSEric Joyner 
28218eb6488eSEric Joyner 	return (0);
2822c19c7afeSEric Joyner } /* ixgbe_if_resume */
28238eb6488eSEric Joyner 
28248eb6488eSEric Joyner /************************************************************************
2825c19c7afeSEric Joyner  * ixgbe_if_mtu_set - Ioctl mtu entry point
28268eb6488eSEric Joyner  *
2827c19c7afeSEric Joyner  *   Return 0 on success, EINVAL on failure
2828c19c7afeSEric Joyner  ************************************************************************/
2829c19c7afeSEric Joyner static int
2830c19c7afeSEric Joyner ixgbe_if_mtu_set(if_ctx_t ctx, uint32_t mtu)
2831c19c7afeSEric Joyner {
2832c19c7afeSEric Joyner 	struct adapter *adapter = iflib_get_softc(ctx);
2833c19c7afeSEric Joyner 	int error = 0;
2834c19c7afeSEric Joyner 
2835c19c7afeSEric Joyner 	IOCTL_DEBUGOUT("ioctl: SIOCIFMTU (Set Interface MTU)");
2836c19c7afeSEric Joyner 
2837c19c7afeSEric Joyner 	if (mtu > IXGBE_MAX_MTU) {
2838c19c7afeSEric Joyner 		error = EINVAL;
2839c19c7afeSEric Joyner 	} else {
2840c19c7afeSEric Joyner 		adapter->max_frame_size = mtu + IXGBE_MTU_HDR;
2841c19c7afeSEric Joyner 	}
2842c19c7afeSEric Joyner 
2843c19c7afeSEric Joyner 	return error;
2844c19c7afeSEric Joyner } /* ixgbe_if_mtu_set */
2845c19c7afeSEric Joyner 
2846c19c7afeSEric Joyner /************************************************************************
2847c19c7afeSEric Joyner  * ixgbe_if_crcstrip_set
28488eb6488eSEric Joyner  ************************************************************************/
28498eb6488eSEric Joyner static void
2850c19c7afeSEric Joyner ixgbe_if_crcstrip_set(if_ctx_t ctx, int onoff, int crcstrip)
28518eb6488eSEric Joyner {
2852c19c7afeSEric Joyner 	struct adapter *sc = iflib_get_softc(ctx);
2853c19c7afeSEric Joyner 	struct ixgbe_hw *hw = &sc->hw;
2854c19c7afeSEric Joyner 	/* crc stripping is set in two places:
2855c19c7afeSEric Joyner 	 * IXGBE_HLREG0 (modified on init_locked and hw reset)
2856c19c7afeSEric Joyner 	 * IXGBE_RDRXCTL (set by the original driver in
2857c19c7afeSEric Joyner 	 *	ixgbe_setup_hw_rsc() called in init_locked.
2858c19c7afeSEric Joyner 	 *	We disable the setting when netmap is compiled in).
2859c19c7afeSEric Joyner 	 * We update the values here, but also in ixgbe.c because
2860c19c7afeSEric Joyner 	 * init_locked sometimes is called outside our control.
2861c19c7afeSEric Joyner 	 */
2862c19c7afeSEric Joyner 	uint32_t hl, rxc;
28638eb6488eSEric Joyner 
2864c19c7afeSEric Joyner 	hl = IXGBE_READ_REG(hw, IXGBE_HLREG0);
2865c19c7afeSEric Joyner 	rxc = IXGBE_READ_REG(hw, IXGBE_RDRXCTL);
2866c19c7afeSEric Joyner #ifdef NETMAP
2867c19c7afeSEric Joyner 	if (netmap_verbose)
2868c19c7afeSEric Joyner 		D("%s read  HLREG 0x%x rxc 0x%x",
2869c19c7afeSEric Joyner 			onoff ? "enter" : "exit", hl, rxc);
28708eb6488eSEric Joyner #endif
2871c19c7afeSEric Joyner 	/* hw requirements ... */
2872c19c7afeSEric Joyner 	rxc &= ~IXGBE_RDRXCTL_RSCFRSTSIZE;
2873c19c7afeSEric Joyner 	rxc |= IXGBE_RDRXCTL_RSCACKC;
2874c19c7afeSEric Joyner 	if (onoff && !crcstrip) {
2875c19c7afeSEric Joyner 		/* keep the crc. Fast rx */
2876c19c7afeSEric Joyner 		hl &= ~IXGBE_HLREG0_RXCRCSTRP;
2877c19c7afeSEric Joyner 		rxc &= ~IXGBE_RDRXCTL_CRCSTRIP;
2878c19c7afeSEric Joyner 	} else {
2879c19c7afeSEric Joyner 		/* reset default mode */
2880c19c7afeSEric Joyner 		hl |= IXGBE_HLREG0_RXCRCSTRP;
2881c19c7afeSEric Joyner 		rxc |= IXGBE_RDRXCTL_CRCSTRIP;
2882c19c7afeSEric Joyner 	}
2883c19c7afeSEric Joyner #ifdef NETMAP
2884c19c7afeSEric Joyner 	if (netmap_verbose)
2885c19c7afeSEric Joyner 		D("%s write HLREG 0x%x rxc 0x%x",
2886c19c7afeSEric Joyner 			onoff ? "enter" : "exit", hl, rxc);
2887c19c7afeSEric Joyner #endif
2888c19c7afeSEric Joyner 	IXGBE_WRITE_REG(hw, IXGBE_HLREG0, hl);
2889c19c7afeSEric Joyner 	IXGBE_WRITE_REG(hw, IXGBE_RDRXCTL, rxc);
2890c19c7afeSEric Joyner } /* ixgbe_if_crcstrip_set */
28918eb6488eSEric Joyner 
2892c19c7afeSEric Joyner /*********************************************************************
2893c19c7afeSEric Joyner  * ixgbe_if_init - Init entry point
28948eb6488eSEric Joyner  *
28958eb6488eSEric Joyner  *   Used in two ways: It is used by the stack as an init
28968eb6488eSEric Joyner  *   entry point in network interface structure. It is also
28978eb6488eSEric Joyner  *   used by the driver as a hw/sw initialization routine to
28988eb6488eSEric Joyner  *   get to a consistent state.
28998eb6488eSEric Joyner  *
2900c19c7afeSEric Joyner  *   Return 0 on success, positive on failure
2901c19c7afeSEric Joyner  **********************************************************************/
29028eb6488eSEric Joyner void
2903c19c7afeSEric Joyner ixgbe_if_init(if_ctx_t ctx)
29048eb6488eSEric Joyner {
2905c19c7afeSEric Joyner 	struct adapter     *adapter = iflib_get_softc(ctx);
2906c19c7afeSEric Joyner 	struct ifnet       *ifp = iflib_get_ifp(ctx);
2907c19c7afeSEric Joyner 	device_t           dev = iflib_get_dev(ctx);
29088eb6488eSEric Joyner 	struct ixgbe_hw *hw = &adapter->hw;
2909c19c7afeSEric Joyner 	struct ix_rx_queue *rx_que;
2910c19c7afeSEric Joyner 	struct ix_tx_queue *tx_que;
29118eb6488eSEric Joyner 	u32             txdctl, mhadd;
29128eb6488eSEric Joyner 	u32             rxdctl, rxctrl;
29138eb6488eSEric Joyner 	u32             ctrl_ext;
29148eb6488eSEric Joyner 
2915c19c7afeSEric Joyner 	int             i, j, err;
29168eb6488eSEric Joyner 
2917c19c7afeSEric Joyner 	INIT_DEBUGOUT("ixgbe_if_init: begin");
29188eb6488eSEric Joyner 
29198eb6488eSEric Joyner 	/* Queue indices may change with IOV mode */
29208eb6488eSEric Joyner 	ixgbe_align_all_queue_indices(adapter);
29218eb6488eSEric Joyner 
29228eb6488eSEric Joyner 	/* reprogram the RAR[0] in case user changed it. */
29238eb6488eSEric Joyner 	ixgbe_set_rar(hw, 0, hw->mac.addr, adapter->pool, IXGBE_RAH_AV);
29248eb6488eSEric Joyner 
29258eb6488eSEric Joyner 	/* Get the latest mac address, User can use a LAA */
29268eb6488eSEric Joyner 	bcopy(IF_LLADDR(ifp), hw->mac.addr, IXGBE_ETH_LENGTH_OF_ADDRESS);
29278eb6488eSEric Joyner 	ixgbe_set_rar(hw, 0, hw->mac.addr, adapter->pool, 1);
29288eb6488eSEric Joyner 	hw->addr_ctrl.rar_used_count = 1;
29298eb6488eSEric Joyner 
29308eb6488eSEric Joyner 	ixgbe_init_hw(hw);
2931c19c7afeSEric Joyner 
29328eb6488eSEric Joyner 	ixgbe_initialize_iov(adapter);
2933c19c7afeSEric Joyner 
2934c19c7afeSEric Joyner 	ixgbe_initialize_transmit_units(ctx);
29358eb6488eSEric Joyner 
29368eb6488eSEric Joyner 	/* Setup Multicast table */
2937c19c7afeSEric Joyner 	ixgbe_if_multi_set(ctx);
29388eb6488eSEric Joyner 
29398eb6488eSEric Joyner 	/* Determine the correct mbuf pool, based on frame size */
29401b9d9394SEric Joyner 	adapter->rx_mbuf_sz = iflib_get_rx_mbuf_sz(ctx);
29418eb6488eSEric Joyner 
29428eb6488eSEric Joyner 	/* Configure RX settings */
2943c19c7afeSEric Joyner 	ixgbe_initialize_receive_units(ctx);
29448eb6488eSEric Joyner 
2945b2c1e8e6SEric Joyner 	/*
2946b2c1e8e6SEric Joyner 	 * Initialize variable holding task enqueue requests
2947b2c1e8e6SEric Joyner 	 * from MSI-X interrupts
2948b2c1e8e6SEric Joyner 	 */
2949b2c1e8e6SEric Joyner 	adapter->task_requests = 0;
2950b2c1e8e6SEric Joyner 
29518eb6488eSEric Joyner 	/* Enable SDP & MSI-X interrupts based on adapter */
29528eb6488eSEric Joyner 	ixgbe_config_gpie(adapter);
29538eb6488eSEric Joyner 
29548eb6488eSEric Joyner 	/* Set MTU size */
29558eb6488eSEric Joyner 	if (ifp->if_mtu > ETHERMTU) {
29568eb6488eSEric Joyner 		/* aka IXGBE_MAXFRS on 82599 and newer */
29578eb6488eSEric Joyner 		mhadd = IXGBE_READ_REG(hw, IXGBE_MHADD);
29588eb6488eSEric Joyner 		mhadd &= ~IXGBE_MHADD_MFS_MASK;
29598eb6488eSEric Joyner 		mhadd |= adapter->max_frame_size << IXGBE_MHADD_MFS_SHIFT;
29608eb6488eSEric Joyner 		IXGBE_WRITE_REG(hw, IXGBE_MHADD, mhadd);
29618eb6488eSEric Joyner 	}
29628eb6488eSEric Joyner 
29638eb6488eSEric Joyner 	/* Now enable all the queues */
2964c19c7afeSEric Joyner 	for (i = 0, tx_que = adapter->tx_queues; i < adapter->num_tx_queues; i++, tx_que++) {
2965c19c7afeSEric Joyner 		struct tx_ring *txr = &tx_que->txr;
2966c19c7afeSEric Joyner 
29678eb6488eSEric Joyner 		txdctl = IXGBE_READ_REG(hw, IXGBE_TXDCTL(txr->me));
29688eb6488eSEric Joyner 		txdctl |= IXGBE_TXDCTL_ENABLE;
29698eb6488eSEric Joyner 		/* Set WTHRESH to 8, burst writeback */
29708eb6488eSEric Joyner 		txdctl |= (8 << 16);
29718eb6488eSEric Joyner 		/*
29728eb6488eSEric Joyner 		 * When the internal queue falls below PTHRESH (32),
29738eb6488eSEric Joyner 		 * start prefetching as long as there are at least
29748eb6488eSEric Joyner 		 * HTHRESH (1) buffers ready. The values are taken
29758eb6488eSEric Joyner 		 * from the Intel linux driver 3.8.21.
29768eb6488eSEric Joyner 		 * Prefetching enables tx line rate even with 1 queue.
29778eb6488eSEric Joyner 		 */
29788eb6488eSEric Joyner 		txdctl |= (32 << 0) | (1 << 8);
29798eb6488eSEric Joyner 		IXGBE_WRITE_REG(hw, IXGBE_TXDCTL(txr->me), txdctl);
29808eb6488eSEric Joyner 	}
29818eb6488eSEric Joyner 
2982c19c7afeSEric Joyner 	for (i = 0, rx_que = adapter->rx_queues; i < adapter->num_rx_queues; i++, rx_que++) {
2983c19c7afeSEric Joyner 		struct rx_ring *rxr = &rx_que->rxr;
2984c19c7afeSEric Joyner 
29858eb6488eSEric Joyner 		rxdctl = IXGBE_READ_REG(hw, IXGBE_RXDCTL(rxr->me));
29868eb6488eSEric Joyner 		if (hw->mac.type == ixgbe_mac_82598EB) {
29878eb6488eSEric Joyner 			/*
29888eb6488eSEric Joyner 			 * PTHRESH = 21
29898eb6488eSEric Joyner 			 * HTHRESH = 4
29908eb6488eSEric Joyner 			 * WTHRESH = 8
29918eb6488eSEric Joyner 			 */
29928eb6488eSEric Joyner 			rxdctl &= ~0x3FFFFF;
29938eb6488eSEric Joyner 			rxdctl |= 0x080420;
29948eb6488eSEric Joyner 		}
29958eb6488eSEric Joyner 		rxdctl |= IXGBE_RXDCTL_ENABLE;
29968eb6488eSEric Joyner 		IXGBE_WRITE_REG(hw, IXGBE_RXDCTL(rxr->me), rxdctl);
2997c19c7afeSEric Joyner 		for (j = 0; j < 10; j++) {
29988eb6488eSEric Joyner 			if (IXGBE_READ_REG(hw, IXGBE_RXDCTL(rxr->me)) &
29998eb6488eSEric Joyner 			    IXGBE_RXDCTL_ENABLE)
30008eb6488eSEric Joyner 				break;
30018eb6488eSEric Joyner 			else
30028eb6488eSEric Joyner 				msec_delay(1);
30038eb6488eSEric Joyner 		}
30048eb6488eSEric Joyner 		wmb();
30058eb6488eSEric Joyner 	}
30068eb6488eSEric Joyner 
30078eb6488eSEric Joyner 	/* Enable Receive engine */
30088eb6488eSEric Joyner 	rxctrl = IXGBE_READ_REG(hw, IXGBE_RXCTRL);
30098eb6488eSEric Joyner 	if (hw->mac.type == ixgbe_mac_82598EB)
30108eb6488eSEric Joyner 		rxctrl |= IXGBE_RXCTRL_DMBYPS;
30118eb6488eSEric Joyner 	rxctrl |= IXGBE_RXCTRL_RXEN;
30128eb6488eSEric Joyner 	ixgbe_enable_rx_dma(hw, rxctrl);
30138eb6488eSEric Joyner 
3014c19c7afeSEric Joyner 	/* Set up MSI/MSI-X routing */
3015c19c7afeSEric Joyner 	if (ixgbe_enable_msix)  {
30168eb6488eSEric Joyner 		ixgbe_configure_ivars(adapter);
30178eb6488eSEric Joyner 		/* Set up auto-mask */
30188eb6488eSEric Joyner 		if (hw->mac.type == ixgbe_mac_82598EB)
30198eb6488eSEric Joyner 			IXGBE_WRITE_REG(hw, IXGBE_EIAM, IXGBE_EICS_RTX_QUEUE);
30208eb6488eSEric Joyner 		else {
30218eb6488eSEric Joyner 			IXGBE_WRITE_REG(hw, IXGBE_EIAM_EX(0), 0xFFFFFFFF);
30228eb6488eSEric Joyner 			IXGBE_WRITE_REG(hw, IXGBE_EIAM_EX(1), 0xFFFFFFFF);
30238eb6488eSEric Joyner 		}
30248eb6488eSEric Joyner 	} else {  /* Simple settings for Legacy/MSI */
30258eb6488eSEric Joyner 		ixgbe_set_ivar(adapter, 0, 0, 0);
30268eb6488eSEric Joyner 		ixgbe_set_ivar(adapter, 0, 0, 1);
30278eb6488eSEric Joyner 		IXGBE_WRITE_REG(hw, IXGBE_EIAM, IXGBE_EICS_RTX_QUEUE);
30288eb6488eSEric Joyner 	}
30298eb6488eSEric Joyner 
30308eb6488eSEric Joyner 	ixgbe_init_fdir(adapter);
30318eb6488eSEric Joyner 
30328eb6488eSEric Joyner 	/*
30338eb6488eSEric Joyner 	 * Check on any SFP devices that
30348eb6488eSEric Joyner 	 * need to be kick-started
30358eb6488eSEric Joyner 	 */
30368eb6488eSEric Joyner 	if (hw->phy.type == ixgbe_phy_none) {
30378eb6488eSEric Joyner 		err = hw->phy.ops.identify(hw);
30388eb6488eSEric Joyner 		if (err == IXGBE_ERR_SFP_NOT_SUPPORTED) {
30398eb6488eSEric Joyner 			device_printf(dev,
30408eb6488eSEric Joyner 			    "Unsupported SFP+ module type was detected.\n");
30418eb6488eSEric Joyner 			return;
30428eb6488eSEric Joyner 		}
30438eb6488eSEric Joyner 	}
30448eb6488eSEric Joyner 
30458eb6488eSEric Joyner 	/* Set moderation on the Link interrupt */
30468eb6488eSEric Joyner 	IXGBE_WRITE_REG(hw, IXGBE_EITR(adapter->vector), IXGBE_LINK_ITR);
30478eb6488eSEric Joyner 
3048c19c7afeSEric Joyner 	/* Enable power to the phy. */
3049c19c7afeSEric Joyner 	ixgbe_set_phy_power(hw, TRUE);
3050c19c7afeSEric Joyner 
30518eb6488eSEric Joyner 	/* Config/Enable Link */
3052b2c1e8e6SEric Joyner 	ixgbe_config_link(ctx);
30538eb6488eSEric Joyner 
30548eb6488eSEric Joyner 	/* Hardware Packet Buffer & Flow Control setup */
30558eb6488eSEric Joyner 	ixgbe_config_delay_values(adapter);
30568eb6488eSEric Joyner 
30578eb6488eSEric Joyner 	/* Initialize the FC settings */
30588eb6488eSEric Joyner 	ixgbe_start_hw(hw);
30598eb6488eSEric Joyner 
30608eb6488eSEric Joyner 	/* Set up VLAN support and filter */
3061c19c7afeSEric Joyner 	ixgbe_setup_vlan_hw_support(ctx);
30628eb6488eSEric Joyner 
30638eb6488eSEric Joyner 	/* Setup DMA Coalescing */
30648eb6488eSEric Joyner 	ixgbe_config_dmac(adapter);
30658eb6488eSEric Joyner 
30668eb6488eSEric Joyner 	/* And now turn on interrupts */
3067c19c7afeSEric Joyner 	ixgbe_if_enable_intr(ctx);
30688eb6488eSEric Joyner 
30698eb6488eSEric Joyner 	/* Enable the use of the MBX by the VF's */
30708eb6488eSEric Joyner 	if (adapter->feat_en & IXGBE_FEATURE_SRIOV) {
30718eb6488eSEric Joyner 		ctrl_ext = IXGBE_READ_REG(hw, IXGBE_CTRL_EXT);
30728eb6488eSEric Joyner 		ctrl_ext |= IXGBE_CTRL_EXT_PFRSTD;
30738eb6488eSEric Joyner 		IXGBE_WRITE_REG(hw, IXGBE_CTRL_EXT, ctrl_ext);
30748eb6488eSEric Joyner 	}
30758eb6488eSEric Joyner 
30768eb6488eSEric Joyner } /* ixgbe_init_locked */
30778eb6488eSEric Joyner 
30788eb6488eSEric Joyner /************************************************************************
30798eb6488eSEric Joyner  * ixgbe_set_ivar
30808eb6488eSEric Joyner  *
30818eb6488eSEric Joyner  *   Setup the correct IVAR register for a particular MSI-X interrupt
30828eb6488eSEric Joyner  *     (yes this is all very magic and confusing :)
30838eb6488eSEric Joyner  *    - entry is the register array entry
30848eb6488eSEric Joyner  *    - vector is the MSI-X vector for this queue
30858eb6488eSEric Joyner  *    - type is RX/TX/MISC
30868eb6488eSEric Joyner  ************************************************************************/
30878eb6488eSEric Joyner static void
30888eb6488eSEric Joyner ixgbe_set_ivar(struct adapter *adapter, u8 entry, u8 vector, s8 type)
30898eb6488eSEric Joyner {
30908eb6488eSEric Joyner 	struct ixgbe_hw *hw = &adapter->hw;
30918eb6488eSEric Joyner 	u32 ivar, index;
30928eb6488eSEric Joyner 
30938eb6488eSEric Joyner 	vector |= IXGBE_IVAR_ALLOC_VAL;
30948eb6488eSEric Joyner 
30958eb6488eSEric Joyner 	switch (hw->mac.type) {
30968eb6488eSEric Joyner 	case ixgbe_mac_82598EB:
30978eb6488eSEric Joyner 		if (type == -1)
30988eb6488eSEric Joyner 			entry = IXGBE_IVAR_OTHER_CAUSES_INDEX;
30998eb6488eSEric Joyner 		else
31008eb6488eSEric Joyner 			entry += (type * 64);
31018eb6488eSEric Joyner 		index = (entry >> 2) & 0x1F;
31028eb6488eSEric Joyner 		ivar = IXGBE_READ_REG(hw, IXGBE_IVAR(index));
31038eb6488eSEric Joyner 		ivar &= ~(0xFF << (8 * (entry & 0x3)));
31048eb6488eSEric Joyner 		ivar |= (vector << (8 * (entry & 0x3)));
31058eb6488eSEric Joyner 		IXGBE_WRITE_REG(&adapter->hw, IXGBE_IVAR(index), ivar);
31068eb6488eSEric Joyner 		break;
31078eb6488eSEric Joyner 	case ixgbe_mac_82599EB:
31088eb6488eSEric Joyner 	case ixgbe_mac_X540:
31098eb6488eSEric Joyner 	case ixgbe_mac_X550:
31108eb6488eSEric Joyner 	case ixgbe_mac_X550EM_x:
31118eb6488eSEric Joyner 	case ixgbe_mac_X550EM_a:
31128eb6488eSEric Joyner 		if (type == -1) { /* MISC IVAR */
31138eb6488eSEric Joyner 			index = (entry & 1) * 8;
31148eb6488eSEric Joyner 			ivar = IXGBE_READ_REG(hw, IXGBE_IVAR_MISC);
31158eb6488eSEric Joyner 			ivar &= ~(0xFF << index);
31168eb6488eSEric Joyner 			ivar |= (vector << index);
31178eb6488eSEric Joyner 			IXGBE_WRITE_REG(hw, IXGBE_IVAR_MISC, ivar);
31188eb6488eSEric Joyner 		} else {          /* RX/TX IVARS */
31198eb6488eSEric Joyner 			index = (16 * (entry & 1)) + (8 * type);
31208eb6488eSEric Joyner 			ivar = IXGBE_READ_REG(hw, IXGBE_IVAR(entry >> 1));
31218eb6488eSEric Joyner 			ivar &= ~(0xFF << index);
31228eb6488eSEric Joyner 			ivar |= (vector << index);
31238eb6488eSEric Joyner 			IXGBE_WRITE_REG(hw, IXGBE_IVAR(entry >> 1), ivar);
31248eb6488eSEric Joyner 		}
31258eb6488eSEric Joyner 	default:
31268eb6488eSEric Joyner 		break;
31278eb6488eSEric Joyner 	}
31288eb6488eSEric Joyner } /* ixgbe_set_ivar */
31298eb6488eSEric Joyner 
31308eb6488eSEric Joyner /************************************************************************
31318eb6488eSEric Joyner  * ixgbe_configure_ivars
31328eb6488eSEric Joyner  ************************************************************************/
31338eb6488eSEric Joyner static void
31348eb6488eSEric Joyner ixgbe_configure_ivars(struct adapter *adapter)
31358eb6488eSEric Joyner {
3136c19c7afeSEric Joyner 	struct ix_rx_queue *rx_que = adapter->rx_queues;
3137c19c7afeSEric Joyner 	struct ix_tx_queue *tx_que = adapter->tx_queues;
31388eb6488eSEric Joyner 	u32                newitr;
31398eb6488eSEric Joyner 
31408eb6488eSEric Joyner 	if (ixgbe_max_interrupt_rate > 0)
31418eb6488eSEric Joyner 		newitr = (4000000 / ixgbe_max_interrupt_rate) & 0x0FF8;
31428eb6488eSEric Joyner 	else {
31438eb6488eSEric Joyner 		/*
31448eb6488eSEric Joyner 		 * Disable DMA coalescing if interrupt moderation is
31458eb6488eSEric Joyner 		 * disabled.
31468eb6488eSEric Joyner 		 */
31478eb6488eSEric Joyner 		adapter->dmac = 0;
31488eb6488eSEric Joyner 		newitr = 0;
31498eb6488eSEric Joyner 	}
31508eb6488eSEric Joyner 
3151c19c7afeSEric Joyner 	for (int i = 0; i < adapter->num_rx_queues; i++, rx_que++) {
3152c19c7afeSEric Joyner 		struct rx_ring *rxr = &rx_que->rxr;
31538eb6488eSEric Joyner 
3154c19c7afeSEric Joyner 		/* First the RX queue entry */
3155c19c7afeSEric Joyner 		ixgbe_set_ivar(adapter, rxr->me, rx_que->msix, 0);
3156c19c7afeSEric Joyner 
3157c19c7afeSEric Joyner 		/* Set an Initial EITR value */
3158c19c7afeSEric Joyner 		IXGBE_WRITE_REG(&adapter->hw, IXGBE_EITR(rx_que->msix), newitr);
3159c19c7afeSEric Joyner 	}
3160c19c7afeSEric Joyner 	for (int i = 0; i < adapter->num_tx_queues; i++, tx_que++) {
3161c19c7afeSEric Joyner 		struct tx_ring *txr = &tx_que->txr;
3162c19c7afeSEric Joyner 
3163c19c7afeSEric Joyner 		/* ... and the TX */
3164c19c7afeSEric Joyner 		ixgbe_set_ivar(adapter, txr->me, tx_que->msix, 1);
3165c19c7afeSEric Joyner 	}
31668eb6488eSEric Joyner 	/* For the Link interrupt */
31678eb6488eSEric Joyner 	ixgbe_set_ivar(adapter, 1, adapter->vector, -1);
31688eb6488eSEric Joyner } /* ixgbe_configure_ivars */
31698eb6488eSEric Joyner 
31708eb6488eSEric Joyner /************************************************************************
31718eb6488eSEric Joyner  * ixgbe_config_gpie
31728eb6488eSEric Joyner  ************************************************************************/
31738eb6488eSEric Joyner static void
31748eb6488eSEric Joyner ixgbe_config_gpie(struct adapter *adapter)
31758eb6488eSEric Joyner {
31768eb6488eSEric Joyner 	struct ixgbe_hw *hw = &adapter->hw;
31778eb6488eSEric Joyner 	u32             gpie;
31788eb6488eSEric Joyner 
31798eb6488eSEric Joyner 	gpie = IXGBE_READ_REG(hw, IXGBE_GPIE);
31808eb6488eSEric Joyner 
3181c19c7afeSEric Joyner 	if (adapter->intr_type == IFLIB_INTR_MSIX) {
31828eb6488eSEric Joyner 		/* Enable Enhanced MSI-X mode */
31838eb6488eSEric Joyner 		gpie |= IXGBE_GPIE_MSIX_MODE
31848eb6488eSEric Joyner 		     |  IXGBE_GPIE_EIAME
31858eb6488eSEric Joyner 		     |  IXGBE_GPIE_PBA_SUPPORT
31868eb6488eSEric Joyner 		     |  IXGBE_GPIE_OCD;
31878eb6488eSEric Joyner 	}
31888eb6488eSEric Joyner 
31898eb6488eSEric Joyner 	/* Fan Failure Interrupt */
31908eb6488eSEric Joyner 	if (adapter->feat_en & IXGBE_FEATURE_FAN_FAIL)
31918eb6488eSEric Joyner 		gpie |= IXGBE_SDP1_GPIEN;
31928eb6488eSEric Joyner 
31938eb6488eSEric Joyner 	/* Thermal Sensor Interrupt */
31948eb6488eSEric Joyner 	if (adapter->feat_en & IXGBE_FEATURE_TEMP_SENSOR)
31958eb6488eSEric Joyner 		gpie |= IXGBE_SDP0_GPIEN_X540;
31968eb6488eSEric Joyner 
31978eb6488eSEric Joyner 	/* Link detection */
31988eb6488eSEric Joyner 	switch (hw->mac.type) {
31998eb6488eSEric Joyner 	case ixgbe_mac_82599EB:
32008eb6488eSEric Joyner 		gpie |= IXGBE_SDP1_GPIEN | IXGBE_SDP2_GPIEN;
32018eb6488eSEric Joyner 		break;
32028eb6488eSEric Joyner 	case ixgbe_mac_X550EM_x:
32038eb6488eSEric Joyner 	case ixgbe_mac_X550EM_a:
32048eb6488eSEric Joyner 		gpie |= IXGBE_SDP0_GPIEN_X540;
32058eb6488eSEric Joyner 		break;
32068eb6488eSEric Joyner 	default:
32078eb6488eSEric Joyner 		break;
32088eb6488eSEric Joyner 	}
32098eb6488eSEric Joyner 
32108eb6488eSEric Joyner 	IXGBE_WRITE_REG(hw, IXGBE_GPIE, gpie);
32118eb6488eSEric Joyner 
32128eb6488eSEric Joyner } /* ixgbe_config_gpie */
32138eb6488eSEric Joyner 
32148eb6488eSEric Joyner /************************************************************************
32158eb6488eSEric Joyner  * ixgbe_config_delay_values
32168eb6488eSEric Joyner  *
32178eb6488eSEric Joyner  *   Requires adapter->max_frame_size to be set.
32188eb6488eSEric Joyner  ************************************************************************/
32198eb6488eSEric Joyner static void
32208eb6488eSEric Joyner ixgbe_config_delay_values(struct adapter *adapter)
32218eb6488eSEric Joyner {
32228eb6488eSEric Joyner 	struct ixgbe_hw *hw = &adapter->hw;
32238eb6488eSEric Joyner 	u32             rxpb, frame, size, tmp;
32248eb6488eSEric Joyner 
32258eb6488eSEric Joyner 	frame = adapter->max_frame_size;
32268eb6488eSEric Joyner 
32278eb6488eSEric Joyner 	/* Calculate High Water */
32288eb6488eSEric Joyner 	switch (hw->mac.type) {
32298eb6488eSEric Joyner 	case ixgbe_mac_X540:
32308eb6488eSEric Joyner 	case ixgbe_mac_X550:
32318eb6488eSEric Joyner 	case ixgbe_mac_X550EM_x:
32328eb6488eSEric Joyner 	case ixgbe_mac_X550EM_a:
32338eb6488eSEric Joyner 		tmp = IXGBE_DV_X540(frame, frame);
32348eb6488eSEric Joyner 		break;
32358eb6488eSEric Joyner 	default:
32368eb6488eSEric Joyner 		tmp = IXGBE_DV(frame, frame);
32378eb6488eSEric Joyner 		break;
32388eb6488eSEric Joyner 	}
32398eb6488eSEric Joyner 	size = IXGBE_BT2KB(tmp);
32408eb6488eSEric Joyner 	rxpb = IXGBE_READ_REG(hw, IXGBE_RXPBSIZE(0)) >> 10;
32418eb6488eSEric Joyner 	hw->fc.high_water[0] = rxpb - size;
32428eb6488eSEric Joyner 
32438eb6488eSEric Joyner 	/* Now calculate Low Water */
32448eb6488eSEric Joyner 	switch (hw->mac.type) {
32458eb6488eSEric Joyner 	case ixgbe_mac_X540:
32468eb6488eSEric Joyner 	case ixgbe_mac_X550:
32478eb6488eSEric Joyner 	case ixgbe_mac_X550EM_x:
32488eb6488eSEric Joyner 	case ixgbe_mac_X550EM_a:
32498eb6488eSEric Joyner 		tmp = IXGBE_LOW_DV_X540(frame);
32508eb6488eSEric Joyner 		break;
32518eb6488eSEric Joyner 	default:
32528eb6488eSEric Joyner 		tmp = IXGBE_LOW_DV(frame);
32538eb6488eSEric Joyner 		break;
32548eb6488eSEric Joyner 	}
32558eb6488eSEric Joyner 	hw->fc.low_water[0] = IXGBE_BT2KB(tmp);
32568eb6488eSEric Joyner 
32578eb6488eSEric Joyner 	hw->fc.pause_time = IXGBE_FC_PAUSE;
32588eb6488eSEric Joyner 	hw->fc.send_xon = TRUE;
32598eb6488eSEric Joyner } /* ixgbe_config_delay_values */
32608eb6488eSEric Joyner 
32618eb6488eSEric Joyner /************************************************************************
32628eb6488eSEric Joyner  * ixgbe_set_multi - Multicast Update
32638eb6488eSEric Joyner  *
32648eb6488eSEric Joyner  *   Called whenever multicast address list is updated.
32658eb6488eSEric Joyner  ************************************************************************/
3266ba76aa63SGleb Smirnoff static u_int
3267ba76aa63SGleb Smirnoff ixgbe_mc_filter_apply(void *arg, struct sockaddr_dl *sdl, u_int count)
32688eb6488eSEric Joyner {
3269c19c7afeSEric Joyner 	struct adapter *adapter = arg;
3270c19c7afeSEric Joyner 	struct ixgbe_mc_addr *mta = adapter->mta;
3271c19c7afeSEric Joyner 
3272c19c7afeSEric Joyner 	if (count == MAX_NUM_MULTICAST_ADDRESSES)
3273c19c7afeSEric Joyner 		return (0);
3274ba76aa63SGleb Smirnoff 	bcopy(LLADDR(sdl), mta[count].addr, IXGBE_ETH_LENGTH_OF_ADDRESS);
3275c19c7afeSEric Joyner 	mta[count].vmdq = adapter->pool;
3276c19c7afeSEric Joyner 
3277c19c7afeSEric Joyner 	return (1);
3278c19c7afeSEric Joyner } /* ixgbe_mc_filter_apply */
3279c19c7afeSEric Joyner 
3280c19c7afeSEric Joyner static void
3281c19c7afeSEric Joyner ixgbe_if_multi_set(if_ctx_t ctx)
3282c19c7afeSEric Joyner {
3283c19c7afeSEric Joyner 	struct adapter       *adapter = iflib_get_softc(ctx);
32848eb6488eSEric Joyner 	struct ixgbe_mc_addr *mta;
3285c19c7afeSEric Joyner 	struct ifnet         *ifp = iflib_get_ifp(ctx);
32868eb6488eSEric Joyner 	u8                   *update_ptr;
32878eb6488eSEric Joyner 	u32                  fctrl;
3288ba76aa63SGleb Smirnoff 	u_int		     mcnt;
32898eb6488eSEric Joyner 
3290c19c7afeSEric Joyner 	IOCTL_DEBUGOUT("ixgbe_if_multi_set: begin");
32918eb6488eSEric Joyner 
32928eb6488eSEric Joyner 	mta = adapter->mta;
32938eb6488eSEric Joyner 	bzero(mta, sizeof(*mta) * MAX_NUM_MULTICAST_ADDRESSES);
32948eb6488eSEric Joyner 
3295ba76aa63SGleb Smirnoff 	mcnt = if_foreach_llmaddr(iflib_get_ifp(ctx), ixgbe_mc_filter_apply,
3296ba76aa63SGleb Smirnoff 	    adapter);
32978eb6488eSEric Joyner 
32988eb6488eSEric Joyner 	fctrl = IXGBE_READ_REG(&adapter->hw, IXGBE_FCTRL);
32998eb6488eSEric Joyner 	fctrl |= (IXGBE_FCTRL_UPE | IXGBE_FCTRL_MPE);
33008eb6488eSEric Joyner 	if (ifp->if_flags & IFF_PROMISC)
33018eb6488eSEric Joyner 		fctrl |= (IXGBE_FCTRL_UPE | IXGBE_FCTRL_MPE);
33028eb6488eSEric Joyner 	else if (mcnt >= MAX_NUM_MULTICAST_ADDRESSES ||
33038eb6488eSEric Joyner 	    ifp->if_flags & IFF_ALLMULTI) {
33048eb6488eSEric Joyner 		fctrl |= IXGBE_FCTRL_MPE;
33058eb6488eSEric Joyner 		fctrl &= ~IXGBE_FCTRL_UPE;
33068eb6488eSEric Joyner 	} else
33078eb6488eSEric Joyner 		fctrl &= ~(IXGBE_FCTRL_UPE | IXGBE_FCTRL_MPE);
33088eb6488eSEric Joyner 
33098eb6488eSEric Joyner 	IXGBE_WRITE_REG(&adapter->hw, IXGBE_FCTRL, fctrl);
33108eb6488eSEric Joyner 
33118eb6488eSEric Joyner 	if (mcnt < MAX_NUM_MULTICAST_ADDRESSES) {
33128eb6488eSEric Joyner 		update_ptr = (u8 *)mta;
33138eb6488eSEric Joyner 		ixgbe_update_mc_addr_list(&adapter->hw, update_ptr, mcnt,
33148eb6488eSEric Joyner 		    ixgbe_mc_array_itr, TRUE);
33158eb6488eSEric Joyner 	}
33168eb6488eSEric Joyner 
3317c19c7afeSEric Joyner } /* ixgbe_if_multi_set */
33188eb6488eSEric Joyner 
33198eb6488eSEric Joyner /************************************************************************
33208eb6488eSEric Joyner  * ixgbe_mc_array_itr
33218eb6488eSEric Joyner  *
33228eb6488eSEric Joyner  *   An iterator function needed by the multicast shared code.
33238eb6488eSEric Joyner  *   It feeds the shared code routine the addresses in the
33248eb6488eSEric Joyner  *   array of ixgbe_set_multi() one by one.
33258eb6488eSEric Joyner  ************************************************************************/
33268eb6488eSEric Joyner static u8 *
33278eb6488eSEric Joyner ixgbe_mc_array_itr(struct ixgbe_hw *hw, u8 **update_ptr, u32 *vmdq)
33288eb6488eSEric Joyner {
33298eb6488eSEric Joyner 	struct ixgbe_mc_addr *mta;
33308eb6488eSEric Joyner 
33318eb6488eSEric Joyner 	mta = (struct ixgbe_mc_addr *)*update_ptr;
33328eb6488eSEric Joyner 	*vmdq = mta->vmdq;
33338eb6488eSEric Joyner 
33348eb6488eSEric Joyner 	*update_ptr = (u8*)(mta + 1);
33358eb6488eSEric Joyner 
33368eb6488eSEric Joyner 	return (mta->addr);
33378eb6488eSEric Joyner } /* ixgbe_mc_array_itr */
33388eb6488eSEric Joyner 
33398eb6488eSEric Joyner /************************************************************************
33408eb6488eSEric Joyner  * ixgbe_local_timer - Timer routine
33418eb6488eSEric Joyner  *
33428eb6488eSEric Joyner  *   Checks for link status, updates statistics,
33438eb6488eSEric Joyner  *   and runs the watchdog check.
33448eb6488eSEric Joyner  ************************************************************************/
33458eb6488eSEric Joyner static void
3346c19c7afeSEric Joyner ixgbe_if_timer(if_ctx_t ctx, uint16_t qid)
33478eb6488eSEric Joyner {
3348c19c7afeSEric Joyner 	struct adapter *adapter = iflib_get_softc(ctx);
33498eb6488eSEric Joyner 
3350c19c7afeSEric Joyner 	if (qid != 0)
3351c19c7afeSEric Joyner 		return;
33528eb6488eSEric Joyner 
33538eb6488eSEric Joyner 	/* Check for pluggable optics */
33548eb6488eSEric Joyner 	if (adapter->sfp_probe)
3355c19c7afeSEric Joyner 		if (!ixgbe_sfp_probe(ctx))
3356c19c7afeSEric Joyner 			return; /* Nothing to do */
33578eb6488eSEric Joyner 
3358c19c7afeSEric Joyner 	ixgbe_check_link(&adapter->hw, &adapter->link_speed,
3359c19c7afeSEric Joyner 	    &adapter->link_up, 0);
33608eb6488eSEric Joyner 
3361c19c7afeSEric Joyner 	/* Fire off the adminq task */
3362c19c7afeSEric Joyner 	iflib_admin_intr_deferred(ctx);
33638eb6488eSEric Joyner 
3364c19c7afeSEric Joyner } /* ixgbe_if_timer */
33658eb6488eSEric Joyner 
33668eb6488eSEric Joyner /************************************************************************
33678eb6488eSEric Joyner  * ixgbe_sfp_probe
33688eb6488eSEric Joyner  *
33698eb6488eSEric Joyner  *   Determine if a port had optics inserted.
33708eb6488eSEric Joyner  ************************************************************************/
33718eb6488eSEric Joyner static bool
3372c19c7afeSEric Joyner ixgbe_sfp_probe(if_ctx_t ctx)
33738eb6488eSEric Joyner {
3374c19c7afeSEric Joyner 	struct adapter  *adapter = iflib_get_softc(ctx);
33758eb6488eSEric Joyner 	struct ixgbe_hw *hw = &adapter->hw;
3376c19c7afeSEric Joyner 	device_t        dev = iflib_get_dev(ctx);
33778eb6488eSEric Joyner 	bool            result = FALSE;
33788eb6488eSEric Joyner 
33798eb6488eSEric Joyner 	if ((hw->phy.type == ixgbe_phy_nl) &&
33808eb6488eSEric Joyner 	    (hw->phy.sfp_type == ixgbe_sfp_type_not_present)) {
33818eb6488eSEric Joyner 		s32 ret = hw->phy.ops.identify_sfp(hw);
33828eb6488eSEric Joyner 		if (ret)
33838eb6488eSEric Joyner 			goto out;
33848eb6488eSEric Joyner 		ret = hw->phy.ops.reset(hw);
33858eb6488eSEric Joyner 		adapter->sfp_probe = FALSE;
33868eb6488eSEric Joyner 		if (ret == IXGBE_ERR_SFP_NOT_SUPPORTED) {
33878eb6488eSEric Joyner 			device_printf(dev, "Unsupported SFP+ module detected!");
33888eb6488eSEric Joyner 			device_printf(dev,
33898eb6488eSEric Joyner 			    "Reload driver with supported module.\n");
33908eb6488eSEric Joyner 			goto out;
33918eb6488eSEric Joyner 		} else
33928eb6488eSEric Joyner 			device_printf(dev, "SFP+ module detected!\n");
33938eb6488eSEric Joyner 		/* We now have supported optics */
33948eb6488eSEric Joyner 		result = TRUE;
33958eb6488eSEric Joyner 	}
33968eb6488eSEric Joyner out:
33978eb6488eSEric Joyner 
33988eb6488eSEric Joyner 	return (result);
33998eb6488eSEric Joyner } /* ixgbe_sfp_probe */
34008eb6488eSEric Joyner 
34018eb6488eSEric Joyner /************************************************************************
34028eb6488eSEric Joyner  * ixgbe_handle_mod - Tasklet for SFP module interrupts
34038eb6488eSEric Joyner  ************************************************************************/
34048eb6488eSEric Joyner static void
3405c19c7afeSEric Joyner ixgbe_handle_mod(void *context)
34068eb6488eSEric Joyner {
3407c19c7afeSEric Joyner 	if_ctx_t        ctx = context;
3408c19c7afeSEric Joyner 	struct adapter  *adapter = iflib_get_softc(ctx);
34098eb6488eSEric Joyner 	struct ixgbe_hw *hw = &adapter->hw;
3410c19c7afeSEric Joyner 	device_t        dev = iflib_get_dev(ctx);
34118eb6488eSEric Joyner 	u32             err, cage_full = 0;
34128eb6488eSEric Joyner 
34138eb6488eSEric Joyner 	if (adapter->hw.need_crosstalk_fix) {
34148eb6488eSEric Joyner 		switch (hw->mac.type) {
34158eb6488eSEric Joyner 		case ixgbe_mac_82599EB:
34168eb6488eSEric Joyner 			cage_full = IXGBE_READ_REG(hw, IXGBE_ESDP) &
34178eb6488eSEric Joyner 			    IXGBE_ESDP_SDP2;
34188eb6488eSEric Joyner 			break;
34198eb6488eSEric Joyner 		case ixgbe_mac_X550EM_x:
34208eb6488eSEric Joyner 		case ixgbe_mac_X550EM_a:
34218eb6488eSEric Joyner 			cage_full = IXGBE_READ_REG(hw, IXGBE_ESDP) &
34228eb6488eSEric Joyner 			    IXGBE_ESDP_SDP0;
34238eb6488eSEric Joyner 			break;
34248eb6488eSEric Joyner 		default:
34258eb6488eSEric Joyner 			break;
34268eb6488eSEric Joyner 		}
34278eb6488eSEric Joyner 
34288eb6488eSEric Joyner 		if (!cage_full)
3429c19c7afeSEric Joyner 			goto handle_mod_out;
34308eb6488eSEric Joyner 	}
34318eb6488eSEric Joyner 
34328eb6488eSEric Joyner 	err = hw->phy.ops.identify_sfp(hw);
34338eb6488eSEric Joyner 	if (err == IXGBE_ERR_SFP_NOT_SUPPORTED) {
34348eb6488eSEric Joyner 		device_printf(dev,
34358eb6488eSEric Joyner 		    "Unsupported SFP+ module type was detected.\n");
3436c19c7afeSEric Joyner 		goto handle_mod_out;
34378eb6488eSEric Joyner 	}
34388eb6488eSEric Joyner 
3439c19c7afeSEric Joyner 	if (hw->mac.type == ixgbe_mac_82598EB)
3440c19c7afeSEric Joyner 		err = hw->phy.ops.reset(hw);
3441c19c7afeSEric Joyner 	else
34428eb6488eSEric Joyner 		err = hw->mac.ops.setup_sfp(hw);
3443c19c7afeSEric Joyner 
34448eb6488eSEric Joyner 	if (err == IXGBE_ERR_SFP_NOT_SUPPORTED) {
34458eb6488eSEric Joyner 		device_printf(dev,
34468eb6488eSEric Joyner 		    "Setup failure - unsupported SFP+ module type.\n");
3447c19c7afeSEric Joyner 		goto handle_mod_out;
34488eb6488eSEric Joyner 	}
3449b2c1e8e6SEric Joyner 	adapter->task_requests |= IXGBE_REQUEST_TASK_MSF;
3450c19c7afeSEric Joyner 	return;
3451c19c7afeSEric Joyner 
3452c19c7afeSEric Joyner handle_mod_out:
3453b2c1e8e6SEric Joyner 	adapter->task_requests &= ~(IXGBE_REQUEST_TASK_MSF);
34548eb6488eSEric Joyner } /* ixgbe_handle_mod */
34558eb6488eSEric Joyner 
34568eb6488eSEric Joyner 
34578eb6488eSEric Joyner /************************************************************************
34588eb6488eSEric Joyner  * ixgbe_handle_msf - Tasklet for MSF (multispeed fiber) interrupts
34598eb6488eSEric Joyner  ************************************************************************/
34608eb6488eSEric Joyner static void
3461c19c7afeSEric Joyner ixgbe_handle_msf(void *context)
34628eb6488eSEric Joyner {
3463c19c7afeSEric Joyner 	if_ctx_t        ctx = context;
3464c19c7afeSEric Joyner 	struct adapter  *adapter = iflib_get_softc(ctx);
34658eb6488eSEric Joyner 	struct ixgbe_hw *hw = &adapter->hw;
34668eb6488eSEric Joyner 	u32             autoneg;
34678eb6488eSEric Joyner 	bool            negotiate;
34688eb6488eSEric Joyner 
34698eb6488eSEric Joyner 	/* get_supported_phy_layer will call hw->phy.ops.identify_sfp() */
34708eb6488eSEric Joyner 	adapter->phy_layer = ixgbe_get_supported_physical_layer(hw);
34718eb6488eSEric Joyner 
34728eb6488eSEric Joyner 	autoneg = hw->phy.autoneg_advertised;
34738eb6488eSEric Joyner 	if ((!autoneg) && (hw->mac.ops.get_link_capabilities))
34748eb6488eSEric Joyner 		hw->mac.ops.get_link_capabilities(hw, &autoneg, &negotiate);
34758eb6488eSEric Joyner 	if (hw->mac.ops.setup_link)
34768eb6488eSEric Joyner 		hw->mac.ops.setup_link(hw, autoneg, TRUE);
34778eb6488eSEric Joyner 
34788eb6488eSEric Joyner 	/* Adjust media types shown in ifconfig */
3479c19c7afeSEric Joyner 	ifmedia_removeall(adapter->media);
3480c19c7afeSEric Joyner 	ixgbe_add_media_types(adapter->ctx);
3481c19c7afeSEric Joyner 	ifmedia_set(adapter->media, IFM_ETHER | IFM_AUTO);
34828eb6488eSEric Joyner } /* ixgbe_handle_msf */
34838eb6488eSEric Joyner 
34848eb6488eSEric Joyner /************************************************************************
34858eb6488eSEric Joyner  * ixgbe_handle_phy - Tasklet for external PHY interrupts
34868eb6488eSEric Joyner  ************************************************************************/
34878eb6488eSEric Joyner static void
3488c19c7afeSEric Joyner ixgbe_handle_phy(void *context)
34898eb6488eSEric Joyner {
3490c19c7afeSEric Joyner 	if_ctx_t        ctx = context;
3491c19c7afeSEric Joyner 	struct adapter  *adapter = iflib_get_softc(ctx);
34928eb6488eSEric Joyner 	struct ixgbe_hw *hw = &adapter->hw;
34938eb6488eSEric Joyner 	int             error;
34948eb6488eSEric Joyner 
34958eb6488eSEric Joyner 	error = hw->phy.ops.handle_lasi(hw);
34968eb6488eSEric Joyner 	if (error == IXGBE_ERR_OVERTEMP)
34978eb6488eSEric Joyner 		device_printf(adapter->dev, "CRITICAL: EXTERNAL PHY OVER TEMP!!  PHY will downshift to lower power state!\n");
34988eb6488eSEric Joyner 	else if (error)
34998eb6488eSEric Joyner 		device_printf(adapter->dev,
35008eb6488eSEric Joyner 		    "Error handling LASI interrupt: %d\n", error);
35018eb6488eSEric Joyner } /* ixgbe_handle_phy */
35028eb6488eSEric Joyner 
35038eb6488eSEric Joyner /************************************************************************
3504c19c7afeSEric Joyner  * ixgbe_if_stop - Stop the hardware
35058eb6488eSEric Joyner  *
35068eb6488eSEric Joyner  *   Disables all traffic on the adapter by issuing a
35078eb6488eSEric Joyner  *   global reset on the MAC and deallocates TX/RX buffers.
35088eb6488eSEric Joyner  ************************************************************************/
35098eb6488eSEric Joyner static void
3510c19c7afeSEric Joyner ixgbe_if_stop(if_ctx_t ctx)
35118eb6488eSEric Joyner {
3512c19c7afeSEric Joyner 	struct adapter  *adapter = iflib_get_softc(ctx);
35138eb6488eSEric Joyner 	struct ixgbe_hw *hw = &adapter->hw;
35148eb6488eSEric Joyner 
3515c19c7afeSEric Joyner 	INIT_DEBUGOUT("ixgbe_if_stop: begin\n");
35168eb6488eSEric Joyner 
35178eb6488eSEric Joyner 	ixgbe_reset_hw(hw);
35188eb6488eSEric Joyner 	hw->adapter_stopped = FALSE;
35198eb6488eSEric Joyner 	ixgbe_stop_adapter(hw);
35208eb6488eSEric Joyner 	if (hw->mac.type == ixgbe_mac_82599EB)
35218eb6488eSEric Joyner 		ixgbe_stop_mac_link_on_d3_82599(hw);
35228eb6488eSEric Joyner 	/* Turn off the laser - noop with no optics */
35238eb6488eSEric Joyner 	ixgbe_disable_tx_laser(hw);
35248eb6488eSEric Joyner 
35258eb6488eSEric Joyner 	/* Update the stack */
35268eb6488eSEric Joyner 	adapter->link_up = FALSE;
3527c19c7afeSEric Joyner 	ixgbe_if_update_admin_status(ctx);
35288eb6488eSEric Joyner 
35298eb6488eSEric Joyner 	/* reprogram the RAR[0] in case user changed it. */
35308eb6488eSEric Joyner 	ixgbe_set_rar(&adapter->hw, 0, adapter->hw.mac.addr, 0, IXGBE_RAH_AV);
35318eb6488eSEric Joyner 
35328eb6488eSEric Joyner 	return;
3533c19c7afeSEric Joyner } /* ixgbe_if_stop */
35348eb6488eSEric Joyner 
35358eb6488eSEric Joyner /************************************************************************
35368eb6488eSEric Joyner  * ixgbe_update_link_status - Update OS on link state
35378eb6488eSEric Joyner  *
35388eb6488eSEric Joyner  * Note: Only updates the OS on the cached link state.
35398eb6488eSEric Joyner  *       The real check of the hardware only happens with
35408eb6488eSEric Joyner  *       a link interrupt.
35418eb6488eSEric Joyner  ************************************************************************/
35428eb6488eSEric Joyner static void
3543c19c7afeSEric Joyner ixgbe_if_update_admin_status(if_ctx_t ctx)
35448eb6488eSEric Joyner {
3545c19c7afeSEric Joyner 	struct adapter *adapter = iflib_get_softc(ctx);
3546c19c7afeSEric Joyner 	device_t       dev = iflib_get_dev(ctx);
35478eb6488eSEric Joyner 
35488eb6488eSEric Joyner 	if (adapter->link_up) {
35498eb6488eSEric Joyner 		if (adapter->link_active == FALSE) {
35508eb6488eSEric Joyner 			if (bootverbose)
35518eb6488eSEric Joyner 				device_printf(dev, "Link is up %d Gbps %s \n",
35528eb6488eSEric Joyner 				    ((adapter->link_speed == 128) ? 10 : 1),
35538eb6488eSEric Joyner 				    "Full Duplex");
35548eb6488eSEric Joyner 			adapter->link_active = TRUE;
35558eb6488eSEric Joyner 			/* Update any Flow Control changes */
35568eb6488eSEric Joyner 			ixgbe_fc_enable(&adapter->hw);
35578eb6488eSEric Joyner 			/* Update DMA coalescing config */
35588eb6488eSEric Joyner 			ixgbe_config_dmac(adapter);
3559c19c7afeSEric Joyner 			/* should actually be negotiated value */
3560c19c7afeSEric Joyner 			iflib_link_state_change(ctx, LINK_STATE_UP, IF_Gbps(10));
3561c19c7afeSEric Joyner 
35628eb6488eSEric Joyner 			if (adapter->feat_en & IXGBE_FEATURE_SRIOV)
35638eb6488eSEric Joyner 				ixgbe_ping_all_vfs(adapter);
35648eb6488eSEric Joyner 		}
35658eb6488eSEric Joyner 	} else { /* Link down */
35668eb6488eSEric Joyner 		if (adapter->link_active == TRUE) {
35678eb6488eSEric Joyner 			if (bootverbose)
35688eb6488eSEric Joyner 				device_printf(dev, "Link is Down\n");
3569c19c7afeSEric Joyner 			iflib_link_state_change(ctx, LINK_STATE_DOWN, 0);
35708eb6488eSEric Joyner 			adapter->link_active = FALSE;
35718eb6488eSEric Joyner 			if (adapter->feat_en & IXGBE_FEATURE_SRIOV)
35728eb6488eSEric Joyner 				ixgbe_ping_all_vfs(adapter);
35738eb6488eSEric Joyner 		}
35748eb6488eSEric Joyner 	}
35758eb6488eSEric Joyner 
3576b2c1e8e6SEric Joyner 	/* Handle task requests from msix_link() */
3577b2c1e8e6SEric Joyner 	if (adapter->task_requests & IXGBE_REQUEST_TASK_MOD)
3578b2c1e8e6SEric Joyner 		ixgbe_handle_mod(ctx);
3579b2c1e8e6SEric Joyner 	if (adapter->task_requests & IXGBE_REQUEST_TASK_MSF)
3580b2c1e8e6SEric Joyner 		ixgbe_handle_msf(ctx);
3581b2c1e8e6SEric Joyner 	if (adapter->task_requests & IXGBE_REQUEST_TASK_MBX)
3582b2c1e8e6SEric Joyner 		ixgbe_handle_mbx(ctx);
3583b2c1e8e6SEric Joyner 	if (adapter->task_requests & IXGBE_REQUEST_TASK_FDIR)
3584b2c1e8e6SEric Joyner 		ixgbe_reinit_fdir(ctx);
3585b2c1e8e6SEric Joyner 	if (adapter->task_requests & IXGBE_REQUEST_TASK_PHY)
3586b2c1e8e6SEric Joyner 		ixgbe_handle_phy(ctx);
3587b2c1e8e6SEric Joyner 	adapter->task_requests = 0;
3588c19c7afeSEric Joyner 
3589b2c1e8e6SEric Joyner 	ixgbe_update_stats_counters(adapter);
3590c19c7afeSEric Joyner } /* ixgbe_if_update_admin_status */
35918eb6488eSEric Joyner 
35928eb6488eSEric Joyner /************************************************************************
35938eb6488eSEric Joyner  * ixgbe_config_dmac - Configure DMA Coalescing
35948eb6488eSEric Joyner  ************************************************************************/
35958eb6488eSEric Joyner static void
35968eb6488eSEric Joyner ixgbe_config_dmac(struct adapter *adapter)
35978eb6488eSEric Joyner {
35988eb6488eSEric Joyner 	struct ixgbe_hw          *hw = &adapter->hw;
35998eb6488eSEric Joyner 	struct ixgbe_dmac_config *dcfg = &hw->mac.dmac_config;
36008eb6488eSEric Joyner 
36018eb6488eSEric Joyner 	if (hw->mac.type < ixgbe_mac_X550 || !hw->mac.ops.dmac_config)
36028eb6488eSEric Joyner 		return;
36038eb6488eSEric Joyner 
36048eb6488eSEric Joyner 	if (dcfg->watchdog_timer ^ adapter->dmac ||
36058eb6488eSEric Joyner 	    dcfg->link_speed ^ adapter->link_speed) {
36068eb6488eSEric Joyner 		dcfg->watchdog_timer = adapter->dmac;
3607c19c7afeSEric Joyner 		dcfg->fcoe_en = FALSE;
36088eb6488eSEric Joyner 		dcfg->link_speed = adapter->link_speed;
36098eb6488eSEric Joyner 		dcfg->num_tcs = 1;
36108eb6488eSEric Joyner 
36118eb6488eSEric Joyner 		INIT_DEBUGOUT2("dmac settings: watchdog %d, link speed %d\n",
36128eb6488eSEric Joyner 		    dcfg->watchdog_timer, dcfg->link_speed);
36138eb6488eSEric Joyner 
36148eb6488eSEric Joyner 		hw->mac.ops.dmac_config(hw);
36158eb6488eSEric Joyner 	}
36168eb6488eSEric Joyner } /* ixgbe_config_dmac */
36178eb6488eSEric Joyner 
36188eb6488eSEric Joyner /************************************************************************
3619c19c7afeSEric Joyner  * ixgbe_if_enable_intr
36208eb6488eSEric Joyner  ************************************************************************/
3621c19c7afeSEric Joyner void
3622c19c7afeSEric Joyner ixgbe_if_enable_intr(if_ctx_t ctx)
36238eb6488eSEric Joyner {
3624c19c7afeSEric Joyner 	struct adapter     *adapter = iflib_get_softc(ctx);
36258eb6488eSEric Joyner 	struct ixgbe_hw    *hw = &adapter->hw;
3626c19c7afeSEric Joyner 	struct ix_rx_queue *que = adapter->rx_queues;
36278eb6488eSEric Joyner 	u32                mask, fwsm;
36288eb6488eSEric Joyner 
36298eb6488eSEric Joyner 	mask = (IXGBE_EIMS_ENABLE_MASK & ~IXGBE_EIMS_RTX_QUEUE);
36308eb6488eSEric Joyner 
36318eb6488eSEric Joyner 	switch (adapter->hw.mac.type) {
36328eb6488eSEric Joyner 	case ixgbe_mac_82599EB:
36338eb6488eSEric Joyner 		mask |= IXGBE_EIMS_ECC;
36348eb6488eSEric Joyner 		/* Temperature sensor on some adapters */
36358eb6488eSEric Joyner 		mask |= IXGBE_EIMS_GPI_SDP0;
36368eb6488eSEric Joyner 		/* SFP+ (RX_LOS_N & MOD_ABS_N) */
36378eb6488eSEric Joyner 		mask |= IXGBE_EIMS_GPI_SDP1;
36388eb6488eSEric Joyner 		mask |= IXGBE_EIMS_GPI_SDP2;
36398eb6488eSEric Joyner 		break;
36408eb6488eSEric Joyner 	case ixgbe_mac_X540:
36418eb6488eSEric Joyner 		/* Detect if Thermal Sensor is enabled */
36428eb6488eSEric Joyner 		fwsm = IXGBE_READ_REG(hw, IXGBE_FWSM);
36438eb6488eSEric Joyner 		if (fwsm & IXGBE_FWSM_TS_ENABLED)
36448eb6488eSEric Joyner 			mask |= IXGBE_EIMS_TS;
36458eb6488eSEric Joyner 		mask |= IXGBE_EIMS_ECC;
36468eb6488eSEric Joyner 		break;
36478eb6488eSEric Joyner 	case ixgbe_mac_X550:
36488eb6488eSEric Joyner 		/* MAC thermal sensor is automatically enabled */
36498eb6488eSEric Joyner 		mask |= IXGBE_EIMS_TS;
36508eb6488eSEric Joyner 		mask |= IXGBE_EIMS_ECC;
36518eb6488eSEric Joyner 		break;
36528eb6488eSEric Joyner 	case ixgbe_mac_X550EM_x:
36538eb6488eSEric Joyner 	case ixgbe_mac_X550EM_a:
36548eb6488eSEric Joyner 		/* Some devices use SDP0 for important information */
36558eb6488eSEric Joyner 		if (hw->device_id == IXGBE_DEV_ID_X550EM_X_SFP ||
36568eb6488eSEric Joyner 		    hw->device_id == IXGBE_DEV_ID_X550EM_A_SFP ||
36578eb6488eSEric Joyner 		    hw->device_id == IXGBE_DEV_ID_X550EM_A_SFP_N ||
36588eb6488eSEric Joyner 		    hw->device_id == IXGBE_DEV_ID_X550EM_X_10G_T)
36598eb6488eSEric Joyner 			mask |= IXGBE_EIMS_GPI_SDP0_BY_MAC(hw);
36608eb6488eSEric Joyner 		if (hw->phy.type == ixgbe_phy_x550em_ext_t)
36618eb6488eSEric Joyner 			mask |= IXGBE_EICR_GPI_SDP0_X540;
36628eb6488eSEric Joyner 		mask |= IXGBE_EIMS_ECC;
36638eb6488eSEric Joyner 		break;
36648eb6488eSEric Joyner 	default:
36658eb6488eSEric Joyner 		break;
36668eb6488eSEric Joyner 	}
36678eb6488eSEric Joyner 
36688eb6488eSEric Joyner 	/* Enable Fan Failure detection */
36698eb6488eSEric Joyner 	if (adapter->feat_en & IXGBE_FEATURE_FAN_FAIL)
36708eb6488eSEric Joyner 		mask |= IXGBE_EIMS_GPI_SDP1;
36718eb6488eSEric Joyner 	/* Enable SR-IOV */
36728eb6488eSEric Joyner 	if (adapter->feat_en & IXGBE_FEATURE_SRIOV)
36738eb6488eSEric Joyner 		mask |= IXGBE_EIMS_MAILBOX;
36748eb6488eSEric Joyner 	/* Enable Flow Director */
36758eb6488eSEric Joyner 	if (adapter->feat_en & IXGBE_FEATURE_FDIR)
36768eb6488eSEric Joyner 		mask |= IXGBE_EIMS_FLOW_DIR;
36778eb6488eSEric Joyner 
36788eb6488eSEric Joyner 	IXGBE_WRITE_REG(hw, IXGBE_EIMS, mask);
36798eb6488eSEric Joyner 
36808eb6488eSEric Joyner 	/* With MSI-X we use auto clear */
3681c19c7afeSEric Joyner 	if (adapter->intr_type == IFLIB_INTR_MSIX) {
36828eb6488eSEric Joyner 		mask = IXGBE_EIMS_ENABLE_MASK;
36838eb6488eSEric Joyner 		/* Don't autoclear Link */
36848eb6488eSEric Joyner 		mask &= ~IXGBE_EIMS_OTHER;
36858eb6488eSEric Joyner 		mask &= ~IXGBE_EIMS_LSC;
36868eb6488eSEric Joyner 		if (adapter->feat_cap & IXGBE_FEATURE_SRIOV)
36878eb6488eSEric Joyner 			mask &= ~IXGBE_EIMS_MAILBOX;
36888eb6488eSEric Joyner 		IXGBE_WRITE_REG(hw, IXGBE_EIAC, mask);
36896f37f232SEric Joyner 	}
36906f37f232SEric Joyner 
3691758cc3dcSJack F Vogel 	/*
36928eb6488eSEric Joyner 	 * Now enable all queues, this is done separately to
36938eb6488eSEric Joyner 	 * allow for handling the extended (beyond 32) MSI-X
36948eb6488eSEric Joyner 	 * vectors that can be used by 82599
3695758cc3dcSJack F Vogel 	 */
3696c19c7afeSEric Joyner 	for (int i = 0; i < adapter->num_rx_queues; i++, que++)
36978eb6488eSEric Joyner 		ixgbe_enable_queue(adapter, que->msix);
36988eb6488eSEric Joyner 
36998eb6488eSEric Joyner 	IXGBE_WRITE_FLUSH(hw);
37008eb6488eSEric Joyner 
3701c19c7afeSEric Joyner } /* ixgbe_if_enable_intr */
37028eb6488eSEric Joyner 
37038eb6488eSEric Joyner /************************************************************************
37048eb6488eSEric Joyner  * ixgbe_disable_intr
37058eb6488eSEric Joyner  ************************************************************************/
3706758cc3dcSJack F Vogel static void
3707c19c7afeSEric Joyner ixgbe_if_disable_intr(if_ctx_t ctx)
3708758cc3dcSJack F Vogel {
3709c19c7afeSEric Joyner 	struct adapter *adapter = iflib_get_softc(ctx);
3710c19c7afeSEric Joyner 
3711c19c7afeSEric Joyner 	if (adapter->intr_type == IFLIB_INTR_MSIX)
37128eb6488eSEric Joyner 		IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIAC, 0);
37138eb6488eSEric Joyner 	if (adapter->hw.mac.type == ixgbe_mac_82598EB) {
37148eb6488eSEric Joyner 		IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMC, ~0);
37158eb6488eSEric Joyner 	} else {
37168eb6488eSEric Joyner 		IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMC, 0xFFFF0000);
37178eb6488eSEric Joyner 		IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMC_EX(0), ~0);
37188eb6488eSEric Joyner 		IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMC_EX(1), ~0);
37198eb6488eSEric Joyner 	}
37208eb6488eSEric Joyner 	IXGBE_WRITE_FLUSH(&adapter->hw);
3721758cc3dcSJack F Vogel 
3722c19c7afeSEric Joyner } /* ixgbe_if_disable_intr */
37238eb6488eSEric Joyner 
37248eb6488eSEric Joyner /************************************************************************
3725b2c1e8e6SEric Joyner  * ixgbe_link_intr_enable
3726b2c1e8e6SEric Joyner  ************************************************************************/
3727b2c1e8e6SEric Joyner static void
3728b2c1e8e6SEric Joyner ixgbe_link_intr_enable(if_ctx_t ctx)
3729b2c1e8e6SEric Joyner {
3730b2c1e8e6SEric Joyner 	struct ixgbe_hw *hw = &((struct adapter *)iflib_get_softc(ctx))->hw;
3731b2c1e8e6SEric Joyner 
3732b2c1e8e6SEric Joyner 	/* Re-enable other interrupts */
3733b2c1e8e6SEric Joyner 	IXGBE_WRITE_REG(hw, IXGBE_EIMS, IXGBE_EIMS_OTHER | IXGBE_EIMS_LSC);
3734b2c1e8e6SEric Joyner } /* ixgbe_link_intr_enable */
3735b2c1e8e6SEric Joyner 
3736b2c1e8e6SEric Joyner /************************************************************************
3737c19c7afeSEric Joyner  * ixgbe_if_rx_queue_intr_enable
3738c19c7afeSEric Joyner  ************************************************************************/
3739c19c7afeSEric Joyner static int
3740c19c7afeSEric Joyner ixgbe_if_rx_queue_intr_enable(if_ctx_t ctx, uint16_t rxqid)
3741c19c7afeSEric Joyner {
3742c19c7afeSEric Joyner 	struct adapter     *adapter = iflib_get_softc(ctx);
3743c19c7afeSEric Joyner 	struct ix_rx_queue *que = &adapter->rx_queues[rxqid];
3744c19c7afeSEric Joyner 
37452dc2d580SEric Joyner 	ixgbe_enable_queue(adapter, que->msix);
3746c19c7afeSEric Joyner 
3747c19c7afeSEric Joyner 	return (0);
3748c19c7afeSEric Joyner } /* ixgbe_if_rx_queue_intr_enable */
3749c19c7afeSEric Joyner 
3750c19c7afeSEric Joyner /************************************************************************
3751c19c7afeSEric Joyner  * ixgbe_enable_queue
37528eb6488eSEric Joyner  ************************************************************************/
37538eb6488eSEric Joyner static void
3754c19c7afeSEric Joyner ixgbe_enable_queue(struct adapter *adapter, u32 vector)
37558eb6488eSEric Joyner {
37568eb6488eSEric Joyner 	struct ixgbe_hw *hw = &adapter->hw;
37572dc2d580SEric Joyner 	u64             queue = 1ULL << vector;
3758c19c7afeSEric Joyner 	u32             mask;
3759758cc3dcSJack F Vogel 
3760c19c7afeSEric Joyner 	if (hw->mac.type == ixgbe_mac_82598EB) {
3761c19c7afeSEric Joyner 		mask = (IXGBE_EIMS_RTX_QUEUE & queue);
3762c19c7afeSEric Joyner 		IXGBE_WRITE_REG(hw, IXGBE_EIMS, mask);
3763c19c7afeSEric Joyner 	} else {
3764c19c7afeSEric Joyner 		mask = (queue & 0xFFFFFFFF);
3765c19c7afeSEric Joyner 		if (mask)
3766c19c7afeSEric Joyner 			IXGBE_WRITE_REG(hw, IXGBE_EIMS_EX(0), mask);
3767c19c7afeSEric Joyner 		mask = (queue >> 32);
3768c19c7afeSEric Joyner 		if (mask)
3769c19c7afeSEric Joyner 			IXGBE_WRITE_REG(hw, IXGBE_EIMS_EX(1), mask);
3770c19c7afeSEric Joyner 	}
3771c19c7afeSEric Joyner } /* ixgbe_enable_queue */
3772c19c7afeSEric Joyner 
3773c19c7afeSEric Joyner /************************************************************************
3774c19c7afeSEric Joyner  * ixgbe_disable_queue
3775c19c7afeSEric Joyner  ************************************************************************/
3776c19c7afeSEric Joyner static void
3777c19c7afeSEric Joyner ixgbe_disable_queue(struct adapter *adapter, u32 vector)
3778c19c7afeSEric Joyner {
3779c19c7afeSEric Joyner 	struct ixgbe_hw *hw = &adapter->hw;
37802dc2d580SEric Joyner 	u64             queue = 1ULL << vector;
3781c19c7afeSEric Joyner 	u32             mask;
3782c19c7afeSEric Joyner 
3783c19c7afeSEric Joyner 	if (hw->mac.type == ixgbe_mac_82598EB) {
3784c19c7afeSEric Joyner 		mask = (IXGBE_EIMS_RTX_QUEUE & queue);
3785c19c7afeSEric Joyner 		IXGBE_WRITE_REG(hw, IXGBE_EIMC, mask);
3786c19c7afeSEric Joyner 	} else {
3787c19c7afeSEric Joyner 		mask = (queue & 0xFFFFFFFF);
3788c19c7afeSEric Joyner 		if (mask)
3789c19c7afeSEric Joyner 			IXGBE_WRITE_REG(hw, IXGBE_EIMC_EX(0), mask);
3790c19c7afeSEric Joyner 		mask = (queue >> 32);
3791c19c7afeSEric Joyner 		if (mask)
3792c19c7afeSEric Joyner 			IXGBE_WRITE_REG(hw, IXGBE_EIMC_EX(1), mask);
3793c19c7afeSEric Joyner 	}
3794c19c7afeSEric Joyner } /* ixgbe_disable_queue */
3795c19c7afeSEric Joyner 
3796c19c7afeSEric Joyner /************************************************************************
3797c19c7afeSEric Joyner  * ixgbe_intr - Legacy Interrupt Service Routine
3798c19c7afeSEric Joyner  ************************************************************************/
3799c19c7afeSEric Joyner int
3800c19c7afeSEric Joyner ixgbe_intr(void *arg)
3801c19c7afeSEric Joyner {
3802c19c7afeSEric Joyner 	struct adapter     *adapter = arg;
3803c19c7afeSEric Joyner 	struct ix_rx_queue *que = adapter->rx_queues;
3804c19c7afeSEric Joyner 	struct ixgbe_hw    *hw = &adapter->hw;
3805c19c7afeSEric Joyner 	if_ctx_t           ctx = adapter->ctx;
3806c19c7afeSEric Joyner 	u32                eicr, eicr_mask;
3807758cc3dcSJack F Vogel 
38088eb6488eSEric Joyner 	eicr = IXGBE_READ_REG(hw, IXGBE_EICR);
3809758cc3dcSJack F Vogel 
38108eb6488eSEric Joyner 	++que->irqs;
38118eb6488eSEric Joyner 	if (eicr == 0) {
3812c19c7afeSEric Joyner 		ixgbe_if_enable_intr(ctx);
3813c19c7afeSEric Joyner 		return (FILTER_HANDLED);
3814758cc3dcSJack F Vogel 	}
3815758cc3dcSJack F Vogel 
38168eb6488eSEric Joyner 	/* Check for fan failure */
3817c19c7afeSEric Joyner 	if ((hw->device_id == IXGBE_DEV_ID_82598AT) &&
3818c19c7afeSEric Joyner 	    (eicr & IXGBE_EICR_GPI_SDP1)) {
3819c19c7afeSEric Joyner 		device_printf(adapter->dev,
3820c19c7afeSEric Joyner 		    "\nCRITICAL: FAN FAILURE!! REPLACE IMMEDIATELY!!\n");
38218eb6488eSEric Joyner 		IXGBE_WRITE_REG(hw, IXGBE_EIMS, IXGBE_EICR_GPI_SDP1_BY_MAC(hw));
3822758cc3dcSJack F Vogel 	}
3823758cc3dcSJack F Vogel 
38248eb6488eSEric Joyner 	/* Link status change */
3825c19c7afeSEric Joyner 	if (eicr & IXGBE_EICR_LSC) {
3826c19c7afeSEric Joyner 		IXGBE_WRITE_REG(hw, IXGBE_EIMC, IXGBE_EIMC_LSC);
3827c19c7afeSEric Joyner 		iflib_admin_intr_deferred(ctx);
3828c19c7afeSEric Joyner 	}
38298eb6488eSEric Joyner 
38308eb6488eSEric Joyner 	if (ixgbe_is_sfp(hw)) {
38318eb6488eSEric Joyner 		/* Pluggable optics-related interrupt */
38328eb6488eSEric Joyner 		if (hw->mac.type >= ixgbe_mac_X540)
38338eb6488eSEric Joyner 			eicr_mask = IXGBE_EICR_GPI_SDP0_X540;
38348eb6488eSEric Joyner 		else
38358eb6488eSEric Joyner 			eicr_mask = IXGBE_EICR_GPI_SDP2_BY_MAC(hw);
38368eb6488eSEric Joyner 
38378eb6488eSEric Joyner 		if (eicr & eicr_mask) {
38388eb6488eSEric Joyner 			IXGBE_WRITE_REG(hw, IXGBE_EICR, eicr_mask);
3839b2c1e8e6SEric Joyner 			adapter->task_requests |= IXGBE_REQUEST_TASK_MOD;
38408eb6488eSEric Joyner 		}
38418eb6488eSEric Joyner 
38428eb6488eSEric Joyner 		if ((hw->mac.type == ixgbe_mac_82599EB) &&
38438eb6488eSEric Joyner 		    (eicr & IXGBE_EICR_GPI_SDP1_BY_MAC(hw))) {
38448eb6488eSEric Joyner 			IXGBE_WRITE_REG(hw, IXGBE_EICR,
38458eb6488eSEric Joyner 			    IXGBE_EICR_GPI_SDP1_BY_MAC(hw));
3846b2c1e8e6SEric Joyner 			adapter->task_requests |= IXGBE_REQUEST_TASK_MSF;
38478eb6488eSEric Joyner 		}
38488eb6488eSEric Joyner 	}
38498eb6488eSEric Joyner 
38508eb6488eSEric Joyner 	/* External PHY interrupt */
38518eb6488eSEric Joyner 	if ((hw->phy.type == ixgbe_phy_x550em_ext_t) &&
38528eb6488eSEric Joyner 	    (eicr & IXGBE_EICR_GPI_SDP0_X540))
3853b2c1e8e6SEric Joyner 		adapter->task_requests |= IXGBE_REQUEST_TASK_PHY;
38548eb6488eSEric Joyner 
3855c19c7afeSEric Joyner 	return (FILTER_SCHEDULE_THREAD);
3856c19c7afeSEric Joyner } /* ixgbe_intr */
38578eb6488eSEric Joyner 
38588eb6488eSEric Joyner /************************************************************************
38598eb6488eSEric Joyner  * ixgbe_free_pci_resources
38608eb6488eSEric Joyner  ************************************************************************/
38618eb6488eSEric Joyner static void
3862c19c7afeSEric Joyner ixgbe_free_pci_resources(if_ctx_t ctx)
38638eb6488eSEric Joyner {
3864c19c7afeSEric Joyner 	struct adapter *adapter = iflib_get_softc(ctx);
3865c19c7afeSEric Joyner 	struct         ix_rx_queue *que = adapter->rx_queues;
3866c19c7afeSEric Joyner 	device_t       dev = iflib_get_dev(ctx);
38678eb6488eSEric Joyner 
3868b97de13aSMarius Strobl 	/* Release all MSI-X queue resources */
3869c19c7afeSEric Joyner 	if (adapter->intr_type == IFLIB_INTR_MSIX)
3870c19c7afeSEric Joyner 		iflib_irq_free(ctx, &adapter->irq);
3871c19c7afeSEric Joyner 
3872c19c7afeSEric Joyner 	if (que != NULL) {
3873c19c7afeSEric Joyner 		for (int i = 0; i < adapter->num_rx_queues; i++, que++) {
3874c19c7afeSEric Joyner 			iflib_irq_free(ctx, &que->que_irq);
3875c19c7afeSEric Joyner 		}
3876c19c7afeSEric Joyner 	}
38778eb6488eSEric Joyner 
38788eb6488eSEric Joyner 	if (adapter->pci_mem != NULL)
3879c19c7afeSEric Joyner 		bus_release_resource(dev, SYS_RES_MEMORY,
3880b97de13aSMarius Strobl 		    rman_get_rid(adapter->pci_mem), adapter->pci_mem);
38818eb6488eSEric Joyner } /* ixgbe_free_pci_resources */
38828eb6488eSEric Joyner 
38838eb6488eSEric Joyner /************************************************************************
38848eb6488eSEric Joyner  * ixgbe_sysctl_flowcntl
38858eb6488eSEric Joyner  *
38868eb6488eSEric Joyner  *   SYSCTL wrapper around setting Flow Control
38878eb6488eSEric Joyner  ************************************************************************/
3888758cc3dcSJack F Vogel static int
3889f2c4db54SSteven Hartland ixgbe_sysctl_flowcntl(SYSCTL_HANDLER_ARGS)
3890758cc3dcSJack F Vogel {
3891f2c4db54SSteven Hartland 	struct adapter *adapter;
38928eb6488eSEric Joyner 	int            error, fc;
3893758cc3dcSJack F Vogel 
3894f2c4db54SSteven Hartland 	adapter = (struct adapter *)arg1;
38958eb6488eSEric Joyner 	fc = adapter->hw.fc.current_mode;
3896f2c4db54SSteven Hartland 
3897f2c4db54SSteven Hartland 	error = sysctl_handle_int(oidp, &fc, 0, req);
3898758cc3dcSJack F Vogel 	if ((error) || (req->newptr == NULL))
3899758cc3dcSJack F Vogel 		return (error);
3900758cc3dcSJack F Vogel 
3901758cc3dcSJack F Vogel 	/* Don't bother if it's not changed */
39028eb6488eSEric Joyner 	if (fc == adapter->hw.fc.current_mode)
3903758cc3dcSJack F Vogel 		return (0);
3904758cc3dcSJack F Vogel 
3905f2c4db54SSteven Hartland 	return ixgbe_set_flowcntl(adapter, fc);
39068eb6488eSEric Joyner } /* ixgbe_sysctl_flowcntl */
3907f2c4db54SSteven Hartland 
39088eb6488eSEric Joyner /************************************************************************
39098eb6488eSEric Joyner  * ixgbe_set_flowcntl - Set flow control
39108eb6488eSEric Joyner  *
39118eb6488eSEric Joyner  *   Flow control values:
39128eb6488eSEric Joyner  *     0 - off
39138eb6488eSEric Joyner  *     1 - rx pause
39148eb6488eSEric Joyner  *     2 - tx pause
39158eb6488eSEric Joyner  *     3 - full
39168eb6488eSEric Joyner  ************************************************************************/
3917f2c4db54SSteven Hartland static int
3918f2c4db54SSteven Hartland ixgbe_set_flowcntl(struct adapter *adapter, int fc)
3919f2c4db54SSteven Hartland {
3920f2c4db54SSteven Hartland 	switch (fc) {
3921758cc3dcSJack F Vogel 	case ixgbe_fc_rx_pause:
3922758cc3dcSJack F Vogel 	case ixgbe_fc_tx_pause:
3923758cc3dcSJack F Vogel 	case ixgbe_fc_full:
39248eb6488eSEric Joyner 		adapter->hw.fc.requested_mode = fc;
3925c19c7afeSEric Joyner 		if (adapter->num_rx_queues > 1)
3926758cc3dcSJack F Vogel 			ixgbe_disable_rx_drop(adapter);
3927758cc3dcSJack F Vogel 		break;
3928758cc3dcSJack F Vogel 	case ixgbe_fc_none:
3929758cc3dcSJack F Vogel 		adapter->hw.fc.requested_mode = ixgbe_fc_none;
3930c19c7afeSEric Joyner 		if (adapter->num_rx_queues > 1)
3931758cc3dcSJack F Vogel 			ixgbe_enable_rx_drop(adapter);
3932758cc3dcSJack F Vogel 		break;
3933758cc3dcSJack F Vogel 	default:
3934758cc3dcSJack F Vogel 		return (EINVAL);
3935758cc3dcSJack F Vogel 	}
39368eb6488eSEric Joyner 
3937758cc3dcSJack F Vogel 	/* Don't autoneg if forcing a value */
3938758cc3dcSJack F Vogel 	adapter->hw.fc.disable_fc_autoneg = TRUE;
3939758cc3dcSJack F Vogel 	ixgbe_fc_enable(&adapter->hw);
39408eb6488eSEric Joyner 
3941f2c4db54SSteven Hartland 	return (0);
39428eb6488eSEric Joyner } /* ixgbe_set_flowcntl */
39438eb6488eSEric Joyner 
39448eb6488eSEric Joyner /************************************************************************
39458eb6488eSEric Joyner  * ixgbe_enable_rx_drop
39468eb6488eSEric Joyner  *
39478eb6488eSEric Joyner  *   Enable the hardware to drop packets when the buffer is
39488eb6488eSEric Joyner  *   full. This is useful with multiqueue, so that no single
39498eb6488eSEric Joyner  *   queue being full stalls the entire RX engine. We only
39508eb6488eSEric Joyner  *   enable this when Multiqueue is enabled AND Flow Control
39518eb6488eSEric Joyner  *   is disabled.
39528eb6488eSEric Joyner  ************************************************************************/
39538eb6488eSEric Joyner static void
39548eb6488eSEric Joyner ixgbe_enable_rx_drop(struct adapter *adapter)
39558eb6488eSEric Joyner {
39568eb6488eSEric Joyner 	struct ixgbe_hw *hw = &adapter->hw;
39578eb6488eSEric Joyner 	struct rx_ring  *rxr;
39588eb6488eSEric Joyner 	u32             srrctl;
39598eb6488eSEric Joyner 
3960c19c7afeSEric Joyner 	for (int i = 0; i < adapter->num_rx_queues; i++) {
3961c19c7afeSEric Joyner 		rxr = &adapter->rx_queues[i].rxr;
39628eb6488eSEric Joyner 		srrctl = IXGBE_READ_REG(hw, IXGBE_SRRCTL(rxr->me));
39638eb6488eSEric Joyner 		srrctl |= IXGBE_SRRCTL_DROP_EN;
39648eb6488eSEric Joyner 		IXGBE_WRITE_REG(hw, IXGBE_SRRCTL(rxr->me), srrctl);
3965758cc3dcSJack F Vogel 	}
3966758cc3dcSJack F Vogel 
39678eb6488eSEric Joyner 	/* enable drop for each vf */
39688eb6488eSEric Joyner 	for (int i = 0; i < adapter->num_vfs; i++) {
39698eb6488eSEric Joyner 		IXGBE_WRITE_REG(hw, IXGBE_QDE,
39708eb6488eSEric Joyner 		                (IXGBE_QDE_WRITE | (i << IXGBE_QDE_IDX_SHIFT) |
39718eb6488eSEric Joyner 		                IXGBE_QDE_ENABLE));
39728eb6488eSEric Joyner 	}
39738eb6488eSEric Joyner } /* ixgbe_enable_rx_drop */
39748eb6488eSEric Joyner 
39758eb6488eSEric Joyner /************************************************************************
39768eb6488eSEric Joyner  * ixgbe_disable_rx_drop
39778eb6488eSEric Joyner  ************************************************************************/
39788eb6488eSEric Joyner static void
39798eb6488eSEric Joyner ixgbe_disable_rx_drop(struct adapter *adapter)
39808eb6488eSEric Joyner {
39818eb6488eSEric Joyner 	struct ixgbe_hw *hw = &adapter->hw;
39828eb6488eSEric Joyner 	struct rx_ring  *rxr;
39838eb6488eSEric Joyner 	u32             srrctl;
39848eb6488eSEric Joyner 
3985c19c7afeSEric Joyner 	for (int i = 0; i < adapter->num_rx_queues; i++) {
3986c19c7afeSEric Joyner 		rxr = &adapter->rx_queues[i].rxr;
39878eb6488eSEric Joyner 		srrctl = IXGBE_READ_REG(hw, IXGBE_SRRCTL(rxr->me));
39888eb6488eSEric Joyner 		srrctl &= ~IXGBE_SRRCTL_DROP_EN;
39898eb6488eSEric Joyner 		IXGBE_WRITE_REG(hw, IXGBE_SRRCTL(rxr->me), srrctl);
39908eb6488eSEric Joyner 	}
39918eb6488eSEric Joyner 
39928eb6488eSEric Joyner 	/* disable drop for each vf */
39938eb6488eSEric Joyner 	for (int i = 0; i < adapter->num_vfs; i++) {
39948eb6488eSEric Joyner 		IXGBE_WRITE_REG(hw, IXGBE_QDE,
39958eb6488eSEric Joyner 		    (IXGBE_QDE_WRITE | (i << IXGBE_QDE_IDX_SHIFT)));
39968eb6488eSEric Joyner 	}
39978eb6488eSEric Joyner } /* ixgbe_disable_rx_drop */
39988eb6488eSEric Joyner 
39998eb6488eSEric Joyner /************************************************************************
40008eb6488eSEric Joyner  * ixgbe_sysctl_advertise
40018eb6488eSEric Joyner  *
40028eb6488eSEric Joyner  *   SYSCTL wrapper around setting advertised speed
40038eb6488eSEric Joyner  ************************************************************************/
4004758cc3dcSJack F Vogel static int
4005f2c4db54SSteven Hartland ixgbe_sysctl_advertise(SYSCTL_HANDLER_ARGS)
4006758cc3dcSJack F Vogel {
4007758cc3dcSJack F Vogel 	struct adapter *adapter;
40088eb6488eSEric Joyner 	int            error, advertise;
4009758cc3dcSJack F Vogel 
4010758cc3dcSJack F Vogel 	adapter = (struct adapter *)arg1;
4011f2c4db54SSteven Hartland 	advertise = adapter->advertise;
4012758cc3dcSJack F Vogel 
4013f2c4db54SSteven Hartland 	error = sysctl_handle_int(oidp, &advertise, 0, req);
4014758cc3dcSJack F Vogel 	if ((error) || (req->newptr == NULL))
4015758cc3dcSJack F Vogel 		return (error);
4016758cc3dcSJack F Vogel 
4017f2c4db54SSteven Hartland 	return ixgbe_set_advertise(adapter, advertise);
40188eb6488eSEric Joyner } /* ixgbe_sysctl_advertise */
4019f2c4db54SSteven Hartland 
40208eb6488eSEric Joyner /************************************************************************
40218eb6488eSEric Joyner  * ixgbe_set_advertise - Control advertised link speed
40228eb6488eSEric Joyner  *
40238eb6488eSEric Joyner  *   Flags:
40248eb6488eSEric Joyner  *     0x1 - advertise 100 Mb
40258eb6488eSEric Joyner  *     0x2 - advertise 1G
40268eb6488eSEric Joyner  *     0x4 - advertise 10G
40278eb6488eSEric Joyner  *     0x8 - advertise 10 Mb (yes, Mb)
40288eb6488eSEric Joyner  ************************************************************************/
4029f2c4db54SSteven Hartland static int
4030f2c4db54SSteven Hartland ixgbe_set_advertise(struct adapter *adapter, int advertise)
4031f2c4db54SSteven Hartland {
4032c19c7afeSEric Joyner 	device_t         dev = iflib_get_dev(adapter->ctx);
4033f2c4db54SSteven Hartland 	struct ixgbe_hw  *hw;
40348eb6488eSEric Joyner 	ixgbe_link_speed speed = 0;
40358eb6488eSEric Joyner 	ixgbe_link_speed link_caps = 0;
40368eb6488eSEric Joyner 	s32              err = IXGBE_NOT_IMPLEMENTED;
40378eb6488eSEric Joyner 	bool             negotiate = FALSE;
4038f2c4db54SSteven Hartland 
4039d775d23aSSteven Hartland 	/* Checks to validate new value */
4040d775d23aSSteven Hartland 	if (adapter->advertise == advertise) /* no change */
4041d775d23aSSteven Hartland 		return (0);
4042d775d23aSSteven Hartland 
40438eb6488eSEric Joyner 	hw = &adapter->hw;
4044f2c4db54SSteven Hartland 
4045a9ca1c79SSean Bruno 	/* No speed changes for backplane media */
4046a9ca1c79SSean Bruno 	if (hw->phy.media_type == ixgbe_media_type_backplane)
4047a9ca1c79SSean Bruno 		return (ENODEV);
4048a9ca1c79SSean Bruno 
4049758cc3dcSJack F Vogel 	if (!((hw->phy.media_type == ixgbe_media_type_copper) ||
4050758cc3dcSJack F Vogel 	      (hw->phy.multispeed_fiber))) {
40518eb6488eSEric Joyner 		device_printf(dev, "Advertised speed can only be set on copper or multispeed fiber media types.\n");
4052758cc3dcSJack F Vogel 		return (EINVAL);
4053758cc3dcSJack F Vogel 	}
4054758cc3dcSJack F Vogel 
40558eb6488eSEric Joyner 	if (advertise < 0x1 || advertise > 0xF) {
40568eb6488eSEric Joyner 		device_printf(dev, "Invalid advertised speed; valid modes are 0x1 through 0xF\n");
4057758cc3dcSJack F Vogel 		return (EINVAL);
4058758cc3dcSJack F Vogel 	}
4059758cc3dcSJack F Vogel 
40608eb6488eSEric Joyner 	if (hw->mac.ops.get_link_capabilities) {
40618eb6488eSEric Joyner 		err = hw->mac.ops.get_link_capabilities(hw, &link_caps,
40628eb6488eSEric Joyner 		    &negotiate);
40638eb6488eSEric Joyner 		if (err != IXGBE_SUCCESS) {
40648eb6488eSEric Joyner 			device_printf(dev, "Unable to determine supported advertise speeds\n");
40658eb6488eSEric Joyner 			return (ENODEV);
40668eb6488eSEric Joyner 		}
4067758cc3dcSJack F Vogel 	}
4068758cc3dcSJack F Vogel 
4069758cc3dcSJack F Vogel 	/* Set new value and report new advertised mode */
40708eb6488eSEric Joyner 	if (advertise & 0x1) {
40718eb6488eSEric Joyner 		if (!(link_caps & IXGBE_LINK_SPEED_100_FULL)) {
40728eb6488eSEric Joyner 			device_printf(dev, "Interface does not support 100Mb advertised speed\n");
40738eb6488eSEric Joyner 			return (EINVAL);
40748eb6488eSEric Joyner 		}
4075758cc3dcSJack F Vogel 		speed |= IXGBE_LINK_SPEED_100_FULL;
40768eb6488eSEric Joyner 	}
40778eb6488eSEric Joyner 	if (advertise & 0x2) {
40788eb6488eSEric Joyner 		if (!(link_caps & IXGBE_LINK_SPEED_1GB_FULL)) {
40798eb6488eSEric Joyner 			device_printf(dev, "Interface does not support 1Gb advertised speed\n");
40808eb6488eSEric Joyner 			return (EINVAL);
40818eb6488eSEric Joyner 		}
4082758cc3dcSJack F Vogel 		speed |= IXGBE_LINK_SPEED_1GB_FULL;
40838eb6488eSEric Joyner 	}
40848eb6488eSEric Joyner 	if (advertise & 0x4) {
40858eb6488eSEric Joyner 		if (!(link_caps & IXGBE_LINK_SPEED_10GB_FULL)) {
40868eb6488eSEric Joyner 			device_printf(dev, "Interface does not support 10Gb advertised speed\n");
40878eb6488eSEric Joyner 			return (EINVAL);
40888eb6488eSEric Joyner 		}
4089758cc3dcSJack F Vogel 		speed |= IXGBE_LINK_SPEED_10GB_FULL;
40908eb6488eSEric Joyner 	}
40918eb6488eSEric Joyner 	if (advertise & 0x8) {
40928eb6488eSEric Joyner 		if (!(link_caps & IXGBE_LINK_SPEED_10_FULL)) {
40938eb6488eSEric Joyner 			device_printf(dev, "Interface does not support 10Mb advertised speed\n");
40948eb6488eSEric Joyner 			return (EINVAL);
40958eb6488eSEric Joyner 		}
40968eb6488eSEric Joyner 		speed |= IXGBE_LINK_SPEED_10_FULL;
40978eb6488eSEric Joyner 	}
4098758cc3dcSJack F Vogel 
4099758cc3dcSJack F Vogel 	hw->mac.autotry_restart = TRUE;
4100758cc3dcSJack F Vogel 	hw->mac.ops.setup_link(hw, speed, TRUE);
41018eb6488eSEric Joyner 	adapter->advertise = advertise;
4102758cc3dcSJack F Vogel 
4103f2c4db54SSteven Hartland 	return (0);
41048eb6488eSEric Joyner } /* ixgbe_set_advertise */
41058eb6488eSEric Joyner 
41068eb6488eSEric Joyner /************************************************************************
41078eb6488eSEric Joyner  * ixgbe_get_advertise - Get current advertised speed settings
41088eb6488eSEric Joyner  *
41098eb6488eSEric Joyner  *   Formatted for sysctl usage.
41108eb6488eSEric Joyner  *   Flags:
41118eb6488eSEric Joyner  *     0x1 - advertise 100 Mb
41128eb6488eSEric Joyner  *     0x2 - advertise 1G
41138eb6488eSEric Joyner  *     0x4 - advertise 10G
41148eb6488eSEric Joyner  *     0x8 - advertise 10 Mb (yes, Mb)
41158eb6488eSEric Joyner  ************************************************************************/
41168eb6488eSEric Joyner static int
41178eb6488eSEric Joyner ixgbe_get_advertise(struct adapter *adapter)
41188eb6488eSEric Joyner {
41198eb6488eSEric Joyner 	struct ixgbe_hw  *hw = &adapter->hw;
41208eb6488eSEric Joyner 	int              speed;
41218eb6488eSEric Joyner 	ixgbe_link_speed link_caps = 0;
41228eb6488eSEric Joyner 	s32              err;
41238eb6488eSEric Joyner 	bool             negotiate = FALSE;
4124758cc3dcSJack F Vogel 
4125758cc3dcSJack F Vogel 	/*
41268eb6488eSEric Joyner 	 * Advertised speed means nothing unless it's copper or
41278eb6488eSEric Joyner 	 * multi-speed fiber
4128758cc3dcSJack F Vogel 	 */
41298eb6488eSEric Joyner 	if (!(hw->phy.media_type == ixgbe_media_type_copper) &&
41308eb6488eSEric Joyner 	    !(hw->phy.multispeed_fiber))
4131758cc3dcSJack F Vogel 		return (0);
4132758cc3dcSJack F Vogel 
41338eb6488eSEric Joyner 	err = hw->mac.ops.get_link_capabilities(hw, &link_caps, &negotiate);
41348eb6488eSEric Joyner 	if (err != IXGBE_SUCCESS)
41358eb6488eSEric Joyner 		return (0);
41368eb6488eSEric Joyner 
41378eb6488eSEric Joyner 	speed =
41388eb6488eSEric Joyner 	    ((link_caps & IXGBE_LINK_SPEED_10GB_FULL) ? 4 : 0) |
41398eb6488eSEric Joyner 	    ((link_caps & IXGBE_LINK_SPEED_1GB_FULL)  ? 2 : 0) |
41408eb6488eSEric Joyner 	    ((link_caps & IXGBE_LINK_SPEED_100_FULL)  ? 1 : 0) |
41418eb6488eSEric Joyner 	    ((link_caps & IXGBE_LINK_SPEED_10_FULL)   ? 8 : 0);
41428eb6488eSEric Joyner 
41438eb6488eSEric Joyner 	return speed;
41448eb6488eSEric Joyner } /* ixgbe_get_advertise */
41458eb6488eSEric Joyner 
41468eb6488eSEric Joyner /************************************************************************
41478eb6488eSEric Joyner  * ixgbe_sysctl_dmac - Manage DMA Coalescing
41488eb6488eSEric Joyner  *
41498eb6488eSEric Joyner  *   Control values:
41508eb6488eSEric Joyner  *     0/1 - off / on (use default value of 1000)
41518eb6488eSEric Joyner  *
41528eb6488eSEric Joyner  *     Legal timer values are:
41538eb6488eSEric Joyner  *     50,100,250,500,1000,2000,5000,10000
41548eb6488eSEric Joyner  *
41558eb6488eSEric Joyner  *     Turning off interrupt moderation will also turn this off.
41568eb6488eSEric Joyner  ************************************************************************/
41576f37f232SEric Joyner static int
41586f37f232SEric Joyner ixgbe_sysctl_dmac(SYSCTL_HANDLER_ARGS)
41596f37f232SEric Joyner {
41606f37f232SEric Joyner 	struct adapter *adapter = (struct adapter *)arg1;
4161c19c7afeSEric Joyner 	struct ifnet   *ifp = iflib_get_ifp(adapter->ctx);
41626f37f232SEric Joyner 	int            error;
4163c19c7afeSEric Joyner 	u16            newval;
41646f37f232SEric Joyner 
4165a9ca1c79SSean Bruno 	newval = adapter->dmac;
4166c19c7afeSEric Joyner 	error = sysctl_handle_16(oidp, &newval, 0, req);
41676f37f232SEric Joyner 	if ((error) || (req->newptr == NULL))
41686f37f232SEric Joyner 		return (error);
41696f37f232SEric Joyner 
4170a9ca1c79SSean Bruno 	switch (newval) {
41716f37f232SEric Joyner 	case 0:
41726f37f232SEric Joyner 		/* Disabled */
4173a9ca1c79SSean Bruno 		adapter->dmac = 0;
41746f37f232SEric Joyner 		break;
4175a9ca1c79SSean Bruno 	case 1:
4176a9ca1c79SSean Bruno 		/* Enable and use default */
41776f37f232SEric Joyner 		adapter->dmac = 1000;
41786f37f232SEric Joyner 		break;
41796f37f232SEric Joyner 	case 50:
41806f37f232SEric Joyner 	case 100:
41816f37f232SEric Joyner 	case 250:
41826f37f232SEric Joyner 	case 500:
41836f37f232SEric Joyner 	case 1000:
41846f37f232SEric Joyner 	case 2000:
41856f37f232SEric Joyner 	case 5000:
41866f37f232SEric Joyner 	case 10000:
41876f37f232SEric Joyner 		/* Legal values - allow */
4188a9ca1c79SSean Bruno 		adapter->dmac = newval;
41896f37f232SEric Joyner 		break;
41906f37f232SEric Joyner 	default:
41916f37f232SEric Joyner 		/* Do nothing, illegal value */
41926f37f232SEric Joyner 		return (EINVAL);
41936f37f232SEric Joyner 	}
41946f37f232SEric Joyner 
41956f37f232SEric Joyner 	/* Re-initialize hardware if it's already running */
41966f37f232SEric Joyner 	if (ifp->if_drv_flags & IFF_DRV_RUNNING)
4197c19c7afeSEric Joyner 		ifp->if_init(ifp);
41986f37f232SEric Joyner 
41996f37f232SEric Joyner 	return (0);
42008eb6488eSEric Joyner } /* ixgbe_sysctl_dmac */
42016f37f232SEric Joyner 
4202a9ca1c79SSean Bruno #ifdef IXGBE_DEBUG
42038eb6488eSEric Joyner /************************************************************************
42048eb6488eSEric Joyner  * ixgbe_sysctl_power_state
42058eb6488eSEric Joyner  *
4206a9ca1c79SSean Bruno  *   Sysctl to test power states
4207a9ca1c79SSean Bruno  *   Values:
4208a9ca1c79SSean Bruno  *     0      - set device to D0
4209a9ca1c79SSean Bruno  *     3      - set device to D3
4210a9ca1c79SSean Bruno  *     (none) - get current device power state
42118eb6488eSEric Joyner  ************************************************************************/
4212a9ca1c79SSean Bruno static int
4213a9ca1c79SSean Bruno ixgbe_sysctl_power_state(SYSCTL_HANDLER_ARGS)
4214a9ca1c79SSean Bruno {
4215a9ca1c79SSean Bruno 	struct adapter *adapter = (struct adapter *)arg1;
4216a9ca1c79SSean Bruno 	device_t       dev = adapter->dev;
4217a9ca1c79SSean Bruno 	int            curr_ps, new_ps, error = 0;
4218a9ca1c79SSean Bruno 
4219a9ca1c79SSean Bruno 	curr_ps = new_ps = pci_get_powerstate(dev);
4220a9ca1c79SSean Bruno 
4221a9ca1c79SSean Bruno 	error = sysctl_handle_int(oidp, &new_ps, 0, req);
4222a9ca1c79SSean Bruno 	if ((error) || (req->newptr == NULL))
4223a9ca1c79SSean Bruno 		return (error);
4224a9ca1c79SSean Bruno 
4225a9ca1c79SSean Bruno 	if (new_ps == curr_ps)
4226a9ca1c79SSean Bruno 		return (0);
4227a9ca1c79SSean Bruno 
4228a9ca1c79SSean Bruno 	if (new_ps == 3 && curr_ps == 0)
4229a9ca1c79SSean Bruno 		error = DEVICE_SUSPEND(dev);
4230a9ca1c79SSean Bruno 	else if (new_ps == 0 && curr_ps == 3)
4231a9ca1c79SSean Bruno 		error = DEVICE_RESUME(dev);
4232a9ca1c79SSean Bruno 	else
4233a9ca1c79SSean Bruno 		return (EINVAL);
4234a9ca1c79SSean Bruno 
4235a9ca1c79SSean Bruno 	device_printf(dev, "New state: %d\n", pci_get_powerstate(dev));
4236a9ca1c79SSean Bruno 
4237a9ca1c79SSean Bruno 	return (error);
42388eb6488eSEric Joyner } /* ixgbe_sysctl_power_state */
4239a9ca1c79SSean Bruno #endif
42408eb6488eSEric Joyner 
42418eb6488eSEric Joyner /************************************************************************
42428eb6488eSEric Joyner  * ixgbe_sysctl_wol_enable
42438eb6488eSEric Joyner  *
42448eb6488eSEric Joyner  *   Sysctl to enable/disable the WoL capability,
42458eb6488eSEric Joyner  *   if supported by the adapter.
42468eb6488eSEric Joyner  *
42476f37f232SEric Joyner  *   Values:
42486f37f232SEric Joyner  *     0 - disabled
42496f37f232SEric Joyner  *     1 - enabled
42508eb6488eSEric Joyner  ************************************************************************/
42516f37f232SEric Joyner static int
42526f37f232SEric Joyner ixgbe_sysctl_wol_enable(SYSCTL_HANDLER_ARGS)
42536f37f232SEric Joyner {
42546f37f232SEric Joyner 	struct adapter  *adapter = (struct adapter *)arg1;
42556f37f232SEric Joyner 	struct ixgbe_hw *hw = &adapter->hw;
42566f37f232SEric Joyner 	int             new_wol_enabled;
42576f37f232SEric Joyner 	int             error = 0;
42586f37f232SEric Joyner 
42596f37f232SEric Joyner 	new_wol_enabled = hw->wol_enabled;
42606f37f232SEric Joyner 	error = sysctl_handle_int(oidp, &new_wol_enabled, 0, req);
42616f37f232SEric Joyner 	if ((error) || (req->newptr == NULL))
42626f37f232SEric Joyner 		return (error);
4263a9ca1c79SSean Bruno 	new_wol_enabled = !!(new_wol_enabled);
42646f37f232SEric Joyner 	if (new_wol_enabled == hw->wol_enabled)
42656f37f232SEric Joyner 		return (0);
42666f37f232SEric Joyner 
42676f37f232SEric Joyner 	if (new_wol_enabled > 0 && !adapter->wol_support)
42686f37f232SEric Joyner 		return (ENODEV);
42696f37f232SEric Joyner 	else
4270a9ca1c79SSean Bruno 		hw->wol_enabled = new_wol_enabled;
42716f37f232SEric Joyner 
42726f37f232SEric Joyner 	return (0);
42738eb6488eSEric Joyner } /* ixgbe_sysctl_wol_enable */
42746f37f232SEric Joyner 
42758eb6488eSEric Joyner /************************************************************************
42768eb6488eSEric Joyner  * ixgbe_sysctl_wufc - Wake Up Filter Control
42778eb6488eSEric Joyner  *
42786f37f232SEric Joyner  *   Sysctl to enable/disable the types of packets that the
42796f37f232SEric Joyner  *   adapter will wake up on upon receipt.
42806f37f232SEric Joyner  *   Flags:
42816f37f232SEric Joyner  *     0x1  - Link Status Change
42826f37f232SEric Joyner  *     0x2  - Magic Packet
42836f37f232SEric Joyner  *     0x4  - Direct Exact
42846f37f232SEric Joyner  *     0x8  - Directed Multicast
42856f37f232SEric Joyner  *     0x10 - Broadcast
42866f37f232SEric Joyner  *     0x20 - ARP/IPv4 Request Packet
42876f37f232SEric Joyner  *     0x40 - Direct IPv4 Packet
42886f37f232SEric Joyner  *     0x80 - Direct IPv6 Packet
42896f37f232SEric Joyner  *
42908eb6488eSEric Joyner  *   Settings not listed above will cause the sysctl to return an error.
42918eb6488eSEric Joyner  ************************************************************************/
42926f37f232SEric Joyner static int
42936f37f232SEric Joyner ixgbe_sysctl_wufc(SYSCTL_HANDLER_ARGS)
42946f37f232SEric Joyner {
42956f37f232SEric Joyner 	struct adapter *adapter = (struct adapter *)arg1;
42966f37f232SEric Joyner 	int            error = 0;
42976f37f232SEric Joyner 	u32            new_wufc;
42986f37f232SEric Joyner 
42996f37f232SEric Joyner 	new_wufc = adapter->wufc;
43006f37f232SEric Joyner 
4301c19c7afeSEric Joyner 	error = sysctl_handle_32(oidp, &new_wufc, 0, req);
43026f37f232SEric Joyner 	if ((error) || (req->newptr == NULL))
43036f37f232SEric Joyner 		return (error);
43046f37f232SEric Joyner 	if (new_wufc == adapter->wufc)
43056f37f232SEric Joyner 		return (0);
43066f37f232SEric Joyner 
43076f37f232SEric Joyner 	if (new_wufc & 0xffffff00)
43086f37f232SEric Joyner 		return (EINVAL);
43098eb6488eSEric Joyner 
43106f37f232SEric Joyner 	new_wufc &= 0xff;
43116f37f232SEric Joyner 	new_wufc |= (0xffffff & adapter->wufc);
43126f37f232SEric Joyner 	adapter->wufc = new_wufc;
43136f37f232SEric Joyner 
43146f37f232SEric Joyner 	return (0);
43158eb6488eSEric Joyner } /* ixgbe_sysctl_wufc */
43166f37f232SEric Joyner 
4317a9ca1c79SSean Bruno #ifdef IXGBE_DEBUG
43188eb6488eSEric Joyner /************************************************************************
43198eb6488eSEric Joyner  * ixgbe_sysctl_print_rss_config
43208eb6488eSEric Joyner  ************************************************************************/
4321a9ca1c79SSean Bruno static int
4322a9ca1c79SSean Bruno ixgbe_sysctl_print_rss_config(SYSCTL_HANDLER_ARGS)
4323a9ca1c79SSean Bruno {
4324a9ca1c79SSean Bruno 	struct adapter  *adapter = (struct adapter *)arg1;
4325a9ca1c79SSean Bruno 	struct ixgbe_hw *hw = &adapter->hw;
4326a9ca1c79SSean Bruno 	device_t        dev = adapter->dev;
4327a9ca1c79SSean Bruno 	struct sbuf     *buf;
43288eb6488eSEric Joyner 	int             error = 0, reta_size;
4329a9ca1c79SSean Bruno 	u32             reg;
4330a9ca1c79SSean Bruno 
4331a9ca1c79SSean Bruno 	buf = sbuf_new_for_sysctl(NULL, NULL, 128, req);
4332a9ca1c79SSean Bruno 	if (!buf) {
4333a9ca1c79SSean Bruno 		device_printf(dev, "Could not allocate sbuf for output.\n");
4334a9ca1c79SSean Bruno 		return (ENOMEM);
4335a9ca1c79SSean Bruno 	}
4336a9ca1c79SSean Bruno 
4337a9ca1c79SSean Bruno 	// TODO: use sbufs to make a string to print out
4338a9ca1c79SSean Bruno 	/* Set multiplier for RETA setup and table size based on MAC */
4339a9ca1c79SSean Bruno 	switch (adapter->hw.mac.type) {
4340a9ca1c79SSean Bruno 	case ixgbe_mac_X550:
4341a9ca1c79SSean Bruno 	case ixgbe_mac_X550EM_x:
43428eb6488eSEric Joyner 	case ixgbe_mac_X550EM_a:
4343a9ca1c79SSean Bruno 		reta_size = 128;
4344a9ca1c79SSean Bruno 		break;
4345a9ca1c79SSean Bruno 	default:
4346a9ca1c79SSean Bruno 		reta_size = 32;
4347a9ca1c79SSean Bruno 		break;
4348a9ca1c79SSean Bruno 	}
4349a9ca1c79SSean Bruno 
4350a9ca1c79SSean Bruno 	/* Print out the redirection table */
4351a9ca1c79SSean Bruno 	sbuf_cat(buf, "\n");
4352a9ca1c79SSean Bruno 	for (int i = 0; i < reta_size; i++) {
4353a9ca1c79SSean Bruno 		if (i < 32) {
4354a9ca1c79SSean Bruno 			reg = IXGBE_READ_REG(hw, IXGBE_RETA(i));
4355a9ca1c79SSean Bruno 			sbuf_printf(buf, "RETA(%2d): 0x%08x\n", i, reg);
4356a9ca1c79SSean Bruno 		} else {
4357a9ca1c79SSean Bruno 			reg = IXGBE_READ_REG(hw, IXGBE_ERETA(i - 32));
4358a9ca1c79SSean Bruno 			sbuf_printf(buf, "ERETA(%2d): 0x%08x\n", i - 32, reg);
4359a9ca1c79SSean Bruno 		}
4360a9ca1c79SSean Bruno 	}
4361a9ca1c79SSean Bruno 
4362a9ca1c79SSean Bruno 	// TODO: print more config
4363a9ca1c79SSean Bruno 
4364a9ca1c79SSean Bruno 	error = sbuf_finish(buf);
4365a9ca1c79SSean Bruno 	if (error)
4366a9ca1c79SSean Bruno 		device_printf(dev, "Error finishing sbuf: %d\n", error);
4367a9ca1c79SSean Bruno 
4368a9ca1c79SSean Bruno 	sbuf_delete(buf);
43698eb6488eSEric Joyner 
4370a9ca1c79SSean Bruno 	return (0);
43718eb6488eSEric Joyner } /* ixgbe_sysctl_print_rss_config */
4372a9ca1c79SSean Bruno #endif /* IXGBE_DEBUG */
4373a9ca1c79SSean Bruno 
43748eb6488eSEric Joyner /************************************************************************
43758eb6488eSEric Joyner  * ixgbe_sysctl_phy_temp - Retrieve temperature of PHY
43768eb6488eSEric Joyner  *
43778eb6488eSEric Joyner  *   For X552/X557-AT devices using an external PHY
43788eb6488eSEric Joyner  ************************************************************************/
43798eb6488eSEric Joyner static int
43808eb6488eSEric Joyner ixgbe_sysctl_phy_temp(SYSCTL_HANDLER_ARGS)
43818eb6488eSEric Joyner {
43828eb6488eSEric Joyner 	struct adapter  *adapter = (struct adapter *)arg1;
43838eb6488eSEric Joyner 	struct ixgbe_hw *hw = &adapter->hw;
43848eb6488eSEric Joyner 	u16             reg;
43858eb6488eSEric Joyner 
43868eb6488eSEric Joyner 	if (hw->device_id != IXGBE_DEV_ID_X550EM_X_10G_T) {
4387c19c7afeSEric Joyner 		device_printf(iflib_get_dev(adapter->ctx),
43888eb6488eSEric Joyner 		    "Device has no supported external thermal sensor.\n");
43898eb6488eSEric Joyner 		return (ENODEV);
43908eb6488eSEric Joyner 	}
43918eb6488eSEric Joyner 
43928eb6488eSEric Joyner 	if (hw->phy.ops.read_reg(hw, IXGBE_PHY_CURRENT_TEMP,
43938eb6488eSEric Joyner 	    IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE, &reg)) {
4394c19c7afeSEric Joyner 		device_printf(iflib_get_dev(adapter->ctx),
43958eb6488eSEric Joyner 		    "Error reading from PHY's current temperature register\n");
43968eb6488eSEric Joyner 		return (EAGAIN);
43978eb6488eSEric Joyner 	}
43988eb6488eSEric Joyner 
43998eb6488eSEric Joyner 	/* Shift temp for output */
44008eb6488eSEric Joyner 	reg = reg >> 8;
44018eb6488eSEric Joyner 
4402c19c7afeSEric Joyner 	return (sysctl_handle_16(oidp, NULL, reg, req));
44038eb6488eSEric Joyner } /* ixgbe_sysctl_phy_temp */
44048eb6488eSEric Joyner 
44058eb6488eSEric Joyner /************************************************************************
44068eb6488eSEric Joyner  * ixgbe_sysctl_phy_overtemp_occurred
44078eb6488eSEric Joyner  *
44088eb6488eSEric Joyner  *   Reports (directly from the PHY) whether the current PHY
44098eb6488eSEric Joyner  *   temperature is over the overtemp threshold.
44108eb6488eSEric Joyner  ************************************************************************/
44118eb6488eSEric Joyner static int
44128eb6488eSEric Joyner ixgbe_sysctl_phy_overtemp_occurred(SYSCTL_HANDLER_ARGS)
44138eb6488eSEric Joyner {
44148eb6488eSEric Joyner 	struct adapter  *adapter = (struct adapter *)arg1;
44158eb6488eSEric Joyner 	struct ixgbe_hw *hw = &adapter->hw;
44168eb6488eSEric Joyner 	u16             reg;
44178eb6488eSEric Joyner 
44188eb6488eSEric Joyner 	if (hw->device_id != IXGBE_DEV_ID_X550EM_X_10G_T) {
4419c19c7afeSEric Joyner 		device_printf(iflib_get_dev(adapter->ctx),
44208eb6488eSEric Joyner 		    "Device has no supported external thermal sensor.\n");
44218eb6488eSEric Joyner 		return (ENODEV);
44228eb6488eSEric Joyner 	}
44238eb6488eSEric Joyner 
44248eb6488eSEric Joyner 	if (hw->phy.ops.read_reg(hw, IXGBE_PHY_OVERTEMP_STATUS,
44258eb6488eSEric Joyner 	    IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE, &reg)) {
4426c19c7afeSEric Joyner 		device_printf(iflib_get_dev(adapter->ctx),
44278eb6488eSEric Joyner 		    "Error reading from PHY's temperature status register\n");
44288eb6488eSEric Joyner 		return (EAGAIN);
44298eb6488eSEric Joyner 	}
44308eb6488eSEric Joyner 
44318eb6488eSEric Joyner 	/* Get occurrence bit */
44328eb6488eSEric Joyner 	reg = !!(reg & 0x4000);
44338eb6488eSEric Joyner 
4434c19c7afeSEric Joyner 	return (sysctl_handle_16(oidp, 0, reg, req));
44358eb6488eSEric Joyner } /* ixgbe_sysctl_phy_overtemp_occurred */
44368eb6488eSEric Joyner 
44378eb6488eSEric Joyner /************************************************************************
44388eb6488eSEric Joyner  * ixgbe_sysctl_eee_state
44398eb6488eSEric Joyner  *
44408eb6488eSEric Joyner  *   Sysctl to set EEE power saving feature
44418eb6488eSEric Joyner  *   Values:
44428eb6488eSEric Joyner  *     0      - disable EEE
44438eb6488eSEric Joyner  *     1      - enable EEE
44448eb6488eSEric Joyner  *     (none) - get current device EEE state
44458eb6488eSEric Joyner  ************************************************************************/
44468eb6488eSEric Joyner static int
44478eb6488eSEric Joyner ixgbe_sysctl_eee_state(SYSCTL_HANDLER_ARGS)
44488eb6488eSEric Joyner {
44498eb6488eSEric Joyner 	struct adapter *adapter = (struct adapter *)arg1;
44508eb6488eSEric Joyner 	device_t       dev = adapter->dev;
4451c19c7afeSEric Joyner 	struct ifnet   *ifp = iflib_get_ifp(adapter->ctx);
44528eb6488eSEric Joyner 	int            curr_eee, new_eee, error = 0;
44538eb6488eSEric Joyner 	s32            retval;
44548eb6488eSEric Joyner 
44558eb6488eSEric Joyner 	curr_eee = new_eee = !!(adapter->feat_en & IXGBE_FEATURE_EEE);
44568eb6488eSEric Joyner 
44578eb6488eSEric Joyner 	error = sysctl_handle_int(oidp, &new_eee, 0, req);
44588eb6488eSEric Joyner 	if ((error) || (req->newptr == NULL))
44598eb6488eSEric Joyner 		return (error);
44608eb6488eSEric Joyner 
44618eb6488eSEric Joyner 	/* Nothing to do */
44628eb6488eSEric Joyner 	if (new_eee == curr_eee)
44638eb6488eSEric Joyner 		return (0);
44648eb6488eSEric Joyner 
44658eb6488eSEric Joyner 	/* Not supported */
44668eb6488eSEric Joyner 	if (!(adapter->feat_cap & IXGBE_FEATURE_EEE))
44678eb6488eSEric Joyner 		return (EINVAL);
44688eb6488eSEric Joyner 
44698eb6488eSEric Joyner 	/* Bounds checking */
44708eb6488eSEric Joyner 	if ((new_eee < 0) || (new_eee > 1))
44718eb6488eSEric Joyner 		return (EINVAL);
44728eb6488eSEric Joyner 
4473d61b6a41SEric Joyner 	retval = ixgbe_setup_eee(&adapter->hw, new_eee);
44748eb6488eSEric Joyner 	if (retval) {
44758eb6488eSEric Joyner 		device_printf(dev, "Error in EEE setup: 0x%08X\n", retval);
44768eb6488eSEric Joyner 		return (EINVAL);
44778eb6488eSEric Joyner 	}
44788eb6488eSEric Joyner 
44798eb6488eSEric Joyner 	/* Restart auto-neg */
4480c19c7afeSEric Joyner 	ifp->if_init(ifp);
44818eb6488eSEric Joyner 
44828eb6488eSEric Joyner 	device_printf(dev, "New EEE state: %d\n", new_eee);
44838eb6488eSEric Joyner 
44848eb6488eSEric Joyner 	/* Cache new value */
44858eb6488eSEric Joyner 	if (new_eee)
44868eb6488eSEric Joyner 		adapter->feat_en |= IXGBE_FEATURE_EEE;
44878eb6488eSEric Joyner 	else
44888eb6488eSEric Joyner 		adapter->feat_en &= ~IXGBE_FEATURE_EEE;
44898eb6488eSEric Joyner 
44908eb6488eSEric Joyner 	return (error);
44918eb6488eSEric Joyner } /* ixgbe_sysctl_eee_state */
44928eb6488eSEric Joyner 
44938eb6488eSEric Joyner /************************************************************************
44948eb6488eSEric Joyner  * ixgbe_init_device_features
44958eb6488eSEric Joyner  ************************************************************************/
44968eb6488eSEric Joyner static void
44978eb6488eSEric Joyner ixgbe_init_device_features(struct adapter *adapter)
44988eb6488eSEric Joyner {
44998eb6488eSEric Joyner 	adapter->feat_cap = IXGBE_FEATURE_NETMAP
45008eb6488eSEric Joyner 	                  | IXGBE_FEATURE_RSS
45018eb6488eSEric Joyner 	                  | IXGBE_FEATURE_MSI
45028eb6488eSEric Joyner 	                  | IXGBE_FEATURE_MSIX
4503c19c7afeSEric Joyner 	                  | IXGBE_FEATURE_LEGACY_IRQ;
45048eb6488eSEric Joyner 
45058eb6488eSEric Joyner 	/* Set capabilities first... */
45068eb6488eSEric Joyner 	switch (adapter->hw.mac.type) {
45078eb6488eSEric Joyner 	case ixgbe_mac_82598EB:
45088eb6488eSEric Joyner 		if (adapter->hw.device_id == IXGBE_DEV_ID_82598AT)
45098eb6488eSEric Joyner 			adapter->feat_cap |= IXGBE_FEATURE_FAN_FAIL;
45108eb6488eSEric Joyner 		break;
45118eb6488eSEric Joyner 	case ixgbe_mac_X540:
45128eb6488eSEric Joyner 		adapter->feat_cap |= IXGBE_FEATURE_SRIOV;
45138eb6488eSEric Joyner 		adapter->feat_cap |= IXGBE_FEATURE_FDIR;
45148eb6488eSEric Joyner 		if ((adapter->hw.device_id == IXGBE_DEV_ID_X540_BYPASS) &&
45158eb6488eSEric Joyner 		    (adapter->hw.bus.func == 0))
45168eb6488eSEric Joyner 			adapter->feat_cap |= IXGBE_FEATURE_BYPASS;
45178eb6488eSEric Joyner 		break;
45188eb6488eSEric Joyner 	case ixgbe_mac_X550:
45198eb6488eSEric Joyner 		adapter->feat_cap |= IXGBE_FEATURE_TEMP_SENSOR;
45208eb6488eSEric Joyner 		adapter->feat_cap |= IXGBE_FEATURE_SRIOV;
45218eb6488eSEric Joyner 		adapter->feat_cap |= IXGBE_FEATURE_FDIR;
45228eb6488eSEric Joyner 		break;
45238eb6488eSEric Joyner 	case ixgbe_mac_X550EM_x:
45248eb6488eSEric Joyner 		adapter->feat_cap |= IXGBE_FEATURE_SRIOV;
45258eb6488eSEric Joyner 		adapter->feat_cap |= IXGBE_FEATURE_FDIR;
45268eb6488eSEric Joyner 		break;
45278eb6488eSEric Joyner 	case ixgbe_mac_X550EM_a:
45288eb6488eSEric Joyner 		adapter->feat_cap |= IXGBE_FEATURE_SRIOV;
45298eb6488eSEric Joyner 		adapter->feat_cap |= IXGBE_FEATURE_FDIR;
45308eb6488eSEric Joyner 		adapter->feat_cap &= ~IXGBE_FEATURE_LEGACY_IRQ;
45318eb6488eSEric Joyner 		if ((adapter->hw.device_id == IXGBE_DEV_ID_X550EM_A_1G_T) ||
45328eb6488eSEric Joyner 		    (adapter->hw.device_id == IXGBE_DEV_ID_X550EM_A_1G_T_L)) {
45338eb6488eSEric Joyner 			adapter->feat_cap |= IXGBE_FEATURE_TEMP_SENSOR;
45348eb6488eSEric Joyner 			adapter->feat_cap |= IXGBE_FEATURE_EEE;
45358eb6488eSEric Joyner 		}
45368eb6488eSEric Joyner 		break;
45378eb6488eSEric Joyner 	case ixgbe_mac_82599EB:
45388eb6488eSEric Joyner 		adapter->feat_cap |= IXGBE_FEATURE_SRIOV;
45398eb6488eSEric Joyner 		adapter->feat_cap |= IXGBE_FEATURE_FDIR;
45408eb6488eSEric Joyner 		if ((adapter->hw.device_id == IXGBE_DEV_ID_82599_BYPASS) &&
45418eb6488eSEric Joyner 		    (adapter->hw.bus.func == 0))
45428eb6488eSEric Joyner 			adapter->feat_cap |= IXGBE_FEATURE_BYPASS;
45438eb6488eSEric Joyner 		if (adapter->hw.device_id == IXGBE_DEV_ID_82599_QSFP_SF_QP)
45448eb6488eSEric Joyner 			adapter->feat_cap &= ~IXGBE_FEATURE_LEGACY_IRQ;
45458eb6488eSEric Joyner 		break;
45468eb6488eSEric Joyner 	default:
45478eb6488eSEric Joyner 		break;
45488eb6488eSEric Joyner 	}
45498eb6488eSEric Joyner 
45508eb6488eSEric Joyner 	/* Enabled by default... */
45518eb6488eSEric Joyner 	/* Fan failure detection */
45528eb6488eSEric Joyner 	if (adapter->feat_cap & IXGBE_FEATURE_FAN_FAIL)
45538eb6488eSEric Joyner 		adapter->feat_en |= IXGBE_FEATURE_FAN_FAIL;
45548eb6488eSEric Joyner 	/* Netmap */
45558eb6488eSEric Joyner 	if (adapter->feat_cap & IXGBE_FEATURE_NETMAP)
45568eb6488eSEric Joyner 		adapter->feat_en |= IXGBE_FEATURE_NETMAP;
45578eb6488eSEric Joyner 	/* EEE */
45588eb6488eSEric Joyner 	if (adapter->feat_cap & IXGBE_FEATURE_EEE)
45598eb6488eSEric Joyner 		adapter->feat_en |= IXGBE_FEATURE_EEE;
45608eb6488eSEric Joyner 	/* Thermal Sensor */
45618eb6488eSEric Joyner 	if (adapter->feat_cap & IXGBE_FEATURE_TEMP_SENSOR)
45628eb6488eSEric Joyner 		adapter->feat_en |= IXGBE_FEATURE_TEMP_SENSOR;
45638eb6488eSEric Joyner 
45648eb6488eSEric Joyner 	/* Enabled via global sysctl... */
45658eb6488eSEric Joyner 	/* Flow Director */
45668eb6488eSEric Joyner 	if (ixgbe_enable_fdir) {
45678eb6488eSEric Joyner 		if (adapter->feat_cap & IXGBE_FEATURE_FDIR)
45688eb6488eSEric Joyner 			adapter->feat_en |= IXGBE_FEATURE_FDIR;
45698eb6488eSEric Joyner 		else
45708eb6488eSEric Joyner 			device_printf(adapter->dev, "Device does not support Flow Director. Leaving disabled.");
45718eb6488eSEric Joyner 	}
45726f37f232SEric Joyner 	/*
45738eb6488eSEric Joyner 	 * Message Signal Interrupts - Extended (MSI-X)
45748eb6488eSEric Joyner 	 * Normal MSI is only enabled if MSI-X calls fail.
4575758cc3dcSJack F Vogel 	 */
45768eb6488eSEric Joyner 	if (!ixgbe_enable_msix)
45778eb6488eSEric Joyner 		adapter->feat_cap &= ~IXGBE_FEATURE_MSIX;
45788eb6488eSEric Joyner 	/* Receive-Side Scaling (RSS) */
45798eb6488eSEric Joyner 	if ((adapter->feat_cap & IXGBE_FEATURE_RSS) && ixgbe_enable_rss)
45808eb6488eSEric Joyner 		adapter->feat_en |= IXGBE_FEATURE_RSS;
45818eb6488eSEric Joyner 
45828eb6488eSEric Joyner 	/* Disable features with unmet dependencies... */
45838eb6488eSEric Joyner 	/* No MSI-X */
45848eb6488eSEric Joyner 	if (!(adapter->feat_cap & IXGBE_FEATURE_MSIX)) {
45858eb6488eSEric Joyner 		adapter->feat_cap &= ~IXGBE_FEATURE_RSS;
45868eb6488eSEric Joyner 		adapter->feat_cap &= ~IXGBE_FEATURE_SRIOV;
45878eb6488eSEric Joyner 		adapter->feat_en &= ~IXGBE_FEATURE_RSS;
45888eb6488eSEric Joyner 		adapter->feat_en &= ~IXGBE_FEATURE_SRIOV;
45898eb6488eSEric Joyner 	}
45908eb6488eSEric Joyner } /* ixgbe_init_device_features */
45918eb6488eSEric Joyner 
45928eb6488eSEric Joyner /************************************************************************
45938eb6488eSEric Joyner  * ixgbe_check_fan_failure
45948eb6488eSEric Joyner  ************************************************************************/
45958eb6488eSEric Joyner static void
45968eb6488eSEric Joyner ixgbe_check_fan_failure(struct adapter *adapter, u32 reg, bool in_interrupt)
45978eb6488eSEric Joyner {
45988eb6488eSEric Joyner 	u32 mask;
45998eb6488eSEric Joyner 
46008eb6488eSEric Joyner 	mask = (in_interrupt) ? IXGBE_EICR_GPI_SDP1_BY_MAC(&adapter->hw) :
46018eb6488eSEric Joyner 	    IXGBE_ESDP_SDP1;
46028eb6488eSEric Joyner 
46038eb6488eSEric Joyner 	if (reg & mask)
46048eb6488eSEric Joyner 		device_printf(adapter->dev, "\nCRITICAL: FAN FAILURE!! REPLACE IMMEDIATELY!!\n");
46058eb6488eSEric Joyner } /* ixgbe_check_fan_failure */
4606