1280182Sjfv/******************************************************************************
2280182Sjfv
3280182Sjfv  Copyright (c) 2001-2015, Intel Corporation
4280182Sjfv  All rights reserved.
5280182Sjfv
6280182Sjfv  Redistribution and use in source and binary forms, with or without
7280182Sjfv  modification, are permitted provided that the following conditions are met:
8280182Sjfv
9280182Sjfv   1. Redistributions of source code must retain the above copyright notice,
10280182Sjfv      this list of conditions and the following disclaimer.
11280182Sjfv
12280182Sjfv   2. Redistributions in binary form must reproduce the above copyright
13280182Sjfv      notice, this list of conditions and the following disclaimer in the
14280182Sjfv      documentation and/or other materials provided with the distribution.
15280182Sjfv
16280182Sjfv   3. Neither the name of the Intel Corporation nor the names of its
17280182Sjfv      contributors may be used to endorse or promote products derived from
18280182Sjfv      this software without specific prior written permission.
19280182Sjfv
20280182Sjfv  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21280182Sjfv  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22280182Sjfv  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23280182Sjfv  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
24280182Sjfv  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25280182Sjfv  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26280182Sjfv  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27280182Sjfv  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28280182Sjfv  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29280182Sjfv  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30280182Sjfv  POSSIBILITY OF SUCH DAMAGE.
31280182Sjfv
32280182Sjfv******************************************************************************/
33280182Sjfv/*$FreeBSD: releng/11.0/sys/dev/ixgbe/if_ix.c 302384 2016-07-07 03:39:18Z sbruno $*/
34280182Sjfv
35280182Sjfv
36280182Sjfv#ifndef IXGBE_STANDALONE_BUILD
37280182Sjfv#include "opt_inet.h"
38280182Sjfv#include "opt_inet6.h"
39280182Sjfv#include "opt_rss.h"
40280182Sjfv#endif
41280182Sjfv
42280182Sjfv#include "ixgbe.h"
43280182Sjfv
44280182Sjfv#ifdef	RSS
45280204Sadrian#include <net/rss_config.h>
46280182Sjfv#include <netinet/in_rss.h>
47280182Sjfv#endif
48280182Sjfv
49280182Sjfv/*********************************************************************
50280182Sjfv *  Driver version
51280182Sjfv *********************************************************************/
52292674Ssbrunochar ixgbe_driver_version[] = "3.1.13-k";
53280182Sjfv
54292674Ssbruno
55280182Sjfv/*********************************************************************
56280182Sjfv *  PCI Device ID Table
57280182Sjfv *
58280182Sjfv *  Used by probe to select devices to load on
59280182Sjfv *  Last field stores an index into ixgbe_strings
60280182Sjfv *  Last entry must be all 0s
61280182Sjfv *
62280182Sjfv *  { Vendor ID, Device ID, SubVendor ID, SubDevice ID, String Index }
63280182Sjfv *********************************************************************/
64280182Sjfv
65280182Sjfvstatic ixgbe_vendor_info_t ixgbe_vendor_info_array[] =
66280182Sjfv{
67280182Sjfv	{IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82598AF_DUAL_PORT, 0, 0, 0},
68280182Sjfv	{IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82598AF_SINGLE_PORT, 0, 0, 0},
69280182Sjfv	{IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82598EB_CX4, 0, 0, 0},
70280182Sjfv	{IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82598AT, 0, 0, 0},
71280182Sjfv	{IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82598AT2, 0, 0, 0},
72280182Sjfv	{IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82598, 0, 0, 0},
73280182Sjfv	{IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82598_DA_DUAL_PORT, 0, 0, 0},
74280182Sjfv	{IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82598_CX4_DUAL_PORT, 0, 0, 0},
75280182Sjfv	{IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82598EB_XF_LR, 0, 0, 0},
76280182Sjfv	{IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82598_SR_DUAL_PORT_EM, 0, 0, 0},
77280182Sjfv	{IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82598EB_SFP_LOM, 0, 0, 0},
78280182Sjfv	{IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82599_KX4, 0, 0, 0},
79280182Sjfv	{IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82599_KX4_MEZZ, 0, 0, 0},
80280182Sjfv	{IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82599_SFP, 0, 0, 0},
81280182Sjfv	{IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82599_XAUI_LOM, 0, 0, 0},
82280182Sjfv	{IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82599_CX4, 0, 0, 0},
83280182Sjfv	{IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82599_T3_LOM, 0, 0, 0},
84280182Sjfv	{IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82599_COMBO_BACKPLANE, 0, 0, 0},
85280182Sjfv	{IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82599_BACKPLANE_FCOE, 0, 0, 0},
86280182Sjfv	{IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82599_SFP_SF2, 0, 0, 0},
87280182Sjfv	{IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82599_SFP_FCOE, 0, 0, 0},
88280182Sjfv	{IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82599EN_SFP, 0, 0, 0},
89280182Sjfv	{IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82599_SFP_SF_QP, 0, 0, 0},
90280182Sjfv	{IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82599_QSFP_SF_QP, 0, 0, 0},
91280182Sjfv	{IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X540T, 0, 0, 0},
92280182Sjfv	{IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X540T1, 0, 0, 0},
93280182Sjfv	{IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X550T, 0, 0, 0},
94292674Ssbruno	{IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X550T1, 0, 0, 0},
95280182Sjfv	{IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X550EM_X_KR, 0, 0, 0},
96280182Sjfv	{IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X550EM_X_KX4, 0, 0, 0},
97280182Sjfv	{IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X550EM_X_10G_T, 0, 0, 0},
98292674Ssbruno	{IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X550EM_X_SFP, 0, 0, 0},
99280182Sjfv	/* required last entry */
100280182Sjfv	{0, 0, 0, 0, 0}
101280182Sjfv};
102280182Sjfv
103280182Sjfv/*********************************************************************
104280182Sjfv *  Table of branding strings
105280182Sjfv *********************************************************************/
106280182Sjfv
107280182Sjfvstatic char    *ixgbe_strings[] = {
108280182Sjfv	"Intel(R) PRO/10GbE PCI-Express Network Driver"
109280182Sjfv};
110280182Sjfv
111280182Sjfv/*********************************************************************
112280182Sjfv *  Function prototypes
113280182Sjfv *********************************************************************/
114280182Sjfvstatic int      ixgbe_probe(device_t);
115280182Sjfvstatic int      ixgbe_attach(device_t);
116280182Sjfvstatic int      ixgbe_detach(device_t);
117280182Sjfvstatic int      ixgbe_shutdown(device_t);
118282289Serjstatic int	ixgbe_suspend(device_t);
119282289Serjstatic int	ixgbe_resume(device_t);
120280182Sjfvstatic int      ixgbe_ioctl(struct ifnet *, u_long, caddr_t);
121280182Sjfvstatic void	ixgbe_init(void *);
122280182Sjfvstatic void	ixgbe_init_locked(struct adapter *);
123280182Sjfvstatic void     ixgbe_stop(void *);
124280182Sjfv#if __FreeBSD_version >= 1100036
125280182Sjfvstatic uint64_t	ixgbe_get_counter(struct ifnet *, ift_counter);
126280182Sjfv#endif
127280182Sjfvstatic void	ixgbe_add_media_types(struct adapter *);
128280182Sjfvstatic void     ixgbe_media_status(struct ifnet *, struct ifmediareq *);
129280182Sjfvstatic int      ixgbe_media_change(struct ifnet *);
130280182Sjfvstatic void     ixgbe_identify_hardware(struct adapter *);
131280182Sjfvstatic int      ixgbe_allocate_pci_resources(struct adapter *);
132292674Ssbrunostatic void	ixgbe_get_slot_info(struct adapter *);
133280182Sjfvstatic int      ixgbe_allocate_msix(struct adapter *);
134280182Sjfvstatic int      ixgbe_allocate_legacy(struct adapter *);
135280182Sjfvstatic int	ixgbe_setup_msix(struct adapter *);
136280182Sjfvstatic void	ixgbe_free_pci_resources(struct adapter *);
137280182Sjfvstatic void	ixgbe_local_timer(void *);
138280182Sjfvstatic int	ixgbe_setup_interface(device_t, struct adapter *);
139283883Sjfvstatic void	ixgbe_config_gpie(struct adapter *);
140282289Serjstatic void	ixgbe_config_dmac(struct adapter *);
141282289Serjstatic void	ixgbe_config_delay_values(struct adapter *);
142280182Sjfvstatic void	ixgbe_config_link(struct adapter *);
143282289Serjstatic void	ixgbe_check_wol_support(struct adapter *);
144282289Serjstatic int	ixgbe_setup_low_power_mode(struct adapter *);
145280182Sjfvstatic void	ixgbe_rearm_queues(struct adapter *, u64);
146280182Sjfv
147280182Sjfvstatic void     ixgbe_initialize_transmit_units(struct adapter *);
148280182Sjfvstatic void     ixgbe_initialize_receive_units(struct adapter *);
149280182Sjfvstatic void	ixgbe_enable_rx_drop(struct adapter *);
150280182Sjfvstatic void	ixgbe_disable_rx_drop(struct adapter *);
151292674Ssbrunostatic void	ixgbe_initialize_rss_mapping(struct adapter *);
152280182Sjfv
153280182Sjfvstatic void     ixgbe_enable_intr(struct adapter *);
154280182Sjfvstatic void     ixgbe_disable_intr(struct adapter *);
155280182Sjfvstatic void     ixgbe_update_stats_counters(struct adapter *);
156280182Sjfvstatic void     ixgbe_set_promisc(struct adapter *);
157280182Sjfvstatic void     ixgbe_set_multi(struct adapter *);
158280182Sjfvstatic void     ixgbe_update_link_status(struct adapter *);
159280182Sjfvstatic void	ixgbe_set_ivar(struct adapter *, u8, u8, s8);
160280182Sjfvstatic void	ixgbe_configure_ivars(struct adapter *);
161280182Sjfvstatic u8 *	ixgbe_mc_array_itr(struct ixgbe_hw *, u8 **, u32 *);
162280182Sjfv
163280182Sjfvstatic void	ixgbe_setup_vlan_hw_support(struct adapter *);
164280182Sjfvstatic void	ixgbe_register_vlan(void *, struct ifnet *, u16);
165280182Sjfvstatic void	ixgbe_unregister_vlan(void *, struct ifnet *, u16);
166280182Sjfv
167282289Serjstatic void	ixgbe_add_device_sysctls(struct adapter *);
168282289Serjstatic void     ixgbe_add_hw_stats(struct adapter *);
169294795Ssmhstatic int	ixgbe_set_flowcntl(struct adapter *, int);
170294795Ssmhstatic int	ixgbe_set_advertise(struct adapter *, int);
171280182Sjfv
172282289Serj/* Sysctl handlers */
173289238Ssbrunostatic void	ixgbe_set_sysctl_value(struct adapter *, const char *,
174292674Ssbruno		     const char *, int *, int);
175294795Ssmhstatic int	ixgbe_sysctl_flowcntl(SYSCTL_HANDLER_ARGS);
176294795Ssmhstatic int	ixgbe_sysctl_advertise(SYSCTL_HANDLER_ARGS);
177282289Serjstatic int	ixgbe_sysctl_thermal_test(SYSCTL_HANDLER_ARGS);
178282289Serjstatic int	ixgbe_sysctl_dmac(SYSCTL_HANDLER_ARGS);
179282289Serjstatic int	ixgbe_sysctl_phy_temp(SYSCTL_HANDLER_ARGS);
180282289Serjstatic int	ixgbe_sysctl_phy_overtemp_occurred(SYSCTL_HANDLER_ARGS);
181292674Ssbruno#ifdef IXGBE_DEBUG
182292674Ssbrunostatic int	ixgbe_sysctl_power_state(SYSCTL_HANDLER_ARGS);
183292674Ssbrunostatic int	ixgbe_sysctl_print_rss_config(SYSCTL_HANDLER_ARGS);
184292674Ssbruno#endif
185282289Serjstatic int	ixgbe_sysctl_wol_enable(SYSCTL_HANDLER_ARGS);
186282289Serjstatic int	ixgbe_sysctl_wufc(SYSCTL_HANDLER_ARGS);
187282289Serjstatic int	ixgbe_sysctl_eee_enable(SYSCTL_HANDLER_ARGS);
188282289Serjstatic int	ixgbe_sysctl_eee_negotiated(SYSCTL_HANDLER_ARGS);
189282289Serjstatic int	ixgbe_sysctl_eee_rx_lpi_status(SYSCTL_HANDLER_ARGS);
190282289Serjstatic int	ixgbe_sysctl_eee_tx_lpi_status(SYSCTL_HANDLER_ARGS);
191292674Ssbrunostatic int	ixgbe_sysctl_eee_tx_lpi_delay(SYSCTL_HANDLER_ARGS);
192282289Serj
193280182Sjfv/* Support for pluggable optic modules */
194280182Sjfvstatic bool	ixgbe_sfp_probe(struct adapter *);
195280182Sjfvstatic void	ixgbe_setup_optics(struct adapter *);
196280182Sjfv
197280182Sjfv/* Legacy (single vector interrupt handler */
198280182Sjfvstatic void	ixgbe_legacy_irq(void *);
199280182Sjfv
200280182Sjfv/* The MSI/X Interrupt handlers */
201280182Sjfvstatic void	ixgbe_msix_que(void *);
202280182Sjfvstatic void	ixgbe_msix_link(void *);
203280182Sjfv
204280182Sjfv/* Deferred interrupt tasklets */
205280182Sjfvstatic void	ixgbe_handle_que(void *, int);
206280182Sjfvstatic void	ixgbe_handle_link(void *, int);
207280182Sjfvstatic void	ixgbe_handle_msf(void *, int);
208280182Sjfvstatic void	ixgbe_handle_mod(void *, int);
209282289Serjstatic void	ixgbe_handle_phy(void *, int);
210280182Sjfv
211280182Sjfv#ifdef IXGBE_FDIR
212280182Sjfvstatic void	ixgbe_reinit_fdir(void *, int);
213280182Sjfv#endif
214280182Sjfv
215283883Sjfv#ifdef PCI_IOV
216283883Sjfvstatic void	ixgbe_ping_all_vfs(struct adapter *);
217283883Sjfvstatic void	ixgbe_handle_mbx(void *, int);
218283883Sjfvstatic int	ixgbe_init_iov(device_t, u16, const nvlist_t *);
219283883Sjfvstatic void	ixgbe_uninit_iov(device_t);
220283883Sjfvstatic int	ixgbe_add_vf(device_t, u16, const nvlist_t *);
221283883Sjfvstatic void	ixgbe_initialize_iov(struct adapter *);
222283883Sjfvstatic void	ixgbe_recalculate_max_frame(struct adapter *);
223283883Sjfvstatic void	ixgbe_init_vf(struct adapter *, struct ixgbe_vf *);
224283883Sjfv#endif /* PCI_IOV */
225283883Sjfv
226283883Sjfv
227280182Sjfv/*********************************************************************
228280182Sjfv *  FreeBSD Device Interface Entry Points
229280182Sjfv *********************************************************************/
230280182Sjfv
231280204Sadrianstatic device_method_t ix_methods[] = {
232280182Sjfv	/* Device interface */
233280182Sjfv	DEVMETHOD(device_probe, ixgbe_probe),
234280182Sjfv	DEVMETHOD(device_attach, ixgbe_attach),
235280182Sjfv	DEVMETHOD(device_detach, ixgbe_detach),
236280182Sjfv	DEVMETHOD(device_shutdown, ixgbe_shutdown),
237282289Serj	DEVMETHOD(device_suspend, ixgbe_suspend),
238282289Serj	DEVMETHOD(device_resume, ixgbe_resume),
239283883Sjfv#ifdef PCI_IOV
240283893Sjhb	DEVMETHOD(pci_iov_init, ixgbe_init_iov),
241283893Sjhb	DEVMETHOD(pci_iov_uninit, ixgbe_uninit_iov),
242283893Sjhb	DEVMETHOD(pci_iov_add_vf, ixgbe_add_vf),
243283883Sjfv#endif /* PCI_IOV */
244280182Sjfv	DEVMETHOD_END
245280182Sjfv};
246280182Sjfv
247280204Sadrianstatic driver_t ix_driver = {
248280204Sadrian	"ix", ix_methods, sizeof(struct adapter),
249280182Sjfv};
250280182Sjfv
251280204Sadriandevclass_t ix_devclass;
252280204SadrianDRIVER_MODULE(ix, pci, ix_driver, ix_devclass, 0, 0);
253280182Sjfv
254280204SadrianMODULE_DEPEND(ix, pci, 1, 1, 1);
255280204SadrianMODULE_DEPEND(ix, ether, 1, 1, 1);
256285349Sluigi#ifdef DEV_NETMAP
257285349SluigiMODULE_DEPEND(ix, netmap, 1, 1, 1);
258285349Sluigi#endif /* DEV_NETMAP */
259280182Sjfv
260280182Sjfv/*
261280182Sjfv** TUNEABLE PARAMETERS:
262280182Sjfv*/
263280182Sjfv
264280182Sjfvstatic SYSCTL_NODE(_hw, OID_AUTO, ix, CTLFLAG_RD, 0,
265280182Sjfv		   "IXGBE driver parameters");
266280182Sjfv
267280182Sjfv/*
268280182Sjfv** AIM: Adaptive Interrupt Moderation
269280182Sjfv** which means that the interrupt rate
270280182Sjfv** is varied over time based on the
271280182Sjfv** traffic for that interrupt vector
272280182Sjfv*/
273280182Sjfvstatic int ixgbe_enable_aim = TRUE;
274280182SjfvSYSCTL_INT(_hw_ix, OID_AUTO, enable_aim, CTLFLAG_RWTUN, &ixgbe_enable_aim, 0,
275280182Sjfv    "Enable adaptive interrupt moderation");
276280182Sjfv
277280182Sjfvstatic int ixgbe_max_interrupt_rate = (4000000 / IXGBE_LOW_LATENCY);
278280182SjfvSYSCTL_INT(_hw_ix, OID_AUTO, max_interrupt_rate, CTLFLAG_RDTUN,
279280182Sjfv    &ixgbe_max_interrupt_rate, 0, "Maximum interrupts per second");
280280182Sjfv
281280182Sjfv/* How many packets rxeof tries to clean at a time */
282280182Sjfvstatic int ixgbe_rx_process_limit = 256;
283280182SjfvSYSCTL_INT(_hw_ix, OID_AUTO, rx_process_limit, CTLFLAG_RDTUN,
284280182Sjfv    &ixgbe_rx_process_limit, 0,
285280182Sjfv    "Maximum number of received packets to process at a time,"
286280182Sjfv    "-1 means unlimited");
287280182Sjfv
288280182Sjfv/* How many packets txeof tries to clean at a time */
289280182Sjfvstatic int ixgbe_tx_process_limit = 256;
290280182SjfvSYSCTL_INT(_hw_ix, OID_AUTO, tx_process_limit, CTLFLAG_RDTUN,
291280182Sjfv    &ixgbe_tx_process_limit, 0,
292280182Sjfv    "Maximum number of sent packets to process at a time,"
293280182Sjfv    "-1 means unlimited");
294280182Sjfv
295294795Ssmh/* Flow control setting, default to full */
296294795Ssmhstatic int ixgbe_flow_control = ixgbe_fc_full;
297294795SsmhSYSCTL_INT(_hw_ix, OID_AUTO, flow_control, CTLFLAG_RDTUN,
298294795Ssmh    &ixgbe_flow_control, 0, "Default flow control used for all adapters");
299294795Ssmh
300294795Ssmh/* Advertise Speed, default to 0 (auto) */
301294795Ssmhstatic int ixgbe_advertise_speed = 0;
302294795SsmhSYSCTL_INT(_hw_ix, OID_AUTO, advertise_speed, CTLFLAG_RDTUN,
303294795Ssmh    &ixgbe_advertise_speed, 0, "Default advertised speed for all adapters");
304294795Ssmh
305280182Sjfv/*
306280182Sjfv** Smart speed setting, default to on
307280182Sjfv** this only works as a compile option
308280182Sjfv** right now as its during attach, set
309280182Sjfv** this to 'ixgbe_smart_speed_off' to
310280182Sjfv** disable.
311280182Sjfv*/
312280182Sjfvstatic int ixgbe_smart_speed = ixgbe_smart_speed_on;
313280182Sjfv
314280182Sjfv/*
315280182Sjfv * MSIX should be the default for best performance,
316280182Sjfv * but this allows it to be forced off for testing.
317280182Sjfv */
318280182Sjfvstatic int ixgbe_enable_msix = 1;
319280182SjfvSYSCTL_INT(_hw_ix, OID_AUTO, enable_msix, CTLFLAG_RDTUN, &ixgbe_enable_msix, 0,
320280182Sjfv    "Enable MSI-X interrupts");
321280182Sjfv
322280182Sjfv/*
323280182Sjfv * Number of Queues, can be set to 0,
324280182Sjfv * it then autoconfigures based on the
325280182Sjfv * number of cpus with a max of 8. This
326280182Sjfv * can be overriden manually here.
327280182Sjfv */
328280182Sjfvstatic int ixgbe_num_queues = 0;
329280182SjfvSYSCTL_INT(_hw_ix, OID_AUTO, num_queues, CTLFLAG_RDTUN, &ixgbe_num_queues, 0,
330280182Sjfv    "Number of queues to configure, 0 indicates autoconfigure");
331280182Sjfv
332280182Sjfv/*
333280182Sjfv** Number of TX descriptors per ring,
334280182Sjfv** setting higher than RX as this seems
335280182Sjfv** the better performing choice.
336280182Sjfv*/
337280182Sjfvstatic int ixgbe_txd = PERFORM_TXD;
338280182SjfvSYSCTL_INT(_hw_ix, OID_AUTO, txd, CTLFLAG_RDTUN, &ixgbe_txd, 0,
339280182Sjfv    "Number of transmit descriptors per queue");
340280182Sjfv
341280182Sjfv/* Number of RX descriptors per ring */
342280182Sjfvstatic int ixgbe_rxd = PERFORM_RXD;
343280182SjfvSYSCTL_INT(_hw_ix, OID_AUTO, rxd, CTLFLAG_RDTUN, &ixgbe_rxd, 0,
344280182Sjfv    "Number of receive descriptors per queue");
345280182Sjfv
346280182Sjfv/*
347280182Sjfv** Defining this on will allow the use
348280182Sjfv** of unsupported SFP+ modules, note that
349280182Sjfv** doing so you are on your own :)
350280182Sjfv*/
351280182Sjfvstatic int allow_unsupported_sfp = FALSE;
352280182SjfvTUNABLE_INT("hw.ix.unsupported_sfp", &allow_unsupported_sfp);
353280182Sjfv
354280182Sjfv/* Keep running tab on them for sanity check */
355280182Sjfvstatic int ixgbe_total_ports;
356280182Sjfv
357280182Sjfv#ifdef IXGBE_FDIR
358280182Sjfv/*
359280182Sjfv** Flow Director actually 'steals'
360280182Sjfv** part of the packet buffer as its
361280182Sjfv** filter pool, this variable controls
362280182Sjfv** how much it uses:
363280182Sjfv**  0 = 64K, 1 = 128K, 2 = 256K
364280182Sjfv*/
365280182Sjfvstatic int fdir_pballoc = 1;
366280182Sjfv#endif
367280182Sjfv
368280182Sjfv#ifdef DEV_NETMAP
369280182Sjfv/*
370280182Sjfv * The #ifdef DEV_NETMAP / #endif blocks in this file are meant to
371280182Sjfv * be a reference on how to implement netmap support in a driver.
372280182Sjfv * Additional comments are in ixgbe_netmap.h .
373280182Sjfv *
374280182Sjfv * <dev/netmap/ixgbe_netmap.h> contains functions for netmap support
375280182Sjfv * that extend the standard driver.
376280182Sjfv */
377280182Sjfv#include <dev/netmap/ixgbe_netmap.h>
378280182Sjfv#endif /* DEV_NETMAP */
379280182Sjfv
380283883Sjfvstatic MALLOC_DEFINE(M_IXGBE, "ix", "ix driver allocations");
381283883Sjfv
382280182Sjfv/*********************************************************************
383280182Sjfv *  Device identification routine
384280182Sjfv *
385280182Sjfv *  ixgbe_probe determines if the driver should be loaded on
386280182Sjfv *  adapter based on PCI vendor/device id of the adapter.
387280182Sjfv *
388280182Sjfv *  return BUS_PROBE_DEFAULT on success, positive on failure
389280182Sjfv *********************************************************************/
390280182Sjfv
391280182Sjfvstatic int
392280182Sjfvixgbe_probe(device_t dev)
393280182Sjfv{
394280182Sjfv	ixgbe_vendor_info_t *ent;
395280182Sjfv
396280182Sjfv	u16	pci_vendor_id = 0;
397280182Sjfv	u16	pci_device_id = 0;
398280182Sjfv	u16	pci_subvendor_id = 0;
399280182Sjfv	u16	pci_subdevice_id = 0;
400280182Sjfv	char	adapter_name[256];
401280182Sjfv
402280182Sjfv	INIT_DEBUGOUT("ixgbe_probe: begin");
403280182Sjfv
404280182Sjfv	pci_vendor_id = pci_get_vendor(dev);
405280182Sjfv	if (pci_vendor_id != IXGBE_INTEL_VENDOR_ID)
406280182Sjfv		return (ENXIO);
407280182Sjfv
408280182Sjfv	pci_device_id = pci_get_device(dev);
409280182Sjfv	pci_subvendor_id = pci_get_subvendor(dev);
410280182Sjfv	pci_subdevice_id = pci_get_subdevice(dev);
411280182Sjfv
412280182Sjfv	ent = ixgbe_vendor_info_array;
413280182Sjfv	while (ent->vendor_id != 0) {
414280182Sjfv		if ((pci_vendor_id == ent->vendor_id) &&
415280182Sjfv		    (pci_device_id == ent->device_id) &&
416280182Sjfv
417280182Sjfv		    ((pci_subvendor_id == ent->subvendor_id) ||
418280182Sjfv		     (ent->subvendor_id == 0)) &&
419280182Sjfv
420280182Sjfv		    ((pci_subdevice_id == ent->subdevice_id) ||
421280182Sjfv		     (ent->subdevice_id == 0))) {
422280182Sjfv			sprintf(adapter_name, "%s, Version - %s",
423280182Sjfv				ixgbe_strings[ent->index],
424280182Sjfv				ixgbe_driver_version);
425280182Sjfv			device_set_desc_copy(dev, adapter_name);
426280182Sjfv			++ixgbe_total_ports;
427280182Sjfv			return (BUS_PROBE_DEFAULT);
428280182Sjfv		}
429280182Sjfv		ent++;
430280182Sjfv	}
431280182Sjfv	return (ENXIO);
432280182Sjfv}
433280182Sjfv
434280182Sjfv/*********************************************************************
435280182Sjfv *  Device initialization routine
436280182Sjfv *
437280182Sjfv *  The attach entry point is called when the driver is being loaded.
438280182Sjfv *  This routine identifies the type of hardware, allocates all resources
439280182Sjfv *  and initializes the hardware.
440280182Sjfv *
441280182Sjfv *  return 0 on success, positive on failure
442280182Sjfv *********************************************************************/
443280182Sjfv
444280182Sjfvstatic int
445280182Sjfvixgbe_attach(device_t dev)
446280182Sjfv{
447280182Sjfv	struct adapter *adapter;
448280182Sjfv	struct ixgbe_hw *hw;
449280182Sjfv	int             error = 0;
450280182Sjfv	u16		csum;
451280182Sjfv	u32		ctrl_ext;
452280182Sjfv
453280182Sjfv	INIT_DEBUGOUT("ixgbe_attach: begin");
454280182Sjfv
455280182Sjfv	/* Allocate, clear, and link in our adapter structure */
456280182Sjfv	adapter = device_get_softc(dev);
457292674Ssbruno	adapter->dev = dev;
458280182Sjfv	hw = &adapter->hw;
459280182Sjfv
460285592Spkelsey#ifdef DEV_NETMAP
461285592Spkelsey	adapter->init_locked = ixgbe_init_locked;
462285592Spkelsey	adapter->stop_locked = ixgbe_stop;
463285592Spkelsey#endif
464285592Spkelsey
465280182Sjfv	/* Core Lock Init*/
466280182Sjfv	IXGBE_CORE_LOCK_INIT(adapter, device_get_nameunit(dev));
467280182Sjfv
468280182Sjfv	/* Set up the timer callout */
469280182Sjfv	callout_init_mtx(&adapter->timer, &adapter->core_mtx, 0);
470280182Sjfv
471280182Sjfv	/* Determine hardware revision */
472280182Sjfv	ixgbe_identify_hardware(adapter);
473280182Sjfv
474280182Sjfv	/* Do base PCI setup - map BAR0 */
475280182Sjfv	if (ixgbe_allocate_pci_resources(adapter)) {
476280182Sjfv		device_printf(dev, "Allocation of PCI resources failed\n");
477280182Sjfv		error = ENXIO;
478280182Sjfv		goto err_out;
479280182Sjfv	}
480280182Sjfv
481289238Ssbruno	/* Sysctls for limiting the amount of work done in the taskqueues */
482289238Ssbruno	ixgbe_set_sysctl_value(adapter, "rx_processing_limit",
483289238Ssbruno	    "max number of rx packets to process",
484289238Ssbruno	    &adapter->rx_process_limit, ixgbe_rx_process_limit);
485289238Ssbruno
486289238Ssbruno	ixgbe_set_sysctl_value(adapter, "tx_processing_limit",
487289238Ssbruno	    "max number of tx packets to process",
488289238Ssbruno	&adapter->tx_process_limit, ixgbe_tx_process_limit);
489289238Ssbruno
490280182Sjfv	/* Do descriptor calc and sanity checks */
491280182Sjfv	if (((ixgbe_txd * sizeof(union ixgbe_adv_tx_desc)) % DBA_ALIGN) != 0 ||
492280182Sjfv	    ixgbe_txd < MIN_TXD || ixgbe_txd > MAX_TXD) {
493280182Sjfv		device_printf(dev, "TXD config issue, using default!\n");
494280182Sjfv		adapter->num_tx_desc = DEFAULT_TXD;
495280182Sjfv	} else
496280182Sjfv		adapter->num_tx_desc = ixgbe_txd;
497280182Sjfv
498280182Sjfv	/*
499280182Sjfv	** With many RX rings it is easy to exceed the
500280182Sjfv	** system mbuf allocation. Tuning nmbclusters
501280182Sjfv	** can alleviate this.
502280182Sjfv	*/
503280182Sjfv	if (nmbclusters > 0) {
504280182Sjfv		int s;
505280182Sjfv		s = (ixgbe_rxd * adapter->num_queues) * ixgbe_total_ports;
506280182Sjfv		if (s > nmbclusters) {
507280182Sjfv			device_printf(dev, "RX Descriptors exceed "
508280182Sjfv			    "system mbuf max, using default instead!\n");
509280182Sjfv			ixgbe_rxd = DEFAULT_RXD;
510280182Sjfv		}
511280182Sjfv	}
512280182Sjfv
513280182Sjfv	if (((ixgbe_rxd * sizeof(union ixgbe_adv_rx_desc)) % DBA_ALIGN) != 0 ||
514280182Sjfv	    ixgbe_rxd < MIN_RXD || ixgbe_rxd > MAX_RXD) {
515280182Sjfv		device_printf(dev, "RXD config issue, using default!\n");
516280182Sjfv		adapter->num_rx_desc = DEFAULT_RXD;
517280182Sjfv	} else
518280182Sjfv		adapter->num_rx_desc = ixgbe_rxd;
519280182Sjfv
520280182Sjfv	/* Allocate our TX/RX Queues */
521280182Sjfv	if (ixgbe_allocate_queues(adapter)) {
522280182Sjfv		error = ENOMEM;
523280182Sjfv		goto err_out;
524280182Sjfv	}
525280182Sjfv
526280182Sjfv	/* Allocate multicast array memory. */
527283883Sjfv	adapter->mta = malloc(sizeof(*adapter->mta) *
528280182Sjfv	    MAX_NUM_MULTICAST_ADDRESSES, M_DEVBUF, M_NOWAIT);
529280182Sjfv	if (adapter->mta == NULL) {
530280182Sjfv		device_printf(dev, "Can not allocate multicast setup array\n");
531280182Sjfv		error = ENOMEM;
532280182Sjfv		goto err_late;
533280182Sjfv	}
534280182Sjfv
535280182Sjfv	/* Initialize the shared code */
536280182Sjfv	hw->allow_unsupported_sfp = allow_unsupported_sfp;
537280182Sjfv	error = ixgbe_init_shared_code(hw);
538280182Sjfv	if (error == IXGBE_ERR_SFP_NOT_PRESENT) {
539280182Sjfv		/*
540280182Sjfv		** No optics in this port, set up
541280182Sjfv		** so the timer routine will probe
542280182Sjfv		** for later insertion.
543280182Sjfv		*/
544280182Sjfv		adapter->sfp_probe = TRUE;
545280182Sjfv		error = 0;
546280182Sjfv	} else if (error == IXGBE_ERR_SFP_NOT_SUPPORTED) {
547292674Ssbruno		device_printf(dev, "Unsupported SFP+ module detected!\n");
548280182Sjfv		error = EIO;
549280182Sjfv		goto err_late;
550280182Sjfv	} else if (error) {
551292674Ssbruno		device_printf(dev, "Unable to initialize the shared code\n");
552280182Sjfv		error = EIO;
553280182Sjfv		goto err_late;
554280182Sjfv	}
555280182Sjfv
556280182Sjfv	/* Make sure we have a good EEPROM before we read from it */
557280182Sjfv	if (ixgbe_validate_eeprom_checksum(&adapter->hw, &csum) < 0) {
558292674Ssbruno		device_printf(dev, "The EEPROM Checksum Is Not Valid\n");
559280182Sjfv		error = EIO;
560280182Sjfv		goto err_late;
561280182Sjfv	}
562280182Sjfv
563280182Sjfv	error = ixgbe_init_hw(hw);
564280182Sjfv	switch (error) {
565280182Sjfv	case IXGBE_ERR_EEPROM_VERSION:
566280182Sjfv		device_printf(dev, "This device is a pre-production adapter/"
567280182Sjfv		    "LOM.  Please be aware there may be issues associated "
568292674Ssbruno		    "with your hardware.\nIf you are experiencing problems "
569280182Sjfv		    "please contact your Intel or hardware representative "
570280182Sjfv		    "who provided you with this hardware.\n");
571280182Sjfv		break;
572280182Sjfv	case IXGBE_ERR_SFP_NOT_SUPPORTED:
573292674Ssbruno		device_printf(dev, "Unsupported SFP+ Module\n");
574280182Sjfv		error = EIO;
575280182Sjfv		goto err_late;
576280182Sjfv	case IXGBE_ERR_SFP_NOT_PRESENT:
577292674Ssbruno		device_printf(dev, "No SFP+ Module found\n");
578280182Sjfv		/* falls thru */
579280182Sjfv	default:
580280182Sjfv		break;
581280182Sjfv	}
582280182Sjfv
583294795Ssmh	/* hw.ix defaults init */
584294795Ssmh	ixgbe_set_advertise(adapter, ixgbe_advertise_speed);
585294795Ssmh	ixgbe_set_flowcntl(adapter, ixgbe_flow_control);
586294795Ssmh	adapter->enable_aim = ixgbe_enable_aim;
587294795Ssmh
588280182Sjfv	if ((adapter->msix > 1) && (ixgbe_enable_msix))
589280182Sjfv		error = ixgbe_allocate_msix(adapter);
590280182Sjfv	else
591280182Sjfv		error = ixgbe_allocate_legacy(adapter);
592280182Sjfv	if (error)
593280182Sjfv		goto err_late;
594280182Sjfv
595295093Ssmh	/* Enable the optics for 82599 SFP+ fiber */
596295093Ssmh	ixgbe_enable_tx_laser(hw);
597295093Ssmh
598295093Ssmh	/* Enable power to the phy. */
599295093Ssmh	ixgbe_set_phy_power(hw, TRUE);
600295093Ssmh
601280182Sjfv	/* Setup OS specific network interface */
602280182Sjfv	if (ixgbe_setup_interface(dev, adapter) != 0)
603280182Sjfv		goto err_late;
604280182Sjfv
605280182Sjfv	/* Initialize statistics */
606280182Sjfv	ixgbe_update_stats_counters(adapter);
607280182Sjfv
608280182Sjfv	/* Register for VLAN events */
609280182Sjfv	adapter->vlan_attach = EVENTHANDLER_REGISTER(vlan_config,
610280182Sjfv	    ixgbe_register_vlan, adapter, EVENTHANDLER_PRI_FIRST);
611280182Sjfv	adapter->vlan_detach = EVENTHANDLER_REGISTER(vlan_unconfig,
612280182Sjfv	    ixgbe_unregister_vlan, adapter, EVENTHANDLER_PRI_FIRST);
613280182Sjfv
614282289Serj        /* Check PCIE slot type/speed/width */
615292674Ssbruno	ixgbe_get_slot_info(adapter);
616280182Sjfv
617292674Ssbruno	/* Set an initial default flow control & dmac value */
618280182Sjfv	adapter->fc = ixgbe_fc_full;
619292674Ssbruno	adapter->dmac = 0;
620292674Ssbruno	adapter->eee_enabled = 0;
621280182Sjfv
622283883Sjfv#ifdef PCI_IOV
623283883Sjfv	if ((hw->mac.type != ixgbe_mac_82598EB) && (adapter->msix > 1)) {
624283883Sjfv		nvlist_t *pf_schema, *vf_schema;
625283883Sjfv
626283883Sjfv		hw->mbx.ops.init_params(hw);
627283883Sjfv		pf_schema = pci_iov_schema_alloc_node();
628283883Sjfv		vf_schema = pci_iov_schema_alloc_node();
629283883Sjfv		pci_iov_schema_add_unicast_mac(vf_schema, "mac-addr", 0, NULL);
630283883Sjfv		pci_iov_schema_add_bool(vf_schema, "mac-anti-spoof",
631283883Sjfv		    IOV_SCHEMA_HASDEFAULT, TRUE);
632283883Sjfv		pci_iov_schema_add_bool(vf_schema, "allow-set-mac",
633283883Sjfv		    IOV_SCHEMA_HASDEFAULT, FALSE);
634283883Sjfv		pci_iov_schema_add_bool(vf_schema, "allow-promisc",
635283883Sjfv		    IOV_SCHEMA_HASDEFAULT, FALSE);
636283883Sjfv		error = pci_iov_attach(dev, pf_schema, vf_schema);
637283883Sjfv		if (error != 0) {
638283883Sjfv			device_printf(dev,
639283883Sjfv			    "Error %d setting up SR-IOV\n", error);
640283883Sjfv		}
641283883Sjfv	}
642283883Sjfv#endif /* PCI_IOV */
643283883Sjfv
644282289Serj	/* Check for certain supported features */
645282289Serj	ixgbe_check_wol_support(adapter);
646282289Serj
647282289Serj	/* Add sysctls */
648282289Serj	ixgbe_add_device_sysctls(adapter);
649282289Serj	ixgbe_add_hw_stats(adapter);
650282289Serj
651280182Sjfv	/* let hardware know driver is loaded */
652280182Sjfv	ctrl_ext = IXGBE_READ_REG(hw, IXGBE_CTRL_EXT);
653280182Sjfv	ctrl_ext |= IXGBE_CTRL_EXT_DRV_LOAD;
654280182Sjfv	IXGBE_WRITE_REG(hw, IXGBE_CTRL_EXT, ctrl_ext);
655280182Sjfv
656280182Sjfv#ifdef DEV_NETMAP
657280182Sjfv	ixgbe_netmap_attach(adapter);
658280182Sjfv#endif /* DEV_NETMAP */
659280182Sjfv	INIT_DEBUGOUT("ixgbe_attach: end");
660280182Sjfv	return (0);
661280182Sjfv
662280182Sjfverr_late:
663280182Sjfv	ixgbe_free_transmit_structures(adapter);
664280182Sjfv	ixgbe_free_receive_structures(adapter);
665280182Sjfverr_out:
666280182Sjfv	if (adapter->ifp != NULL)
667280182Sjfv		if_free(adapter->ifp);
668280182Sjfv	ixgbe_free_pci_resources(adapter);
669280182Sjfv	free(adapter->mta, M_DEVBUF);
670280182Sjfv	return (error);
671280182Sjfv}
672280182Sjfv
673280182Sjfv/*********************************************************************
674280182Sjfv *  Device removal routine
675280182Sjfv *
676280182Sjfv *  The detach entry point is called when the driver is being removed.
677280182Sjfv *  This routine stops the adapter and deallocates all the resources
678280182Sjfv *  that were allocated for driver operation.
679280182Sjfv *
680280182Sjfv *  return 0 on success, positive on failure
681280182Sjfv *********************************************************************/
682280182Sjfv
683280182Sjfvstatic int
684280182Sjfvixgbe_detach(device_t dev)
685280182Sjfv{
686280182Sjfv	struct adapter *adapter = device_get_softc(dev);
687280182Sjfv	struct ix_queue *que = adapter->queues;
688280182Sjfv	struct tx_ring *txr = adapter->tx_rings;
689280182Sjfv	u32	ctrl_ext;
690280182Sjfv
691280182Sjfv	INIT_DEBUGOUT("ixgbe_detach: begin");
692280182Sjfv
693280182Sjfv	/* Make sure VLANS are not using driver */
694280182Sjfv	if (adapter->ifp->if_vlantrunk != NULL) {
695280182Sjfv		device_printf(dev,"Vlan in use, detach first\n");
696280182Sjfv		return (EBUSY);
697280182Sjfv	}
698280182Sjfv
699283883Sjfv#ifdef PCI_IOV
700283883Sjfv	if (pci_iov_detach(dev) != 0) {
701283883Sjfv		device_printf(dev, "SR-IOV in use; detach first.\n");
702283883Sjfv		return (EBUSY);
703283883Sjfv	}
704283883Sjfv#endif /* PCI_IOV */
705283883Sjfv
706292674Ssbruno	ether_ifdetach(adapter->ifp);
707282289Serj	/* Stop the adapter */
708280182Sjfv	IXGBE_CORE_LOCK(adapter);
709282289Serj	ixgbe_setup_low_power_mode(adapter);
710280182Sjfv	IXGBE_CORE_UNLOCK(adapter);
711280182Sjfv
712280182Sjfv	for (int i = 0; i < adapter->num_queues; i++, que++, txr++) {
713280182Sjfv		if (que->tq) {
714280182Sjfv#ifndef IXGBE_LEGACY_TX
715280182Sjfv			taskqueue_drain(que->tq, &txr->txq_task);
716280182Sjfv#endif
717280182Sjfv			taskqueue_drain(que->tq, &que->que_task);
718280182Sjfv			taskqueue_free(que->tq);
719280182Sjfv		}
720280182Sjfv	}
721280182Sjfv
722280182Sjfv	/* Drain the Link queue */
723280182Sjfv	if (adapter->tq) {
724280182Sjfv		taskqueue_drain(adapter->tq, &adapter->link_task);
725280182Sjfv		taskqueue_drain(adapter->tq, &adapter->mod_task);
726280182Sjfv		taskqueue_drain(adapter->tq, &adapter->msf_task);
727283883Sjfv#ifdef PCI_IOV
728283883Sjfv		taskqueue_drain(adapter->tq, &adapter->mbx_task);
729283883Sjfv#endif
730282289Serj		taskqueue_drain(adapter->tq, &adapter->phy_task);
731280182Sjfv#ifdef IXGBE_FDIR
732280182Sjfv		taskqueue_drain(adapter->tq, &adapter->fdir_task);
733280182Sjfv#endif
734280182Sjfv		taskqueue_free(adapter->tq);
735280182Sjfv	}
736280182Sjfv
737280182Sjfv	/* let hardware know driver is unloading */
738280182Sjfv	ctrl_ext = IXGBE_READ_REG(&adapter->hw, IXGBE_CTRL_EXT);
739280182Sjfv	ctrl_ext &= ~IXGBE_CTRL_EXT_DRV_LOAD;
740280182Sjfv	IXGBE_WRITE_REG(&adapter->hw, IXGBE_CTRL_EXT, ctrl_ext);
741280182Sjfv
742280182Sjfv	/* Unregister VLAN events */
743280182Sjfv	if (adapter->vlan_attach != NULL)
744280182Sjfv		EVENTHANDLER_DEREGISTER(vlan_config, adapter->vlan_attach);
745280182Sjfv	if (adapter->vlan_detach != NULL)
746280182Sjfv		EVENTHANDLER_DEREGISTER(vlan_unconfig, adapter->vlan_detach);
747280182Sjfv
748280182Sjfv	callout_drain(&adapter->timer);
749280182Sjfv#ifdef DEV_NETMAP
750280182Sjfv	netmap_detach(adapter->ifp);
751280182Sjfv#endif /* DEV_NETMAP */
752280182Sjfv	ixgbe_free_pci_resources(adapter);
753280182Sjfv	bus_generic_detach(dev);
754280182Sjfv	if_free(adapter->ifp);
755280182Sjfv
756280182Sjfv	ixgbe_free_transmit_structures(adapter);
757280182Sjfv	ixgbe_free_receive_structures(adapter);
758280182Sjfv	free(adapter->mta, M_DEVBUF);
759280182Sjfv
760280182Sjfv	IXGBE_CORE_LOCK_DESTROY(adapter);
761280182Sjfv	return (0);
762280182Sjfv}
763280182Sjfv
764280182Sjfv/*********************************************************************
765280182Sjfv *
766280182Sjfv *  Shutdown entry point
767280182Sjfv *
768280182Sjfv **********************************************************************/
769280182Sjfv
770280182Sjfvstatic int
771280182Sjfvixgbe_shutdown(device_t dev)
772280182Sjfv{
773280182Sjfv	struct adapter *adapter = device_get_softc(dev);
774282289Serj	int error = 0;
775282289Serj
776282289Serj	INIT_DEBUGOUT("ixgbe_shutdown: begin");
777282289Serj
778280182Sjfv	IXGBE_CORE_LOCK(adapter);
779282289Serj	error = ixgbe_setup_low_power_mode(adapter);
780280182Sjfv	IXGBE_CORE_UNLOCK(adapter);
781282289Serj
782282289Serj	return (error);
783282289Serj}
784282289Serj
785282289Serj/**
786282289Serj * Methods for going from:
787282289Serj * D0 -> D3: ixgbe_suspend
788282289Serj * D3 -> D0: ixgbe_resume
789282289Serj */
790282289Serjstatic int
791282289Serjixgbe_suspend(device_t dev)
792282289Serj{
793282289Serj	struct adapter *adapter = device_get_softc(dev);
794282289Serj	int error = 0;
795282289Serj
796282289Serj	INIT_DEBUGOUT("ixgbe_suspend: begin");
797282289Serj
798282289Serj	IXGBE_CORE_LOCK(adapter);
799282289Serj
800282289Serj	error = ixgbe_setup_low_power_mode(adapter);
801282289Serj
802282289Serj	IXGBE_CORE_UNLOCK(adapter);
803282289Serj
804282289Serj	return (error);
805282289Serj}
806282289Serj
807282289Serjstatic int
808282289Serjixgbe_resume(device_t dev)
809282289Serj{
810282289Serj	struct adapter *adapter = device_get_softc(dev);
811282289Serj	struct ifnet *ifp = adapter->ifp;
812282289Serj	struct ixgbe_hw *hw = &adapter->hw;
813282289Serj	u32 wus;
814282289Serj
815282289Serj	INIT_DEBUGOUT("ixgbe_resume: begin");
816282289Serj
817282289Serj	IXGBE_CORE_LOCK(adapter);
818282289Serj
819282289Serj	/* Read & clear WUS register */
820282289Serj	wus = IXGBE_READ_REG(hw, IXGBE_WUS);
821282289Serj	if (wus)
822282289Serj		device_printf(dev, "Woken up by (WUS): %#010x\n",
823282289Serj		    IXGBE_READ_REG(hw, IXGBE_WUS));
824282289Serj	IXGBE_WRITE_REG(hw, IXGBE_WUS, 0xffffffff);
825282289Serj	/* And clear WUFC until next low-power transition */
826282289Serj	IXGBE_WRITE_REG(hw, IXGBE_WUFC, 0);
827282289Serj
828282289Serj	/*
829282289Serj	 * Required after D3->D0 transition;
830282289Serj	 * will re-advertise all previous advertised speeds
831282289Serj	 */
832282289Serj	if (ifp->if_flags & IFF_UP)
833282289Serj		ixgbe_init_locked(adapter);
834282289Serj
835282289Serj	IXGBE_CORE_UNLOCK(adapter);
836282289Serj
837280182Sjfv	return (0);
838280182Sjfv}
839280182Sjfv
840280182Sjfv
841280182Sjfv/*********************************************************************
842280182Sjfv *  Ioctl entry point
843280182Sjfv *
844280182Sjfv *  ixgbe_ioctl is called when the user wants to configure the
845280182Sjfv *  interface.
846280182Sjfv *
847280182Sjfv *  return 0 on success, positive on failure
848280182Sjfv **********************************************************************/
849280182Sjfv
850280182Sjfvstatic int
851280182Sjfvixgbe_ioctl(struct ifnet * ifp, u_long command, caddr_t data)
852280182Sjfv{
853280182Sjfv	struct adapter	*adapter = ifp->if_softc;
854280182Sjfv	struct ifreq	*ifr = (struct ifreq *) data;
855280182Sjfv#if defined(INET) || defined(INET6)
856280182Sjfv	struct ifaddr *ifa = (struct ifaddr *)data;
857280182Sjfv#endif
858280182Sjfv	int             error = 0;
859286238Ssbruno	bool		avoid_reset = FALSE;
860280182Sjfv
861280182Sjfv	switch (command) {
862280182Sjfv
863280182Sjfv        case SIOCSIFADDR:
864280182Sjfv#ifdef INET
865280182Sjfv		if (ifa->ifa_addr->sa_family == AF_INET)
866280182Sjfv			avoid_reset = TRUE;
867280182Sjfv#endif
868280182Sjfv#ifdef INET6
869280182Sjfv		if (ifa->ifa_addr->sa_family == AF_INET6)
870280182Sjfv			avoid_reset = TRUE;
871280182Sjfv#endif
872280182Sjfv		/*
873280182Sjfv		** Calling init results in link renegotiation,
874280182Sjfv		** so we avoid doing it when possible.
875280182Sjfv		*/
876280182Sjfv		if (avoid_reset) {
877280182Sjfv			ifp->if_flags |= IFF_UP;
878280182Sjfv			if (!(ifp->if_drv_flags & IFF_DRV_RUNNING))
879280182Sjfv				ixgbe_init(adapter);
880292674Ssbruno#ifdef INET
881280182Sjfv			if (!(ifp->if_flags & IFF_NOARP))
882280182Sjfv				arp_ifinit(ifp, ifa);
883286238Ssbruno#endif
884280182Sjfv		} else
885280182Sjfv			error = ether_ioctl(ifp, command, data);
886280182Sjfv		break;
887280182Sjfv	case SIOCSIFMTU:
888280182Sjfv		IOCTL_DEBUGOUT("ioctl: SIOCSIFMTU (Set Interface MTU)");
889282289Serj		if (ifr->ifr_mtu > IXGBE_MAX_MTU) {
890280182Sjfv			error = EINVAL;
891280182Sjfv		} else {
892280182Sjfv			IXGBE_CORE_LOCK(adapter);
893280182Sjfv			ifp->if_mtu = ifr->ifr_mtu;
894280182Sjfv			adapter->max_frame_size =
895282289Serj				ifp->if_mtu + IXGBE_MTU_HDR;
896302384Ssbruno			if (ifp->if_drv_flags & IFF_DRV_RUNNING)
897302384Ssbruno				ixgbe_init_locked(adapter);
898283883Sjfv#ifdef PCI_IOV
899283883Sjfv			ixgbe_recalculate_max_frame(adapter);
900283883Sjfv#endif
901280182Sjfv			IXGBE_CORE_UNLOCK(adapter);
902280182Sjfv		}
903280182Sjfv		break;
904280182Sjfv	case SIOCSIFFLAGS:
905280182Sjfv		IOCTL_DEBUGOUT("ioctl: SIOCSIFFLAGS (Set Interface Flags)");
906280182Sjfv		IXGBE_CORE_LOCK(adapter);
907280182Sjfv		if (ifp->if_flags & IFF_UP) {
908280182Sjfv			if ((ifp->if_drv_flags & IFF_DRV_RUNNING)) {
909280182Sjfv				if ((ifp->if_flags ^ adapter->if_flags) &
910280182Sjfv				    (IFF_PROMISC | IFF_ALLMULTI)) {
911280182Sjfv					ixgbe_set_promisc(adapter);
912280182Sjfv                                }
913280182Sjfv			} else
914280182Sjfv				ixgbe_init_locked(adapter);
915280182Sjfv		} else
916280182Sjfv			if (ifp->if_drv_flags & IFF_DRV_RUNNING)
917280182Sjfv				ixgbe_stop(adapter);
918280182Sjfv		adapter->if_flags = ifp->if_flags;
919280182Sjfv		IXGBE_CORE_UNLOCK(adapter);
920280182Sjfv		break;
921280182Sjfv	case SIOCADDMULTI:
922280182Sjfv	case SIOCDELMULTI:
923280182Sjfv		IOCTL_DEBUGOUT("ioctl: SIOC(ADD|DEL)MULTI");
924280182Sjfv		if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
925280182Sjfv			IXGBE_CORE_LOCK(adapter);
926280182Sjfv			ixgbe_disable_intr(adapter);
927280182Sjfv			ixgbe_set_multi(adapter);
928280182Sjfv			ixgbe_enable_intr(adapter);
929280182Sjfv			IXGBE_CORE_UNLOCK(adapter);
930280182Sjfv		}
931280182Sjfv		break;
932280182Sjfv	case SIOCSIFMEDIA:
933280182Sjfv	case SIOCGIFMEDIA:
934280182Sjfv		IOCTL_DEBUGOUT("ioctl: SIOCxIFMEDIA (Get/Set Interface Media)");
935280182Sjfv		error = ifmedia_ioctl(ifp, ifr, &adapter->media, command);
936280182Sjfv		break;
937280182Sjfv	case SIOCSIFCAP:
938280182Sjfv	{
939292674Ssbruno		IOCTL_DEBUGOUT("ioctl: SIOCSIFCAP (Set Capabilities)");
940292674Ssbruno
941280182Sjfv		int mask = ifr->ifr_reqcap ^ ifp->if_capenable;
942292674Ssbruno		if (!mask)
943292674Ssbruno			break;
944292674Ssbruno
945292674Ssbruno		/* HW cannot turn these on/off separately */
946292674Ssbruno		if (mask & (IFCAP_RXCSUM | IFCAP_RXCSUM_IPV6)) {
947292674Ssbruno			ifp->if_capenable ^= IFCAP_RXCSUM;
948292674Ssbruno			ifp->if_capenable ^= IFCAP_RXCSUM_IPV6;
949292674Ssbruno		}
950292674Ssbruno		if (mask & IFCAP_TXCSUM)
951292674Ssbruno			ifp->if_capenable ^= IFCAP_TXCSUM;
952292674Ssbruno		if (mask & IFCAP_TXCSUM_IPV6)
953292674Ssbruno			ifp->if_capenable ^= IFCAP_TXCSUM_IPV6;
954280182Sjfv		if (mask & IFCAP_TSO4)
955280182Sjfv			ifp->if_capenable ^= IFCAP_TSO4;
956280182Sjfv		if (mask & IFCAP_TSO6)
957280182Sjfv			ifp->if_capenable ^= IFCAP_TSO6;
958280182Sjfv		if (mask & IFCAP_LRO)
959280182Sjfv			ifp->if_capenable ^= IFCAP_LRO;
960280182Sjfv		if (mask & IFCAP_VLAN_HWTAGGING)
961280182Sjfv			ifp->if_capenable ^= IFCAP_VLAN_HWTAGGING;
962280182Sjfv		if (mask & IFCAP_VLAN_HWFILTER)
963280182Sjfv			ifp->if_capenable ^= IFCAP_VLAN_HWFILTER;
964280182Sjfv		if (mask & IFCAP_VLAN_HWTSO)
965280182Sjfv			ifp->if_capenable ^= IFCAP_VLAN_HWTSO;
966292674Ssbruno
967280182Sjfv		if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
968280182Sjfv			IXGBE_CORE_LOCK(adapter);
969280182Sjfv			ixgbe_init_locked(adapter);
970280182Sjfv			IXGBE_CORE_UNLOCK(adapter);
971280182Sjfv		}
972280182Sjfv		VLAN_CAPABILITIES(ifp);
973280182Sjfv		break;
974280182Sjfv	}
975280182Sjfv#if __FreeBSD_version >= 1100036
976280182Sjfv	case SIOCGI2C:
977280182Sjfv	{
978280182Sjfv		struct ixgbe_hw *hw = &adapter->hw;
979280182Sjfv		struct ifi2creq i2c;
980280182Sjfv		int i;
981280182Sjfv		IOCTL_DEBUGOUT("ioctl: SIOCGI2C (Get I2C Data)");
982280182Sjfv		error = copyin(ifr->ifr_data, &i2c, sizeof(i2c));
983280182Sjfv		if (error != 0)
984280182Sjfv			break;
985280182Sjfv		if (i2c.dev_addr != 0xA0 && i2c.dev_addr != 0xA2) {
986280182Sjfv			error = EINVAL;
987280182Sjfv			break;
988280182Sjfv		}
989280182Sjfv		if (i2c.len > sizeof(i2c.data)) {
990280182Sjfv			error = EINVAL;
991280182Sjfv			break;
992280182Sjfv		}
993280182Sjfv
994280182Sjfv		for (i = 0; i < i2c.len; i++)
995280182Sjfv			hw->phy.ops.read_i2c_byte(hw, i2c.offset + i,
996280182Sjfv			    i2c.dev_addr, &i2c.data[i]);
997280182Sjfv		error = copyout(&i2c, ifr->ifr_data, sizeof(i2c));
998280182Sjfv		break;
999280182Sjfv	}
1000280182Sjfv#endif
1001280182Sjfv	default:
1002280182Sjfv		IOCTL_DEBUGOUT1("ioctl: UNKNOWN (0x%X)\n", (int)command);
1003280182Sjfv		error = ether_ioctl(ifp, command, data);
1004280182Sjfv		break;
1005280182Sjfv	}
1006280182Sjfv
1007280182Sjfv	return (error);
1008280182Sjfv}
1009280182Sjfv
1010292674Ssbruno/*
1011292674Ssbruno * Set the various hardware offload abilities.
1012292674Ssbruno *
1013292674Ssbruno * This takes the ifnet's if_capenable flags (e.g. set by the user using
1014292674Ssbruno * ifconfig) and indicates to the OS via the ifnet's if_hwassist field what
1015292674Ssbruno * mbuf offload flags the driver will understand.
1016292674Ssbruno */
1017292674Ssbrunostatic void
1018292674Ssbrunoixgbe_set_if_hwassist(struct adapter *adapter)
1019292674Ssbruno{
1020292674Ssbruno	struct ifnet *ifp = adapter->ifp;
1021295273Stuexen	struct ixgbe_hw *hw = &adapter->hw;
1022292674Ssbruno
1023292674Ssbruno	ifp->if_hwassist = 0;
1024292674Ssbruno#if __FreeBSD_version >= 1000000
1025292674Ssbruno	if (ifp->if_capenable & IFCAP_TSO4)
1026292674Ssbruno		ifp->if_hwassist |= CSUM_IP_TSO;
1027292674Ssbruno	if (ifp->if_capenable & IFCAP_TSO6)
1028292674Ssbruno		ifp->if_hwassist |= CSUM_IP6_TSO;
1029295273Stuexen	if (ifp->if_capenable & IFCAP_TXCSUM) {
1030295273Stuexen		ifp->if_hwassist |= (CSUM_IP | CSUM_IP_UDP | CSUM_IP_TCP);
1031295273Stuexen		if (hw->mac.type != ixgbe_mac_82598EB)
1032295273Stuexen			ifp->if_hwassist |= CSUM_IP_SCTP;
1033295273Stuexen	}
1034295273Stuexen	if (ifp->if_capenable & IFCAP_TXCSUM_IPV6) {
1035295273Stuexen		ifp->if_hwassist |= (CSUM_IP6_UDP | CSUM_IP6_TCP);
1036295273Stuexen		if (hw->mac.type != ixgbe_mac_82598EB)
1037295273Stuexen			ifp->if_hwassist |= CSUM_IP6_SCTP;
1038295273Stuexen	}
1039292674Ssbruno#else
1040292674Ssbruno	if (ifp->if_capenable & IFCAP_TSO)
1041292674Ssbruno		ifp->if_hwassist |= CSUM_TSO;
1042292674Ssbruno	if (ifp->if_capenable & IFCAP_TXCSUM) {
1043292674Ssbruno		ifp->if_hwassist |= (CSUM_TCP | CSUM_UDP);
1044292674Ssbruno		if (hw->mac.type != ixgbe_mac_82598EB)
1045292674Ssbruno			ifp->if_hwassist |= CSUM_SCTP;
1046292674Ssbruno	}
1047292674Ssbruno#endif
1048292674Ssbruno}
1049292674Ssbruno
1050280182Sjfv/*********************************************************************
1051280182Sjfv *  Init entry point
1052280182Sjfv *
1053280182Sjfv *  This routine is used in two ways. It is used by the stack as
1054280182Sjfv *  init entry point in network interface structure. It is also used
1055280182Sjfv *  by the driver as a hw/sw initialization routine to get to a
1056280182Sjfv *  consistent state.
1057280182Sjfv *
1058280182Sjfv *  return 0 on success, positive on failure
1059280182Sjfv **********************************************************************/
1060280182Sjfv#define IXGBE_MHADD_MFS_SHIFT 16
1061280182Sjfv
1062280182Sjfvstatic void
1063280182Sjfvixgbe_init_locked(struct adapter *adapter)
1064280182Sjfv{
1065280182Sjfv	struct ifnet   *ifp = adapter->ifp;
1066280182Sjfv	device_t 	dev = adapter->dev;
1067280182Sjfv	struct ixgbe_hw *hw = &adapter->hw;
1068283883Sjfv	struct tx_ring  *txr;
1069283883Sjfv	struct rx_ring  *rxr;
1070283883Sjfv	u32		txdctl, mhadd;
1071280182Sjfv	u32		rxdctl, rxctrl;
1072292674Ssbruno	int err = 0;
1073283883Sjfv#ifdef PCI_IOV
1074283883Sjfv	enum ixgbe_iov_mode mode;
1075283883Sjfv#endif
1076280182Sjfv
1077280182Sjfv	mtx_assert(&adapter->core_mtx, MA_OWNED);
1078280182Sjfv	INIT_DEBUGOUT("ixgbe_init_locked: begin");
1079283883Sjfv
1080280182Sjfv	hw->adapter_stopped = FALSE;
1081280182Sjfv	ixgbe_stop_adapter(hw);
1082280182Sjfv        callout_stop(&adapter->timer);
1083280182Sjfv
1084283883Sjfv#ifdef PCI_IOV
1085283883Sjfv	mode = ixgbe_get_iov_mode(adapter);
1086283883Sjfv	adapter->pool = ixgbe_max_vfs(mode);
1087283883Sjfv	/* Queue indices may change with IOV mode */
1088283883Sjfv	for (int i = 0; i < adapter->num_queues; i++) {
1089283883Sjfv		adapter->rx_rings[i].me = ixgbe_pf_que_index(mode, i);
1090283883Sjfv		adapter->tx_rings[i].me = ixgbe_pf_que_index(mode, i);
1091283883Sjfv	}
1092283883Sjfv#endif
1093280182Sjfv        /* reprogram the RAR[0] in case user changed it. */
1094283883Sjfv	ixgbe_set_rar(hw, 0, hw->mac.addr, adapter->pool, IXGBE_RAH_AV);
1095280182Sjfv
1096280182Sjfv	/* Get the latest mac address, User can use a LAA */
1097283883Sjfv	bcopy(IF_LLADDR(ifp), hw->mac.addr, IXGBE_ETH_LENGTH_OF_ADDRESS);
1098283883Sjfv	ixgbe_set_rar(hw, 0, hw->mac.addr, adapter->pool, 1);
1099280182Sjfv	hw->addr_ctrl.rar_used_count = 1;
1100280182Sjfv
1101292674Ssbruno	/* Set hardware offload abilities from ifnet flags */
1102292674Ssbruno	ixgbe_set_if_hwassist(adapter);
1103280182Sjfv
1104280182Sjfv	/* Prepare transmit descriptors and buffers */
1105280182Sjfv	if (ixgbe_setup_transmit_structures(adapter)) {
1106282289Serj		device_printf(dev, "Could not setup transmit structures\n");
1107280182Sjfv		ixgbe_stop(adapter);
1108280182Sjfv		return;
1109280182Sjfv	}
1110280182Sjfv
1111280182Sjfv	ixgbe_init_hw(hw);
1112283883Sjfv#ifdef PCI_IOV
1113283883Sjfv	ixgbe_initialize_iov(adapter);
1114283883Sjfv#endif
1115280182Sjfv	ixgbe_initialize_transmit_units(adapter);
1116280182Sjfv
1117280182Sjfv	/* Setup Multicast table */
1118280182Sjfv	ixgbe_set_multi(adapter);
1119280182Sjfv
1120292674Ssbruno	/* Determine the correct mbuf pool, based on frame size */
1121283883Sjfv	if (adapter->max_frame_size <= MCLBYTES)
1122280182Sjfv		adapter->rx_mbuf_sz = MCLBYTES;
1123283883Sjfv	else
1124283882Sjfv		adapter->rx_mbuf_sz = MJUMPAGESIZE;
1125280182Sjfv
1126280182Sjfv	/* Prepare receive descriptors and buffers */
1127280182Sjfv	if (ixgbe_setup_receive_structures(adapter)) {
1128282289Serj		device_printf(dev, "Could not setup receive structures\n");
1129280182Sjfv		ixgbe_stop(adapter);
1130280182Sjfv		return;
1131280182Sjfv	}
1132280182Sjfv
1133280182Sjfv	/* Configure RX settings */
1134280182Sjfv	ixgbe_initialize_receive_units(adapter);
1135280182Sjfv
1136283883Sjfv	/* Enable SDP & MSIX interrupts based on adapter */
1137283883Sjfv	ixgbe_config_gpie(adapter);
1138280182Sjfv
1139280182Sjfv	/* Set MTU size */
1140280182Sjfv	if (ifp->if_mtu > ETHERMTU) {
1141282289Serj		/* aka IXGBE_MAXFRS on 82599 and newer */
1142280182Sjfv		mhadd = IXGBE_READ_REG(hw, IXGBE_MHADD);
1143280182Sjfv		mhadd &= ~IXGBE_MHADD_MFS_MASK;
1144280182Sjfv		mhadd |= adapter->max_frame_size << IXGBE_MHADD_MFS_SHIFT;
1145280182Sjfv		IXGBE_WRITE_REG(hw, IXGBE_MHADD, mhadd);
1146280182Sjfv	}
1147280182Sjfv
1148280182Sjfv	/* Now enable all the queues */
1149280182Sjfv	for (int i = 0; i < adapter->num_queues; i++) {
1150283883Sjfv		txr = &adapter->tx_rings[i];
1151283883Sjfv		txdctl = IXGBE_READ_REG(hw, IXGBE_TXDCTL(txr->me));
1152280182Sjfv		txdctl |= IXGBE_TXDCTL_ENABLE;
1153280182Sjfv		/* Set WTHRESH to 8, burst writeback */
1154280182Sjfv		txdctl |= (8 << 16);
1155280182Sjfv		/*
1156280182Sjfv		 * When the internal queue falls below PTHRESH (32),
1157280182Sjfv		 * start prefetching as long as there are at least
1158280182Sjfv		 * HTHRESH (1) buffers ready. The values are taken
1159280182Sjfv		 * from the Intel linux driver 3.8.21.
1160280182Sjfv		 * Prefetching enables tx line rate even with 1 queue.
1161280182Sjfv		 */
1162280182Sjfv		txdctl |= (32 << 0) | (1 << 8);
1163283883Sjfv		IXGBE_WRITE_REG(hw, IXGBE_TXDCTL(txr->me), txdctl);
1164280182Sjfv	}
1165280182Sjfv
1166283883Sjfv	for (int i = 0, j = 0; i < adapter->num_queues; i++) {
1167283883Sjfv		rxr = &adapter->rx_rings[i];
1168283883Sjfv		rxdctl = IXGBE_READ_REG(hw, IXGBE_RXDCTL(rxr->me));
1169280182Sjfv		if (hw->mac.type == ixgbe_mac_82598EB) {
1170280182Sjfv			/*
1171280182Sjfv			** PTHRESH = 21
1172280182Sjfv			** HTHRESH = 4
1173280182Sjfv			** WTHRESH = 8
1174280182Sjfv			*/
1175280182Sjfv			rxdctl &= ~0x3FFFFF;
1176280182Sjfv			rxdctl |= 0x080420;
1177280182Sjfv		}
1178280182Sjfv		rxdctl |= IXGBE_RXDCTL_ENABLE;
1179283883Sjfv		IXGBE_WRITE_REG(hw, IXGBE_RXDCTL(rxr->me), rxdctl);
1180283883Sjfv		for (; j < 10; j++) {
1181283883Sjfv			if (IXGBE_READ_REG(hw, IXGBE_RXDCTL(rxr->me)) &
1182280182Sjfv			    IXGBE_RXDCTL_ENABLE)
1183280182Sjfv				break;
1184280182Sjfv			else
1185280182Sjfv				msec_delay(1);
1186280182Sjfv		}
1187280182Sjfv		wmb();
1188280182Sjfv#ifdef DEV_NETMAP
1189280182Sjfv		/*
1190280182Sjfv		 * In netmap mode, we must preserve the buffers made
1191280182Sjfv		 * available to userspace before the if_init()
1192280182Sjfv		 * (this is true by default on the TX side, because
1193280182Sjfv		 * init makes all buffers available to userspace).
1194280182Sjfv		 *
1195280182Sjfv		 * netmap_reset() and the device specific routines
1196280182Sjfv		 * (e.g. ixgbe_setup_receive_rings()) map these
1197280182Sjfv		 * buffers at the end of the NIC ring, so here we
1198280182Sjfv		 * must set the RDT (tail) register to make sure
1199280182Sjfv		 * they are not overwritten.
1200280182Sjfv		 *
1201280182Sjfv		 * In this driver the NIC ring starts at RDH = 0,
1202280182Sjfv		 * RDT points to the last slot available for reception (?),
1203280182Sjfv		 * so RDT = num_rx_desc - 1 means the whole ring is available.
1204280182Sjfv		 */
1205280182Sjfv		if (ifp->if_capenable & IFCAP_NETMAP) {
1206280182Sjfv			struct netmap_adapter *na = NA(adapter->ifp);
1207280182Sjfv			struct netmap_kring *kring = &na->rx_rings[i];
1208280182Sjfv			int t = na->num_rx_desc - 1 - nm_kr_rxspace(kring);
1209280182Sjfv
1210283883Sjfv			IXGBE_WRITE_REG(hw, IXGBE_RDT(rxr->me), t);
1211280182Sjfv		} else
1212280182Sjfv#endif /* DEV_NETMAP */
1213283883Sjfv		IXGBE_WRITE_REG(hw, IXGBE_RDT(rxr->me), adapter->num_rx_desc - 1);
1214280182Sjfv	}
1215280182Sjfv
1216280182Sjfv	/* Enable Receive engine */
1217280182Sjfv	rxctrl = IXGBE_READ_REG(hw, IXGBE_RXCTRL);
1218280182Sjfv	if (hw->mac.type == ixgbe_mac_82598EB)
1219280182Sjfv		rxctrl |= IXGBE_RXCTRL_DMBYPS;
1220280182Sjfv	rxctrl |= IXGBE_RXCTRL_RXEN;
1221280182Sjfv	ixgbe_enable_rx_dma(hw, rxctrl);
1222280182Sjfv
1223280182Sjfv	callout_reset(&adapter->timer, hz, ixgbe_local_timer, adapter);
1224280182Sjfv
1225280182Sjfv	/* Set up MSI/X routing */
1226280182Sjfv	if (ixgbe_enable_msix)  {
1227280182Sjfv		ixgbe_configure_ivars(adapter);
1228280182Sjfv		/* Set up auto-mask */
1229280182Sjfv		if (hw->mac.type == ixgbe_mac_82598EB)
1230280182Sjfv			IXGBE_WRITE_REG(hw, IXGBE_EIAM, IXGBE_EICS_RTX_QUEUE);
1231280182Sjfv		else {
1232280182Sjfv			IXGBE_WRITE_REG(hw, IXGBE_EIAM_EX(0), 0xFFFFFFFF);
1233280182Sjfv			IXGBE_WRITE_REG(hw, IXGBE_EIAM_EX(1), 0xFFFFFFFF);
1234280182Sjfv		}
1235280182Sjfv	} else {  /* Simple settings for Legacy/MSI */
1236280182Sjfv                ixgbe_set_ivar(adapter, 0, 0, 0);
1237280182Sjfv                ixgbe_set_ivar(adapter, 0, 0, 1);
1238280182Sjfv		IXGBE_WRITE_REG(hw, IXGBE_EIAM, IXGBE_EICS_RTX_QUEUE);
1239280182Sjfv	}
1240280182Sjfv
1241280182Sjfv#ifdef IXGBE_FDIR
1242280182Sjfv	/* Init Flow director */
1243280182Sjfv	if (hw->mac.type != ixgbe_mac_82598EB) {
1244280182Sjfv		u32 hdrm = 32 << fdir_pballoc;
1245280182Sjfv
1246280182Sjfv		hw->mac.ops.setup_rxpba(hw, 0, hdrm, PBA_STRATEGY_EQUAL);
1247280182Sjfv		ixgbe_init_fdir_signature_82599(&adapter->hw, fdir_pballoc);
1248280182Sjfv	}
1249280182Sjfv#endif
1250280182Sjfv
1251280182Sjfv	/*
1252283883Sjfv	 * Check on any SFP devices that
1253283883Sjfv	 * need to be kick-started
1254283883Sjfv	 */
1255280182Sjfv	if (hw->phy.type == ixgbe_phy_none) {
1256292674Ssbruno		err = hw->phy.ops.identify(hw);
1257280182Sjfv		if (err == IXGBE_ERR_SFP_NOT_SUPPORTED) {
1258280182Sjfv                	device_printf(dev,
1259280182Sjfv			    "Unsupported SFP+ module type was detected.\n");
1260280182Sjfv			return;
1261280182Sjfv        	}
1262280182Sjfv	}
1263280182Sjfv
1264280182Sjfv	/* Set moderation on the Link interrupt */
1265280182Sjfv	IXGBE_WRITE_REG(hw, IXGBE_EITR(adapter->vector), IXGBE_LINK_ITR);
1266280182Sjfv
1267282289Serj	/* Configure Energy Efficient Ethernet for supported devices */
1268292674Ssbruno	if (hw->mac.ops.setup_eee) {
1269292674Ssbruno		err = hw->mac.ops.setup_eee(hw, adapter->eee_enabled);
1270292674Ssbruno		if (err)
1271292674Ssbruno			device_printf(dev, "Error setting up EEE: %d\n", err);
1272292674Ssbruno	}
1273282289Serj
1274295093Ssmh	/* Enable power to the phy. */
1275295093Ssmh	ixgbe_set_phy_power(hw, TRUE);
1276295093Ssmh
1277280182Sjfv	/* Config/Enable Link */
1278280182Sjfv	ixgbe_config_link(adapter);
1279280182Sjfv
1280280182Sjfv	/* Hardware Packet Buffer & Flow Control setup */
1281282289Serj	ixgbe_config_delay_values(adapter);
1282280182Sjfv
1283280182Sjfv	/* Initialize the FC settings */
1284280182Sjfv	ixgbe_start_hw(hw);
1285280182Sjfv
1286280182Sjfv	/* Set up VLAN support and filter */
1287280182Sjfv	ixgbe_setup_vlan_hw_support(adapter);
1288280182Sjfv
1289282289Serj	/* Setup DMA Coalescing */
1290282289Serj	ixgbe_config_dmac(adapter);
1291282289Serj
1292280182Sjfv	/* And now turn on interrupts */
1293280182Sjfv	ixgbe_enable_intr(adapter);
1294280182Sjfv
1295283883Sjfv#ifdef PCI_IOV
1296283883Sjfv	/* Enable the use of the MBX by the VF's */
1297283883Sjfv	{
1298283883Sjfv		u32 reg = IXGBE_READ_REG(hw, IXGBE_CTRL_EXT);
1299283883Sjfv		reg |= IXGBE_CTRL_EXT_PFRSTD;
1300283883Sjfv		IXGBE_WRITE_REG(hw, IXGBE_CTRL_EXT, reg);
1301283883Sjfv	}
1302283883Sjfv#endif
1303283883Sjfv
1304280182Sjfv	/* Now inform the stack we're ready */
1305280182Sjfv	ifp->if_drv_flags |= IFF_DRV_RUNNING;
1306280182Sjfv
1307280182Sjfv	return;
1308280182Sjfv}
1309280182Sjfv
1310280182Sjfvstatic void
1311280182Sjfvixgbe_init(void *arg)
1312280182Sjfv{
1313280182Sjfv	struct adapter *adapter = arg;
1314280182Sjfv
1315280182Sjfv	IXGBE_CORE_LOCK(adapter);
1316280182Sjfv	ixgbe_init_locked(adapter);
1317280182Sjfv	IXGBE_CORE_UNLOCK(adapter);
1318280182Sjfv	return;
1319280182Sjfv}
1320280182Sjfv
1321282289Serjstatic void
1322283883Sjfvixgbe_config_gpie(struct adapter *adapter)
1323283883Sjfv{
1324283883Sjfv	struct ixgbe_hw *hw = &adapter->hw;
1325283883Sjfv	u32 gpie;
1326283883Sjfv
1327283883Sjfv	gpie = IXGBE_READ_REG(hw, IXGBE_GPIE);
1328283883Sjfv
1329283883Sjfv	/* Fan Failure Interrupt */
1330283883Sjfv	if (hw->device_id == IXGBE_DEV_ID_82598AT)
1331283883Sjfv		gpie |= IXGBE_SDP1_GPIEN;
1332283883Sjfv
1333283883Sjfv	/*
1334283883Sjfv	 * Module detection (SDP2)
1335283883Sjfv	 * Media ready (SDP1)
1336283883Sjfv	 */
1337283883Sjfv	if (hw->mac.type == ixgbe_mac_82599EB) {
1338283883Sjfv		gpie |= IXGBE_SDP2_GPIEN;
1339283883Sjfv		if (hw->device_id != IXGBE_DEV_ID_82599_QSFP_SF_QP)
1340283883Sjfv			gpie |= IXGBE_SDP1_GPIEN;
1341283883Sjfv	}
1342283883Sjfv
1343283883Sjfv	/*
1344283883Sjfv	 * Thermal Failure Detection (X540)
1345292674Ssbruno	 * Link Detection (X552 SFP+, X552/X557-AT)
1346283883Sjfv	 */
1347283883Sjfv	if (hw->mac.type == ixgbe_mac_X540 ||
1348283883Sjfv	    hw->device_id == IXGBE_DEV_ID_X550EM_X_SFP ||
1349283883Sjfv	    hw->device_id == IXGBE_DEV_ID_X550EM_X_10G_T)
1350283883Sjfv		gpie |= IXGBE_SDP0_GPIEN_X540;
1351283883Sjfv
1352283883Sjfv	if (adapter->msix > 1) {
1353283883Sjfv		/* Enable Enhanced MSIX mode */
1354283883Sjfv		gpie |= IXGBE_GPIE_MSIX_MODE;
1355283883Sjfv		gpie |= IXGBE_GPIE_EIAME | IXGBE_GPIE_PBA_SUPPORT |
1356283883Sjfv		    IXGBE_GPIE_OCD;
1357283883Sjfv	}
1358283883Sjfv
1359283883Sjfv	IXGBE_WRITE_REG(hw, IXGBE_GPIE, gpie);
1360283883Sjfv	return;
1361283883Sjfv}
1362283883Sjfv
1363283883Sjfv/*
1364283883Sjfv * Requires adapter->max_frame_size to be set.
1365283883Sjfv */
1366283883Sjfvstatic void
1367282289Serjixgbe_config_delay_values(struct adapter *adapter)
1368282289Serj{
1369282289Serj	struct ixgbe_hw *hw = &adapter->hw;
1370282289Serj	u32 rxpb, frame, size, tmp;
1371280182Sjfv
1372282289Serj	frame = adapter->max_frame_size;
1373282289Serj
1374282289Serj	/* Calculate High Water */
1375282289Serj	switch (hw->mac.type) {
1376282289Serj	case ixgbe_mac_X540:
1377282289Serj	case ixgbe_mac_X550:
1378282289Serj	case ixgbe_mac_X550EM_x:
1379282289Serj		tmp = IXGBE_DV_X540(frame, frame);
1380282289Serj		break;
1381282289Serj	default:
1382282289Serj		tmp = IXGBE_DV(frame, frame);
1383282289Serj		break;
1384282289Serj	}
1385282289Serj	size = IXGBE_BT2KB(tmp);
1386282289Serj	rxpb = IXGBE_READ_REG(hw, IXGBE_RXPBSIZE(0)) >> 10;
1387282289Serj	hw->fc.high_water[0] = rxpb - size;
1388282289Serj
1389282289Serj	/* Now calculate Low Water */
1390282289Serj	switch (hw->mac.type) {
1391282289Serj	case ixgbe_mac_X540:
1392282289Serj	case ixgbe_mac_X550:
1393282289Serj	case ixgbe_mac_X550EM_x:
1394282289Serj		tmp = IXGBE_LOW_DV_X540(frame);
1395282289Serj		break;
1396282289Serj	default:
1397282289Serj		tmp = IXGBE_LOW_DV(frame);
1398282289Serj		break;
1399282289Serj	}
1400282289Serj	hw->fc.low_water[0] = IXGBE_BT2KB(tmp);
1401282289Serj
1402282289Serj	hw->fc.requested_mode = adapter->fc;
1403282289Serj	hw->fc.pause_time = IXGBE_FC_PAUSE;
1404282289Serj	hw->fc.send_xon = TRUE;
1405282289Serj}
1406282289Serj
1407280182Sjfv/*
1408280182Sjfv**
1409280182Sjfv** MSIX Interrupt Handlers and Tasklets
1410280182Sjfv**
1411280182Sjfv*/
1412280182Sjfv
1413280182Sjfvstatic inline void
1414280182Sjfvixgbe_enable_queue(struct adapter *adapter, u32 vector)
1415280182Sjfv{
1416280182Sjfv	struct ixgbe_hw *hw = &adapter->hw;
1417280182Sjfv	u64	queue = (u64)(1 << vector);
1418280182Sjfv	u32	mask;
1419280182Sjfv
1420280182Sjfv	if (hw->mac.type == ixgbe_mac_82598EB) {
1421280182Sjfv                mask = (IXGBE_EIMS_RTX_QUEUE & queue);
1422280182Sjfv                IXGBE_WRITE_REG(hw, IXGBE_EIMS, mask);
1423280182Sjfv	} else {
1424280182Sjfv                mask = (queue & 0xFFFFFFFF);
1425280182Sjfv                if (mask)
1426280182Sjfv                        IXGBE_WRITE_REG(hw, IXGBE_EIMS_EX(0), mask);
1427280182Sjfv                mask = (queue >> 32);
1428280182Sjfv                if (mask)
1429280182Sjfv                        IXGBE_WRITE_REG(hw, IXGBE_EIMS_EX(1), mask);
1430280182Sjfv	}
1431280182Sjfv}
1432280182Sjfv
1433280182Sjfvstatic inline void
1434280182Sjfvixgbe_disable_queue(struct adapter *adapter, u32 vector)
1435280182Sjfv{
1436280182Sjfv	struct ixgbe_hw *hw = &adapter->hw;
1437280182Sjfv	u64	queue = (u64)(1 << vector);
1438280182Sjfv	u32	mask;
1439280182Sjfv
1440280182Sjfv	if (hw->mac.type == ixgbe_mac_82598EB) {
1441280182Sjfv                mask = (IXGBE_EIMS_RTX_QUEUE & queue);
1442280182Sjfv                IXGBE_WRITE_REG(hw, IXGBE_EIMC, mask);
1443280182Sjfv	} else {
1444280182Sjfv                mask = (queue & 0xFFFFFFFF);
1445280182Sjfv                if (mask)
1446280182Sjfv                        IXGBE_WRITE_REG(hw, IXGBE_EIMC_EX(0), mask);
1447280182Sjfv                mask = (queue >> 32);
1448280182Sjfv                if (mask)
1449280182Sjfv                        IXGBE_WRITE_REG(hw, IXGBE_EIMC_EX(1), mask);
1450280182Sjfv	}
1451280182Sjfv}
1452280182Sjfv
1453280182Sjfvstatic void
1454280182Sjfvixgbe_handle_que(void *context, int pending)
1455280182Sjfv{
1456280182Sjfv	struct ix_queue *que = context;
1457280182Sjfv	struct adapter  *adapter = que->adapter;
1458280182Sjfv	struct tx_ring  *txr = que->txr;
1459280182Sjfv	struct ifnet    *ifp = adapter->ifp;
1460280182Sjfv
1461280182Sjfv	if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
1462283883Sjfv		ixgbe_rxeof(que);
1463280182Sjfv		IXGBE_TX_LOCK(txr);
1464280182Sjfv		ixgbe_txeof(txr);
1465280182Sjfv#ifndef IXGBE_LEGACY_TX
1466280182Sjfv		if (!drbr_empty(ifp, txr->br))
1467280182Sjfv			ixgbe_mq_start_locked(ifp, txr);
1468280182Sjfv#else
1469280182Sjfv		if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd))
1470280182Sjfv			ixgbe_start_locked(txr, ifp);
1471280182Sjfv#endif
1472280182Sjfv		IXGBE_TX_UNLOCK(txr);
1473280182Sjfv	}
1474280182Sjfv
1475280182Sjfv	/* Reenable this interrupt */
1476280182Sjfv	if (que->res != NULL)
1477280182Sjfv		ixgbe_enable_queue(adapter, que->msix);
1478280182Sjfv	else
1479280182Sjfv		ixgbe_enable_intr(adapter);
1480280182Sjfv	return;
1481280182Sjfv}
1482280182Sjfv
1483280182Sjfv
1484280182Sjfv/*********************************************************************
1485280182Sjfv *
1486280182Sjfv *  Legacy Interrupt Service routine
1487280182Sjfv *
1488280182Sjfv **********************************************************************/
1489280182Sjfv
1490280182Sjfvstatic void
1491280182Sjfvixgbe_legacy_irq(void *arg)
1492280182Sjfv{
1493280182Sjfv	struct ix_queue *que = arg;
1494280182Sjfv	struct adapter	*adapter = que->adapter;
1495280182Sjfv	struct ixgbe_hw	*hw = &adapter->hw;
1496280182Sjfv	struct ifnet    *ifp = adapter->ifp;
1497280182Sjfv	struct 		tx_ring *txr = adapter->tx_rings;
1498280182Sjfv	bool		more;
1499280182Sjfv	u32       	reg_eicr;
1500280182Sjfv
1501280182Sjfv
1502280182Sjfv	reg_eicr = IXGBE_READ_REG(hw, IXGBE_EICR);
1503280182Sjfv
1504280182Sjfv	++que->irqs;
1505280182Sjfv	if (reg_eicr == 0) {
1506280182Sjfv		ixgbe_enable_intr(adapter);
1507280182Sjfv		return;
1508280182Sjfv	}
1509280182Sjfv
1510280182Sjfv	more = ixgbe_rxeof(que);
1511280182Sjfv
1512280182Sjfv	IXGBE_TX_LOCK(txr);
1513280182Sjfv	ixgbe_txeof(txr);
1514280182Sjfv#ifdef IXGBE_LEGACY_TX
1515280182Sjfv	if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd))
1516280182Sjfv		ixgbe_start_locked(txr, ifp);
1517280182Sjfv#else
1518280182Sjfv	if (!drbr_empty(ifp, txr->br))
1519280182Sjfv		ixgbe_mq_start_locked(ifp, txr);
1520280182Sjfv#endif
1521280182Sjfv	IXGBE_TX_UNLOCK(txr);
1522280182Sjfv
1523280182Sjfv	/* Check for fan failure */
1524283883Sjfv	if ((hw->device_id == IXGBE_DEV_ID_82598AT) &&
1525283883Sjfv	    (reg_eicr & IXGBE_EICR_GPI_SDP1)) {
1526280182Sjfv                device_printf(adapter->dev, "\nCRITICAL: FAN FAILURE!! "
1527280182Sjfv		    "REPLACE IMMEDIATELY!!\n");
1528280182Sjfv		IXGBE_WRITE_REG(hw, IXGBE_EIMS, IXGBE_EICR_GPI_SDP1_BY_MAC(hw));
1529280182Sjfv	}
1530280182Sjfv
1531280182Sjfv	/* Link status change */
1532280182Sjfv	if (reg_eicr & IXGBE_EICR_LSC)
1533280182Sjfv		taskqueue_enqueue(adapter->tq, &adapter->link_task);
1534280182Sjfv
1535282289Serj	/* External PHY interrupt */
1536282289Serj	if (hw->device_id == IXGBE_DEV_ID_X550EM_X_10G_T &&
1537282289Serj	    (reg_eicr & IXGBE_EICR_GPI_SDP0_X540))
1538282289Serj		taskqueue_enqueue(adapter->tq, &adapter->phy_task);
1539282289Serj
1540280182Sjfv	if (more)
1541280182Sjfv		taskqueue_enqueue(que->tq, &que->que_task);
1542280182Sjfv	else
1543280182Sjfv		ixgbe_enable_intr(adapter);
1544280182Sjfv	return;
1545280182Sjfv}
1546280182Sjfv
1547280182Sjfv
1548280182Sjfv/*********************************************************************
1549280182Sjfv *
1550280182Sjfv *  MSIX Queue Interrupt Service routine
1551280182Sjfv *
1552280182Sjfv **********************************************************************/
1553280182Sjfvvoid
1554280182Sjfvixgbe_msix_que(void *arg)
1555280182Sjfv{
1556280182Sjfv	struct ix_queue	*que = arg;
1557280182Sjfv	struct adapter  *adapter = que->adapter;
1558280182Sjfv	struct ifnet    *ifp = adapter->ifp;
1559280182Sjfv	struct tx_ring	*txr = que->txr;
1560280182Sjfv	struct rx_ring	*rxr = que->rxr;
1561280182Sjfv	bool		more;
1562280182Sjfv	u32		newitr = 0;
1563280182Sjfv
1564283883Sjfv
1565280182Sjfv	/* Protect against spurious interrupts */
1566280182Sjfv	if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0)
1567280182Sjfv		return;
1568280182Sjfv
1569280182Sjfv	ixgbe_disable_queue(adapter, que->msix);
1570280182Sjfv	++que->irqs;
1571280182Sjfv
1572280182Sjfv	more = ixgbe_rxeof(que);
1573280182Sjfv
1574280182Sjfv	IXGBE_TX_LOCK(txr);
1575280182Sjfv	ixgbe_txeof(txr);
1576280182Sjfv#ifdef IXGBE_LEGACY_TX
1577280182Sjfv	if (!IFQ_DRV_IS_EMPTY(ifp->if_snd))
1578280182Sjfv		ixgbe_start_locked(txr, ifp);
1579280182Sjfv#else
1580280182Sjfv	if (!drbr_empty(ifp, txr->br))
1581280182Sjfv		ixgbe_mq_start_locked(ifp, txr);
1582280182Sjfv#endif
1583280182Sjfv	IXGBE_TX_UNLOCK(txr);
1584280182Sjfv
1585280182Sjfv	/* Do AIM now? */
1586280182Sjfv
1587294795Ssmh	if (adapter->enable_aim == FALSE)
1588280182Sjfv		goto no_calc;
1589280182Sjfv	/*
1590280182Sjfv	** Do Adaptive Interrupt Moderation:
1591280182Sjfv        **  - Write out last calculated setting
1592280182Sjfv	**  - Calculate based on average size over
1593280182Sjfv	**    the last interval.
1594280182Sjfv	*/
1595280182Sjfv        if (que->eitr_setting)
1596280182Sjfv                IXGBE_WRITE_REG(&adapter->hw,
1597280182Sjfv                    IXGBE_EITR(que->msix), que->eitr_setting);
1598280182Sjfv
1599280182Sjfv        que->eitr_setting = 0;
1600280182Sjfv
1601280182Sjfv        /* Idle, do nothing */
1602280182Sjfv        if ((txr->bytes == 0) && (rxr->bytes == 0))
1603280182Sjfv                goto no_calc;
1604280182Sjfv
1605280182Sjfv	if ((txr->bytes) && (txr->packets))
1606280182Sjfv               	newitr = txr->bytes/txr->packets;
1607280182Sjfv	if ((rxr->bytes) && (rxr->packets))
1608280182Sjfv		newitr = max(newitr,
1609280182Sjfv		    (rxr->bytes / rxr->packets));
1610280182Sjfv	newitr += 24; /* account for hardware frame, crc */
1611280182Sjfv
1612280182Sjfv	/* set an upper boundary */
1613280182Sjfv	newitr = min(newitr, 3000);
1614280182Sjfv
1615280182Sjfv	/* Be nice to the mid range */
1616280182Sjfv	if ((newitr > 300) && (newitr < 1200))
1617280182Sjfv		newitr = (newitr / 3);
1618280182Sjfv	else
1619280182Sjfv		newitr = (newitr / 2);
1620280182Sjfv
1621280182Sjfv        if (adapter->hw.mac.type == ixgbe_mac_82598EB)
1622280182Sjfv                newitr |= newitr << 16;
1623280182Sjfv        else
1624280182Sjfv                newitr |= IXGBE_EITR_CNT_WDIS;
1625280182Sjfv
1626280182Sjfv        /* save for next interrupt */
1627280182Sjfv        que->eitr_setting = newitr;
1628280182Sjfv
1629280182Sjfv        /* Reset state */
1630280182Sjfv        txr->bytes = 0;
1631280182Sjfv        txr->packets = 0;
1632280182Sjfv        rxr->bytes = 0;
1633280182Sjfv        rxr->packets = 0;
1634280182Sjfv
1635280182Sjfvno_calc:
1636280182Sjfv	if (more)
1637280182Sjfv		taskqueue_enqueue(que->tq, &que->que_task);
1638280182Sjfv	else
1639280182Sjfv		ixgbe_enable_queue(adapter, que->msix);
1640280182Sjfv	return;
1641280182Sjfv}
1642280182Sjfv
1643280182Sjfv
1644280182Sjfvstatic void
1645280182Sjfvixgbe_msix_link(void *arg)
1646280182Sjfv{
1647280182Sjfv	struct adapter	*adapter = arg;
1648280182Sjfv	struct ixgbe_hw *hw = &adapter->hw;
1649282289Serj	u32		reg_eicr, mod_mask;
1650280182Sjfv
1651282289Serj	++adapter->link_irq;
1652280182Sjfv
1653292674Ssbruno	/* Pause other interrupts */
1654292674Ssbruno	IXGBE_WRITE_REG(hw, IXGBE_EIMC, IXGBE_EIMC_OTHER);
1655292674Ssbruno
1656280182Sjfv	/* First get the cause */
1657280182Sjfv	reg_eicr = IXGBE_READ_REG(hw, IXGBE_EICS);
1658280182Sjfv	/* Be sure the queue bits are not cleared */
1659280182Sjfv	reg_eicr &= ~IXGBE_EICR_RTX_QUEUE;
1660280182Sjfv	/* Clear interrupt with write */
1661280182Sjfv	IXGBE_WRITE_REG(hw, IXGBE_EICR, reg_eicr);
1662280182Sjfv
1663280182Sjfv	/* Link status change */
1664292674Ssbruno	if (reg_eicr & IXGBE_EICR_LSC) {
1665292674Ssbruno		IXGBE_WRITE_REG(hw, IXGBE_EIMC, IXGBE_EIMC_LSC);
1666280182Sjfv		taskqueue_enqueue(adapter->tq, &adapter->link_task);
1667292674Ssbruno	}
1668280182Sjfv
1669280182Sjfv	if (adapter->hw.mac.type != ixgbe_mac_82598EB) {
1670280182Sjfv#ifdef IXGBE_FDIR
1671280182Sjfv		if (reg_eicr & IXGBE_EICR_FLOW_DIR) {
1672280182Sjfv			/* This is probably overkill :) */
1673280182Sjfv			if (!atomic_cmpset_int(&adapter->fdir_reinit, 0, 1))
1674280182Sjfv				return;
1675280182Sjfv                	/* Disable the interrupt */
1676280182Sjfv			IXGBE_WRITE_REG(hw, IXGBE_EIMC, IXGBE_EICR_FLOW_DIR);
1677280182Sjfv			taskqueue_enqueue(adapter->tq, &adapter->fdir_task);
1678280182Sjfv		} else
1679280182Sjfv#endif
1680280182Sjfv		if (reg_eicr & IXGBE_EICR_ECC) {
1681292674Ssbruno			device_printf(adapter->dev, "CRITICAL: ECC ERROR!! "
1682280182Sjfv			    "Please Reboot!!\n");
1683280182Sjfv			IXGBE_WRITE_REG(hw, IXGBE_EICR, IXGBE_EICR_ECC);
1684282289Serj		}
1685280182Sjfv
1686282289Serj		/* Check for over temp condition */
1687282289Serj		if (reg_eicr & IXGBE_EICR_TS) {
1688292674Ssbruno			device_printf(adapter->dev, "CRITICAL: OVER TEMP!! "
1689282289Serj			    "PHY IS SHUT DOWN!!\n");
1690282289Serj			device_printf(adapter->dev, "System shutdown required!\n");
1691282289Serj			IXGBE_WRITE_REG(hw, IXGBE_EICR, IXGBE_EICR_TS);
1692280182Sjfv		}
1693283883Sjfv#ifdef PCI_IOV
1694283883Sjfv		if (reg_eicr & IXGBE_EICR_MAILBOX)
1695283883Sjfv			taskqueue_enqueue(adapter->tq, &adapter->mbx_task);
1696283883Sjfv#endif
1697282289Serj	}
1698280182Sjfv
1699282289Serj	/* Pluggable optics-related interrupt */
1700282289Serj	if (hw->device_id == IXGBE_DEV_ID_X550EM_X_SFP)
1701282289Serj		mod_mask = IXGBE_EICR_GPI_SDP0_X540;
1702282289Serj	else
1703282289Serj		mod_mask = IXGBE_EICR_GPI_SDP2_BY_MAC(hw);
1704282289Serj
1705282289Serj	if (ixgbe_is_sfp(hw)) {
1706282289Serj		if (reg_eicr & IXGBE_EICR_GPI_SDP1_BY_MAC(hw)) {
1707282289Serj			IXGBE_WRITE_REG(hw, IXGBE_EICR, IXGBE_EICR_GPI_SDP1_BY_MAC(hw));
1708282289Serj			taskqueue_enqueue(adapter->tq, &adapter->msf_task);
1709282289Serj		} else if (reg_eicr & mod_mask) {
1710282289Serj			IXGBE_WRITE_REG(hw, IXGBE_EICR, mod_mask);
1711282289Serj			taskqueue_enqueue(adapter->tq, &adapter->mod_task);
1712282289Serj		}
1713282289Serj	}
1714282289Serj
1715280182Sjfv	/* Check for fan failure */
1716280182Sjfv	if ((hw->device_id == IXGBE_DEV_ID_82598AT) &&
1717282289Serj	    (reg_eicr & IXGBE_EICR_GPI_SDP1)) {
1718282289Serj		IXGBE_WRITE_REG(hw, IXGBE_EICR, IXGBE_EICR_GPI_SDP1);
1719280182Sjfv                device_printf(adapter->dev, "\nCRITICAL: FAN FAILURE!! "
1720280182Sjfv		    "REPLACE IMMEDIATELY!!\n");
1721280182Sjfv	}
1722280182Sjfv
1723282289Serj	/* External PHY interrupt */
1724282289Serj	if (hw->device_id == IXGBE_DEV_ID_X550EM_X_10G_T &&
1725282289Serj	    (reg_eicr & IXGBE_EICR_GPI_SDP0_X540)) {
1726282289Serj		IXGBE_WRITE_REG(hw, IXGBE_EICR, IXGBE_EICR_GPI_SDP0_X540);
1727282289Serj		taskqueue_enqueue(adapter->tq, &adapter->phy_task);
1728280182Sjfv	}
1729280182Sjfv
1730292674Ssbruno	/* Re-enable other interrupts */
1731280182Sjfv	IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMS, IXGBE_EIMS_OTHER);
1732280182Sjfv	return;
1733280182Sjfv}
1734280182Sjfv
1735280182Sjfv/*********************************************************************
1736280182Sjfv *
1737280182Sjfv *  Media Ioctl callback
1738280182Sjfv *
1739280182Sjfv *  This routine is called whenever the user queries the status of
1740280182Sjfv *  the interface using ifconfig.
1741280182Sjfv *
1742280182Sjfv **********************************************************************/
1743280182Sjfvstatic void
1744280182Sjfvixgbe_media_status(struct ifnet * ifp, struct ifmediareq * ifmr)
1745280182Sjfv{
1746280182Sjfv	struct adapter *adapter = ifp->if_softc;
1747280182Sjfv	struct ixgbe_hw *hw = &adapter->hw;
1748280182Sjfv	int layer;
1749280182Sjfv
1750280182Sjfv	INIT_DEBUGOUT("ixgbe_media_status: begin");
1751280182Sjfv	IXGBE_CORE_LOCK(adapter);
1752280182Sjfv	ixgbe_update_link_status(adapter);
1753280182Sjfv
1754280182Sjfv	ifmr->ifm_status = IFM_AVALID;
1755280182Sjfv	ifmr->ifm_active = IFM_ETHER;
1756280182Sjfv
1757280182Sjfv	if (!adapter->link_active) {
1758280182Sjfv		IXGBE_CORE_UNLOCK(adapter);
1759280182Sjfv		return;
1760280182Sjfv	}
1761280182Sjfv
1762280182Sjfv	ifmr->ifm_status |= IFM_ACTIVE;
1763283883Sjfv	layer = adapter->phy_layer;
1764280182Sjfv
1765280182Sjfv	if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_T ||
1766280182Sjfv	    layer & IXGBE_PHYSICAL_LAYER_1000BASE_T ||
1767280182Sjfv	    layer & IXGBE_PHYSICAL_LAYER_100BASE_TX)
1768280182Sjfv		switch (adapter->link_speed) {
1769280182Sjfv		case IXGBE_LINK_SPEED_10GB_FULL:
1770280182Sjfv			ifmr->ifm_active |= IFM_10G_T | IFM_FDX;
1771280182Sjfv			break;
1772280182Sjfv		case IXGBE_LINK_SPEED_1GB_FULL:
1773280182Sjfv			ifmr->ifm_active |= IFM_1000_T | IFM_FDX;
1774280182Sjfv			break;
1775280182Sjfv		case IXGBE_LINK_SPEED_100_FULL:
1776280182Sjfv			ifmr->ifm_active |= IFM_100_TX | IFM_FDX;
1777280182Sjfv			break;
1778280182Sjfv		}
1779280182Sjfv	if (layer & IXGBE_PHYSICAL_LAYER_SFP_PLUS_CU ||
1780280182Sjfv	    layer & IXGBE_PHYSICAL_LAYER_SFP_ACTIVE_DA)
1781280182Sjfv		switch (adapter->link_speed) {
1782280182Sjfv		case IXGBE_LINK_SPEED_10GB_FULL:
1783280182Sjfv			ifmr->ifm_active |= IFM_10G_TWINAX | IFM_FDX;
1784280182Sjfv			break;
1785280182Sjfv		}
1786280182Sjfv	if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_LR)
1787280182Sjfv		switch (adapter->link_speed) {
1788280182Sjfv		case IXGBE_LINK_SPEED_10GB_FULL:
1789280182Sjfv			ifmr->ifm_active |= IFM_10G_LR | IFM_FDX;
1790280182Sjfv			break;
1791280182Sjfv		case IXGBE_LINK_SPEED_1GB_FULL:
1792280182Sjfv			ifmr->ifm_active |= IFM_1000_LX | IFM_FDX;
1793280182Sjfv			break;
1794280182Sjfv		}
1795280182Sjfv	if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_LRM)
1796280182Sjfv		switch (adapter->link_speed) {
1797280182Sjfv		case IXGBE_LINK_SPEED_10GB_FULL:
1798280182Sjfv			ifmr->ifm_active |= IFM_10G_LRM | IFM_FDX;
1799280182Sjfv			break;
1800280182Sjfv		case IXGBE_LINK_SPEED_1GB_FULL:
1801280182Sjfv			ifmr->ifm_active |= IFM_1000_LX | IFM_FDX;
1802280182Sjfv			break;
1803280182Sjfv		}
1804280182Sjfv	if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_SR ||
1805280182Sjfv	    layer & IXGBE_PHYSICAL_LAYER_1000BASE_SX)
1806280182Sjfv		switch (adapter->link_speed) {
1807280182Sjfv		case IXGBE_LINK_SPEED_10GB_FULL:
1808280182Sjfv			ifmr->ifm_active |= IFM_10G_SR | IFM_FDX;
1809280182Sjfv			break;
1810280182Sjfv		case IXGBE_LINK_SPEED_1GB_FULL:
1811280182Sjfv			ifmr->ifm_active |= IFM_1000_SX | IFM_FDX;
1812280182Sjfv			break;
1813280182Sjfv		}
1814280182Sjfv	if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_CX4)
1815280182Sjfv		switch (adapter->link_speed) {
1816280182Sjfv		case IXGBE_LINK_SPEED_10GB_FULL:
1817280182Sjfv			ifmr->ifm_active |= IFM_10G_CX4 | IFM_FDX;
1818280182Sjfv			break;
1819280182Sjfv		}
1820280182Sjfv	/*
1821280182Sjfv	** XXX: These need to use the proper media types once
1822280182Sjfv	** they're added.
1823280182Sjfv	*/
1824292674Ssbruno#ifndef IFM_ETH_XTYPE
1825280182Sjfv	if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_KR)
1826280182Sjfv		switch (adapter->link_speed) {
1827280182Sjfv		case IXGBE_LINK_SPEED_10GB_FULL:
1828282289Serj			ifmr->ifm_active |= IFM_10G_SR | IFM_FDX;
1829280182Sjfv			break;
1830282289Serj		case IXGBE_LINK_SPEED_2_5GB_FULL:
1831282289Serj			ifmr->ifm_active |= IFM_2500_SX | IFM_FDX;
1832282289Serj			break;
1833280182Sjfv		case IXGBE_LINK_SPEED_1GB_FULL:
1834282289Serj			ifmr->ifm_active |= IFM_1000_CX | IFM_FDX;
1835280182Sjfv			break;
1836280182Sjfv		}
1837282289Serj	else if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_KX4
1838280182Sjfv	    || layer & IXGBE_PHYSICAL_LAYER_1000BASE_KX)
1839280182Sjfv		switch (adapter->link_speed) {
1840280182Sjfv		case IXGBE_LINK_SPEED_10GB_FULL:
1841282289Serj			ifmr->ifm_active |= IFM_10G_CX4 | IFM_FDX;
1842280182Sjfv			break;
1843282289Serj		case IXGBE_LINK_SPEED_2_5GB_FULL:
1844282289Serj			ifmr->ifm_active |= IFM_2500_SX | IFM_FDX;
1845282289Serj			break;
1846280182Sjfv		case IXGBE_LINK_SPEED_1GB_FULL:
1847282289Serj			ifmr->ifm_active |= IFM_1000_CX | IFM_FDX;
1848280182Sjfv			break;
1849280182Sjfv		}
1850292674Ssbruno#else
1851292674Ssbruno	if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_KR)
1852292674Ssbruno		switch (adapter->link_speed) {
1853292674Ssbruno		case IXGBE_LINK_SPEED_10GB_FULL:
1854292674Ssbruno			ifmr->ifm_active |= IFM_10G_KR | IFM_FDX;
1855292674Ssbruno			break;
1856292674Ssbruno		case IXGBE_LINK_SPEED_2_5GB_FULL:
1857292674Ssbruno			ifmr->ifm_active |= IFM_2500_KX | IFM_FDX;
1858292674Ssbruno			break;
1859292674Ssbruno		case IXGBE_LINK_SPEED_1GB_FULL:
1860292674Ssbruno			ifmr->ifm_active |= IFM_1000_KX | IFM_FDX;
1861292674Ssbruno			break;
1862292674Ssbruno		}
1863292674Ssbruno	else if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_KX4
1864292674Ssbruno	    || layer & IXGBE_PHYSICAL_LAYER_1000BASE_KX)
1865292674Ssbruno		switch (adapter->link_speed) {
1866292674Ssbruno		case IXGBE_LINK_SPEED_10GB_FULL:
1867292674Ssbruno			ifmr->ifm_active |= IFM_10G_KX4 | IFM_FDX;
1868292674Ssbruno			break;
1869292674Ssbruno		case IXGBE_LINK_SPEED_2_5GB_FULL:
1870292674Ssbruno			ifmr->ifm_active |= IFM_2500_KX | IFM_FDX;
1871292674Ssbruno			break;
1872292674Ssbruno		case IXGBE_LINK_SPEED_1GB_FULL:
1873292674Ssbruno			ifmr->ifm_active |= IFM_1000_KX | IFM_FDX;
1874292674Ssbruno			break;
1875292674Ssbruno		}
1876292674Ssbruno#endif
1877280182Sjfv
1878280182Sjfv	/* If nothing is recognized... */
1879280182Sjfv	if (IFM_SUBTYPE(ifmr->ifm_active) == 0)
1880280182Sjfv		ifmr->ifm_active |= IFM_UNKNOWN;
1881280182Sjfv
1882280182Sjfv#if __FreeBSD_version >= 900025
1883282289Serj	/* Display current flow control setting used on link */
1884282289Serj	if (hw->fc.current_mode == ixgbe_fc_rx_pause ||
1885282289Serj	    hw->fc.current_mode == ixgbe_fc_full)
1886280182Sjfv		ifmr->ifm_active |= IFM_ETH_RXPAUSE;
1887282289Serj	if (hw->fc.current_mode == ixgbe_fc_tx_pause ||
1888282289Serj	    hw->fc.current_mode == ixgbe_fc_full)
1889280182Sjfv		ifmr->ifm_active |= IFM_ETH_TXPAUSE;
1890280182Sjfv#endif
1891280182Sjfv
1892280182Sjfv	IXGBE_CORE_UNLOCK(adapter);
1893280182Sjfv
1894280182Sjfv	return;
1895280182Sjfv}
1896280182Sjfv
1897280182Sjfv/*********************************************************************
1898280182Sjfv *
1899280182Sjfv *  Media Ioctl callback
1900280182Sjfv *
1901280182Sjfv *  This routine is called when the user changes speed/duplex using
1902280182Sjfv *  media/mediopt option with ifconfig.
1903280182Sjfv *
1904280182Sjfv **********************************************************************/
1905280182Sjfvstatic int
1906280182Sjfvixgbe_media_change(struct ifnet * ifp)
1907280182Sjfv{
1908280182Sjfv	struct adapter *adapter = ifp->if_softc;
1909280182Sjfv	struct ifmedia *ifm = &adapter->media;
1910280182Sjfv	struct ixgbe_hw *hw = &adapter->hw;
1911280182Sjfv	ixgbe_link_speed speed = 0;
1912280182Sjfv
1913280182Sjfv	INIT_DEBUGOUT("ixgbe_media_change: begin");
1914280182Sjfv
1915280182Sjfv	if (IFM_TYPE(ifm->ifm_media) != IFM_ETHER)
1916280182Sjfv		return (EINVAL);
1917280182Sjfv
1918282289Serj	if (hw->phy.media_type == ixgbe_media_type_backplane)
1919292674Ssbruno		return (ENODEV);
1920282289Serj
1921280182Sjfv	/*
1922280182Sjfv	** We don't actually need to check against the supported
1923280182Sjfv	** media types of the adapter; ifmedia will take care of
1924280182Sjfv	** that for us.
1925280182Sjfv	*/
1926292674Ssbruno#ifndef IFM_ETH_XTYPE
1927280182Sjfv	switch (IFM_SUBTYPE(ifm->ifm_media)) {
1928280182Sjfv		case IFM_AUTO:
1929280182Sjfv		case IFM_10G_T:
1930280182Sjfv			speed |= IXGBE_LINK_SPEED_100_FULL;
1931280182Sjfv		case IFM_10G_LRM:
1932282289Serj		case IFM_10G_SR: /* KR, too */
1933280182Sjfv		case IFM_10G_LR:
1934282289Serj		case IFM_10G_CX4: /* KX4 */
1935280182Sjfv			speed |= IXGBE_LINK_SPEED_1GB_FULL;
1936280182Sjfv		case IFM_10G_TWINAX:
1937280182Sjfv			speed |= IXGBE_LINK_SPEED_10GB_FULL;
1938280182Sjfv			break;
1939280182Sjfv		case IFM_1000_T:
1940280182Sjfv			speed |= IXGBE_LINK_SPEED_100_FULL;
1941280182Sjfv		case IFM_1000_LX:
1942280182Sjfv		case IFM_1000_SX:
1943282289Serj		case IFM_1000_CX: /* KX */
1944280182Sjfv			speed |= IXGBE_LINK_SPEED_1GB_FULL;
1945280182Sjfv			break;
1946280182Sjfv		case IFM_100_TX:
1947280182Sjfv			speed |= IXGBE_LINK_SPEED_100_FULL;
1948280182Sjfv			break;
1949280182Sjfv		default:
1950280182Sjfv			goto invalid;
1951280182Sjfv	}
1952292674Ssbruno#else
1953292674Ssbruno	switch (IFM_SUBTYPE(ifm->ifm_media)) {
1954292674Ssbruno		case IFM_AUTO:
1955292674Ssbruno		case IFM_10G_T:
1956292674Ssbruno			speed |= IXGBE_LINK_SPEED_100_FULL;
1957292674Ssbruno		case IFM_10G_LRM:
1958292674Ssbruno		case IFM_10G_KR:
1959292674Ssbruno		case IFM_10G_LR:
1960292674Ssbruno		case IFM_10G_KX4:
1961292674Ssbruno			speed |= IXGBE_LINK_SPEED_1GB_FULL;
1962292674Ssbruno		case IFM_10G_TWINAX:
1963292674Ssbruno			speed |= IXGBE_LINK_SPEED_10GB_FULL;
1964292674Ssbruno			break;
1965292674Ssbruno		case IFM_1000_T:
1966292674Ssbruno			speed |= IXGBE_LINK_SPEED_100_FULL;
1967292674Ssbruno		case IFM_1000_LX:
1968292674Ssbruno		case IFM_1000_SX:
1969292674Ssbruno		case IFM_1000_KX:
1970292674Ssbruno			speed |= IXGBE_LINK_SPEED_1GB_FULL;
1971292674Ssbruno			break;
1972292674Ssbruno		case IFM_100_TX:
1973292674Ssbruno			speed |= IXGBE_LINK_SPEED_100_FULL;
1974292674Ssbruno			break;
1975292674Ssbruno		default:
1976292674Ssbruno			goto invalid;
1977292674Ssbruno	}
1978292674Ssbruno#endif
1979280182Sjfv
1980280182Sjfv	hw->mac.autotry_restart = TRUE;
1981280182Sjfv	hw->mac.ops.setup_link(hw, speed, TRUE);
1982294578Ssmh	if (IFM_SUBTYPE(ifm->ifm_media) == IFM_AUTO) {
1983294578Ssmh		adapter->advertise = 0;
1984294578Ssmh	} else {
1985294578Ssmh		if ((speed & IXGBE_LINK_SPEED_10GB_FULL) != 0)
1986294578Ssmh			adapter->advertise |= 1 << 2;
1987294578Ssmh		if ((speed & IXGBE_LINK_SPEED_1GB_FULL) != 0)
1988294578Ssmh			adapter->advertise |= 1 << 1;
1989294578Ssmh		if ((speed & IXGBE_LINK_SPEED_100_FULL) != 0)
1990294578Ssmh			adapter->advertise |= 1 << 0;
1991294578Ssmh	}
1992280182Sjfv
1993280182Sjfv	return (0);
1994280182Sjfv
1995280182Sjfvinvalid:
1996282289Serj	device_printf(adapter->dev, "Invalid media type!\n");
1997280182Sjfv	return (EINVAL);
1998280182Sjfv}
1999280182Sjfv
2000280182Sjfvstatic void
2001280182Sjfvixgbe_set_promisc(struct adapter *adapter)
2002280182Sjfv{
2003280182Sjfv	u_int32_t       reg_rctl;
2004280182Sjfv	struct ifnet   *ifp = adapter->ifp;
2005280182Sjfv	int		mcnt = 0;
2006280182Sjfv
2007280182Sjfv	reg_rctl = IXGBE_READ_REG(&adapter->hw, IXGBE_FCTRL);
2008280182Sjfv	reg_rctl &= (~IXGBE_FCTRL_UPE);
2009280182Sjfv	if (ifp->if_flags & IFF_ALLMULTI)
2010280182Sjfv		mcnt = MAX_NUM_MULTICAST_ADDRESSES;
2011280182Sjfv	else {
2012280182Sjfv		struct	ifmultiaddr *ifma;
2013280182Sjfv#if __FreeBSD_version < 800000
2014280182Sjfv		IF_ADDR_LOCK(ifp);
2015280182Sjfv#else
2016280182Sjfv		if_maddr_rlock(ifp);
2017280182Sjfv#endif
2018280182Sjfv		TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
2019280182Sjfv			if (ifma->ifma_addr->sa_family != AF_LINK)
2020280182Sjfv				continue;
2021280182Sjfv			if (mcnt == MAX_NUM_MULTICAST_ADDRESSES)
2022280182Sjfv				break;
2023280182Sjfv			mcnt++;
2024280182Sjfv		}
2025280182Sjfv#if __FreeBSD_version < 800000
2026280182Sjfv		IF_ADDR_UNLOCK(ifp);
2027280182Sjfv#else
2028280182Sjfv		if_maddr_runlock(ifp);
2029280182Sjfv#endif
2030280182Sjfv	}
2031280182Sjfv	if (mcnt < MAX_NUM_MULTICAST_ADDRESSES)
2032280182Sjfv		reg_rctl &= (~IXGBE_FCTRL_MPE);
2033280182Sjfv	IXGBE_WRITE_REG(&adapter->hw, IXGBE_FCTRL, reg_rctl);
2034280182Sjfv
2035280182Sjfv	if (ifp->if_flags & IFF_PROMISC) {
2036280182Sjfv		reg_rctl |= (IXGBE_FCTRL_UPE | IXGBE_FCTRL_MPE);
2037280182Sjfv		IXGBE_WRITE_REG(&adapter->hw, IXGBE_FCTRL, reg_rctl);
2038280182Sjfv	} else if (ifp->if_flags & IFF_ALLMULTI) {
2039280182Sjfv		reg_rctl |= IXGBE_FCTRL_MPE;
2040280182Sjfv		reg_rctl &= ~IXGBE_FCTRL_UPE;
2041280182Sjfv		IXGBE_WRITE_REG(&adapter->hw, IXGBE_FCTRL, reg_rctl);
2042280182Sjfv	}
2043280182Sjfv	return;
2044280182Sjfv}
2045280182Sjfv
2046280182Sjfv
2047280182Sjfv/*********************************************************************
2048280182Sjfv *  Multicast Update
2049280182Sjfv *
2050280182Sjfv *  This routine is called whenever multicast address list is updated.
2051280182Sjfv *
2052280182Sjfv **********************************************************************/
2053280182Sjfv#define IXGBE_RAR_ENTRIES 16
2054280182Sjfv
2055280182Sjfvstatic void
2056280182Sjfvixgbe_set_multi(struct adapter *adapter)
2057280182Sjfv{
2058283883Sjfv	u32			fctrl;
2059283883Sjfv	u8			*update_ptr;
2060283883Sjfv	struct ifmultiaddr	*ifma;
2061283883Sjfv	struct ixgbe_mc_addr	*mta;
2062283883Sjfv	int			mcnt = 0;
2063283883Sjfv	struct ifnet		*ifp = adapter->ifp;
2064280182Sjfv
2065280182Sjfv	IOCTL_DEBUGOUT("ixgbe_set_multi: begin");
2066280182Sjfv
2067280182Sjfv	mta = adapter->mta;
2068283883Sjfv	bzero(mta, sizeof(*mta) * MAX_NUM_MULTICAST_ADDRESSES);
2069280182Sjfv
2070280182Sjfv#if __FreeBSD_version < 800000
2071280182Sjfv	IF_ADDR_LOCK(ifp);
2072280182Sjfv#else
2073280182Sjfv	if_maddr_rlock(ifp);
2074280182Sjfv#endif
2075280182Sjfv	TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
2076280182Sjfv		if (ifma->ifma_addr->sa_family != AF_LINK)
2077280182Sjfv			continue;
2078280182Sjfv		if (mcnt == MAX_NUM_MULTICAST_ADDRESSES)
2079280182Sjfv			break;
2080280182Sjfv		bcopy(LLADDR((struct sockaddr_dl *) ifma->ifma_addr),
2081283883Sjfv		    mta[mcnt].addr, IXGBE_ETH_LENGTH_OF_ADDRESS);
2082283883Sjfv		mta[mcnt].vmdq = adapter->pool;
2083280182Sjfv		mcnt++;
2084280182Sjfv	}
2085280182Sjfv#if __FreeBSD_version < 800000
2086280182Sjfv	IF_ADDR_UNLOCK(ifp);
2087280182Sjfv#else
2088280182Sjfv	if_maddr_runlock(ifp);
2089280182Sjfv#endif
2090280182Sjfv
2091280182Sjfv	fctrl = IXGBE_READ_REG(&adapter->hw, IXGBE_FCTRL);
2092280182Sjfv	fctrl |= (IXGBE_FCTRL_UPE | IXGBE_FCTRL_MPE);
2093280182Sjfv	if (ifp->if_flags & IFF_PROMISC)
2094280182Sjfv		fctrl |= (IXGBE_FCTRL_UPE | IXGBE_FCTRL_MPE);
2095280182Sjfv	else if (mcnt >= MAX_NUM_MULTICAST_ADDRESSES ||
2096280182Sjfv	    ifp->if_flags & IFF_ALLMULTI) {
2097280182Sjfv		fctrl |= IXGBE_FCTRL_MPE;
2098280182Sjfv		fctrl &= ~IXGBE_FCTRL_UPE;
2099280182Sjfv	} else
2100280182Sjfv		fctrl &= ~(IXGBE_FCTRL_UPE | IXGBE_FCTRL_MPE);
2101280182Sjfv
2102280182Sjfv	IXGBE_WRITE_REG(&adapter->hw, IXGBE_FCTRL, fctrl);
2103280182Sjfv
2104280182Sjfv	if (mcnt < MAX_NUM_MULTICAST_ADDRESSES) {
2105283883Sjfv		update_ptr = (u8 *)mta;
2106280182Sjfv		ixgbe_update_mc_addr_list(&adapter->hw,
2107280182Sjfv		    update_ptr, mcnt, ixgbe_mc_array_itr, TRUE);
2108280182Sjfv	}
2109280182Sjfv
2110280182Sjfv	return;
2111280182Sjfv}
2112280182Sjfv
2113280182Sjfv/*
2114280182Sjfv * This is an iterator function now needed by the multicast
2115280182Sjfv * shared code. It simply feeds the shared code routine the
2116280182Sjfv * addresses in the array of ixgbe_set_multi() one by one.
2117280182Sjfv */
2118280182Sjfvstatic u8 *
2119280182Sjfvixgbe_mc_array_itr(struct ixgbe_hw *hw, u8 **update_ptr, u32 *vmdq)
2120280182Sjfv{
2121283883Sjfv	struct ixgbe_mc_addr *mta;
2122280182Sjfv
2123283883Sjfv	mta = (struct ixgbe_mc_addr *)*update_ptr;
2124283883Sjfv	*vmdq = mta->vmdq;
2125283883Sjfv
2126297793Spfg	*update_ptr = (u8*)(mta + 1);
2127283883Sjfv	return (mta->addr);
2128280182Sjfv}
2129280182Sjfv
2130280182Sjfv
2131280182Sjfv/*********************************************************************
2132280182Sjfv *  Timer routine
2133280182Sjfv *
2134280182Sjfv *  This routine checks for link status,updates statistics,
2135280182Sjfv *  and runs the watchdog check.
2136280182Sjfv *
2137280182Sjfv **********************************************************************/
2138280182Sjfv
2139280182Sjfvstatic void
2140280182Sjfvixgbe_local_timer(void *arg)
2141280182Sjfv{
2142280182Sjfv	struct adapter	*adapter = arg;
2143280182Sjfv	device_t	dev = adapter->dev;
2144280182Sjfv	struct ix_queue *que = adapter->queues;
2145280182Sjfv	u64		queues = 0;
2146280182Sjfv	int		hung = 0;
2147280182Sjfv
2148280182Sjfv	mtx_assert(&adapter->core_mtx, MA_OWNED);
2149280182Sjfv
2150280182Sjfv	/* Check for pluggable optics */
2151280182Sjfv	if (adapter->sfp_probe)
2152280182Sjfv		if (!ixgbe_sfp_probe(adapter))
2153280182Sjfv			goto out; /* Nothing to do */
2154280182Sjfv
2155280182Sjfv	ixgbe_update_link_status(adapter);
2156280182Sjfv	ixgbe_update_stats_counters(adapter);
2157280182Sjfv
2158280182Sjfv	/*
2159280182Sjfv	** Check the TX queues status
2160280182Sjfv	**	- mark hung queues so we don't schedule on them
2161280182Sjfv	**      - watchdog only if all queues show hung
2162280182Sjfv	*/
2163280182Sjfv	for (int i = 0; i < adapter->num_queues; i++, que++) {
2164280182Sjfv		/* Keep track of queues with work for soft irq */
2165280182Sjfv		if (que->txr->busy)
2166280182Sjfv			queues |= ((u64)1 << que->me);
2167280182Sjfv		/*
2168280182Sjfv		** Each time txeof runs without cleaning, but there
2169280182Sjfv		** are uncleaned descriptors it increments busy. If
2170280182Sjfv		** we get to the MAX we declare it hung.
2171280182Sjfv		*/
2172280182Sjfv		if (que->busy == IXGBE_QUEUE_HUNG) {
2173280182Sjfv			++hung;
2174280182Sjfv			/* Mark the queue as inactive */
2175280182Sjfv			adapter->active_queues &= ~((u64)1 << que->me);
2176280182Sjfv			continue;
2177280182Sjfv		} else {
2178280182Sjfv			/* Check if we've come back from hung */
2179280182Sjfv			if ((adapter->active_queues & ((u64)1 << que->me)) == 0)
2180280182Sjfv                                adapter->active_queues |= ((u64)1 << que->me);
2181280182Sjfv		}
2182280182Sjfv		if (que->busy >= IXGBE_MAX_TX_BUSY) {
2183280182Sjfv			device_printf(dev,"Warning queue %d "
2184280182Sjfv			    "appears to be hung!\n", i);
2185280182Sjfv			que->txr->busy = IXGBE_QUEUE_HUNG;
2186280182Sjfv			++hung;
2187280182Sjfv		}
2188280182Sjfv
2189280182Sjfv	}
2190280182Sjfv
2191280182Sjfv	/* Only truly watchdog if all queues show hung */
2192280182Sjfv	if (hung == adapter->num_queues)
2193280182Sjfv		goto watchdog;
2194280182Sjfv	else if (queues != 0) { /* Force an IRQ on queues with work */
2195280182Sjfv		ixgbe_rearm_queues(adapter, queues);
2196280182Sjfv	}
2197280182Sjfv
2198280182Sjfvout:
2199280182Sjfv	callout_reset(&adapter->timer, hz, ixgbe_local_timer, adapter);
2200280182Sjfv	return;
2201280182Sjfv
2202280182Sjfvwatchdog:
2203280182Sjfv	device_printf(adapter->dev, "Watchdog timeout -- resetting\n");
2204280182Sjfv	adapter->ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
2205280182Sjfv	adapter->watchdog_events++;
2206280182Sjfv	ixgbe_init_locked(adapter);
2207280182Sjfv}
2208280182Sjfv
2209283883Sjfv
2210280182Sjfv/*
2211280182Sjfv** Note: this routine updates the OS on the link state
2212280182Sjfv**	the real check of the hardware only happens with
2213280182Sjfv**	a link interrupt.
2214280182Sjfv*/
2215280182Sjfvstatic void
2216280182Sjfvixgbe_update_link_status(struct adapter *adapter)
2217280182Sjfv{
2218280182Sjfv	struct ifnet	*ifp = adapter->ifp;
2219280182Sjfv	device_t dev = adapter->dev;
2220280182Sjfv
2221280182Sjfv	if (adapter->link_up){
2222280182Sjfv		if (adapter->link_active == FALSE) {
2223280182Sjfv			if (bootverbose)
2224280182Sjfv				device_printf(dev,"Link is up %d Gbps %s \n",
2225280182Sjfv				    ((adapter->link_speed == 128)? 10:1),
2226280182Sjfv				    "Full Duplex");
2227280182Sjfv			adapter->link_active = TRUE;
2228280182Sjfv			/* Update any Flow Control changes */
2229280182Sjfv			ixgbe_fc_enable(&adapter->hw);
2230282289Serj			/* Update DMA coalescing config */
2231282289Serj			ixgbe_config_dmac(adapter);
2232280182Sjfv			if_link_state_change(ifp, LINK_STATE_UP);
2233283883Sjfv#ifdef PCI_IOV
2234283883Sjfv			ixgbe_ping_all_vfs(adapter);
2235283883Sjfv#endif
2236280182Sjfv		}
2237280182Sjfv	} else { /* Link down */
2238280182Sjfv		if (adapter->link_active == TRUE) {
2239280182Sjfv			if (bootverbose)
2240280182Sjfv				device_printf(dev,"Link is Down\n");
2241280182Sjfv			if_link_state_change(ifp, LINK_STATE_DOWN);
2242280182Sjfv			adapter->link_active = FALSE;
2243283883Sjfv#ifdef PCI_IOV
2244283883Sjfv			ixgbe_ping_all_vfs(adapter);
2245283883Sjfv#endif
2246280182Sjfv		}
2247280182Sjfv	}
2248280182Sjfv
2249280182Sjfv	return;
2250280182Sjfv}
2251280182Sjfv
2252280182Sjfv
2253280182Sjfv/*********************************************************************
2254280182Sjfv *
2255280182Sjfv *  This routine disables all traffic on the adapter by issuing a
2256280182Sjfv *  global reset on the MAC and deallocates TX/RX buffers.
2257280182Sjfv *
2258280182Sjfv **********************************************************************/
2259280182Sjfv
2260280182Sjfvstatic void
2261280182Sjfvixgbe_stop(void *arg)
2262280182Sjfv{
2263280182Sjfv	struct ifnet   *ifp;
2264280182Sjfv	struct adapter *adapter = arg;
2265280182Sjfv	struct ixgbe_hw *hw = &adapter->hw;
2266280182Sjfv	ifp = adapter->ifp;
2267280182Sjfv
2268280182Sjfv	mtx_assert(&adapter->core_mtx, MA_OWNED);
2269280182Sjfv
2270280182Sjfv	INIT_DEBUGOUT("ixgbe_stop: begin\n");
2271280182Sjfv	ixgbe_disable_intr(adapter);
2272280182Sjfv	callout_stop(&adapter->timer);
2273280182Sjfv
2274280182Sjfv	/* Let the stack know...*/
2275280182Sjfv	ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
2276280182Sjfv
2277280182Sjfv	ixgbe_reset_hw(hw);
2278280182Sjfv	hw->adapter_stopped = FALSE;
2279280182Sjfv	ixgbe_stop_adapter(hw);
2280280182Sjfv	if (hw->mac.type == ixgbe_mac_82599EB)
2281280182Sjfv		ixgbe_stop_mac_link_on_d3_82599(hw);
2282280182Sjfv	/* Turn off the laser - noop with no optics */
2283280182Sjfv	ixgbe_disable_tx_laser(hw);
2284280182Sjfv
2285280182Sjfv	/* Update the stack */
2286280182Sjfv	adapter->link_up = FALSE;
2287280182Sjfv       	ixgbe_update_link_status(adapter);
2288280182Sjfv
2289280182Sjfv	/* reprogram the RAR[0] in case user changed it. */
2290280182Sjfv	ixgbe_set_rar(&adapter->hw, 0, adapter->hw.mac.addr, 0, IXGBE_RAH_AV);
2291280182Sjfv
2292280182Sjfv	return;
2293280182Sjfv}
2294280182Sjfv
2295280182Sjfv
2296280182Sjfv/*********************************************************************
2297280182Sjfv *
2298280182Sjfv *  Determine hardware revision.
2299280182Sjfv *
2300280182Sjfv **********************************************************************/
2301280182Sjfvstatic void
2302280182Sjfvixgbe_identify_hardware(struct adapter *adapter)
2303280182Sjfv{
2304280182Sjfv	device_t        dev = adapter->dev;
2305280182Sjfv	struct ixgbe_hw *hw = &adapter->hw;
2306280182Sjfv
2307280182Sjfv	/* Save off the information about this board */
2308280182Sjfv	hw->vendor_id = pci_get_vendor(dev);
2309280182Sjfv	hw->device_id = pci_get_device(dev);
2310280182Sjfv	hw->revision_id = pci_read_config(dev, PCIR_REVID, 1);
2311280182Sjfv	hw->subsystem_vendor_id =
2312280182Sjfv	    pci_read_config(dev, PCIR_SUBVEND_0, 2);
2313280182Sjfv	hw->subsystem_device_id =
2314280182Sjfv	    pci_read_config(dev, PCIR_SUBDEV_0, 2);
2315280182Sjfv
2316280182Sjfv	/*
2317280182Sjfv	** Make sure BUSMASTER is set
2318280182Sjfv	*/
2319280182Sjfv	pci_enable_busmaster(dev);
2320280182Sjfv
2321280182Sjfv	/* We need this here to set the num_segs below */
2322280182Sjfv	ixgbe_set_mac_type(hw);
2323280182Sjfv
2324282289Serj	/* Pick up the 82599 settings */
2325280182Sjfv	if (hw->mac.type != ixgbe_mac_82598EB) {
2326280182Sjfv		hw->phy.smart_speed = ixgbe_smart_speed;
2327280182Sjfv		adapter->num_segs = IXGBE_82599_SCATTER;
2328280182Sjfv	} else
2329280182Sjfv		adapter->num_segs = IXGBE_82598_SCATTER;
2330280182Sjfv
2331280182Sjfv	return;
2332280182Sjfv}
2333280182Sjfv
2334280182Sjfv/*********************************************************************
2335280182Sjfv *
2336280182Sjfv *  Determine optic type
2337280182Sjfv *
2338280182Sjfv **********************************************************************/
2339280182Sjfvstatic void
2340280182Sjfvixgbe_setup_optics(struct adapter *adapter)
2341280182Sjfv{
2342280182Sjfv	struct ixgbe_hw *hw = &adapter->hw;
2343280182Sjfv	int		layer;
2344280182Sjfv
2345283883Sjfv	layer = adapter->phy_layer = ixgbe_get_supported_physical_layer(hw);
2346280182Sjfv
2347280182Sjfv	if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_T) {
2348280182Sjfv		adapter->optics = IFM_10G_T;
2349280182Sjfv		return;
2350280182Sjfv	}
2351280182Sjfv
2352280182Sjfv	if (layer & IXGBE_PHYSICAL_LAYER_1000BASE_T) {
2353280182Sjfv		adapter->optics = IFM_1000_T;
2354280182Sjfv		return;
2355280182Sjfv	}
2356280182Sjfv
2357280182Sjfv	if (layer & IXGBE_PHYSICAL_LAYER_1000BASE_SX) {
2358280182Sjfv		adapter->optics = IFM_1000_SX;
2359280182Sjfv		return;
2360280182Sjfv	}
2361280182Sjfv
2362280182Sjfv	if (layer & (IXGBE_PHYSICAL_LAYER_10GBASE_LR |
2363280182Sjfv	    IXGBE_PHYSICAL_LAYER_10GBASE_LRM)) {
2364280182Sjfv		adapter->optics = IFM_10G_LR;
2365280182Sjfv		return;
2366280182Sjfv	}
2367280182Sjfv
2368280182Sjfv	if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_SR) {
2369280182Sjfv		adapter->optics = IFM_10G_SR;
2370280182Sjfv		return;
2371280182Sjfv	}
2372280182Sjfv
2373280182Sjfv	if (layer & IXGBE_PHYSICAL_LAYER_SFP_PLUS_CU) {
2374280182Sjfv		adapter->optics = IFM_10G_TWINAX;
2375280182Sjfv		return;
2376280182Sjfv	}
2377280182Sjfv
2378280182Sjfv	if (layer & (IXGBE_PHYSICAL_LAYER_10GBASE_KX4 |
2379280182Sjfv	    IXGBE_PHYSICAL_LAYER_10GBASE_CX4)) {
2380280182Sjfv		adapter->optics = IFM_10G_CX4;
2381280182Sjfv		return;
2382280182Sjfv	}
2383280182Sjfv
2384280182Sjfv	/* If we get here just set the default */
2385280182Sjfv	adapter->optics = IFM_ETHER | IFM_AUTO;
2386280182Sjfv	return;
2387280182Sjfv}
2388280182Sjfv
2389280182Sjfv/*********************************************************************
2390280182Sjfv *
2391280182Sjfv *  Setup the Legacy or MSI Interrupt handler
2392280182Sjfv *
2393280182Sjfv **********************************************************************/
2394280182Sjfvstatic int
2395280182Sjfvixgbe_allocate_legacy(struct adapter *adapter)
2396280182Sjfv{
2397280182Sjfv	device_t	dev = adapter->dev;
2398280182Sjfv	struct		ix_queue *que = adapter->queues;
2399280182Sjfv#ifndef IXGBE_LEGACY_TX
2400280182Sjfv	struct tx_ring		*txr = adapter->tx_rings;
2401280182Sjfv#endif
2402280182Sjfv	int		error, rid = 0;
2403280182Sjfv
2404280182Sjfv	/* MSI RID at 1 */
2405280182Sjfv	if (adapter->msix == 1)
2406280182Sjfv		rid = 1;
2407280182Sjfv
2408280182Sjfv	/* We allocate a single interrupt resource */
2409280182Sjfv	adapter->res = bus_alloc_resource_any(dev,
2410280182Sjfv            SYS_RES_IRQ, &rid, RF_SHAREABLE | RF_ACTIVE);
2411280182Sjfv	if (adapter->res == NULL) {
2412280182Sjfv		device_printf(dev, "Unable to allocate bus resource: "
2413280182Sjfv		    "interrupt\n");
2414280182Sjfv		return (ENXIO);
2415280182Sjfv	}
2416280182Sjfv
2417280182Sjfv	/*
2418280182Sjfv	 * Try allocating a fast interrupt and the associated deferred
2419280182Sjfv	 * processing contexts.
2420280182Sjfv	 */
2421280182Sjfv#ifndef IXGBE_LEGACY_TX
2422280182Sjfv	TASK_INIT(&txr->txq_task, 0, ixgbe_deferred_mq_start, txr);
2423280182Sjfv#endif
2424280182Sjfv	TASK_INIT(&que->que_task, 0, ixgbe_handle_que, que);
2425280182Sjfv	que->tq = taskqueue_create_fast("ixgbe_que", M_NOWAIT,
2426280182Sjfv            taskqueue_thread_enqueue, &que->tq);
2427280182Sjfv	taskqueue_start_threads(&que->tq, 1, PI_NET, "%s ixq",
2428280182Sjfv            device_get_nameunit(adapter->dev));
2429280182Sjfv
2430280182Sjfv	/* Tasklets for Link, SFP and Multispeed Fiber */
2431280182Sjfv	TASK_INIT(&adapter->link_task, 0, ixgbe_handle_link, adapter);
2432280182Sjfv	TASK_INIT(&adapter->mod_task, 0, ixgbe_handle_mod, adapter);
2433280182Sjfv	TASK_INIT(&adapter->msf_task, 0, ixgbe_handle_msf, adapter);
2434282289Serj	TASK_INIT(&adapter->phy_task, 0, ixgbe_handle_phy, adapter);
2435280182Sjfv#ifdef IXGBE_FDIR
2436280182Sjfv	TASK_INIT(&adapter->fdir_task, 0, ixgbe_reinit_fdir, adapter);
2437280182Sjfv#endif
2438280182Sjfv	adapter->tq = taskqueue_create_fast("ixgbe_link", M_NOWAIT,
2439280182Sjfv	    taskqueue_thread_enqueue, &adapter->tq);
2440280182Sjfv	taskqueue_start_threads(&adapter->tq, 1, PI_NET, "%s linkq",
2441280182Sjfv	    device_get_nameunit(adapter->dev));
2442280182Sjfv
2443280182Sjfv	if ((error = bus_setup_intr(dev, adapter->res,
2444280182Sjfv            INTR_TYPE_NET | INTR_MPSAFE, NULL, ixgbe_legacy_irq,
2445280182Sjfv            que, &adapter->tag)) != 0) {
2446280182Sjfv		device_printf(dev, "Failed to register fast interrupt "
2447280182Sjfv		    "handler: %d\n", error);
2448280182Sjfv		taskqueue_free(que->tq);
2449280182Sjfv		taskqueue_free(adapter->tq);
2450280182Sjfv		que->tq = NULL;
2451280182Sjfv		adapter->tq = NULL;
2452280182Sjfv		return (error);
2453280182Sjfv	}
2454280182Sjfv	/* For simplicity in the handlers */
2455280182Sjfv	adapter->active_queues = IXGBE_EIMS_ENABLE_MASK;
2456280182Sjfv
2457280182Sjfv	return (0);
2458280182Sjfv}
2459280182Sjfv
2460280182Sjfv
2461280182Sjfv/*********************************************************************
2462280182Sjfv *
2463280182Sjfv *  Setup MSIX Interrupt resources and handlers
2464280182Sjfv *
2465280182Sjfv **********************************************************************/
2466280182Sjfvstatic int
2467280182Sjfvixgbe_allocate_msix(struct adapter *adapter)
2468280182Sjfv{
2469280182Sjfv	device_t        dev = adapter->dev;
2470280182Sjfv	struct 		ix_queue *que = adapter->queues;
2471280182Sjfv	struct  	tx_ring *txr = adapter->tx_rings;
2472280182Sjfv	int 		error, rid, vector = 0;
2473280182Sjfv	int		cpu_id = 0;
2474280204Sadrian#ifdef	RSS
2475280204Sadrian	cpuset_t	cpu_mask;
2476280204Sadrian#endif
2477280182Sjfv
2478280182Sjfv#ifdef	RSS
2479280182Sjfv	/*
2480280182Sjfv	 * If we're doing RSS, the number of queues needs to
2481280182Sjfv	 * match the number of RSS buckets that are configured.
2482280182Sjfv	 *
2483280182Sjfv	 * + If there's more queues than RSS buckets, we'll end
2484280182Sjfv	 *   up with queues that get no traffic.
2485280182Sjfv	 *
2486280182Sjfv	 * + If there's more RSS buckets than queues, we'll end
2487280182Sjfv	 *   up having multiple RSS buckets map to the same queue,
2488280182Sjfv	 *   so there'll be some contention.
2489280182Sjfv	 */
2490280182Sjfv	if (adapter->num_queues != rss_getnumbuckets()) {
2491280182Sjfv		device_printf(dev,
2492280182Sjfv		    "%s: number of queues (%d) != number of RSS buckets (%d)"
2493280182Sjfv		    "; performance will be impacted.\n",
2494280182Sjfv		    __func__,
2495280182Sjfv		    adapter->num_queues,
2496280182Sjfv		    rss_getnumbuckets());
2497280182Sjfv	}
2498280182Sjfv#endif
2499280182Sjfv
2500280182Sjfv	for (int i = 0; i < adapter->num_queues; i++, vector++, que++, txr++) {
2501280182Sjfv		rid = vector + 1;
2502280182Sjfv		que->res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid,
2503280182Sjfv		    RF_SHAREABLE | RF_ACTIVE);
2504280182Sjfv		if (que->res == NULL) {
2505280182Sjfv			device_printf(dev,"Unable to allocate"
2506280182Sjfv		    	    " bus resource: que interrupt [%d]\n", vector);
2507280182Sjfv			return (ENXIO);
2508280182Sjfv		}
2509280182Sjfv		/* Set the handler function */
2510280182Sjfv		error = bus_setup_intr(dev, que->res,
2511280182Sjfv		    INTR_TYPE_NET | INTR_MPSAFE, NULL,
2512280182Sjfv		    ixgbe_msix_que, que, &que->tag);
2513280182Sjfv		if (error) {
2514280182Sjfv			que->res = NULL;
2515280182Sjfv			device_printf(dev, "Failed to register QUE handler");
2516280182Sjfv			return (error);
2517280182Sjfv		}
2518280182Sjfv#if __FreeBSD_version >= 800504
2519292674Ssbruno		bus_describe_intr(dev, que->res, que->tag, "q%d", i);
2520280182Sjfv#endif
2521280182Sjfv		que->msix = vector;
2522280182Sjfv		adapter->active_queues |= (u64)(1 << que->msix);
2523280182Sjfv#ifdef	RSS
2524280182Sjfv		/*
2525280182Sjfv		 * The queue ID is used as the RSS layer bucket ID.
2526280182Sjfv		 * We look up the queue ID -> RSS CPU ID and select
2527280182Sjfv		 * that.
2528280182Sjfv		 */
2529280182Sjfv		cpu_id = rss_getcpu(i % rss_getnumbuckets());
2530280182Sjfv#else
2531280182Sjfv		/*
2532280182Sjfv		 * Bind the msix vector, and thus the
2533280182Sjfv		 * rings to the corresponding cpu.
2534280182Sjfv		 *
2535280182Sjfv		 * This just happens to match the default RSS round-robin
2536280182Sjfv		 * bucket -> queue -> CPU allocation.
2537280182Sjfv		 */
2538280182Sjfv		if (adapter->num_queues > 1)
2539280182Sjfv			cpu_id = i;
2540280182Sjfv#endif
2541280182Sjfv		if (adapter->num_queues > 1)
2542280182Sjfv			bus_bind_intr(dev, que->res, cpu_id);
2543283883Sjfv#ifdef IXGBE_DEBUG
2544280182Sjfv#ifdef	RSS
2545280182Sjfv		device_printf(dev,
2546280182Sjfv		    "Bound RSS bucket %d to CPU %d\n",
2547280182Sjfv		    i, cpu_id);
2548280182Sjfv#else
2549283883Sjfv		device_printf(dev,
2550283883Sjfv		    "Bound queue %d to cpu %d\n",
2551283883Sjfv		    i, cpu_id);
2552280182Sjfv#endif
2553283883Sjfv#endif /* IXGBE_DEBUG */
2554283883Sjfv
2555283883Sjfv
2556280182Sjfv#ifndef IXGBE_LEGACY_TX
2557280182Sjfv		TASK_INIT(&txr->txq_task, 0, ixgbe_deferred_mq_start, txr);
2558280182Sjfv#endif
2559280182Sjfv		TASK_INIT(&que->que_task, 0, ixgbe_handle_que, que);
2560280182Sjfv		que->tq = taskqueue_create_fast("ixgbe_que", M_NOWAIT,
2561280182Sjfv		    taskqueue_thread_enqueue, &que->tq);
2562280182Sjfv#ifdef	RSS
2563280204Sadrian		CPU_SETOF(cpu_id, &cpu_mask);
2564280204Sadrian		taskqueue_start_threads_cpuset(&que->tq, 1, PI_NET,
2565280204Sadrian		    &cpu_mask,
2566280182Sjfv		    "%s (bucket %d)",
2567280182Sjfv		    device_get_nameunit(adapter->dev),
2568280182Sjfv		    cpu_id);
2569280182Sjfv#else
2570292674Ssbruno		taskqueue_start_threads(&que->tq, 1, PI_NET, "%s:q%d",
2571292674Ssbruno		    device_get_nameunit(adapter->dev), i);
2572280182Sjfv#endif
2573280182Sjfv	}
2574280182Sjfv
2575280182Sjfv	/* and Link */
2576280182Sjfv	rid = vector + 1;
2577280182Sjfv	adapter->res = bus_alloc_resource_any(dev,
2578280182Sjfv    	    SYS_RES_IRQ, &rid, RF_SHAREABLE | RF_ACTIVE);
2579280182Sjfv	if (!adapter->res) {
2580280182Sjfv		device_printf(dev,"Unable to allocate"
2581280182Sjfv    	    " bus resource: Link interrupt [%d]\n", rid);
2582280182Sjfv		return (ENXIO);
2583280182Sjfv	}
2584280182Sjfv	/* Set the link handler function */
2585280182Sjfv	error = bus_setup_intr(dev, adapter->res,
2586280182Sjfv	    INTR_TYPE_NET | INTR_MPSAFE, NULL,
2587280182Sjfv	    ixgbe_msix_link, adapter, &adapter->tag);
2588280182Sjfv	if (error) {
2589280182Sjfv		adapter->res = NULL;
2590280182Sjfv		device_printf(dev, "Failed to register LINK handler");
2591280182Sjfv		return (error);
2592280182Sjfv	}
2593280182Sjfv#if __FreeBSD_version >= 800504
2594280182Sjfv	bus_describe_intr(dev, adapter->res, adapter->tag, "link");
2595280182Sjfv#endif
2596280182Sjfv	adapter->vector = vector;
2597280182Sjfv	/* Tasklets for Link, SFP and Multispeed Fiber */
2598280182Sjfv	TASK_INIT(&adapter->link_task, 0, ixgbe_handle_link, adapter);
2599280182Sjfv	TASK_INIT(&adapter->mod_task, 0, ixgbe_handle_mod, adapter);
2600280182Sjfv	TASK_INIT(&adapter->msf_task, 0, ixgbe_handle_msf, adapter);
2601283883Sjfv#ifdef PCI_IOV
2602283883Sjfv	TASK_INIT(&adapter->mbx_task, 0, ixgbe_handle_mbx, adapter);
2603283883Sjfv#endif
2604282289Serj	TASK_INIT(&adapter->phy_task, 0, ixgbe_handle_phy, adapter);
2605280182Sjfv#ifdef IXGBE_FDIR
2606280182Sjfv	TASK_INIT(&adapter->fdir_task, 0, ixgbe_reinit_fdir, adapter);
2607280182Sjfv#endif
2608280182Sjfv	adapter->tq = taskqueue_create_fast("ixgbe_link", M_NOWAIT,
2609280182Sjfv	    taskqueue_thread_enqueue, &adapter->tq);
2610280182Sjfv	taskqueue_start_threads(&adapter->tq, 1, PI_NET, "%s linkq",
2611280182Sjfv	    device_get_nameunit(adapter->dev));
2612280182Sjfv
2613280182Sjfv	return (0);
2614280182Sjfv}
2615280182Sjfv
2616280182Sjfv/*
2617280182Sjfv * Setup Either MSI/X or MSI
2618280182Sjfv */
2619280182Sjfvstatic int
2620280182Sjfvixgbe_setup_msix(struct adapter *adapter)
2621280182Sjfv{
2622280182Sjfv	device_t dev = adapter->dev;
2623280182Sjfv	int rid, want, queues, msgs;
2624280182Sjfv
2625280182Sjfv	/* Override by tuneable */
2626280182Sjfv	if (ixgbe_enable_msix == 0)
2627280182Sjfv		goto msi;
2628280182Sjfv
2629280182Sjfv	/* First try MSI/X */
2630280182Sjfv	msgs = pci_msix_count(dev);
2631280182Sjfv	if (msgs == 0)
2632280182Sjfv		goto msi;
2633280182Sjfv	rid = PCIR_BAR(MSIX_82598_BAR);
2634280182Sjfv	adapter->msix_mem = bus_alloc_resource_any(dev,
2635280182Sjfv	    SYS_RES_MEMORY, &rid, RF_ACTIVE);
2636280182Sjfv       	if (adapter->msix_mem == NULL) {
2637280182Sjfv		rid += 4;	/* 82599 maps in higher BAR */
2638280182Sjfv		adapter->msix_mem = bus_alloc_resource_any(dev,
2639280182Sjfv		    SYS_RES_MEMORY, &rid, RF_ACTIVE);
2640280182Sjfv	}
2641280182Sjfv       	if (adapter->msix_mem == NULL) {
2642280182Sjfv		/* May not be enabled */
2643280182Sjfv		device_printf(adapter->dev,
2644280182Sjfv		    "Unable to map MSIX table \n");
2645280182Sjfv		goto msi;
2646280182Sjfv	}
2647280182Sjfv
2648280182Sjfv	/* Figure out a reasonable auto config value */
2649292674Ssbruno	queues = (mp_ncpus > (msgs - 1)) ? (msgs - 1) : mp_ncpus;
2650280182Sjfv
2651280182Sjfv#ifdef	RSS
2652280182Sjfv	/* If we're doing RSS, clamp at the number of RSS buckets */
2653280182Sjfv	if (queues > rss_getnumbuckets())
2654280182Sjfv		queues = rss_getnumbuckets();
2655280182Sjfv#endif
2656280182Sjfv
2657280182Sjfv	if (ixgbe_num_queues != 0)
2658280182Sjfv		queues = ixgbe_num_queues;
2659292674Ssbruno	/* Set max queues to 8 when autoconfiguring */
2660292674Ssbruno	else if ((ixgbe_num_queues == 0) && (queues > 8))
2661292674Ssbruno		queues = 8;
2662280182Sjfv
2663280182Sjfv	/* reflect correct sysctl value */
2664280182Sjfv	ixgbe_num_queues = queues;
2665280182Sjfv
2666280182Sjfv	/*
2667280182Sjfv	** Want one vector (RX/TX pair) per queue
2668280182Sjfv	** plus an additional for Link.
2669280182Sjfv	*/
2670280182Sjfv	want = queues + 1;
2671280182Sjfv	if (msgs >= want)
2672280182Sjfv		msgs = want;
2673280182Sjfv	else {
2674280182Sjfv               	device_printf(adapter->dev,
2675280182Sjfv		    "MSIX Configuration Problem, "
2676280182Sjfv		    "%d vectors but %d queues wanted!\n",
2677280182Sjfv		    msgs, want);
2678280182Sjfv		goto msi;
2679280182Sjfv	}
2680280182Sjfv	if ((pci_alloc_msix(dev, &msgs) == 0) && (msgs == want)) {
2681280182Sjfv               	device_printf(adapter->dev,
2682280182Sjfv		    "Using MSIX interrupts with %d vectors\n", msgs);
2683280182Sjfv		adapter->num_queues = queues;
2684280182Sjfv		return (msgs);
2685280182Sjfv	}
2686280182Sjfv	/*
2687280182Sjfv	** If MSIX alloc failed or provided us with
2688280182Sjfv	** less than needed, free and fall through to MSI
2689280182Sjfv	*/
2690280182Sjfv	pci_release_msi(dev);
2691280182Sjfv
2692280182Sjfvmsi:
2693280182Sjfv       	if (adapter->msix_mem != NULL) {
2694280182Sjfv		bus_release_resource(dev, SYS_RES_MEMORY,
2695280182Sjfv		    rid, adapter->msix_mem);
2696280182Sjfv		adapter->msix_mem = NULL;
2697280182Sjfv	}
2698292674Ssbruno	msgs = 1;
2699292674Ssbruno	if (pci_alloc_msi(dev, &msgs) == 0) {
2700292674Ssbruno		device_printf(adapter->dev, "Using an MSI interrupt\n");
2701280182Sjfv		return (msgs);
2702280182Sjfv	}
2703292674Ssbruno	device_printf(adapter->dev, "Using a Legacy interrupt\n");
2704280182Sjfv	return (0);
2705280182Sjfv}
2706280182Sjfv
2707280182Sjfv
2708280182Sjfvstatic int
2709280182Sjfvixgbe_allocate_pci_resources(struct adapter *adapter)
2710280182Sjfv{
2711280182Sjfv	int             rid;
2712280182Sjfv	device_t        dev = adapter->dev;
2713280182Sjfv
2714280182Sjfv	rid = PCIR_BAR(0);
2715280182Sjfv	adapter->pci_mem = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
2716280182Sjfv	    &rid, RF_ACTIVE);
2717280182Sjfv
2718280182Sjfv	if (!(adapter->pci_mem)) {
2719292674Ssbruno		device_printf(dev, "Unable to allocate bus resource: memory\n");
2720280182Sjfv		return (ENXIO);
2721280182Sjfv	}
2722280182Sjfv
2723292674Ssbruno	/* Save bus_space values for READ/WRITE_REG macros */
2724280182Sjfv	adapter->osdep.mem_bus_space_tag =
2725280182Sjfv		rman_get_bustag(adapter->pci_mem);
2726280182Sjfv	adapter->osdep.mem_bus_space_handle =
2727280182Sjfv		rman_get_bushandle(adapter->pci_mem);
2728292674Ssbruno	/* Set hw values for shared code */
2729280182Sjfv	adapter->hw.hw_addr = (u8 *) &adapter->osdep.mem_bus_space_handle;
2730292674Ssbruno	adapter->hw.back = adapter;
2731280182Sjfv
2732292674Ssbruno	/* Default to 1 queue if MSI-X setup fails */
2733280182Sjfv	adapter->num_queues = 1;
2734280182Sjfv
2735280182Sjfv	/*
2736292674Ssbruno	** Now setup MSI or MSI-X, should
2737280182Sjfv	** return us the number of supported
2738280182Sjfv	** vectors. (Will be 1 for MSI)
2739280182Sjfv	*/
2740280182Sjfv	adapter->msix = ixgbe_setup_msix(adapter);
2741280182Sjfv	return (0);
2742280182Sjfv}
2743280182Sjfv
2744280182Sjfvstatic void
2745280182Sjfvixgbe_free_pci_resources(struct adapter * adapter)
2746280182Sjfv{
2747280182Sjfv	struct 		ix_queue *que = adapter->queues;
2748280182Sjfv	device_t	dev = adapter->dev;
2749280182Sjfv	int		rid, memrid;
2750280182Sjfv
2751280182Sjfv	if (adapter->hw.mac.type == ixgbe_mac_82598EB)
2752280182Sjfv		memrid = PCIR_BAR(MSIX_82598_BAR);
2753280182Sjfv	else
2754280182Sjfv		memrid = PCIR_BAR(MSIX_82599_BAR);
2755280182Sjfv
2756280182Sjfv	/*
2757280182Sjfv	** There is a slight possibility of a failure mode
2758280182Sjfv	** in attach that will result in entering this function
2759280182Sjfv	** before interrupt resources have been initialized, and
2760280182Sjfv	** in that case we do not want to execute the loops below
2761280182Sjfv	** We can detect this reliably by the state of the adapter
2762280182Sjfv	** res pointer.
2763280182Sjfv	*/
2764280182Sjfv	if (adapter->res == NULL)
2765280182Sjfv		goto mem;
2766280182Sjfv
2767280182Sjfv	/*
2768280182Sjfv	**  Release all msix queue resources:
2769280182Sjfv	*/
2770280182Sjfv	for (int i = 0; i < adapter->num_queues; i++, que++) {
2771280182Sjfv		rid = que->msix + 1;
2772280182Sjfv		if (que->tag != NULL) {
2773280182Sjfv			bus_teardown_intr(dev, que->res, que->tag);
2774280182Sjfv			que->tag = NULL;
2775280182Sjfv		}
2776280182Sjfv		if (que->res != NULL)
2777280182Sjfv			bus_release_resource(dev, SYS_RES_IRQ, rid, que->res);
2778280182Sjfv	}
2779280182Sjfv
2780280182Sjfv
2781280182Sjfv	/* Clean the Legacy or Link interrupt last */
2782280182Sjfv	if (adapter->vector) /* we are doing MSIX */
2783280182Sjfv		rid = adapter->vector + 1;
2784280182Sjfv	else
2785280182Sjfv		(adapter->msix != 0) ? (rid = 1):(rid = 0);
2786280182Sjfv
2787280182Sjfv	if (adapter->tag != NULL) {
2788280182Sjfv		bus_teardown_intr(dev, adapter->res, adapter->tag);
2789280182Sjfv		adapter->tag = NULL;
2790280182Sjfv	}
2791280182Sjfv	if (adapter->res != NULL)
2792280182Sjfv		bus_release_resource(dev, SYS_RES_IRQ, rid, adapter->res);
2793280182Sjfv
2794280182Sjfvmem:
2795280182Sjfv	if (adapter->msix)
2796280182Sjfv		pci_release_msi(dev);
2797280182Sjfv
2798280182Sjfv	if (adapter->msix_mem != NULL)
2799280182Sjfv		bus_release_resource(dev, SYS_RES_MEMORY,
2800280182Sjfv		    memrid, adapter->msix_mem);
2801280182Sjfv
2802280182Sjfv	if (adapter->pci_mem != NULL)
2803280182Sjfv		bus_release_resource(dev, SYS_RES_MEMORY,
2804280182Sjfv		    PCIR_BAR(0), adapter->pci_mem);
2805280182Sjfv
2806280182Sjfv	return;
2807280182Sjfv}
2808280182Sjfv
2809280182Sjfv/*********************************************************************
2810280182Sjfv *
2811280182Sjfv *  Setup networking device structure and register an interface.
2812280182Sjfv *
2813280182Sjfv **********************************************************************/
2814280182Sjfvstatic int
2815280182Sjfvixgbe_setup_interface(device_t dev, struct adapter *adapter)
2816280182Sjfv{
2817280182Sjfv	struct ifnet   *ifp;
2818280182Sjfv
2819280182Sjfv	INIT_DEBUGOUT("ixgbe_setup_interface: begin");
2820280182Sjfv
2821280182Sjfv	ifp = adapter->ifp = if_alloc(IFT_ETHER);
2822280182Sjfv	if (ifp == NULL) {
2823280182Sjfv		device_printf(dev, "can not allocate ifnet structure\n");
2824280182Sjfv		return (-1);
2825280182Sjfv	}
2826280182Sjfv	if_initname(ifp, device_get_name(dev), device_get_unit(dev));
2827280182Sjfv	ifp->if_baudrate = IF_Gbps(10);
2828280182Sjfv	ifp->if_init = ixgbe_init;
2829280182Sjfv	ifp->if_softc = adapter;
2830280182Sjfv	ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
2831280182Sjfv	ifp->if_ioctl = ixgbe_ioctl;
2832280182Sjfv#if __FreeBSD_version >= 1100036
2833280182Sjfv	if_setgetcounterfn(ifp, ixgbe_get_counter);
2834280182Sjfv#endif
2835282289Serj#if __FreeBSD_version >= 1100045
2836282289Serj	/* TSO parameters */
2837282289Serj	ifp->if_hw_tsomax = 65518;
2838282289Serj	ifp->if_hw_tsomaxsegcount = IXGBE_82599_SCATTER;
2839282289Serj	ifp->if_hw_tsomaxsegsize = 2048;
2840282289Serj#endif
2841280182Sjfv#ifndef IXGBE_LEGACY_TX
2842280182Sjfv	ifp->if_transmit = ixgbe_mq_start;
2843280182Sjfv	ifp->if_qflush = ixgbe_qflush;
2844280182Sjfv#else
2845280182Sjfv	ifp->if_start = ixgbe_start;
2846280182Sjfv	IFQ_SET_MAXLEN(&ifp->if_snd, adapter->num_tx_desc - 2);
2847280182Sjfv	ifp->if_snd.ifq_drv_maxlen = adapter->num_tx_desc - 2;
2848280182Sjfv	IFQ_SET_READY(&ifp->if_snd);
2849280182Sjfv#endif
2850280182Sjfv
2851280182Sjfv	ether_ifattach(ifp, adapter->hw.mac.addr);
2852280182Sjfv
2853280182Sjfv	adapter->max_frame_size =
2854280182Sjfv	    ifp->if_mtu + ETHER_HDR_LEN + ETHER_CRC_LEN;
2855280182Sjfv
2856280182Sjfv	/*
2857280182Sjfv	 * Tell the upper layer(s) we support long frames.
2858280182Sjfv	 */
2859280182Sjfv	ifp->if_hdrlen = sizeof(struct ether_vlan_header);
2860280182Sjfv
2861292674Ssbruno	/* Set capability flags */
2862292674Ssbruno	ifp->if_capabilities |= IFCAP_RXCSUM
2863292674Ssbruno			     |  IFCAP_TXCSUM
2864292674Ssbruno			     |  IFCAP_RXCSUM_IPV6
2865292674Ssbruno			     |  IFCAP_TXCSUM_IPV6
2866292674Ssbruno			     |  IFCAP_TSO4
2867292674Ssbruno			     |  IFCAP_TSO6
2868292674Ssbruno			     |  IFCAP_LRO
2869292674Ssbruno			     |  IFCAP_VLAN_HWTAGGING
2870280182Sjfv			     |  IFCAP_VLAN_HWTSO
2871292674Ssbruno			     |  IFCAP_VLAN_HWCSUM
2872292674Ssbruno			     |  IFCAP_JUMBO_MTU
2873280182Sjfv			     |  IFCAP_VLAN_MTU
2874280182Sjfv			     |  IFCAP_HWSTATS;
2875292674Ssbruno
2876292674Ssbruno	/* Enable the above capabilities by default */
2877280182Sjfv	ifp->if_capenable = ifp->if_capabilities;
2878280182Sjfv
2879280182Sjfv	/*
2880280182Sjfv	** Don't turn this on by default, if vlans are
2881280182Sjfv	** created on another pseudo device (eg. lagg)
2882280182Sjfv	** then vlan events are not passed thru, breaking
2883280182Sjfv	** operation, but with HW FILTER off it works. If
2884280182Sjfv	** using vlans directly on the ixgbe driver you can
2885280182Sjfv	** enable this and get full hardware tag filtering.
2886280182Sjfv	*/
2887280182Sjfv	ifp->if_capabilities |= IFCAP_VLAN_HWFILTER;
2888280182Sjfv
2889280182Sjfv	/*
2890280182Sjfv	 * Specify the media types supported by this adapter and register
2891280182Sjfv	 * callbacks to update media and link information
2892280182Sjfv	 */
2893280182Sjfv	ifmedia_init(&adapter->media, IFM_IMASK, ixgbe_media_change,
2894280182Sjfv		    ixgbe_media_status);
2895280182Sjfv
2896292674Ssbruno	adapter->phy_layer = ixgbe_get_supported_physical_layer(&adapter->hw);
2897280182Sjfv	ixgbe_add_media_types(adapter);
2898280182Sjfv
2899292674Ssbruno	/* Set autoselect media by default */
2900280182Sjfv	ifmedia_set(&adapter->media, IFM_ETHER | IFM_AUTO);
2901280182Sjfv
2902280182Sjfv	return (0);
2903280182Sjfv}
2904280182Sjfv
2905280182Sjfvstatic void
2906280182Sjfvixgbe_add_media_types(struct adapter *adapter)
2907280182Sjfv{
2908280182Sjfv	struct ixgbe_hw *hw = &adapter->hw;
2909280182Sjfv	device_t dev = adapter->dev;
2910280182Sjfv	int layer;
2911280182Sjfv
2912292674Ssbruno	layer = adapter->phy_layer;
2913280182Sjfv
2914280182Sjfv	/* Media types with matching FreeBSD media defines */
2915280182Sjfv	if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_T)
2916280182Sjfv		ifmedia_add(&adapter->media, IFM_ETHER | IFM_10G_T, 0, NULL);
2917280182Sjfv	if (layer & IXGBE_PHYSICAL_LAYER_1000BASE_T)
2918280182Sjfv		ifmedia_add(&adapter->media, IFM_ETHER | IFM_1000_T, 0, NULL);
2919280182Sjfv	if (layer & IXGBE_PHYSICAL_LAYER_100BASE_TX)
2920280182Sjfv		ifmedia_add(&adapter->media, IFM_ETHER | IFM_100_TX, 0, NULL);
2921280182Sjfv
2922280182Sjfv	if (layer & IXGBE_PHYSICAL_LAYER_SFP_PLUS_CU ||
2923280182Sjfv	    layer & IXGBE_PHYSICAL_LAYER_SFP_ACTIVE_DA)
2924280182Sjfv		ifmedia_add(&adapter->media, IFM_ETHER | IFM_10G_TWINAX, 0, NULL);
2925280182Sjfv
2926292674Ssbruno	if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_LR) {
2927280182Sjfv		ifmedia_add(&adapter->media, IFM_ETHER | IFM_10G_LR, 0, NULL);
2928292674Ssbruno		if (hw->phy.multispeed_fiber)
2929292674Ssbruno			ifmedia_add(&adapter->media, IFM_ETHER | IFM_1000_LX, 0, NULL);
2930292674Ssbruno	}
2931292674Ssbruno	if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_SR) {
2932280182Sjfv		ifmedia_add(&adapter->media, IFM_ETHER | IFM_10G_SR, 0, NULL);
2933292674Ssbruno		if (hw->phy.multispeed_fiber)
2934292674Ssbruno			ifmedia_add(&adapter->media, IFM_ETHER | IFM_1000_SX, 0, NULL);
2935292674Ssbruno	} else if (layer & IXGBE_PHYSICAL_LAYER_1000BASE_SX)
2936292674Ssbruno		ifmedia_add(&adapter->media, IFM_ETHER | IFM_1000_SX, 0, NULL);
2937280182Sjfv	if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_CX4)
2938280182Sjfv		ifmedia_add(&adapter->media, IFM_ETHER | IFM_10G_CX4, 0, NULL);
2939280182Sjfv
2940292674Ssbruno#ifdef IFM_ETH_XTYPE
2941292674Ssbruno	if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_KR)
2942292674Ssbruno		ifmedia_add(&adapter->media, IFM_ETHER | IFM_10G_KR, 0, NULL);
2943292674Ssbruno	if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_KX4)
2944292674Ssbruno		ifmedia_add(&adapter->media, IFM_ETHER | IFM_10G_KX4, 0, NULL);
2945292674Ssbruno	if (layer & IXGBE_PHYSICAL_LAYER_1000BASE_KX)
2946292674Ssbruno		ifmedia_add(&adapter->media, IFM_ETHER | IFM_1000_KX, 0, NULL);
2947292674Ssbruno#else
2948280182Sjfv	if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_KR) {
2949280182Sjfv		device_printf(dev, "Media supported: 10GbaseKR\n");
2950282289Serj		device_printf(dev, "10GbaseKR mapped to 10GbaseSR\n");
2951282289Serj		ifmedia_add(&adapter->media, IFM_ETHER | IFM_10G_SR, 0, NULL);
2952280182Sjfv	}
2953280182Sjfv	if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_KX4) {
2954280182Sjfv		device_printf(dev, "Media supported: 10GbaseKX4\n");
2955282289Serj		device_printf(dev, "10GbaseKX4 mapped to 10GbaseCX4\n");
2956282289Serj		ifmedia_add(&adapter->media, IFM_ETHER | IFM_10G_CX4, 0, NULL);
2957280182Sjfv	}
2958280182Sjfv	if (layer & IXGBE_PHYSICAL_LAYER_1000BASE_KX) {
2959280182Sjfv		device_printf(dev, "Media supported: 1000baseKX\n");
2960282289Serj		device_printf(dev, "1000baseKX mapped to 1000baseCX\n");
2961282289Serj		ifmedia_add(&adapter->media, IFM_ETHER | IFM_1000_CX, 0, NULL);
2962280182Sjfv	}
2963292674Ssbruno#endif
2964292674Ssbruno	if (layer & IXGBE_PHYSICAL_LAYER_1000BASE_BX)
2965280182Sjfv		device_printf(dev, "Media supported: 1000baseBX\n");
2966280182Sjfv
2967280182Sjfv	if (hw->device_id == IXGBE_DEV_ID_82598AT) {
2968280182Sjfv		ifmedia_add(&adapter->media,
2969280182Sjfv		    IFM_ETHER | IFM_1000_T | IFM_FDX, 0, NULL);
2970280182Sjfv		ifmedia_add(&adapter->media,
2971280182Sjfv		    IFM_ETHER | IFM_1000_T, 0, NULL);
2972280182Sjfv	}
2973280182Sjfv
2974280182Sjfv	ifmedia_add(&adapter->media, IFM_ETHER | IFM_AUTO, 0, NULL);
2975280182Sjfv}
2976280182Sjfv
2977280182Sjfvstatic void
2978280182Sjfvixgbe_config_link(struct adapter *adapter)
2979280182Sjfv{
2980280182Sjfv	struct ixgbe_hw *hw = &adapter->hw;
2981280182Sjfv	u32	autoneg, err = 0;
2982280182Sjfv	bool	sfp, negotiate;
2983280182Sjfv
2984280182Sjfv	sfp = ixgbe_is_sfp(hw);
2985280182Sjfv
2986280182Sjfv	if (sfp) {
2987293334Ssbruno		taskqueue_enqueue(adapter->tq, &adapter->mod_task);
2988280182Sjfv	} else {
2989280182Sjfv		if (hw->mac.ops.check_link)
2990280182Sjfv			err = ixgbe_check_link(hw, &adapter->link_speed,
2991280182Sjfv			    &adapter->link_up, FALSE);
2992280182Sjfv		if (err)
2993280182Sjfv			goto out;
2994280182Sjfv		autoneg = hw->phy.autoneg_advertised;
2995280182Sjfv		if ((!autoneg) && (hw->mac.ops.get_link_capabilities))
2996280182Sjfv                	err  = hw->mac.ops.get_link_capabilities(hw,
2997280182Sjfv			    &autoneg, &negotiate);
2998280182Sjfv		if (err)
2999280182Sjfv			goto out;
3000280182Sjfv		if (hw->mac.ops.setup_link)
3001280182Sjfv                	err = hw->mac.ops.setup_link(hw,
3002280182Sjfv			    autoneg, adapter->link_up);
3003280182Sjfv	}
3004280182Sjfvout:
3005280182Sjfv	return;
3006280182Sjfv}
3007280182Sjfv
3008280182Sjfv
3009280182Sjfv/*********************************************************************
3010280182Sjfv *
3011280182Sjfv *  Enable transmit units.
3012280182Sjfv *
3013280182Sjfv **********************************************************************/
3014280182Sjfvstatic void
3015280182Sjfvixgbe_initialize_transmit_units(struct adapter *adapter)
3016280182Sjfv{
3017280182Sjfv	struct tx_ring	*txr = adapter->tx_rings;
3018280182Sjfv	struct ixgbe_hw	*hw = &adapter->hw;
3019280182Sjfv
3020280182Sjfv	/* Setup the Base and Length of the Tx Descriptor Ring */
3021280182Sjfv	for (int i = 0; i < adapter->num_queues; i++, txr++) {
3022280182Sjfv		u64	tdba = txr->txdma.dma_paddr;
3023280182Sjfv		u32	txctrl = 0;
3024283883Sjfv		int	j = txr->me;
3025280182Sjfv
3026283883Sjfv		IXGBE_WRITE_REG(hw, IXGBE_TDBAL(j),
3027280182Sjfv		       (tdba & 0x00000000ffffffffULL));
3028283883Sjfv		IXGBE_WRITE_REG(hw, IXGBE_TDBAH(j), (tdba >> 32));
3029283883Sjfv		IXGBE_WRITE_REG(hw, IXGBE_TDLEN(j),
3030280182Sjfv		    adapter->num_tx_desc * sizeof(union ixgbe_adv_tx_desc));
3031280182Sjfv
3032280182Sjfv		/* Setup the HW Tx Head and Tail descriptor pointers */
3033283883Sjfv		IXGBE_WRITE_REG(hw, IXGBE_TDH(j), 0);
3034283883Sjfv		IXGBE_WRITE_REG(hw, IXGBE_TDT(j), 0);
3035280182Sjfv
3036280182Sjfv		/* Cache the tail address */
3037283883Sjfv		txr->tail = IXGBE_TDT(j);
3038280182Sjfv
3039280182Sjfv		/* Disable Head Writeback */
3040292674Ssbruno		/*
3041292674Ssbruno		 * Note: for X550 series devices, these registers are actually
3042292674Ssbruno		 * prefixed with TPH_ isntead of DCA_, but the addresses and
3043292674Ssbruno		 * fields remain the same.
3044292674Ssbruno		 */
3045280182Sjfv		switch (hw->mac.type) {
3046280182Sjfv		case ixgbe_mac_82598EB:
3047283883Sjfv			txctrl = IXGBE_READ_REG(hw, IXGBE_DCA_TXCTRL(j));
3048280182Sjfv			break;
3049280182Sjfv		default:
3050283883Sjfv			txctrl = IXGBE_READ_REG(hw, IXGBE_DCA_TXCTRL_82599(j));
3051280182Sjfv			break;
3052280182Sjfv                }
3053280182Sjfv		txctrl &= ~IXGBE_DCA_TXCTRL_DESC_WRO_EN;
3054280182Sjfv		switch (hw->mac.type) {
3055280182Sjfv		case ixgbe_mac_82598EB:
3056283883Sjfv			IXGBE_WRITE_REG(hw, IXGBE_DCA_TXCTRL(j), txctrl);
3057280182Sjfv			break;
3058280182Sjfv		default:
3059283883Sjfv			IXGBE_WRITE_REG(hw, IXGBE_DCA_TXCTRL_82599(j), txctrl);
3060280182Sjfv			break;
3061280182Sjfv		}
3062280182Sjfv
3063280182Sjfv	}
3064280182Sjfv
3065280182Sjfv	if (hw->mac.type != ixgbe_mac_82598EB) {
3066280182Sjfv		u32 dmatxctl, rttdcs;
3067283883Sjfv#ifdef PCI_IOV
3068283883Sjfv		enum ixgbe_iov_mode mode = ixgbe_get_iov_mode(adapter);
3069283883Sjfv#endif
3070280182Sjfv		dmatxctl = IXGBE_READ_REG(hw, IXGBE_DMATXCTL);
3071280182Sjfv		dmatxctl |= IXGBE_DMATXCTL_TE;
3072280182Sjfv		IXGBE_WRITE_REG(hw, IXGBE_DMATXCTL, dmatxctl);
3073280182Sjfv		/* Disable arbiter to set MTQC */
3074280182Sjfv		rttdcs = IXGBE_READ_REG(hw, IXGBE_RTTDCS);
3075280182Sjfv		rttdcs |= IXGBE_RTTDCS_ARBDIS;
3076280182Sjfv		IXGBE_WRITE_REG(hw, IXGBE_RTTDCS, rttdcs);
3077283883Sjfv#ifdef PCI_IOV
3078283883Sjfv		IXGBE_WRITE_REG(hw, IXGBE_MTQC, ixgbe_get_mtqc(mode));
3079283883Sjfv#else
3080280182Sjfv		IXGBE_WRITE_REG(hw, IXGBE_MTQC, IXGBE_MTQC_64Q_1PB);
3081283883Sjfv#endif
3082280182Sjfv		rttdcs &= ~IXGBE_RTTDCS_ARBDIS;
3083280182Sjfv		IXGBE_WRITE_REG(hw, IXGBE_RTTDCS, rttdcs);
3084280182Sjfv	}
3085280182Sjfv
3086280182Sjfv	return;
3087280182Sjfv}
3088280182Sjfv
3089280182Sjfvstatic void
3090292674Ssbrunoixgbe_initialize_rss_mapping(struct adapter *adapter)
3091280182Sjfv{
3092280182Sjfv	struct ixgbe_hw	*hw = &adapter->hw;
3093283883Sjfv	u32 reta = 0, mrqc, rss_key[10];
3094283883Sjfv	int queue_id, table_size, index_mult;
3095280182Sjfv#ifdef	RSS
3096283883Sjfv	u32 rss_hash_config;
3097280182Sjfv#endif
3098283883Sjfv#ifdef PCI_IOV
3099283883Sjfv	enum ixgbe_iov_mode mode;
3100283883Sjfv#endif
3101280182Sjfv
3102280182Sjfv#ifdef	RSS
3103280182Sjfv	/* Fetch the configured RSS key */
3104280182Sjfv	rss_getkey((uint8_t *) &rss_key);
3105280182Sjfv#else
3106280182Sjfv	/* set up random bits */
3107280182Sjfv	arc4rand(&rss_key, sizeof(rss_key), 0);
3108280182Sjfv#endif
3109280182Sjfv
3110282289Serj	/* Set multiplier for RETA setup and table size based on MAC */
3111282289Serj	index_mult = 0x1;
3112282289Serj	table_size = 128;
3113282289Serj	switch (adapter->hw.mac.type) {
3114282289Serj	case ixgbe_mac_82598EB:
3115282289Serj		index_mult = 0x11;
3116282289Serj		break;
3117282289Serj	case ixgbe_mac_X550:
3118282289Serj	case ixgbe_mac_X550EM_x:
3119282289Serj		table_size = 512;
3120282289Serj		break;
3121282289Serj	default:
3122282289Serj		break;
3123282289Serj	}
3124282289Serj
3125280182Sjfv	/* Set up the redirection table */
3126283883Sjfv	for (int i = 0, j = 0; i < table_size; i++, j++) {
3127280182Sjfv		if (j == adapter->num_queues) j = 0;
3128280182Sjfv#ifdef	RSS
3129280182Sjfv		/*
3130280182Sjfv		 * Fetch the RSS bucket id for the given indirection entry.
3131280182Sjfv		 * Cap it at the number of configured buckets (which is
3132280182Sjfv		 * num_queues.)
3133280182Sjfv		 */
3134280182Sjfv		queue_id = rss_get_indirection_to_bucket(i);
3135280182Sjfv		queue_id = queue_id % adapter->num_queues;
3136280182Sjfv#else
3137282289Serj		queue_id = (j * index_mult);
3138280182Sjfv#endif
3139280182Sjfv		/*
3140280182Sjfv		 * The low 8 bits are for hash value (n+0);
3141280182Sjfv		 * The next 8 bits are for hash value (n+1), etc.
3142280182Sjfv		 */
3143280182Sjfv		reta = reta >> 8;
3144280182Sjfv		reta = reta | ( ((uint32_t) queue_id) << 24);
3145280182Sjfv		if ((i & 3) == 3) {
3146282289Serj			if (i < 128)
3147282289Serj				IXGBE_WRITE_REG(hw, IXGBE_RETA(i >> 2), reta);
3148282289Serj			else
3149282289Serj				IXGBE_WRITE_REG(hw, IXGBE_ERETA((i >> 2) - 32), reta);
3150280182Sjfv			reta = 0;
3151280182Sjfv		}
3152280182Sjfv	}
3153280182Sjfv
3154280182Sjfv	/* Now fill our hash function seeds */
3155280182Sjfv	for (int i = 0; i < 10; i++)
3156280182Sjfv		IXGBE_WRITE_REG(hw, IXGBE_RSSRK(i), rss_key[i]);
3157280182Sjfv
3158280182Sjfv	/* Perform hash on these packet types */
3159280182Sjfv#ifdef	RSS
3160280182Sjfv	mrqc = IXGBE_MRQC_RSSEN;
3161280182Sjfv	rss_hash_config = rss_gethashconfig();
3162280182Sjfv	if (rss_hash_config & RSS_HASHTYPE_RSS_IPV4)
3163280182Sjfv		mrqc |= IXGBE_MRQC_RSS_FIELD_IPV4;
3164280182Sjfv	if (rss_hash_config & RSS_HASHTYPE_RSS_TCP_IPV4)
3165280182Sjfv		mrqc |= IXGBE_MRQC_RSS_FIELD_IPV4_TCP;
3166280182Sjfv	if (rss_hash_config & RSS_HASHTYPE_RSS_IPV6)
3167280182Sjfv		mrqc |= IXGBE_MRQC_RSS_FIELD_IPV6;
3168280182Sjfv	if (rss_hash_config & RSS_HASHTYPE_RSS_TCP_IPV6)
3169280182Sjfv		mrqc |= IXGBE_MRQC_RSS_FIELD_IPV6_TCP;
3170280182Sjfv	if (rss_hash_config & RSS_HASHTYPE_RSS_IPV6_EX)
3171280182Sjfv		mrqc |= IXGBE_MRQC_RSS_FIELD_IPV6_EX;
3172280182Sjfv	if (rss_hash_config & RSS_HASHTYPE_RSS_TCP_IPV6_EX)
3173280182Sjfv		mrqc |= IXGBE_MRQC_RSS_FIELD_IPV6_EX_TCP;
3174280182Sjfv	if (rss_hash_config & RSS_HASHTYPE_RSS_UDP_IPV4)
3175280182Sjfv		mrqc |= IXGBE_MRQC_RSS_FIELD_IPV4_UDP;
3176280182Sjfv	if (rss_hash_config & RSS_HASHTYPE_RSS_UDP_IPV4_EX)
3177280182Sjfv		device_printf(adapter->dev,
3178280182Sjfv		    "%s: RSS_HASHTYPE_RSS_UDP_IPV4_EX defined, "
3179280182Sjfv		    "but not supported\n", __func__);
3180280182Sjfv	if (rss_hash_config & RSS_HASHTYPE_RSS_UDP_IPV6)
3181280182Sjfv		mrqc |= IXGBE_MRQC_RSS_FIELD_IPV6_UDP;
3182280182Sjfv	if (rss_hash_config & RSS_HASHTYPE_RSS_UDP_IPV6_EX)
3183280182Sjfv		mrqc |= IXGBE_MRQC_RSS_FIELD_IPV6_EX_UDP;
3184280182Sjfv#else
3185280182Sjfv	/*
3186280182Sjfv	 * Disable UDP - IP fragments aren't currently being handled
3187280182Sjfv	 * and so we end up with a mix of 2-tuple and 4-tuple
3188280182Sjfv	 * traffic.
3189280182Sjfv	 */
3190280182Sjfv	mrqc = IXGBE_MRQC_RSSEN
3191280182Sjfv	     | IXGBE_MRQC_RSS_FIELD_IPV4
3192280182Sjfv	     | IXGBE_MRQC_RSS_FIELD_IPV4_TCP
3193280182Sjfv	     | IXGBE_MRQC_RSS_FIELD_IPV6_EX_TCP
3194280182Sjfv	     | IXGBE_MRQC_RSS_FIELD_IPV6_EX
3195280182Sjfv	     | IXGBE_MRQC_RSS_FIELD_IPV6
3196280182Sjfv	     | IXGBE_MRQC_RSS_FIELD_IPV6_TCP
3197280182Sjfv	;
3198280182Sjfv#endif /* RSS */
3199283883Sjfv#ifdef PCI_IOV
3200283883Sjfv	mode = ixgbe_get_iov_mode(adapter);
3201283883Sjfv	mrqc |= ixgbe_get_mrqc(mode);
3202283883Sjfv#endif
3203280182Sjfv	IXGBE_WRITE_REG(hw, IXGBE_MRQC, mrqc);
3204280182Sjfv}
3205280182Sjfv
3206280182Sjfv
3207280182Sjfv/*********************************************************************
3208280182Sjfv *
3209280182Sjfv *  Setup receive registers and features.
3210280182Sjfv *
3211280182Sjfv **********************************************************************/
3212280182Sjfv#define IXGBE_SRRCTL_BSIZEHDRSIZE_SHIFT 2
3213280182Sjfv
3214280182Sjfv#define BSIZEPKT_ROUNDUP ((1<<IXGBE_SRRCTL_BSIZEPKT_SHIFT)-1)
3215280182Sjfv
3216280182Sjfvstatic void
3217280182Sjfvixgbe_initialize_receive_units(struct adapter *adapter)
3218280182Sjfv{
3219280182Sjfv	struct	rx_ring	*rxr = adapter->rx_rings;
3220280182Sjfv	struct ixgbe_hw	*hw = &adapter->hw;
3221280182Sjfv	struct ifnet   *ifp = adapter->ifp;
3222280182Sjfv	u32		bufsz, fctrl, srrctl, rxcsum;
3223280182Sjfv	u32		hlreg;
3224280182Sjfv
3225280182Sjfv	/*
3226280182Sjfv	 * Make sure receives are disabled while
3227280182Sjfv	 * setting up the descriptor ring
3228280182Sjfv	 */
3229280182Sjfv	ixgbe_disable_rx(hw);
3230280182Sjfv
3231280182Sjfv	/* Enable broadcasts */
3232280182Sjfv	fctrl = IXGBE_READ_REG(hw, IXGBE_FCTRL);
3233280182Sjfv	fctrl |= IXGBE_FCTRL_BAM;
3234282289Serj	if (adapter->hw.mac.type == ixgbe_mac_82598EB) {
3235282289Serj		fctrl |= IXGBE_FCTRL_DPF;
3236282289Serj		fctrl |= IXGBE_FCTRL_PMCF;
3237282289Serj	}
3238280182Sjfv	IXGBE_WRITE_REG(hw, IXGBE_FCTRL, fctrl);
3239280182Sjfv
3240280182Sjfv	/* Set for Jumbo Frames? */
3241280182Sjfv	hlreg = IXGBE_READ_REG(hw, IXGBE_HLREG0);
3242280182Sjfv	if (ifp->if_mtu > ETHERMTU)
3243280182Sjfv		hlreg |= IXGBE_HLREG0_JUMBOEN;
3244280182Sjfv	else
3245280182Sjfv		hlreg &= ~IXGBE_HLREG0_JUMBOEN;
3246280182Sjfv#ifdef DEV_NETMAP
3247280182Sjfv	/* crcstrip is conditional in netmap (in RDRXCTL too ?) */
3248280182Sjfv	if (ifp->if_capenable & IFCAP_NETMAP && !ix_crcstrip)
3249280182Sjfv		hlreg &= ~IXGBE_HLREG0_RXCRCSTRP;
3250280182Sjfv	else
3251280182Sjfv		hlreg |= IXGBE_HLREG0_RXCRCSTRP;
3252280182Sjfv#endif /* DEV_NETMAP */
3253280182Sjfv	IXGBE_WRITE_REG(hw, IXGBE_HLREG0, hlreg);
3254280182Sjfv
3255280182Sjfv	bufsz = (adapter->rx_mbuf_sz +
3256280182Sjfv	    BSIZEPKT_ROUNDUP) >> IXGBE_SRRCTL_BSIZEPKT_SHIFT;
3257280182Sjfv
3258280182Sjfv	for (int i = 0; i < adapter->num_queues; i++, rxr++) {
3259280182Sjfv		u64 rdba = rxr->rxdma.dma_paddr;
3260283883Sjfv		int j = rxr->me;
3261280182Sjfv
3262280182Sjfv		/* Setup the Base and Length of the Rx Descriptor Ring */
3263283883Sjfv		IXGBE_WRITE_REG(hw, IXGBE_RDBAL(j),
3264280182Sjfv			       (rdba & 0x00000000ffffffffULL));
3265283883Sjfv		IXGBE_WRITE_REG(hw, IXGBE_RDBAH(j), (rdba >> 32));
3266283883Sjfv		IXGBE_WRITE_REG(hw, IXGBE_RDLEN(j),
3267280182Sjfv		    adapter->num_rx_desc * sizeof(union ixgbe_adv_rx_desc));
3268280182Sjfv
3269280182Sjfv		/* Set up the SRRCTL register */
3270283883Sjfv		srrctl = IXGBE_READ_REG(hw, IXGBE_SRRCTL(j));
3271280182Sjfv		srrctl &= ~IXGBE_SRRCTL_BSIZEHDR_MASK;
3272280182Sjfv		srrctl &= ~IXGBE_SRRCTL_BSIZEPKT_MASK;
3273280182Sjfv		srrctl |= bufsz;
3274280182Sjfv		srrctl |= IXGBE_SRRCTL_DESCTYPE_ADV_ONEBUF;
3275280182Sjfv
3276280182Sjfv		/*
3277280182Sjfv		 * Set DROP_EN iff we have no flow control and >1 queue.
3278280182Sjfv		 * Note that srrctl was cleared shortly before during reset,
3279280182Sjfv		 * so we do not need to clear the bit, but do it just in case
3280280182Sjfv		 * this code is moved elsewhere.
3281280182Sjfv		 */
3282283882Sjfv		if (adapter->num_queues > 1 &&
3283283882Sjfv		    adapter->hw.fc.requested_mode == ixgbe_fc_none) {
3284280182Sjfv			srrctl |= IXGBE_SRRCTL_DROP_EN;
3285283882Sjfv		} else {
3286280182Sjfv			srrctl &= ~IXGBE_SRRCTL_DROP_EN;
3287283882Sjfv		}
3288280182Sjfv
3289283883Sjfv		IXGBE_WRITE_REG(hw, IXGBE_SRRCTL(j), srrctl);
3290280182Sjfv
3291280182Sjfv		/* Setup the HW Rx Head and Tail Descriptor Pointers */
3292283883Sjfv		IXGBE_WRITE_REG(hw, IXGBE_RDH(j), 0);
3293283883Sjfv		IXGBE_WRITE_REG(hw, IXGBE_RDT(j), 0);
3294280182Sjfv
3295280182Sjfv		/* Set the driver rx tail address */
3296280182Sjfv		rxr->tail =  IXGBE_RDT(rxr->me);
3297280182Sjfv	}
3298280182Sjfv
3299280182Sjfv	if (adapter->hw.mac.type != ixgbe_mac_82598EB) {
3300280182Sjfv		u32 psrtype = IXGBE_PSRTYPE_TCPHDR |
3301280182Sjfv			      IXGBE_PSRTYPE_UDPHDR |
3302280182Sjfv			      IXGBE_PSRTYPE_IPV4HDR |
3303280182Sjfv			      IXGBE_PSRTYPE_IPV6HDR;
3304280182Sjfv		IXGBE_WRITE_REG(hw, IXGBE_PSRTYPE(0), psrtype);
3305280182Sjfv	}
3306280182Sjfv
3307280182Sjfv	rxcsum = IXGBE_READ_REG(hw, IXGBE_RXCSUM);
3308280182Sjfv
3309292674Ssbruno	ixgbe_initialize_rss_mapping(adapter);
3310280182Sjfv
3311280182Sjfv	if (adapter->num_queues > 1) {
3312280182Sjfv		/* RSS and RX IPP Checksum are mutually exclusive */
3313280182Sjfv		rxcsum |= IXGBE_RXCSUM_PCSD;
3314280182Sjfv	}
3315280182Sjfv
3316280182Sjfv	if (ifp->if_capenable & IFCAP_RXCSUM)
3317280182Sjfv		rxcsum |= IXGBE_RXCSUM_PCSD;
3318280182Sjfv
3319292674Ssbruno	/* This is useful for calculating UDP/IP fragment checksums */
3320280182Sjfv	if (!(rxcsum & IXGBE_RXCSUM_PCSD))
3321280182Sjfv		rxcsum |= IXGBE_RXCSUM_IPPCSE;
3322280182Sjfv
3323280182Sjfv	IXGBE_WRITE_REG(hw, IXGBE_RXCSUM, rxcsum);
3324280182Sjfv
3325280182Sjfv	return;
3326280182Sjfv}
3327280182Sjfv
3328280182Sjfv
3329280182Sjfv/*
3330280182Sjfv** This routine is run via an vlan config EVENT,
3331280182Sjfv** it enables us to use the HW Filter table since
3332280182Sjfv** we can get the vlan id. This just creates the
3333280182Sjfv** entry in the soft version of the VFTA, init will
3334280182Sjfv** repopulate the real table.
3335280182Sjfv*/
3336280182Sjfvstatic void
3337280182Sjfvixgbe_register_vlan(void *arg, struct ifnet *ifp, u16 vtag)
3338280182Sjfv{
3339280182Sjfv	struct adapter	*adapter = ifp->if_softc;
3340280182Sjfv	u16		index, bit;
3341280182Sjfv
3342280182Sjfv	if (ifp->if_softc !=  arg)   /* Not our event */
3343280182Sjfv		return;
3344280182Sjfv
3345280182Sjfv	if ((vtag == 0) || (vtag > 4095))	/* Invalid */
3346280182Sjfv		return;
3347280182Sjfv
3348280182Sjfv	IXGBE_CORE_LOCK(adapter);
3349280182Sjfv	index = (vtag >> 5) & 0x7F;
3350280182Sjfv	bit = vtag & 0x1F;
3351280182Sjfv	adapter->shadow_vfta[index] |= (1 << bit);
3352280182Sjfv	++adapter->num_vlans;
3353280182Sjfv	ixgbe_setup_vlan_hw_support(adapter);
3354280182Sjfv	IXGBE_CORE_UNLOCK(adapter);
3355280182Sjfv}
3356280182Sjfv
3357280182Sjfv/*
3358280182Sjfv** This routine is run via an vlan
3359280182Sjfv** unconfig EVENT, remove our entry
3360280182Sjfv** in the soft vfta.
3361280182Sjfv*/
3362280182Sjfvstatic void
3363280182Sjfvixgbe_unregister_vlan(void *arg, struct ifnet *ifp, u16 vtag)
3364280182Sjfv{
3365280182Sjfv	struct adapter	*adapter = ifp->if_softc;
3366280182Sjfv	u16		index, bit;
3367280182Sjfv
3368280182Sjfv	if (ifp->if_softc !=  arg)
3369280182Sjfv		return;
3370280182Sjfv
3371280182Sjfv	if ((vtag == 0) || (vtag > 4095))	/* Invalid */
3372280182Sjfv		return;
3373280182Sjfv
3374280182Sjfv	IXGBE_CORE_LOCK(adapter);
3375280182Sjfv	index = (vtag >> 5) & 0x7F;
3376280182Sjfv	bit = vtag & 0x1F;
3377280182Sjfv	adapter->shadow_vfta[index] &= ~(1 << bit);
3378280182Sjfv	--adapter->num_vlans;
3379280182Sjfv	/* Re-init to load the changes */
3380280182Sjfv	ixgbe_setup_vlan_hw_support(adapter);
3381280182Sjfv	IXGBE_CORE_UNLOCK(adapter);
3382280182Sjfv}
3383280182Sjfv
3384280182Sjfvstatic void
3385280182Sjfvixgbe_setup_vlan_hw_support(struct adapter *adapter)
3386280182Sjfv{
3387280182Sjfv	struct ifnet 	*ifp = adapter->ifp;
3388280182Sjfv	struct ixgbe_hw *hw = &adapter->hw;
3389280182Sjfv	struct rx_ring	*rxr;
3390280182Sjfv	u32		ctrl;
3391280182Sjfv
3392280182Sjfv
3393280182Sjfv	/*
3394280182Sjfv	** We get here thru init_locked, meaning
3395280182Sjfv	** a soft reset, this has already cleared
3396280182Sjfv	** the VFTA and other state, so if there
3397280182Sjfv	** have been no vlan's registered do nothing.
3398280182Sjfv	*/
3399280182Sjfv	if (adapter->num_vlans == 0)
3400280182Sjfv		return;
3401280182Sjfv
3402280182Sjfv	/* Setup the queues for vlans */
3403280182Sjfv	for (int i = 0; i < adapter->num_queues; i++) {
3404280182Sjfv		rxr = &adapter->rx_rings[i];
3405280182Sjfv		/* On 82599 the VLAN enable is per/queue in RXDCTL */
3406280182Sjfv		if (hw->mac.type != ixgbe_mac_82598EB) {
3407283883Sjfv			ctrl = IXGBE_READ_REG(hw, IXGBE_RXDCTL(rxr->me));
3408280182Sjfv			ctrl |= IXGBE_RXDCTL_VME;
3409283883Sjfv			IXGBE_WRITE_REG(hw, IXGBE_RXDCTL(rxr->me), ctrl);
3410280182Sjfv		}
3411280182Sjfv		rxr->vtag_strip = TRUE;
3412280182Sjfv	}
3413280182Sjfv
3414280182Sjfv	if ((ifp->if_capenable & IFCAP_VLAN_HWFILTER) == 0)
3415280182Sjfv		return;
3416280182Sjfv	/*
3417280182Sjfv	** A soft reset zero's out the VFTA, so
3418280182Sjfv	** we need to repopulate it now.
3419280182Sjfv	*/
3420280182Sjfv	for (int i = 0; i < IXGBE_VFTA_SIZE; i++)
3421280182Sjfv		if (adapter->shadow_vfta[i] != 0)
3422280182Sjfv			IXGBE_WRITE_REG(hw, IXGBE_VFTA(i),
3423280182Sjfv			    adapter->shadow_vfta[i]);
3424280182Sjfv
3425280182Sjfv	ctrl = IXGBE_READ_REG(hw, IXGBE_VLNCTRL);
3426280182Sjfv	/* Enable the Filter Table if enabled */
3427280182Sjfv	if (ifp->if_capenable & IFCAP_VLAN_HWFILTER) {
3428280182Sjfv		ctrl &= ~IXGBE_VLNCTRL_CFIEN;
3429280182Sjfv		ctrl |= IXGBE_VLNCTRL_VFE;
3430280182Sjfv	}
3431280182Sjfv	if (hw->mac.type == ixgbe_mac_82598EB)
3432280182Sjfv		ctrl |= IXGBE_VLNCTRL_VME;
3433280182Sjfv	IXGBE_WRITE_REG(hw, IXGBE_VLNCTRL, ctrl);
3434280182Sjfv}
3435280182Sjfv
3436280182Sjfvstatic void
3437280182Sjfvixgbe_enable_intr(struct adapter *adapter)
3438280182Sjfv{
3439280182Sjfv	struct ixgbe_hw	*hw = &adapter->hw;
3440280182Sjfv	struct ix_queue	*que = adapter->queues;
3441280182Sjfv	u32		mask, fwsm;
3442280182Sjfv
3443280182Sjfv	mask = (IXGBE_EIMS_ENABLE_MASK & ~IXGBE_EIMS_RTX_QUEUE);
3444280182Sjfv	/* Enable Fan Failure detection */
3445280182Sjfv	if (hw->device_id == IXGBE_DEV_ID_82598AT)
3446282289Serj		    mask |= IXGBE_EIMS_GPI_SDP1;
3447280182Sjfv
3448280182Sjfv	switch (adapter->hw.mac.type) {
3449280182Sjfv		case ixgbe_mac_82599EB:
3450280182Sjfv			mask |= IXGBE_EIMS_ECC;
3451280182Sjfv			/* Temperature sensor on some adapters */
3452282289Serj			mask |= IXGBE_EIMS_GPI_SDP0;
3453280182Sjfv			/* SFP+ (RX_LOS_N & MOD_ABS_N) */
3454282289Serj			mask |= IXGBE_EIMS_GPI_SDP1;
3455282289Serj			mask |= IXGBE_EIMS_GPI_SDP2;
3456280182Sjfv#ifdef IXGBE_FDIR
3457280182Sjfv			mask |= IXGBE_EIMS_FLOW_DIR;
3458280182Sjfv#endif
3459283883Sjfv#ifdef PCI_IOV
3460283883Sjfv			mask |= IXGBE_EIMS_MAILBOX;
3461283883Sjfv#endif
3462280182Sjfv			break;
3463280182Sjfv		case ixgbe_mac_X540:
3464280182Sjfv			/* Detect if Thermal Sensor is enabled */
3465280182Sjfv			fwsm = IXGBE_READ_REG(hw, IXGBE_FWSM);
3466280182Sjfv			if (fwsm & IXGBE_FWSM_TS_ENABLED)
3467280182Sjfv				mask |= IXGBE_EIMS_TS;
3468282289Serj			mask |= IXGBE_EIMS_ECC;
3469282289Serj#ifdef IXGBE_FDIR
3470282289Serj			mask |= IXGBE_EIMS_FLOW_DIR;
3471282289Serj#endif
3472282289Serj			break;
3473282289Serj		case ixgbe_mac_X550:
3474282289Serj		case ixgbe_mac_X550EM_x:
3475282289Serj			/* MAC thermal sensor is automatically enabled */
3476282289Serj			mask |= IXGBE_EIMS_TS;
3477282289Serj			/* Some devices use SDP0 for important information */
3478282289Serj			if (hw->device_id == IXGBE_DEV_ID_X550EM_X_SFP ||
3479282289Serj			    hw->device_id == IXGBE_DEV_ID_X550EM_X_10G_T)
3480280182Sjfv				mask |= IXGBE_EIMS_GPI_SDP0_BY_MAC(hw);
3481280182Sjfv			mask |= IXGBE_EIMS_ECC;
3482280182Sjfv#ifdef IXGBE_FDIR
3483280182Sjfv			mask |= IXGBE_EIMS_FLOW_DIR;
3484280182Sjfv#endif
3485283883Sjfv#ifdef PCI_IOV
3486283883Sjfv			mask |= IXGBE_EIMS_MAILBOX;
3487283883Sjfv#endif
3488280182Sjfv		/* falls through */
3489280182Sjfv		default:
3490280182Sjfv			break;
3491280182Sjfv	}
3492280182Sjfv
3493280182Sjfv	IXGBE_WRITE_REG(hw, IXGBE_EIMS, mask);
3494280182Sjfv
3495282289Serj	/* With MSI-X we use auto clear */
3496280182Sjfv	if (adapter->msix_mem) {
3497280182Sjfv		mask = IXGBE_EIMS_ENABLE_MASK;
3498280182Sjfv		/* Don't autoclear Link */
3499280182Sjfv		mask &= ~IXGBE_EIMS_OTHER;
3500280182Sjfv		mask &= ~IXGBE_EIMS_LSC;
3501283883Sjfv#ifdef PCI_IOV
3502283883Sjfv		mask &= ~IXGBE_EIMS_MAILBOX;
3503283883Sjfv#endif
3504280182Sjfv		IXGBE_WRITE_REG(hw, IXGBE_EIAC, mask);
3505280182Sjfv	}
3506280182Sjfv
3507280182Sjfv	/*
3508280182Sjfv	** Now enable all queues, this is done separately to
3509280182Sjfv	** allow for handling the extended (beyond 32) MSIX
3510280182Sjfv	** vectors that can be used by 82599
3511280182Sjfv	*/
3512280182Sjfv        for (int i = 0; i < adapter->num_queues; i++, que++)
3513280182Sjfv                ixgbe_enable_queue(adapter, que->msix);
3514280182Sjfv
3515280182Sjfv	IXGBE_WRITE_FLUSH(hw);
3516280182Sjfv
3517280182Sjfv	return;
3518280182Sjfv}
3519280182Sjfv
3520280182Sjfvstatic void
3521280182Sjfvixgbe_disable_intr(struct adapter *adapter)
3522280182Sjfv{
3523280182Sjfv	if (adapter->msix_mem)
3524280182Sjfv		IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIAC, 0);
3525280182Sjfv	if (adapter->hw.mac.type == ixgbe_mac_82598EB) {
3526280182Sjfv		IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMC, ~0);
3527280182Sjfv	} else {
3528280182Sjfv		IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMC, 0xFFFF0000);
3529280182Sjfv		IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMC_EX(0), ~0);
3530280182Sjfv		IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMC_EX(1), ~0);
3531280182Sjfv	}
3532280182Sjfv	IXGBE_WRITE_FLUSH(&adapter->hw);
3533280182Sjfv	return;
3534280182Sjfv}
3535280182Sjfv
3536280182Sjfv/*
3537280182Sjfv** Get the width and transaction speed of
3538280182Sjfv** the slot this adapter is plugged into.
3539280182Sjfv*/
3540280182Sjfvstatic void
3541292674Ssbrunoixgbe_get_slot_info(struct adapter *adapter)
3542280182Sjfv{
3543292674Ssbruno	device_t		dev = adapter->dev;
3544292674Ssbruno	struct ixgbe_hw		*hw = &adapter->hw;
3545280182Sjfv	struct ixgbe_mac_info	*mac = &hw->mac;
3546280182Sjfv	u16			link;
3547280182Sjfv	u32			offset;
3548280182Sjfv
3549280182Sjfv	/* For most devices simply call the shared code routine */
3550280182Sjfv	if (hw->device_id != IXGBE_DEV_ID_82599_SFP_SF_QP) {
3551280182Sjfv		ixgbe_get_bus_info(hw);
3552280182Sjfv		/* These devices don't use PCI-E */
3553282289Serj		switch (hw->mac.type) {
3554282289Serj		case ixgbe_mac_X550EM_x:
3555280182Sjfv			return;
3556282289Serj		default:
3557282289Serj			goto display;
3558282289Serj		}
3559280182Sjfv	}
3560280182Sjfv
3561280182Sjfv	/*
3562280182Sjfv	** For the Quad port adapter we need to parse back
3563280182Sjfv	** up the PCI tree to find the speed of the expansion
3564280182Sjfv	** slot into which this adapter is plugged. A bit more work.
3565280182Sjfv	*/
3566280182Sjfv	dev = device_get_parent(device_get_parent(dev));
3567280182Sjfv#ifdef IXGBE_DEBUG
3568280182Sjfv	device_printf(dev, "parent pcib = %x,%x,%x\n",
3569280182Sjfv	    pci_get_bus(dev), pci_get_slot(dev), pci_get_function(dev));
3570280182Sjfv#endif
3571280182Sjfv	dev = device_get_parent(device_get_parent(dev));
3572280182Sjfv#ifdef IXGBE_DEBUG
3573280182Sjfv	device_printf(dev, "slot pcib = %x,%x,%x\n",
3574280182Sjfv	    pci_get_bus(dev), pci_get_slot(dev), pci_get_function(dev));
3575280182Sjfv#endif
3576280182Sjfv	/* Now get the PCI Express Capabilities offset */
3577280182Sjfv	pci_find_cap(dev, PCIY_EXPRESS, &offset);
3578280182Sjfv	/* ...and read the Link Status Register */
3579280182Sjfv	link = pci_read_config(dev, offset + PCIER_LINK_STA, 2);
3580280182Sjfv	switch (link & IXGBE_PCI_LINK_WIDTH) {
3581280182Sjfv	case IXGBE_PCI_LINK_WIDTH_1:
3582280182Sjfv		hw->bus.width = ixgbe_bus_width_pcie_x1;
3583280182Sjfv		break;
3584280182Sjfv	case IXGBE_PCI_LINK_WIDTH_2:
3585280182Sjfv		hw->bus.width = ixgbe_bus_width_pcie_x2;
3586280182Sjfv		break;
3587280182Sjfv	case IXGBE_PCI_LINK_WIDTH_4:
3588280182Sjfv		hw->bus.width = ixgbe_bus_width_pcie_x4;
3589280182Sjfv		break;
3590280182Sjfv	case IXGBE_PCI_LINK_WIDTH_8:
3591280182Sjfv		hw->bus.width = ixgbe_bus_width_pcie_x8;
3592280182Sjfv		break;
3593280182Sjfv	default:
3594280182Sjfv		hw->bus.width = ixgbe_bus_width_unknown;
3595280182Sjfv		break;
3596280182Sjfv	}
3597280182Sjfv
3598280182Sjfv	switch (link & IXGBE_PCI_LINK_SPEED) {
3599280182Sjfv	case IXGBE_PCI_LINK_SPEED_2500:
3600280182Sjfv		hw->bus.speed = ixgbe_bus_speed_2500;
3601280182Sjfv		break;
3602280182Sjfv	case IXGBE_PCI_LINK_SPEED_5000:
3603280182Sjfv		hw->bus.speed = ixgbe_bus_speed_5000;
3604280182Sjfv		break;
3605280182Sjfv	case IXGBE_PCI_LINK_SPEED_8000:
3606280182Sjfv		hw->bus.speed = ixgbe_bus_speed_8000;
3607280182Sjfv		break;
3608280182Sjfv	default:
3609280182Sjfv		hw->bus.speed = ixgbe_bus_speed_unknown;
3610280182Sjfv		break;
3611280182Sjfv	}
3612280182Sjfv
3613280182Sjfv	mac->ops.set_lan_id(hw);
3614280182Sjfv
3615280182Sjfvdisplay:
3616280182Sjfv	device_printf(dev,"PCI Express Bus: Speed %s %s\n",
3617280182Sjfv	    ((hw->bus.speed == ixgbe_bus_speed_8000) ? "8.0GT/s":
3618280182Sjfv	    (hw->bus.speed == ixgbe_bus_speed_5000) ? "5.0GT/s":
3619280182Sjfv	    (hw->bus.speed == ixgbe_bus_speed_2500) ? "2.5GT/s":"Unknown"),
3620280182Sjfv	    (hw->bus.width == ixgbe_bus_width_pcie_x8) ? "Width x8" :
3621280182Sjfv	    (hw->bus.width == ixgbe_bus_width_pcie_x4) ? "Width x4" :
3622280182Sjfv	    (hw->bus.width == ixgbe_bus_width_pcie_x1) ? "Width x1" :
3623280182Sjfv	    ("Unknown"));
3624280182Sjfv
3625280182Sjfv	if ((hw->device_id != IXGBE_DEV_ID_82599_SFP_SF_QP) &&
3626280182Sjfv	    ((hw->bus.width <= ixgbe_bus_width_pcie_x4) &&
3627280182Sjfv	    (hw->bus.speed == ixgbe_bus_speed_2500))) {
3628280182Sjfv		device_printf(dev, "PCI-Express bandwidth available"
3629280182Sjfv		    " for this card\n     is not sufficient for"
3630280182Sjfv		    " optimal performance.\n");
3631280182Sjfv		device_printf(dev, "For optimal performance a x8 "
3632280182Sjfv		    "PCIE, or x4 PCIE Gen2 slot is required.\n");
3633280182Sjfv        }
3634280182Sjfv	if ((hw->device_id == IXGBE_DEV_ID_82599_SFP_SF_QP) &&
3635280182Sjfv	    ((hw->bus.width <= ixgbe_bus_width_pcie_x8) &&
3636280182Sjfv	    (hw->bus.speed < ixgbe_bus_speed_8000))) {
3637280182Sjfv		device_printf(dev, "PCI-Express bandwidth available"
3638280182Sjfv		    " for this card\n     is not sufficient for"
3639280182Sjfv		    " optimal performance.\n");
3640280182Sjfv		device_printf(dev, "For optimal performance a x8 "
3641280182Sjfv		    "PCIE Gen3 slot is required.\n");
3642280182Sjfv        }
3643280182Sjfv
3644280182Sjfv	return;
3645280182Sjfv}
3646280182Sjfv
3647280182Sjfv
3648280182Sjfv/*
3649280182Sjfv** Setup the correct IVAR register for a particular MSIX interrupt
3650280182Sjfv**   (yes this is all very magic and confusing :)
3651280182Sjfv**  - entry is the register array entry
3652280182Sjfv**  - vector is the MSIX vector for this queue
3653280182Sjfv**  - type is RX/TX/MISC
3654280182Sjfv*/
3655280182Sjfvstatic void
3656280182Sjfvixgbe_set_ivar(struct adapter *adapter, u8 entry, u8 vector, s8 type)
3657280182Sjfv{
3658280182Sjfv	struct ixgbe_hw *hw = &adapter->hw;
3659280182Sjfv	u32 ivar, index;
3660280182Sjfv
3661280182Sjfv	vector |= IXGBE_IVAR_ALLOC_VAL;
3662280182Sjfv
3663280182Sjfv	switch (hw->mac.type) {
3664280182Sjfv
3665280182Sjfv	case ixgbe_mac_82598EB:
3666280182Sjfv		if (type == -1)
3667280182Sjfv			entry = IXGBE_IVAR_OTHER_CAUSES_INDEX;
3668280182Sjfv		else
3669280182Sjfv			entry += (type * 64);
3670280182Sjfv		index = (entry >> 2) & 0x1F;
3671280182Sjfv		ivar = IXGBE_READ_REG(hw, IXGBE_IVAR(index));
3672280182Sjfv		ivar &= ~(0xFF << (8 * (entry & 0x3)));
3673280182Sjfv		ivar |= (vector << (8 * (entry & 0x3)));
3674280182Sjfv		IXGBE_WRITE_REG(&adapter->hw, IXGBE_IVAR(index), ivar);
3675280182Sjfv		break;
3676280182Sjfv
3677280182Sjfv	case ixgbe_mac_82599EB:
3678280182Sjfv	case ixgbe_mac_X540:
3679280182Sjfv	case ixgbe_mac_X550:
3680280182Sjfv	case ixgbe_mac_X550EM_x:
3681280182Sjfv		if (type == -1) { /* MISC IVAR */
3682280182Sjfv			index = (entry & 1) * 8;
3683280182Sjfv			ivar = IXGBE_READ_REG(hw, IXGBE_IVAR_MISC);
3684280182Sjfv			ivar &= ~(0xFF << index);
3685280182Sjfv			ivar |= (vector << index);
3686280182Sjfv			IXGBE_WRITE_REG(hw, IXGBE_IVAR_MISC, ivar);
3687280182Sjfv		} else {	/* RX/TX IVARS */
3688280182Sjfv			index = (16 * (entry & 1)) + (8 * type);
3689280182Sjfv			ivar = IXGBE_READ_REG(hw, IXGBE_IVAR(entry >> 1));
3690280182Sjfv			ivar &= ~(0xFF << index);
3691280182Sjfv			ivar |= (vector << index);
3692280182Sjfv			IXGBE_WRITE_REG(hw, IXGBE_IVAR(entry >> 1), ivar);
3693280182Sjfv		}
3694280182Sjfv
3695280182Sjfv	default:
3696280182Sjfv		break;
3697280182Sjfv	}
3698280182Sjfv}
3699280182Sjfv
3700280182Sjfvstatic void
3701280182Sjfvixgbe_configure_ivars(struct adapter *adapter)
3702280182Sjfv{
3703283883Sjfv	struct  ix_queue	*que = adapter->queues;
3704283883Sjfv	u32			newitr;
3705280182Sjfv
3706280182Sjfv	if (ixgbe_max_interrupt_rate > 0)
3707280182Sjfv		newitr = (4000000 / ixgbe_max_interrupt_rate) & 0x0FF8;
3708282289Serj	else {
3709282289Serj		/*
3710282289Serj		** Disable DMA coalescing if interrupt moderation is
3711282289Serj		** disabled.
3712282289Serj		*/
3713282289Serj		adapter->dmac = 0;
3714280182Sjfv		newitr = 0;
3715282289Serj	}
3716280182Sjfv
3717280182Sjfv        for (int i = 0; i < adapter->num_queues; i++, que++) {
3718283883Sjfv		struct rx_ring *rxr = &adapter->rx_rings[i];
3719283883Sjfv		struct tx_ring *txr = &adapter->tx_rings[i];
3720280182Sjfv		/* First the RX queue entry */
3721283883Sjfv                ixgbe_set_ivar(adapter, rxr->me, que->msix, 0);
3722280182Sjfv		/* ... and the TX */
3723283883Sjfv		ixgbe_set_ivar(adapter, txr->me, que->msix, 1);
3724280182Sjfv		/* Set an Initial EITR value */
3725280182Sjfv                IXGBE_WRITE_REG(&adapter->hw,
3726280182Sjfv                    IXGBE_EITR(que->msix), newitr);
3727280182Sjfv	}
3728280182Sjfv
3729280182Sjfv	/* For the Link interrupt */
3730280182Sjfv        ixgbe_set_ivar(adapter, 1, adapter->vector, -1);
3731280182Sjfv}
3732280182Sjfv
3733280182Sjfv/*
3734280182Sjfv** ixgbe_sfp_probe - called in the local timer to
3735280182Sjfv** determine if a port had optics inserted.
3736280182Sjfv*/
3737283883Sjfvstatic bool
3738283883Sjfvixgbe_sfp_probe(struct adapter *adapter)
3739280182Sjfv{
3740280182Sjfv	struct ixgbe_hw	*hw = &adapter->hw;
3741280182Sjfv	device_t	dev = adapter->dev;
3742280182Sjfv	bool		result = FALSE;
3743280182Sjfv
3744280182Sjfv	if ((hw->phy.type == ixgbe_phy_nl) &&
3745280182Sjfv	    (hw->phy.sfp_type == ixgbe_sfp_type_not_present)) {
3746280182Sjfv		s32 ret = hw->phy.ops.identify_sfp(hw);
3747280182Sjfv		if (ret)
3748280182Sjfv                        goto out;
3749280182Sjfv		ret = hw->phy.ops.reset(hw);
3750280182Sjfv		if (ret == IXGBE_ERR_SFP_NOT_SUPPORTED) {
3751292674Ssbruno			device_printf(dev, "Unsupported SFP+ module detected!");
3752292674Ssbruno			device_printf(dev, "Reload driver with supported module.\n");
3753280182Sjfv			adapter->sfp_probe = FALSE;
3754280182Sjfv                        goto out;
3755280182Sjfv		} else
3756292674Ssbruno			device_printf(dev, "SFP+ module detected!\n");
3757280182Sjfv		/* We now have supported optics */
3758280182Sjfv		adapter->sfp_probe = FALSE;
3759280182Sjfv		/* Set the optics type so system reports correctly */
3760280182Sjfv		ixgbe_setup_optics(adapter);
3761280182Sjfv		result = TRUE;
3762280182Sjfv	}
3763280182Sjfvout:
3764280182Sjfv	return (result);
3765280182Sjfv}
3766280182Sjfv
3767280182Sjfv/*
3768280182Sjfv** Tasklet handler for MSIX Link interrupts
3769280182Sjfv**  - do outside interrupt since it might sleep
3770280182Sjfv*/
3771280182Sjfvstatic void
3772280182Sjfvixgbe_handle_link(void *context, int pending)
3773280182Sjfv{
3774280182Sjfv	struct adapter  *adapter = context;
3775292674Ssbruno	struct ixgbe_hw *hw = &adapter->hw;
3776280182Sjfv
3777292674Ssbruno	ixgbe_check_link(hw,
3778280182Sjfv	    &adapter->link_speed, &adapter->link_up, 0);
3779282289Serj	ixgbe_update_link_status(adapter);
3780292674Ssbruno
3781292674Ssbruno	/* Re-enable link interrupts */
3782292674Ssbruno	IXGBE_WRITE_REG(hw, IXGBE_EIMS, IXGBE_EIMS_LSC);
3783280182Sjfv}
3784280182Sjfv
3785280182Sjfv/*
3786280182Sjfv** Tasklet for handling SFP module interrupts
3787280182Sjfv*/
3788280182Sjfvstatic void
3789280182Sjfvixgbe_handle_mod(void *context, int pending)
3790280182Sjfv{
3791280182Sjfv	struct adapter  *adapter = context;
3792280182Sjfv	struct ixgbe_hw *hw = &adapter->hw;
3793293334Ssbruno	enum ixgbe_phy_type orig_type = hw->phy.type;
3794280182Sjfv	device_t	dev = adapter->dev;
3795280182Sjfv	u32 err;
3796280182Sjfv
3797293334Ssbruno	IXGBE_CORE_LOCK(adapter);
3798293334Ssbruno
3799293334Ssbruno	/* Check to see if the PHY type changed */
3800293334Ssbruno	if (hw->phy.ops.identify) {
3801293334Ssbruno		hw->phy.type = ixgbe_phy_unknown;
3802293334Ssbruno		hw->phy.ops.identify(hw);
3803293334Ssbruno	}
3804293334Ssbruno
3805293334Ssbruno	if (hw->phy.type != orig_type) {
3806293334Ssbruno		device_printf(dev, "Detected phy_type %d\n", hw->phy.type);
3807293334Ssbruno
3808293334Ssbruno		if (hw->phy.type == ixgbe_phy_none) {
3809293334Ssbruno			hw->phy.sfp_type = ixgbe_sfp_type_unknown;
3810293334Ssbruno			goto out;
3811293334Ssbruno		}
3812293334Ssbruno
3813293334Ssbruno		/* Try to do the initialization that was skipped before */
3814293334Ssbruno		if (hw->phy.ops.init)
3815293334Ssbruno			hw->phy.ops.init(hw);
3816293334Ssbruno		if (hw->phy.ops.reset)
3817293334Ssbruno			hw->phy.ops.reset(hw);
3818293334Ssbruno	}
3819293334Ssbruno
3820280182Sjfv	err = hw->phy.ops.identify_sfp(hw);
3821280182Sjfv	if (err == IXGBE_ERR_SFP_NOT_SUPPORTED) {
3822280182Sjfv		device_printf(dev,
3823280182Sjfv		    "Unsupported SFP+ module type was detected.\n");
3824293334Ssbruno		goto out;
3825280182Sjfv	}
3826283883Sjfv
3827280182Sjfv	err = hw->mac.ops.setup_sfp(hw);
3828280182Sjfv	if (err == IXGBE_ERR_SFP_NOT_SUPPORTED) {
3829280182Sjfv		device_printf(dev,
3830280182Sjfv		    "Setup failure - unsupported SFP+ module type.\n");
3831293334Ssbruno		goto out;
3832280182Sjfv	}
3833293334Ssbruno	if (hw->phy.multispeed_fiber)
3834293334Ssbruno		taskqueue_enqueue(adapter->tq, &adapter->msf_task);
3835293334Ssbrunoout:
3836293334Ssbruno	/* Update media type */
3837293334Ssbruno	switch (hw->mac.ops.get_media_type(hw)) {
3838293334Ssbruno		case ixgbe_media_type_fiber:
3839293334Ssbruno			adapter->optics = IFM_10G_SR;
3840293334Ssbruno			break;
3841293334Ssbruno		case ixgbe_media_type_copper:
3842293334Ssbruno			adapter->optics = IFM_10G_TWINAX;
3843293334Ssbruno			break;
3844293334Ssbruno		case ixgbe_media_type_cx4:
3845293334Ssbruno			adapter->optics = IFM_10G_CX4;
3846293334Ssbruno			break;
3847293334Ssbruno		default:
3848293334Ssbruno			adapter->optics = 0;
3849293334Ssbruno			break;
3850293334Ssbruno	}
3851293334Ssbruno
3852293334Ssbruno	IXGBE_CORE_UNLOCK(adapter);
3853280182Sjfv	return;
3854280182Sjfv}
3855280182Sjfv
3856280182Sjfv
3857280182Sjfv/*
3858280182Sjfv** Tasklet for handling MSF (multispeed fiber) interrupts
3859280182Sjfv*/
3860280182Sjfvstatic void
3861280182Sjfvixgbe_handle_msf(void *context, int pending)
3862280182Sjfv{
3863280182Sjfv	struct adapter  *adapter = context;
3864280182Sjfv	struct ixgbe_hw *hw = &adapter->hw;
3865280182Sjfv	u32 autoneg;
3866280182Sjfv	bool negotiate;
3867280182Sjfv
3868293334Ssbruno	IXGBE_CORE_LOCK(adapter);
3869292674Ssbruno	/* get_supported_phy_layer will call hw->phy.ops.identify_sfp() */
3870292674Ssbruno	adapter->phy_layer = ixgbe_get_supported_physical_layer(hw);
3871280182Sjfv
3872280182Sjfv	autoneg = hw->phy.autoneg_advertised;
3873280182Sjfv	if ((!autoneg) && (hw->mac.ops.get_link_capabilities))
3874280182Sjfv		hw->mac.ops.get_link_capabilities(hw, &autoneg, &negotiate);
3875280182Sjfv	if (hw->mac.ops.setup_link)
3876280182Sjfv		hw->mac.ops.setup_link(hw, autoneg, TRUE);
3877280182Sjfv
3878292674Ssbruno	/* Adjust media types shown in ifconfig */
3879280182Sjfv	ifmedia_removeall(&adapter->media);
3880280182Sjfv	ixgbe_add_media_types(adapter);
3881293334Ssbruno	IXGBE_CORE_UNLOCK(adapter);
3882280182Sjfv	return;
3883280182Sjfv}
3884280182Sjfv
3885282289Serj/*
3886282289Serj** Tasklet for handling interrupts from an external PHY
3887282289Serj*/
3888282289Serjstatic void
3889282289Serjixgbe_handle_phy(void *context, int pending)
3890282289Serj{
3891282289Serj	struct adapter  *adapter = context;
3892282289Serj	struct ixgbe_hw *hw = &adapter->hw;
3893282289Serj	int error;
3894282289Serj
3895282289Serj	error = hw->phy.ops.handle_lasi(hw);
3896282289Serj	if (error == IXGBE_ERR_OVERTEMP)
3897282289Serj		device_printf(adapter->dev,
3898282289Serj		    "CRITICAL: EXTERNAL PHY OVER TEMP!! "
3899282289Serj		    " PHY will downshift to lower power state!\n");
3900282289Serj	else if (error)
3901282289Serj		device_printf(adapter->dev,
3902282289Serj		    "Error handling LASI interrupt: %d\n",
3903282289Serj		    error);
3904282289Serj	return;
3905282289Serj}
3906282289Serj
3907280182Sjfv#ifdef IXGBE_FDIR
3908280182Sjfv/*
3909280182Sjfv** Tasklet for reinitializing the Flow Director filter table
3910280182Sjfv*/
3911280182Sjfvstatic void
3912280182Sjfvixgbe_reinit_fdir(void *context, int pending)
3913280182Sjfv{
3914280182Sjfv	struct adapter  *adapter = context;
3915280182Sjfv	struct ifnet   *ifp = adapter->ifp;
3916280182Sjfv
3917280182Sjfv	if (adapter->fdir_reinit != 1) /* Shouldn't happen */
3918280182Sjfv		return;
3919280182Sjfv	ixgbe_reinit_fdir_tables_82599(&adapter->hw);
3920280182Sjfv	adapter->fdir_reinit = 0;
3921280182Sjfv	/* re-enable flow director interrupts */
3922280182Sjfv	IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMS, IXGBE_EIMS_FLOW_DIR);
3923280182Sjfv	/* Restart the interface */
3924280182Sjfv	ifp->if_drv_flags |= IFF_DRV_RUNNING;
3925280182Sjfv	return;
3926280182Sjfv}
3927280182Sjfv#endif
3928280182Sjfv
3929282289Serj/*********************************************************************
3930282289Serj *
3931282289Serj *  Configure DMA Coalescing
3932282289Serj *
3933282289Serj **********************************************************************/
3934282289Serjstatic void
3935282289Serjixgbe_config_dmac(struct adapter *adapter)
3936282289Serj{
3937282289Serj	struct ixgbe_hw *hw = &adapter->hw;
3938282289Serj	struct ixgbe_dmac_config *dcfg = &hw->mac.dmac_config;
3939282289Serj
3940282289Serj	if (hw->mac.type < ixgbe_mac_X550 ||
3941282289Serj	    !hw->mac.ops.dmac_config)
3942282289Serj		return;
3943282289Serj
3944282289Serj	if (dcfg->watchdog_timer ^ adapter->dmac ||
3945282289Serj	    dcfg->link_speed ^ adapter->link_speed) {
3946282289Serj		dcfg->watchdog_timer = adapter->dmac;
3947282289Serj		dcfg->fcoe_en = false;
3948282289Serj		dcfg->link_speed = adapter->link_speed;
3949282289Serj		dcfg->num_tcs = 1;
3950282289Serj
3951282289Serj		INIT_DEBUGOUT2("dmac settings: watchdog %d, link speed %d\n",
3952282289Serj		    dcfg->watchdog_timer, dcfg->link_speed);
3953282289Serj
3954282289Serj		hw->mac.ops.dmac_config(hw);
3955282289Serj	}
3956282289Serj}
3957282289Serj
3958282289Serj/*
3959282289Serj * Checks whether the adapter's ports are capable of
3960282289Serj * Wake On LAN by reading the adapter's NVM.
3961282289Serj *
3962282289Serj * Sets each port's hw->wol_enabled value depending
3963282289Serj * on the value read here.
3964282289Serj */
3965282289Serjstatic void
3966282289Serjixgbe_check_wol_support(struct adapter *adapter)
3967282289Serj{
3968282289Serj	struct ixgbe_hw *hw = &adapter->hw;
3969282289Serj	u16 dev_caps = 0;
3970282289Serj
3971282289Serj	/* Find out WoL support for port */
3972282289Serj	adapter->wol_support = hw->wol_enabled = 0;
3973282289Serj	ixgbe_get_device_caps(hw, &dev_caps);
3974282289Serj	if ((dev_caps & IXGBE_DEVICE_CAPS_WOL_PORT0_1) ||
3975282289Serj	    ((dev_caps & IXGBE_DEVICE_CAPS_WOL_PORT0) &&
3976292674Ssbruno	      hw->bus.func == 0))
3977292674Ssbruno		adapter->wol_support = hw->wol_enabled = 1;
3978282289Serj
3979282289Serj	/* Save initial wake up filter configuration */
3980282289Serj	adapter->wufc = IXGBE_READ_REG(hw, IXGBE_WUFC);
3981282289Serj
3982282289Serj	return;
3983282289Serj}
3984282289Serj
3985282289Serj/*
3986282289Serj * Prepare the adapter/port for LPLU and/or WoL
3987282289Serj */
3988282289Serjstatic int
3989282289Serjixgbe_setup_low_power_mode(struct adapter *adapter)
3990282289Serj{
3991282289Serj	struct ixgbe_hw *hw = &adapter->hw;
3992282289Serj	device_t dev = adapter->dev;
3993282289Serj	s32 error = 0;
3994282289Serj
3995282289Serj	mtx_assert(&adapter->core_mtx, MA_OWNED);
3996282289Serj
3997295093Ssmh	if (!hw->wol_enabled)
3998295093Ssmh		ixgbe_set_phy_power(hw, FALSE);
3999295093Ssmh
4000282289Serj	/* Limit power management flow to X550EM baseT */
4001282289Serj	if (hw->device_id == IXGBE_DEV_ID_X550EM_X_10G_T
4002282289Serj	    && hw->phy.ops.enter_lplu) {
4003282289Serj		/* Turn off support for APM wakeup. (Using ACPI instead) */
4004282289Serj		IXGBE_WRITE_REG(hw, IXGBE_GRC,
4005282289Serj		    IXGBE_READ_REG(hw, IXGBE_GRC) & ~(u32)2);
4006282289Serj
4007282289Serj		/*
4008282289Serj		 * Clear Wake Up Status register to prevent any previous wakeup
4009282289Serj		 * events from waking us up immediately after we suspend.
4010282289Serj		 */
4011282289Serj		IXGBE_WRITE_REG(hw, IXGBE_WUS, 0xffffffff);
4012282289Serj
4013282289Serj		/*
4014282289Serj		 * Program the Wakeup Filter Control register with user filter
4015282289Serj		 * settings
4016282289Serj		 */
4017282289Serj		IXGBE_WRITE_REG(hw, IXGBE_WUFC, adapter->wufc);
4018282289Serj
4019282289Serj		/* Enable wakeups and power management in Wakeup Control */
4020282289Serj		IXGBE_WRITE_REG(hw, IXGBE_WUC,
4021282289Serj		    IXGBE_WUC_WKEN | IXGBE_WUC_PME_EN);
4022282289Serj
4023282289Serj		/* X550EM baseT adapters need a special LPLU flow */
4024282289Serj		hw->phy.reset_disable = true;
4025282289Serj		ixgbe_stop(adapter);
4026282289Serj		error = hw->phy.ops.enter_lplu(hw);
4027282289Serj		if (error)
4028282289Serj			device_printf(dev,
4029282289Serj			    "Error entering LPLU: %d\n", error);
4030282289Serj		hw->phy.reset_disable = false;
4031282289Serj	} else {
4032282289Serj		/* Just stop for other adapters */
4033282289Serj		ixgbe_stop(adapter);
4034282289Serj	}
4035282289Serj
4036282289Serj	return error;
4037282289Serj}
4038282289Serj
4039280182Sjfv/**********************************************************************
4040280182Sjfv *
4041280182Sjfv *  Update the board statistics counters.
4042280182Sjfv *
4043280182Sjfv **********************************************************************/
4044280182Sjfvstatic void
4045280182Sjfvixgbe_update_stats_counters(struct adapter *adapter)
4046280182Sjfv{
4047280182Sjfv	struct ixgbe_hw *hw = &adapter->hw;
4048280182Sjfv	u32 missed_rx = 0, bprc, lxon, lxoff, total;
4049280182Sjfv	u64 total_missed_rx = 0;
4050280182Sjfv
4051280182Sjfv	adapter->stats.pf.crcerrs += IXGBE_READ_REG(hw, IXGBE_CRCERRS);
4052280182Sjfv	adapter->stats.pf.illerrc += IXGBE_READ_REG(hw, IXGBE_ILLERRC);
4053280182Sjfv	adapter->stats.pf.errbc += IXGBE_READ_REG(hw, IXGBE_ERRBC);
4054280182Sjfv	adapter->stats.pf.mspdc += IXGBE_READ_REG(hw, IXGBE_MSPDC);
4055280182Sjfv
4056280182Sjfv	for (int i = 0; i < 16; i++) {
4057280182Sjfv		adapter->stats.pf.qprc[i] += IXGBE_READ_REG(hw, IXGBE_QPRC(i));
4058280182Sjfv		adapter->stats.pf.qptc[i] += IXGBE_READ_REG(hw, IXGBE_QPTC(i));
4059280182Sjfv		adapter->stats.pf.qprdc[i] += IXGBE_READ_REG(hw, IXGBE_QPRDC(i));
4060280182Sjfv	}
4061280182Sjfv	adapter->stats.pf.mlfc += IXGBE_READ_REG(hw, IXGBE_MLFC);
4062280182Sjfv	adapter->stats.pf.mrfc += IXGBE_READ_REG(hw, IXGBE_MRFC);
4063280182Sjfv	adapter->stats.pf.rlec += IXGBE_READ_REG(hw, IXGBE_RLEC);
4064280182Sjfv
4065280182Sjfv	/* Hardware workaround, gprc counts missed packets */
4066280182Sjfv	adapter->stats.pf.gprc += IXGBE_READ_REG(hw, IXGBE_GPRC);
4067280182Sjfv	adapter->stats.pf.gprc -= missed_rx;
4068280182Sjfv
4069280182Sjfv	if (hw->mac.type != ixgbe_mac_82598EB) {
4070280182Sjfv		adapter->stats.pf.gorc += IXGBE_READ_REG(hw, IXGBE_GORCL) +
4071280182Sjfv		    ((u64)IXGBE_READ_REG(hw, IXGBE_GORCH) << 32);
4072280182Sjfv		adapter->stats.pf.gotc += IXGBE_READ_REG(hw, IXGBE_GOTCL) +
4073280182Sjfv		    ((u64)IXGBE_READ_REG(hw, IXGBE_GOTCH) << 32);
4074280182Sjfv		adapter->stats.pf.tor += IXGBE_READ_REG(hw, IXGBE_TORL) +
4075280182Sjfv		    ((u64)IXGBE_READ_REG(hw, IXGBE_TORH) << 32);
4076280182Sjfv		adapter->stats.pf.lxonrxc += IXGBE_READ_REG(hw, IXGBE_LXONRXCNT);
4077280182Sjfv		adapter->stats.pf.lxoffrxc += IXGBE_READ_REG(hw, IXGBE_LXOFFRXCNT);
4078280182Sjfv	} else {
4079280182Sjfv		adapter->stats.pf.lxonrxc += IXGBE_READ_REG(hw, IXGBE_LXONRXC);
4080280182Sjfv		adapter->stats.pf.lxoffrxc += IXGBE_READ_REG(hw, IXGBE_LXOFFRXC);
4081280182Sjfv		/* 82598 only has a counter in the high register */
4082280182Sjfv		adapter->stats.pf.gorc += IXGBE_READ_REG(hw, IXGBE_GORCH);
4083280182Sjfv		adapter->stats.pf.gotc += IXGBE_READ_REG(hw, IXGBE_GOTCH);
4084280182Sjfv		adapter->stats.pf.tor += IXGBE_READ_REG(hw, IXGBE_TORH);
4085280182Sjfv	}
4086280182Sjfv
4087280182Sjfv	/*
4088280182Sjfv	 * Workaround: mprc hardware is incorrectly counting
4089280182Sjfv	 * broadcasts, so for now we subtract those.
4090280182Sjfv	 */
4091280182Sjfv	bprc = IXGBE_READ_REG(hw, IXGBE_BPRC);
4092280182Sjfv	adapter->stats.pf.bprc += bprc;
4093280182Sjfv	adapter->stats.pf.mprc += IXGBE_READ_REG(hw, IXGBE_MPRC);
4094280182Sjfv	if (hw->mac.type == ixgbe_mac_82598EB)
4095280182Sjfv		adapter->stats.pf.mprc -= bprc;
4096280182Sjfv
4097280182Sjfv	adapter->stats.pf.prc64 += IXGBE_READ_REG(hw, IXGBE_PRC64);
4098280182Sjfv	adapter->stats.pf.prc127 += IXGBE_READ_REG(hw, IXGBE_PRC127);
4099280182Sjfv	adapter->stats.pf.prc255 += IXGBE_READ_REG(hw, IXGBE_PRC255);
4100280182Sjfv	adapter->stats.pf.prc511 += IXGBE_READ_REG(hw, IXGBE_PRC511);
4101280182Sjfv	adapter->stats.pf.prc1023 += IXGBE_READ_REG(hw, IXGBE_PRC1023);
4102280182Sjfv	adapter->stats.pf.prc1522 += IXGBE_READ_REG(hw, IXGBE_PRC1522);
4103280182Sjfv
4104280182Sjfv	lxon = IXGBE_READ_REG(hw, IXGBE_LXONTXC);
4105280182Sjfv	adapter->stats.pf.lxontxc += lxon;
4106280182Sjfv	lxoff = IXGBE_READ_REG(hw, IXGBE_LXOFFTXC);
4107280182Sjfv	adapter->stats.pf.lxofftxc += lxoff;
4108280182Sjfv	total = lxon + lxoff;
4109280182Sjfv
4110280182Sjfv	adapter->stats.pf.gptc += IXGBE_READ_REG(hw, IXGBE_GPTC);
4111280182Sjfv	adapter->stats.pf.mptc += IXGBE_READ_REG(hw, IXGBE_MPTC);
4112280182Sjfv	adapter->stats.pf.ptc64 += IXGBE_READ_REG(hw, IXGBE_PTC64);
4113280182Sjfv	adapter->stats.pf.gptc -= total;
4114280182Sjfv	adapter->stats.pf.mptc -= total;
4115280182Sjfv	adapter->stats.pf.ptc64 -= total;
4116280182Sjfv	adapter->stats.pf.gotc -= total * ETHER_MIN_LEN;
4117280182Sjfv
4118280182Sjfv	adapter->stats.pf.ruc += IXGBE_READ_REG(hw, IXGBE_RUC);
4119280182Sjfv	adapter->stats.pf.rfc += IXGBE_READ_REG(hw, IXGBE_RFC);
4120280182Sjfv	adapter->stats.pf.roc += IXGBE_READ_REG(hw, IXGBE_ROC);
4121280182Sjfv	adapter->stats.pf.rjc += IXGBE_READ_REG(hw, IXGBE_RJC);
4122280182Sjfv	adapter->stats.pf.mngprc += IXGBE_READ_REG(hw, IXGBE_MNGPRC);
4123280182Sjfv	adapter->stats.pf.mngpdc += IXGBE_READ_REG(hw, IXGBE_MNGPDC);
4124280182Sjfv	adapter->stats.pf.mngptc += IXGBE_READ_REG(hw, IXGBE_MNGPTC);
4125280182Sjfv	adapter->stats.pf.tpr += IXGBE_READ_REG(hw, IXGBE_TPR);
4126280182Sjfv	adapter->stats.pf.tpt += IXGBE_READ_REG(hw, IXGBE_TPT);
4127280182Sjfv	adapter->stats.pf.ptc127 += IXGBE_READ_REG(hw, IXGBE_PTC127);
4128280182Sjfv	adapter->stats.pf.ptc255 += IXGBE_READ_REG(hw, IXGBE_PTC255);
4129280182Sjfv	adapter->stats.pf.ptc511 += IXGBE_READ_REG(hw, IXGBE_PTC511);
4130280182Sjfv	adapter->stats.pf.ptc1023 += IXGBE_READ_REG(hw, IXGBE_PTC1023);
4131280182Sjfv	adapter->stats.pf.ptc1522 += IXGBE_READ_REG(hw, IXGBE_PTC1522);
4132280182Sjfv	adapter->stats.pf.bptc += IXGBE_READ_REG(hw, IXGBE_BPTC);
4133280182Sjfv	adapter->stats.pf.xec += IXGBE_READ_REG(hw, IXGBE_XEC);
4134280182Sjfv	adapter->stats.pf.fccrc += IXGBE_READ_REG(hw, IXGBE_FCCRC);
4135280182Sjfv	adapter->stats.pf.fclast += IXGBE_READ_REG(hw, IXGBE_FCLAST);
4136280182Sjfv	/* Only read FCOE on 82599 */
4137280182Sjfv	if (hw->mac.type != ixgbe_mac_82598EB) {
4138280182Sjfv		adapter->stats.pf.fcoerpdc += IXGBE_READ_REG(hw, IXGBE_FCOERPDC);
4139280182Sjfv		adapter->stats.pf.fcoeprc += IXGBE_READ_REG(hw, IXGBE_FCOEPRC);
4140280182Sjfv		adapter->stats.pf.fcoeptc += IXGBE_READ_REG(hw, IXGBE_FCOEPTC);
4141280182Sjfv		adapter->stats.pf.fcoedwrc += IXGBE_READ_REG(hw, IXGBE_FCOEDWRC);
4142280182Sjfv		adapter->stats.pf.fcoedwtc += IXGBE_READ_REG(hw, IXGBE_FCOEDWTC);
4143280182Sjfv	}
4144280182Sjfv
4145280182Sjfv	/* Fill out the OS statistics structure */
4146280182Sjfv	IXGBE_SET_IPACKETS(adapter, adapter->stats.pf.gprc);
4147280182Sjfv	IXGBE_SET_OPACKETS(adapter, adapter->stats.pf.gptc);
4148280182Sjfv	IXGBE_SET_IBYTES(adapter, adapter->stats.pf.gorc);
4149280182Sjfv	IXGBE_SET_OBYTES(adapter, adapter->stats.pf.gotc);
4150280182Sjfv	IXGBE_SET_IMCASTS(adapter, adapter->stats.pf.mprc);
4151280182Sjfv	IXGBE_SET_OMCASTS(adapter, adapter->stats.pf.mptc);
4152280182Sjfv	IXGBE_SET_COLLISIONS(adapter, 0);
4153280182Sjfv	IXGBE_SET_IQDROPS(adapter, total_missed_rx);
4154280182Sjfv	IXGBE_SET_IERRORS(adapter, adapter->stats.pf.crcerrs
4155280182Sjfv	    + adapter->stats.pf.rlec);
4156280182Sjfv}
4157280182Sjfv
4158280182Sjfv#if __FreeBSD_version >= 1100036
4159280182Sjfvstatic uint64_t
4160280182Sjfvixgbe_get_counter(struct ifnet *ifp, ift_counter cnt)
4161280182Sjfv{
4162280182Sjfv	struct adapter *adapter;
4163282280Sjhb	struct tx_ring *txr;
4164282280Sjhb	uint64_t rv;
4165280182Sjfv
4166280182Sjfv	adapter = if_getsoftc(ifp);
4167280182Sjfv
4168280182Sjfv	switch (cnt) {
4169280182Sjfv	case IFCOUNTER_IPACKETS:
4170280182Sjfv		return (adapter->ipackets);
4171280182Sjfv	case IFCOUNTER_OPACKETS:
4172280182Sjfv		return (adapter->opackets);
4173280182Sjfv	case IFCOUNTER_IBYTES:
4174280182Sjfv		return (adapter->ibytes);
4175280182Sjfv	case IFCOUNTER_OBYTES:
4176280182Sjfv		return (adapter->obytes);
4177280182Sjfv	case IFCOUNTER_IMCASTS:
4178280182Sjfv		return (adapter->imcasts);
4179280182Sjfv	case IFCOUNTER_OMCASTS:
4180280182Sjfv		return (adapter->omcasts);
4181280182Sjfv	case IFCOUNTER_COLLISIONS:
4182280182Sjfv		return (0);
4183280182Sjfv	case IFCOUNTER_IQDROPS:
4184280182Sjfv		return (adapter->iqdrops);
4185282280Sjhb	case IFCOUNTER_OQDROPS:
4186282280Sjhb		rv = 0;
4187282280Sjhb		txr = adapter->tx_rings;
4188282280Sjhb		for (int i = 0; i < adapter->num_queues; i++, txr++)
4189282280Sjhb			rv += txr->br->br_drops;
4190282280Sjhb		return (rv);
4191280182Sjfv	case IFCOUNTER_IERRORS:
4192280182Sjfv		return (adapter->ierrors);
4193280182Sjfv	default:
4194280182Sjfv		return (if_get_counter_default(ifp, cnt));
4195280182Sjfv	}
4196280182Sjfv}
4197280182Sjfv#endif
4198280182Sjfv
4199280182Sjfv/** ixgbe_sysctl_tdh_handler - Handler function
4200280182Sjfv *  Retrieves the TDH value from the hardware
4201280182Sjfv */
4202280182Sjfvstatic int
4203280182Sjfvixgbe_sysctl_tdh_handler(SYSCTL_HANDLER_ARGS)
4204280182Sjfv{
4205280182Sjfv	int error;
4206280182Sjfv
4207280182Sjfv	struct tx_ring *txr = ((struct tx_ring *)oidp->oid_arg1);
4208280182Sjfv	if (!txr) return 0;
4209280182Sjfv
4210280182Sjfv	unsigned val = IXGBE_READ_REG(&txr->adapter->hw, IXGBE_TDH(txr->me));
4211280182Sjfv	error = sysctl_handle_int(oidp, &val, 0, req);
4212280182Sjfv	if (error || !req->newptr)
4213280182Sjfv		return error;
4214280182Sjfv	return 0;
4215280182Sjfv}
4216280182Sjfv
4217280182Sjfv/** ixgbe_sysctl_tdt_handler - Handler function
4218280182Sjfv *  Retrieves the TDT value from the hardware
4219280182Sjfv */
4220280182Sjfvstatic int
4221280182Sjfvixgbe_sysctl_tdt_handler(SYSCTL_HANDLER_ARGS)
4222280182Sjfv{
4223280182Sjfv	int error;
4224280182Sjfv
4225280182Sjfv	struct tx_ring *txr = ((struct tx_ring *)oidp->oid_arg1);
4226280182Sjfv	if (!txr) return 0;
4227280182Sjfv
4228280182Sjfv	unsigned val = IXGBE_READ_REG(&txr->adapter->hw, IXGBE_TDT(txr->me));
4229280182Sjfv	error = sysctl_handle_int(oidp, &val, 0, req);
4230280182Sjfv	if (error || !req->newptr)
4231280182Sjfv		return error;
4232280182Sjfv	return 0;
4233280182Sjfv}
4234280182Sjfv
4235280182Sjfv/** ixgbe_sysctl_rdh_handler - Handler function
4236280182Sjfv *  Retrieves the RDH value from the hardware
4237280182Sjfv */
4238280182Sjfvstatic int
4239280182Sjfvixgbe_sysctl_rdh_handler(SYSCTL_HANDLER_ARGS)
4240280182Sjfv{
4241280182Sjfv	int error;
4242280182Sjfv
4243280182Sjfv	struct rx_ring *rxr = ((struct rx_ring *)oidp->oid_arg1);
4244280182Sjfv	if (!rxr) return 0;
4245280182Sjfv
4246280182Sjfv	unsigned val = IXGBE_READ_REG(&rxr->adapter->hw, IXGBE_RDH(rxr->me));
4247280182Sjfv	error = sysctl_handle_int(oidp, &val, 0, req);
4248280182Sjfv	if (error || !req->newptr)
4249280182Sjfv		return error;
4250280182Sjfv	return 0;
4251280182Sjfv}
4252280182Sjfv
4253280182Sjfv/** ixgbe_sysctl_rdt_handler - Handler function
4254280182Sjfv *  Retrieves the RDT value from the hardware
4255280182Sjfv */
4256280182Sjfvstatic int
4257280182Sjfvixgbe_sysctl_rdt_handler(SYSCTL_HANDLER_ARGS)
4258280182Sjfv{
4259280182Sjfv	int error;
4260280182Sjfv
4261280182Sjfv	struct rx_ring *rxr = ((struct rx_ring *)oidp->oid_arg1);
4262280182Sjfv	if (!rxr) return 0;
4263280182Sjfv
4264280182Sjfv	unsigned val = IXGBE_READ_REG(&rxr->adapter->hw, IXGBE_RDT(rxr->me));
4265280182Sjfv	error = sysctl_handle_int(oidp, &val, 0, req);
4266280182Sjfv	if (error || !req->newptr)
4267280182Sjfv		return error;
4268280182Sjfv	return 0;
4269280182Sjfv}
4270280182Sjfv
4271280182Sjfvstatic int
4272280182Sjfvixgbe_sysctl_interrupt_rate_handler(SYSCTL_HANDLER_ARGS)
4273280182Sjfv{
4274280182Sjfv	int error;
4275280182Sjfv	struct ix_queue *que = ((struct ix_queue *)oidp->oid_arg1);
4276280182Sjfv	unsigned int reg, usec, rate;
4277280182Sjfv
4278280182Sjfv	reg = IXGBE_READ_REG(&que->adapter->hw, IXGBE_EITR(que->msix));
4279280182Sjfv	usec = ((reg & 0x0FF8) >> 3);
4280280182Sjfv	if (usec > 0)
4281280182Sjfv		rate = 500000 / usec;
4282280182Sjfv	else
4283280182Sjfv		rate = 0;
4284280182Sjfv	error = sysctl_handle_int(oidp, &rate, 0, req);
4285280182Sjfv	if (error || !req->newptr)
4286280182Sjfv		return error;
4287280182Sjfv	reg &= ~0xfff; /* default, no limitation */
4288280182Sjfv	ixgbe_max_interrupt_rate = 0;
4289280182Sjfv	if (rate > 0 && rate < 500000) {
4290280182Sjfv		if (rate < 1000)
4291280182Sjfv			rate = 1000;
4292280182Sjfv		ixgbe_max_interrupt_rate = rate;
4293280182Sjfv		reg |= ((4000000/rate) & 0xff8 );
4294280182Sjfv	}
4295280182Sjfv	IXGBE_WRITE_REG(&que->adapter->hw, IXGBE_EITR(que->msix), reg);
4296280182Sjfv	return 0;
4297280182Sjfv}
4298280182Sjfv
4299282289Serjstatic void
4300282289Serjixgbe_add_device_sysctls(struct adapter *adapter)
4301282289Serj{
4302282289Serj	device_t dev = adapter->dev;
4303282289Serj	struct ixgbe_hw *hw = &adapter->hw;
4304282289Serj	struct sysctl_oid_list *child;
4305282289Serj	struct sysctl_ctx_list *ctx;
4306282289Serj
4307282289Serj	ctx = device_get_sysctl_ctx(dev);
4308282289Serj	child = SYSCTL_CHILDREN(device_get_sysctl_tree(dev));
4309282289Serj
4310282289Serj	/* Sysctls for all devices */
4311282289Serj	SYSCTL_ADD_PROC(ctx, child, OID_AUTO, "fc",
4312282289Serj			CTLTYPE_INT | CTLFLAG_RW, adapter, 0,
4313294795Ssmh			ixgbe_sysctl_flowcntl, "I", IXGBE_SYSCTL_DESC_SET_FC);
4314282289Serj
4315282289Serj        SYSCTL_ADD_INT(ctx, child, OID_AUTO, "enable_aim",
4316282289Serj			CTLFLAG_RW,
4317282289Serj			&ixgbe_enable_aim, 1, "Interrupt Moderation");
4318282289Serj
4319282289Serj	SYSCTL_ADD_PROC(ctx, child, OID_AUTO, "advertise_speed",
4320282289Serj			CTLTYPE_INT | CTLFLAG_RW, adapter, 0,
4321294795Ssmh			ixgbe_sysctl_advertise, "I", IXGBE_SYSCTL_DESC_ADV_SPEED);
4322282289Serj
4323282289Serj	SYSCTL_ADD_PROC(ctx, child, OID_AUTO, "thermal_test",
4324282289Serj			CTLTYPE_INT | CTLFLAG_RW, adapter, 0,
4325282289Serj			ixgbe_sysctl_thermal_test, "I", "Thermal Test");
4326282289Serj
4327292674Ssbruno#ifdef IXGBE_DEBUG
4328292674Ssbruno	/* testing sysctls (for all devices) */
4329292674Ssbruno	SYSCTL_ADD_PROC(ctx, child, OID_AUTO, "power_state",
4330292674Ssbruno			CTLTYPE_INT | CTLFLAG_RW, adapter, 0,
4331292674Ssbruno			ixgbe_sysctl_power_state, "I", "PCI Power State");
4332292674Ssbruno
4333292674Ssbruno	SYSCTL_ADD_PROC(ctx, child, OID_AUTO, "print_rss_config",
4334292674Ssbruno			CTLTYPE_STRING | CTLFLAG_RD, adapter, 0,
4335292674Ssbruno			ixgbe_sysctl_print_rss_config, "A", "Prints RSS Configuration");
4336292674Ssbruno#endif
4337292674Ssbruno	/* for X550 series devices */
4338282289Serj	if (hw->mac.type >= ixgbe_mac_X550)
4339282289Serj		SYSCTL_ADD_PROC(ctx, child, OID_AUTO, "dmac",
4340282289Serj				CTLTYPE_INT | CTLFLAG_RW, adapter, 0,
4341282289Serj				ixgbe_sysctl_dmac, "I", "DMA Coalesce");
4342282289Serj
4343292674Ssbruno	/* for X552 backplane devices */
4344292674Ssbruno	if (hw->device_id == IXGBE_DEV_ID_X550EM_X_KR) {
4345282289Serj		struct sysctl_oid *eee_node;
4346282289Serj		struct sysctl_oid_list *eee_list;
4347282289Serj
4348282289Serj		eee_node = SYSCTL_ADD_NODE(ctx, child, OID_AUTO, "eee",
4349282289Serj					   CTLFLAG_RD, NULL,
4350282289Serj					   "Energy Efficient Ethernet sysctls");
4351282289Serj		eee_list = SYSCTL_CHILDREN(eee_node);
4352282289Serj
4353282289Serj		SYSCTL_ADD_PROC(ctx, eee_list, OID_AUTO, "enable",
4354282289Serj				CTLTYPE_INT | CTLFLAG_RW, adapter, 0,
4355282289Serj				ixgbe_sysctl_eee_enable, "I",
4356282289Serj				"Enable or Disable EEE");
4357282289Serj
4358282289Serj		SYSCTL_ADD_PROC(ctx, eee_list, OID_AUTO, "negotiated",
4359282289Serj				CTLTYPE_INT | CTLFLAG_RD, adapter, 0,
4360282289Serj				ixgbe_sysctl_eee_negotiated, "I",
4361282289Serj				"EEE negotiated on link");
4362282289Serj
4363282289Serj		SYSCTL_ADD_PROC(ctx, eee_list, OID_AUTO, "tx_lpi_status",
4364282289Serj				CTLTYPE_INT | CTLFLAG_RD, adapter, 0,
4365282289Serj				ixgbe_sysctl_eee_tx_lpi_status, "I",
4366282289Serj				"Whether or not TX link is in LPI state");
4367282289Serj
4368282289Serj		SYSCTL_ADD_PROC(ctx, eee_list, OID_AUTO, "rx_lpi_status",
4369282289Serj				CTLTYPE_INT | CTLFLAG_RD, adapter, 0,
4370282289Serj				ixgbe_sysctl_eee_rx_lpi_status, "I",
4371282289Serj				"Whether or not RX link is in LPI state");
4372292674Ssbruno
4373292674Ssbruno		SYSCTL_ADD_PROC(ctx, eee_list, OID_AUTO, "tx_lpi_delay",
4374292674Ssbruno				CTLTYPE_INT | CTLFLAG_RD, adapter, 0,
4375292674Ssbruno				ixgbe_sysctl_eee_tx_lpi_delay, "I",
4376292674Ssbruno				"TX LPI entry delay in microseconds");
4377282289Serj	}
4378282289Serj
4379292674Ssbruno	/* for WoL-capable devices */
4380292674Ssbruno	if (hw->device_id == IXGBE_DEV_ID_X550EM_X_10G_T) {
4381282289Serj		SYSCTL_ADD_PROC(ctx, child, OID_AUTO, "wol_enable",
4382282289Serj				CTLTYPE_INT | CTLFLAG_RW, adapter, 0,
4383282289Serj				ixgbe_sysctl_wol_enable, "I",
4384282289Serj				"Enable/Disable Wake on LAN");
4385282289Serj
4386282289Serj		SYSCTL_ADD_PROC(ctx, child, OID_AUTO, "wufc",
4387282289Serj				CTLTYPE_INT | CTLFLAG_RW, adapter, 0,
4388282289Serj				ixgbe_sysctl_wufc, "I",
4389282289Serj				"Enable/Disable Wake Up Filters");
4390282289Serj	}
4391282289Serj
4392292674Ssbruno	/* for X552/X557-AT devices */
4393282289Serj	if (hw->device_id == IXGBE_DEV_ID_X550EM_X_10G_T) {
4394282289Serj		struct sysctl_oid *phy_node;
4395282289Serj		struct sysctl_oid_list *phy_list;
4396282289Serj
4397282289Serj		phy_node = SYSCTL_ADD_NODE(ctx, child, OID_AUTO, "phy",
4398282289Serj					   CTLFLAG_RD, NULL,
4399282289Serj					   "External PHY sysctls");
4400282289Serj		phy_list = SYSCTL_CHILDREN(phy_node);
4401282289Serj
4402282289Serj		SYSCTL_ADD_PROC(ctx, phy_list, OID_AUTO, "temp",
4403282289Serj				CTLTYPE_INT | CTLFLAG_RD, adapter, 0,
4404282289Serj				ixgbe_sysctl_phy_temp, "I",
4405282289Serj				"Current External PHY Temperature (Celsius)");
4406282289Serj
4407282289Serj		SYSCTL_ADD_PROC(ctx, phy_list, OID_AUTO, "overtemp_occurred",
4408282289Serj				CTLTYPE_INT | CTLFLAG_RD, adapter, 0,
4409282289Serj				ixgbe_sysctl_phy_overtemp_occurred, "I",
4410282289Serj				"External PHY High Temperature Event Occurred");
4411282289Serj	}
4412282289Serj}
4413282289Serj
4414280182Sjfv/*
4415280182Sjfv * Add sysctl variables, one per statistic, to the system.
4416280182Sjfv */
4417280182Sjfvstatic void
4418280182Sjfvixgbe_add_hw_stats(struct adapter *adapter)
4419280182Sjfv{
4420280182Sjfv	device_t dev = adapter->dev;
4421280182Sjfv
4422280182Sjfv	struct tx_ring *txr = adapter->tx_rings;
4423280182Sjfv	struct rx_ring *rxr = adapter->rx_rings;
4424280182Sjfv
4425280182Sjfv	struct sysctl_ctx_list *ctx = device_get_sysctl_ctx(dev);
4426280182Sjfv	struct sysctl_oid *tree = device_get_sysctl_tree(dev);
4427280182Sjfv	struct sysctl_oid_list *child = SYSCTL_CHILDREN(tree);
4428280182Sjfv	struct ixgbe_hw_stats *stats = &adapter->stats.pf;
4429280182Sjfv
4430280182Sjfv	struct sysctl_oid *stat_node, *queue_node;
4431280182Sjfv	struct sysctl_oid_list *stat_list, *queue_list;
4432280182Sjfv
4433280182Sjfv#define QUEUE_NAME_LEN 32
4434280182Sjfv	char namebuf[QUEUE_NAME_LEN];
4435280182Sjfv
4436280182Sjfv	/* Driver Statistics */
4437280182Sjfv	SYSCTL_ADD_ULONG(ctx, child, OID_AUTO, "dropped",
4438280182Sjfv			CTLFLAG_RD, &adapter->dropped_pkts,
4439280182Sjfv			"Driver dropped packets");
4440280182Sjfv	SYSCTL_ADD_ULONG(ctx, child, OID_AUTO, "mbuf_defrag_failed",
4441280182Sjfv			CTLFLAG_RD, &adapter->mbuf_defrag_failed,
4442280182Sjfv			"m_defrag() failed");
4443280182Sjfv	SYSCTL_ADD_ULONG(ctx, child, OID_AUTO, "watchdog_events",
4444280182Sjfv			CTLFLAG_RD, &adapter->watchdog_events,
4445280182Sjfv			"Watchdog timeouts");
4446280182Sjfv	SYSCTL_ADD_ULONG(ctx, child, OID_AUTO, "link_irq",
4447282289Serj			CTLFLAG_RD, &adapter->link_irq,
4448280182Sjfv			"Link MSIX IRQ Handled");
4449280182Sjfv
4450280182Sjfv	for (int i = 0; i < adapter->num_queues; i++, txr++) {
4451280182Sjfv		snprintf(namebuf, QUEUE_NAME_LEN, "queue%d", i);
4452280182Sjfv		queue_node = SYSCTL_ADD_NODE(ctx, child, OID_AUTO, namebuf,
4453280182Sjfv					    CTLFLAG_RD, NULL, "Queue Name");
4454280182Sjfv		queue_list = SYSCTL_CHILDREN(queue_node);
4455280182Sjfv
4456280182Sjfv		SYSCTL_ADD_PROC(ctx, queue_list, OID_AUTO, "interrupt_rate",
4457280182Sjfv				CTLTYPE_UINT | CTLFLAG_RW, &adapter->queues[i],
4458280182Sjfv				sizeof(&adapter->queues[i]),
4459280182Sjfv				ixgbe_sysctl_interrupt_rate_handler, "IU",
4460280182Sjfv				"Interrupt Rate");
4461280182Sjfv		SYSCTL_ADD_UQUAD(ctx, queue_list, OID_AUTO, "irqs",
4462280182Sjfv				CTLFLAG_RD, &(adapter->queues[i].irqs),
4463280182Sjfv				"irqs on this queue");
4464280182Sjfv		SYSCTL_ADD_PROC(ctx, queue_list, OID_AUTO, "txd_head",
4465280182Sjfv				CTLTYPE_UINT | CTLFLAG_RD, txr, sizeof(txr),
4466280182Sjfv				ixgbe_sysctl_tdh_handler, "IU",
4467280182Sjfv				"Transmit Descriptor Head");
4468280182Sjfv		SYSCTL_ADD_PROC(ctx, queue_list, OID_AUTO, "txd_tail",
4469280182Sjfv				CTLTYPE_UINT | CTLFLAG_RD, txr, sizeof(txr),
4470280182Sjfv				ixgbe_sysctl_tdt_handler, "IU",
4471280182Sjfv				"Transmit Descriptor Tail");
4472280182Sjfv		SYSCTL_ADD_ULONG(ctx, queue_list, OID_AUTO, "tso_tx",
4473280182Sjfv				CTLFLAG_RD, &txr->tso_tx,
4474280182Sjfv				"TSO");
4475280182Sjfv		SYSCTL_ADD_ULONG(ctx, queue_list, OID_AUTO, "no_tx_dma_setup",
4476280182Sjfv				CTLFLAG_RD, &txr->no_tx_dma_setup,
4477280182Sjfv				"Driver tx dma failure in xmit");
4478280182Sjfv		SYSCTL_ADD_UQUAD(ctx, queue_list, OID_AUTO, "no_desc_avail",
4479280182Sjfv				CTLFLAG_RD, &txr->no_desc_avail,
4480280182Sjfv				"Queue No Descriptor Available");
4481280182Sjfv		SYSCTL_ADD_UQUAD(ctx, queue_list, OID_AUTO, "tx_packets",
4482280182Sjfv				CTLFLAG_RD, &txr->total_packets,
4483280182Sjfv				"Queue Packets Transmitted");
4484282280Sjhb		SYSCTL_ADD_UQUAD(ctx, queue_list, OID_AUTO, "br_drops",
4485282280Sjhb				CTLFLAG_RD, &txr->br->br_drops,
4486282280Sjhb				"Packets dropped in buf_ring");
4487280182Sjfv	}
4488280182Sjfv
4489280182Sjfv	for (int i = 0; i < adapter->num_queues; i++, rxr++) {
4490280182Sjfv		snprintf(namebuf, QUEUE_NAME_LEN, "queue%d", i);
4491280182Sjfv		queue_node = SYSCTL_ADD_NODE(ctx, child, OID_AUTO, namebuf,
4492280182Sjfv					    CTLFLAG_RD, NULL, "Queue Name");
4493280182Sjfv		queue_list = SYSCTL_CHILDREN(queue_node);
4494280182Sjfv
4495280182Sjfv		struct lro_ctrl *lro = &rxr->lro;
4496280182Sjfv
4497280182Sjfv		snprintf(namebuf, QUEUE_NAME_LEN, "queue%d", i);
4498280182Sjfv		queue_node = SYSCTL_ADD_NODE(ctx, child, OID_AUTO, namebuf,
4499280182Sjfv					    CTLFLAG_RD, NULL, "Queue Name");
4500280182Sjfv		queue_list = SYSCTL_CHILDREN(queue_node);
4501280182Sjfv
4502280182Sjfv		SYSCTL_ADD_PROC(ctx, queue_list, OID_AUTO, "rxd_head",
4503280182Sjfv				CTLTYPE_UINT | CTLFLAG_RD, rxr, sizeof(rxr),
4504280182Sjfv				ixgbe_sysctl_rdh_handler, "IU",
4505280182Sjfv				"Receive Descriptor Head");
4506280182Sjfv		SYSCTL_ADD_PROC(ctx, queue_list, OID_AUTO, "rxd_tail",
4507280182Sjfv				CTLTYPE_UINT | CTLFLAG_RD, rxr, sizeof(rxr),
4508280182Sjfv				ixgbe_sysctl_rdt_handler, "IU",
4509280182Sjfv				"Receive Descriptor Tail");
4510280182Sjfv		SYSCTL_ADD_UQUAD(ctx, queue_list, OID_AUTO, "rx_packets",
4511280182Sjfv				CTLFLAG_RD, &rxr->rx_packets,
4512280182Sjfv				"Queue Packets Received");
4513280182Sjfv		SYSCTL_ADD_UQUAD(ctx, queue_list, OID_AUTO, "rx_bytes",
4514280182Sjfv				CTLFLAG_RD, &rxr->rx_bytes,
4515280182Sjfv				"Queue Bytes Received");
4516280182Sjfv		SYSCTL_ADD_UQUAD(ctx, queue_list, OID_AUTO, "rx_copies",
4517280182Sjfv				CTLFLAG_RD, &rxr->rx_copies,
4518280182Sjfv				"Copied RX Frames");
4519294327Shselasky		SYSCTL_ADD_U64(ctx, queue_list, OID_AUTO, "lro_queued",
4520280182Sjfv				CTLFLAG_RD, &lro->lro_queued, 0,
4521280182Sjfv				"LRO Queued");
4522294327Shselasky		SYSCTL_ADD_U64(ctx, queue_list, OID_AUTO, "lro_flushed",
4523280182Sjfv				CTLFLAG_RD, &lro->lro_flushed, 0,
4524280182Sjfv				"LRO Flushed");
4525280182Sjfv	}
4526280182Sjfv
4527280182Sjfv	/* MAC stats get the own sub node */
4528280182Sjfv
4529280182Sjfv	stat_node = SYSCTL_ADD_NODE(ctx, child, OID_AUTO, "mac_stats",
4530280182Sjfv				    CTLFLAG_RD, NULL, "MAC Statistics");
4531280182Sjfv	stat_list = SYSCTL_CHILDREN(stat_node);
4532280182Sjfv
4533280182Sjfv	SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "crc_errs",
4534280182Sjfv			CTLFLAG_RD, &stats->crcerrs,
4535280182Sjfv			"CRC Errors");
4536280182Sjfv	SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "ill_errs",
4537280182Sjfv			CTLFLAG_RD, &stats->illerrc,
4538280182Sjfv			"Illegal Byte Errors");
4539280182Sjfv	SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "byte_errs",
4540280182Sjfv			CTLFLAG_RD, &stats->errbc,
4541280182Sjfv			"Byte Errors");
4542280182Sjfv	SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "short_discards",
4543280182Sjfv			CTLFLAG_RD, &stats->mspdc,
4544280182Sjfv			"MAC Short Packets Discarded");
4545280182Sjfv	SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "local_faults",
4546280182Sjfv			CTLFLAG_RD, &stats->mlfc,
4547280182Sjfv			"MAC Local Faults");
4548280182Sjfv	SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "remote_faults",
4549280182Sjfv			CTLFLAG_RD, &stats->mrfc,
4550280182Sjfv			"MAC Remote Faults");
4551280182Sjfv	SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "rec_len_errs",
4552280182Sjfv			CTLFLAG_RD, &stats->rlec,
4553280182Sjfv			"Receive Length Errors");
4554280182Sjfv
4555280182Sjfv	/* Flow Control stats */
4556280182Sjfv	SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "xon_txd",
4557280182Sjfv			CTLFLAG_RD, &stats->lxontxc,
4558280182Sjfv			"Link XON Transmitted");
4559280182Sjfv	SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "xon_recvd",
4560280182Sjfv			CTLFLAG_RD, &stats->lxonrxc,
4561280182Sjfv			"Link XON Received");
4562280182Sjfv	SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "xoff_txd",
4563280182Sjfv			CTLFLAG_RD, &stats->lxofftxc,
4564280182Sjfv			"Link XOFF Transmitted");
4565280182Sjfv	SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "xoff_recvd",
4566280182Sjfv			CTLFLAG_RD, &stats->lxoffrxc,
4567280182Sjfv			"Link XOFF Received");
4568280182Sjfv
4569280182Sjfv	/* Packet Reception Stats */
4570280182Sjfv	SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "total_octets_rcvd",
4571280182Sjfv			CTLFLAG_RD, &stats->tor,
4572280182Sjfv			"Total Octets Received");
4573280182Sjfv	SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "good_octets_rcvd",
4574280182Sjfv			CTLFLAG_RD, &stats->gorc,
4575280182Sjfv			"Good Octets Received");
4576280182Sjfv	SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "total_pkts_rcvd",
4577280182Sjfv			CTLFLAG_RD, &stats->tpr,
4578280182Sjfv			"Total Packets Received");
4579280182Sjfv	SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "good_pkts_rcvd",
4580280182Sjfv			CTLFLAG_RD, &stats->gprc,
4581280182Sjfv			"Good Packets Received");
4582280182Sjfv	SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "mcast_pkts_rcvd",
4583280182Sjfv			CTLFLAG_RD, &stats->mprc,
4584280182Sjfv			"Multicast Packets Received");
4585280182Sjfv	SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "bcast_pkts_rcvd",
4586280182Sjfv			CTLFLAG_RD, &stats->bprc,
4587280182Sjfv			"Broadcast Packets Received");
4588280182Sjfv	SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "rx_frames_64",
4589280182Sjfv			CTLFLAG_RD, &stats->prc64,
4590280182Sjfv			"64 byte frames received ");
4591280182Sjfv	SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "rx_frames_65_127",
4592280182Sjfv			CTLFLAG_RD, &stats->prc127,
4593280182Sjfv			"65-127 byte frames received");
4594280182Sjfv	SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "rx_frames_128_255",
4595280182Sjfv			CTLFLAG_RD, &stats->prc255,
4596280182Sjfv			"128-255 byte frames received");
4597280182Sjfv	SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "rx_frames_256_511",
4598280182Sjfv			CTLFLAG_RD, &stats->prc511,
4599280182Sjfv			"256-511 byte frames received");
4600280182Sjfv	SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "rx_frames_512_1023",
4601280182Sjfv			CTLFLAG_RD, &stats->prc1023,
4602280182Sjfv			"512-1023 byte frames received");
4603280182Sjfv	SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "rx_frames_1024_1522",
4604280182Sjfv			CTLFLAG_RD, &stats->prc1522,
4605280182Sjfv			"1023-1522 byte frames received");
4606280182Sjfv	SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "recv_undersized",
4607280182Sjfv			CTLFLAG_RD, &stats->ruc,
4608280182Sjfv			"Receive Undersized");
4609280182Sjfv	SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "recv_fragmented",
4610280182Sjfv			CTLFLAG_RD, &stats->rfc,
4611280182Sjfv			"Fragmented Packets Received ");
4612280182Sjfv	SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "recv_oversized",
4613280182Sjfv			CTLFLAG_RD, &stats->roc,
4614280182Sjfv			"Oversized Packets Received");
4615280182Sjfv	SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "recv_jabberd",
4616280182Sjfv			CTLFLAG_RD, &stats->rjc,
4617280182Sjfv			"Received Jabber");
4618280182Sjfv	SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "management_pkts_rcvd",
4619280182Sjfv			CTLFLAG_RD, &stats->mngprc,
4620280182Sjfv			"Management Packets Received");
4621280182Sjfv	SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "management_pkts_drpd",
4622280182Sjfv			CTLFLAG_RD, &stats->mngptc,
4623280182Sjfv			"Management Packets Dropped");
4624280182Sjfv	SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "checksum_errs",
4625280182Sjfv			CTLFLAG_RD, &stats->xec,
4626280182Sjfv			"Checksum Errors");
4627280182Sjfv
4628280182Sjfv	/* Packet Transmission Stats */
4629280182Sjfv	SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "good_octets_txd",
4630280182Sjfv			CTLFLAG_RD, &stats->gotc,
4631280182Sjfv			"Good Octets Transmitted");
4632280182Sjfv	SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "total_pkts_txd",
4633280182Sjfv			CTLFLAG_RD, &stats->tpt,
4634280182Sjfv			"Total Packets Transmitted");
4635280182Sjfv	SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "good_pkts_txd",
4636280182Sjfv			CTLFLAG_RD, &stats->gptc,
4637280182Sjfv			"Good Packets Transmitted");
4638280182Sjfv	SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "bcast_pkts_txd",
4639280182Sjfv			CTLFLAG_RD, &stats->bptc,
4640280182Sjfv			"Broadcast Packets Transmitted");
4641280182Sjfv	SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "mcast_pkts_txd",
4642280182Sjfv			CTLFLAG_RD, &stats->mptc,
4643280182Sjfv			"Multicast Packets Transmitted");
4644280182Sjfv	SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "management_pkts_txd",
4645280182Sjfv			CTLFLAG_RD, &stats->mngptc,
4646280182Sjfv			"Management Packets Transmitted");
4647280182Sjfv	SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "tx_frames_64",
4648280182Sjfv			CTLFLAG_RD, &stats->ptc64,
4649280182Sjfv			"64 byte frames transmitted ");
4650280182Sjfv	SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "tx_frames_65_127",
4651280182Sjfv			CTLFLAG_RD, &stats->ptc127,
4652280182Sjfv			"65-127 byte frames transmitted");
4653280182Sjfv	SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "tx_frames_128_255",
4654280182Sjfv			CTLFLAG_RD, &stats->ptc255,
4655280182Sjfv			"128-255 byte frames transmitted");
4656280182Sjfv	SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "tx_frames_256_511",
4657280182Sjfv			CTLFLAG_RD, &stats->ptc511,
4658280182Sjfv			"256-511 byte frames transmitted");
4659280182Sjfv	SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "tx_frames_512_1023",
4660280182Sjfv			CTLFLAG_RD, &stats->ptc1023,
4661280182Sjfv			"512-1023 byte frames transmitted");
4662280182Sjfv	SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "tx_frames_1024_1522",
4663280182Sjfv			CTLFLAG_RD, &stats->ptc1522,
4664280182Sjfv			"1024-1522 byte frames transmitted");
4665280182Sjfv}
4666280182Sjfv
4667289238Ssbrunostatic void
4668289238Ssbrunoixgbe_set_sysctl_value(struct adapter *adapter, const char *name,
4669289238Ssbruno    const char *description, int *limit, int value)
4670289238Ssbruno{
4671289238Ssbruno	*limit = value;
4672289238Ssbruno	SYSCTL_ADD_INT(device_get_sysctl_ctx(adapter->dev),
4673289238Ssbruno	    SYSCTL_CHILDREN(device_get_sysctl_tree(adapter->dev)),
4674289238Ssbruno	    OID_AUTO, name, CTLFLAG_RW, limit, value, description);
4675289238Ssbruno}
4676289238Ssbruno
4677280182Sjfv/*
4678280182Sjfv** Set flow control using sysctl:
4679280182Sjfv** Flow control values:
4680280182Sjfv** 	0 - off
4681280182Sjfv**	1 - rx pause
4682280182Sjfv**	2 - tx pause
4683280182Sjfv**	3 - full
4684280182Sjfv*/
4685280182Sjfvstatic int
4686294795Ssmhixgbe_sysctl_flowcntl(SYSCTL_HANDLER_ARGS)
4687280182Sjfv{
4688294795Ssmh	int error, fc;
4689294795Ssmh	struct adapter *adapter;
4690280182Sjfv
4691294795Ssmh	adapter = (struct adapter *) arg1;
4692294795Ssmh	fc = adapter->fc;
4693294795Ssmh
4694294795Ssmh	error = sysctl_handle_int(oidp, &fc, 0, req);
4695280182Sjfv	if ((error) || (req->newptr == NULL))
4696280182Sjfv		return (error);
4697280182Sjfv
4698280182Sjfv	/* Don't bother if it's not changed */
4699294795Ssmh	if (adapter->fc == fc)
4700280182Sjfv		return (0);
4701280182Sjfv
4702294795Ssmh	return ixgbe_set_flowcntl(adapter, fc);
4703294795Ssmh}
4704294795Ssmh
4705294795Ssmh
4706294795Ssmhstatic int
4707294795Ssmhixgbe_set_flowcntl(struct adapter *adapter, int fc)
4708294795Ssmh{
4709294795Ssmh
4710294795Ssmh	switch (fc) {
4711294795Ssmh	case ixgbe_fc_rx_pause:
4712294795Ssmh	case ixgbe_fc_tx_pause:
4713294795Ssmh	case ixgbe_fc_full:
4714294795Ssmh		adapter->hw.fc.requested_mode = adapter->fc;
4715294795Ssmh		if (adapter->num_queues > 1)
4716294795Ssmh			ixgbe_disable_rx_drop(adapter);
4717294795Ssmh		break;
4718294795Ssmh	case ixgbe_fc_none:
4719294795Ssmh		adapter->hw.fc.requested_mode = ixgbe_fc_none;
4720294795Ssmh		if (adapter->num_queues > 1)
4721294795Ssmh			ixgbe_enable_rx_drop(adapter);
4722294795Ssmh		break;
4723294795Ssmh	default:
4724294795Ssmh		return (EINVAL);
4725280182Sjfv	}
4726294795Ssmh	adapter->fc = fc;
4727280182Sjfv	/* Don't autoneg if forcing a value */
4728280182Sjfv	adapter->hw.fc.disable_fc_autoneg = TRUE;
4729280182Sjfv	ixgbe_fc_enable(&adapter->hw);
4730294795Ssmh	return (0);
4731280182Sjfv}
4732280182Sjfv
4733280182Sjfv/*
4734280182Sjfv** Control advertised link speed:
4735280182Sjfv**	Flags:
4736280182Sjfv**	0x1 - advertise 100 Mb
4737280182Sjfv**	0x2 - advertise 1G
4738280182Sjfv**	0x4 - advertise 10G
4739280182Sjfv*/
4740280182Sjfvstatic int
4741294795Ssmhixgbe_sysctl_advertise(SYSCTL_HANDLER_ARGS)
4742280182Sjfv{
4743294795Ssmh	int error, advertise;
4744294795Ssmh	struct adapter *adapter;
4745280182Sjfv
4746280182Sjfv	adapter = (struct adapter *) arg1;
4747294795Ssmh	advertise = adapter->advertise;
4748280182Sjfv
4749294795Ssmh	error = sysctl_handle_int(oidp, &advertise, 0, req);
4750280182Sjfv	if ((error) || (req->newptr == NULL))
4751280182Sjfv		return (error);
4752280182Sjfv
4753294795Ssmh	return ixgbe_set_advertise(adapter, advertise);
4754294795Ssmh}
4755294795Ssmh
4756294795Ssmhstatic int
4757294795Ssmhixgbe_set_advertise(struct adapter *adapter, int advertise)
4758294795Ssmh{
4759294795Ssmh	device_t		dev;
4760294795Ssmh	struct ixgbe_hw		*hw;
4761294795Ssmh	ixgbe_link_speed	speed;
4762294795Ssmh
4763296922Ssmh	/* Checks to validate new value */
4764296922Ssmh	if (adapter->advertise == advertise) /* no change */
4765296922Ssmh		return (0);
4766296922Ssmh
4767294795Ssmh	hw = &adapter->hw;
4768294795Ssmh	dev = adapter->dev;
4769294795Ssmh
4770292674Ssbruno	/* No speed changes for backplane media */
4771292674Ssbruno	if (hw->phy.media_type == ixgbe_media_type_backplane)
4772292674Ssbruno		return (ENODEV);
4773292674Ssbruno
4774280182Sjfv	if (!((hw->phy.media_type == ixgbe_media_type_copper) ||
4775280182Sjfv	    (hw->phy.multispeed_fiber))) {
4776280182Sjfv		device_printf(dev,
4777280182Sjfv		    "Advertised speed can only be set on copper or "
4778280182Sjfv		    "multispeed fiber media types.\n");
4779280182Sjfv		return (EINVAL);
4780280182Sjfv	}
4781280182Sjfv
4782294795Ssmh	if (advertise < 0x1 || advertise > 0x7) {
4783280182Sjfv		device_printf(dev,
4784280182Sjfv		    "Invalid advertised speed; valid modes are 0x1 through 0x7\n");
4785280182Sjfv		return (EINVAL);
4786280182Sjfv	}
4787280182Sjfv
4788294795Ssmh	if ((advertise & 0x1)
4789280182Sjfv	    && (hw->mac.type != ixgbe_mac_X540)
4790280182Sjfv	    && (hw->mac.type != ixgbe_mac_X550)) {
4791280182Sjfv		device_printf(dev, "Set Advertise: 100Mb on X540/X550 only\n");
4792280182Sjfv		return (EINVAL);
4793280182Sjfv	}
4794280182Sjfv
4795280182Sjfv	/* Set new value and report new advertised mode */
4796294795Ssmh	speed = 0;
4797294795Ssmh	if (advertise & 0x1)
4798280182Sjfv		speed |= IXGBE_LINK_SPEED_100_FULL;
4799294795Ssmh	if (advertise & 0x2)
4800280182Sjfv		speed |= IXGBE_LINK_SPEED_1GB_FULL;
4801294795Ssmh	if (advertise & 0x4)
4802280182Sjfv		speed |= IXGBE_LINK_SPEED_10GB_FULL;
4803294795Ssmh	adapter->advertise = advertise;
4804280182Sjfv
4805280182Sjfv	hw->mac.autotry_restart = TRUE;
4806280182Sjfv	hw->mac.ops.setup_link(hw, speed, TRUE);
4807280182Sjfv
4808294795Ssmh	return (0);
4809280182Sjfv}
4810280182Sjfv
4811280182Sjfv/*
4812292674Ssbruno * The following two sysctls are for X552/X557-AT devices;
4813282289Serj * they deal with the external PHY used in them.
4814282289Serj */
4815280182Sjfvstatic int
4816282289Serjixgbe_sysctl_phy_temp(SYSCTL_HANDLER_ARGS)
4817280182Sjfv{
4818280182Sjfv	struct adapter	*adapter = (struct adapter *) arg1;
4819280182Sjfv	struct ixgbe_hw *hw = &adapter->hw;
4820282289Serj	u16 reg;
4821280182Sjfv
4822282289Serj	if (hw->device_id != IXGBE_DEV_ID_X550EM_X_10G_T) {
4823282289Serj		device_printf(adapter->dev,
4824282289Serj		    "Device has no supported external thermal sensor.\n");
4825282289Serj		return (ENODEV);
4826282289Serj	}
4827280182Sjfv
4828282289Serj	if (hw->phy.ops.read_reg(hw, IXGBE_PHY_CURRENT_TEMP,
4829282289Serj				      IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE,
4830282289Serj				      &reg)) {
4831282289Serj		device_printf(adapter->dev,
4832282289Serj		    "Error reading from PHY's current temperature register\n");
4833282289Serj		return (EAGAIN);
4834282289Serj	}
4835280182Sjfv
4836282289Serj	/* Shift temp for output */
4837282289Serj	reg = reg >> 8;
4838282289Serj
4839282289Serj	return (sysctl_handle_int(oidp, NULL, reg, req));
4840282289Serj}
4841282289Serj
4842282289Serj/*
4843282289Serj * Reports whether the current PHY temperature is over
4844282289Serj * the overtemp threshold.
4845282289Serj *  - This is reported directly from the PHY
4846282289Serj */
4847282289Serjstatic int
4848282289Serjixgbe_sysctl_phy_overtemp_occurred(SYSCTL_HANDLER_ARGS)
4849282289Serj{
4850282289Serj	struct adapter	*adapter = (struct adapter *) arg1;
4851282289Serj	struct ixgbe_hw *hw = &adapter->hw;
4852282289Serj	u16 reg;
4853282289Serj
4854282289Serj	if (hw->device_id != IXGBE_DEV_ID_X550EM_X_10G_T) {
4855282289Serj		device_printf(adapter->dev,
4856282289Serj		    "Device has no supported external thermal sensor.\n");
4857282289Serj		return (ENODEV);
4858282289Serj	}
4859282289Serj
4860282289Serj	if (hw->phy.ops.read_reg(hw, IXGBE_PHY_OVERTEMP_STATUS,
4861282289Serj				      IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE,
4862282289Serj				      &reg)) {
4863282289Serj		device_printf(adapter->dev,
4864282289Serj		    "Error reading from PHY's temperature status register\n");
4865282289Serj		return (EAGAIN);
4866282289Serj	}
4867282289Serj
4868282289Serj	/* Get occurrence bit */
4869282289Serj	reg = !!(reg & 0x4000);
4870282289Serj	return (sysctl_handle_int(oidp, 0, reg, req));
4871282289Serj}
4872282289Serj
4873282289Serj/*
4874282289Serj** Thermal Shutdown Trigger (internal MAC)
4875282289Serj**   - Set this to 1 to cause an overtemp event to occur
4876282289Serj*/
4877282289Serjstatic int
4878282289Serjixgbe_sysctl_thermal_test(SYSCTL_HANDLER_ARGS)
4879282289Serj{
4880282289Serj	struct adapter	*adapter = (struct adapter *) arg1;
4881282289Serj	struct ixgbe_hw *hw = &adapter->hw;
4882282289Serj	int error, fire = 0;
4883282289Serj
4884280182Sjfv	error = sysctl_handle_int(oidp, &fire, 0, req);
4885280182Sjfv	if ((error) || (req->newptr == NULL))
4886280182Sjfv		return (error);
4887280182Sjfv
4888280182Sjfv	if (fire) {
4889280182Sjfv		u32 reg = IXGBE_READ_REG(hw, IXGBE_EICS);
4890280182Sjfv		reg |= IXGBE_EICR_TS;
4891280182Sjfv		IXGBE_WRITE_REG(hw, IXGBE_EICS, reg);
4892280182Sjfv	}
4893280182Sjfv
4894280182Sjfv	return (0);
4895280182Sjfv}
4896280182Sjfv
4897280182Sjfv/*
4898282289Serj** Manage DMA Coalescing.
4899282289Serj** Control values:
4900282289Serj** 	0/1 - off / on (use default value of 1000)
4901282289Serj**
4902282289Serj**	Legal timer values are:
4903282289Serj**	50,100,250,500,1000,2000,5000,10000
4904282289Serj**
4905282289Serj**	Turning off interrupt moderation will also turn this off.
4906282289Serj*/
4907282289Serjstatic int
4908282289Serjixgbe_sysctl_dmac(SYSCTL_HANDLER_ARGS)
4909282289Serj{
4910282289Serj	struct adapter *adapter = (struct adapter *) arg1;
4911282289Serj	struct ifnet *ifp = adapter->ifp;
4912282289Serj	int		error;
4913292674Ssbruno	u32		newval;
4914282289Serj
4915292674Ssbruno	newval = adapter->dmac;
4916292674Ssbruno	error = sysctl_handle_int(oidp, &newval, 0, req);
4917282289Serj	if ((error) || (req->newptr == NULL))
4918282289Serj		return (error);
4919282289Serj
4920292674Ssbruno	switch (newval) {
4921282289Serj	case 0:
4922282289Serj		/* Disabled */
4923292674Ssbruno		adapter->dmac = 0;
4924282289Serj		break;
4925292674Ssbruno	case 1:
4926292674Ssbruno		/* Enable and use default */
4927282289Serj		adapter->dmac = 1000;
4928282289Serj		break;
4929282289Serj	case 50:
4930282289Serj	case 100:
4931282289Serj	case 250:
4932282289Serj	case 500:
4933282289Serj	case 1000:
4934282289Serj	case 2000:
4935282289Serj	case 5000:
4936282289Serj	case 10000:
4937282289Serj		/* Legal values - allow */
4938292674Ssbruno		adapter->dmac = newval;
4939282289Serj		break;
4940282289Serj	default:
4941282289Serj		/* Do nothing, illegal value */
4942282289Serj		return (EINVAL);
4943282289Serj	}
4944282289Serj
4945282289Serj	/* Re-initialize hardware if it's already running */
4946282289Serj	if (ifp->if_drv_flags & IFF_DRV_RUNNING)
4947282289Serj		ixgbe_init(adapter);
4948282289Serj
4949282289Serj	return (0);
4950282289Serj}
4951282289Serj
4952292674Ssbruno#ifdef IXGBE_DEBUG
4953292674Ssbruno/**
4954292674Ssbruno * Sysctl to test power states
4955292674Ssbruno * Values:
4956292674Ssbruno *	0      - set device to D0
4957292674Ssbruno *	3      - set device to D3
4958292674Ssbruno *	(none) - get current device power state
4959292674Ssbruno */
4960292674Ssbrunostatic int
4961292674Ssbrunoixgbe_sysctl_power_state(SYSCTL_HANDLER_ARGS)
4962292674Ssbruno{
4963292674Ssbruno	struct adapter *adapter = (struct adapter *) arg1;
4964292674Ssbruno	device_t dev =  adapter->dev;
4965292674Ssbruno	int curr_ps, new_ps, error = 0;
4966292674Ssbruno
4967292674Ssbruno	curr_ps = new_ps = pci_get_powerstate(dev);
4968292674Ssbruno
4969292674Ssbruno	error = sysctl_handle_int(oidp, &new_ps, 0, req);
4970292674Ssbruno	if ((error) || (req->newptr == NULL))
4971292674Ssbruno		return (error);
4972292674Ssbruno
4973292674Ssbruno	if (new_ps == curr_ps)
4974292674Ssbruno		return (0);
4975292674Ssbruno
4976292674Ssbruno	if (new_ps == 3 && curr_ps == 0)
4977292674Ssbruno		error = DEVICE_SUSPEND(dev);
4978292674Ssbruno	else if (new_ps == 0 && curr_ps == 3)
4979292674Ssbruno		error = DEVICE_RESUME(dev);
4980292674Ssbruno	else
4981292674Ssbruno		return (EINVAL);
4982292674Ssbruno
4983292674Ssbruno	device_printf(dev, "New state: %d\n", pci_get_powerstate(dev));
4984292674Ssbruno
4985292674Ssbruno	return (error);
4986292674Ssbruno}
4987292674Ssbruno#endif
4988282289Serj/*
4989282289Serj * Sysctl to enable/disable the WoL capability, if supported by the adapter.
4990282289Serj * Values:
4991282289Serj *	0 - disabled
4992282289Serj *	1 - enabled
4993282289Serj */
4994282289Serjstatic int
4995282289Serjixgbe_sysctl_wol_enable(SYSCTL_HANDLER_ARGS)
4996282289Serj{
4997282289Serj	struct adapter *adapter = (struct adapter *) arg1;
4998282289Serj	struct ixgbe_hw *hw = &adapter->hw;
4999282289Serj	int new_wol_enabled;
5000282289Serj	int error = 0;
5001282289Serj
5002282289Serj	new_wol_enabled = hw->wol_enabled;
5003282289Serj	error = sysctl_handle_int(oidp, &new_wol_enabled, 0, req);
5004282289Serj	if ((error) || (req->newptr == NULL))
5005282289Serj		return (error);
5006292674Ssbruno	new_wol_enabled = !!(new_wol_enabled);
5007282289Serj	if (new_wol_enabled == hw->wol_enabled)
5008282289Serj		return (0);
5009282289Serj
5010282289Serj	if (new_wol_enabled > 0 && !adapter->wol_support)
5011282289Serj		return (ENODEV);
5012282289Serj	else
5013292674Ssbruno		hw->wol_enabled = new_wol_enabled;
5014282289Serj
5015282289Serj	return (0);
5016282289Serj}
5017282289Serj
5018282289Serj/*
5019282289Serj * Sysctl to enable/disable the Energy Efficient Ethernet capability,
5020282289Serj * if supported by the adapter.
5021282289Serj * Values:
5022282289Serj *	0 - disabled
5023282289Serj *	1 - enabled
5024282289Serj */
5025282289Serjstatic int
5026282289Serjixgbe_sysctl_eee_enable(SYSCTL_HANDLER_ARGS)
5027282289Serj{
5028282289Serj	struct adapter *adapter = (struct adapter *) arg1;
5029283883Sjfv	struct ixgbe_hw *hw = &adapter->hw;
5030282289Serj	struct ifnet *ifp = adapter->ifp;
5031282289Serj	int new_eee_enabled, error = 0;
5032282289Serj
5033282289Serj	new_eee_enabled = adapter->eee_enabled;
5034282289Serj	error = sysctl_handle_int(oidp, &new_eee_enabled, 0, req);
5035282289Serj	if ((error) || (req->newptr == NULL))
5036282289Serj		return (error);
5037292674Ssbruno	new_eee_enabled = !!(new_eee_enabled);
5038282289Serj	if (new_eee_enabled == adapter->eee_enabled)
5039282289Serj		return (0);
5040282289Serj
5041283883Sjfv	if (new_eee_enabled > 0 && !hw->mac.ops.setup_eee)
5042282289Serj		return (ENODEV);
5043282289Serj	else
5044292674Ssbruno		adapter->eee_enabled = new_eee_enabled;
5045282289Serj
5046282289Serj	/* Re-initialize hardware if it's already running */
5047282289Serj	if (ifp->if_drv_flags & IFF_DRV_RUNNING)
5048282289Serj		ixgbe_init(adapter);
5049282289Serj
5050282289Serj	return (0);
5051282289Serj}
5052282289Serj
5053282289Serj/*
5054282289Serj * Read-only sysctl indicating whether EEE support was negotiated
5055282289Serj * on the link.
5056282289Serj */
5057282289Serjstatic int
5058282289Serjixgbe_sysctl_eee_negotiated(SYSCTL_HANDLER_ARGS)
5059282289Serj{
5060282289Serj	struct adapter *adapter = (struct adapter *) arg1;
5061282289Serj	struct ixgbe_hw *hw = &adapter->hw;
5062282289Serj	bool status;
5063282289Serj
5064282289Serj	status = !!(IXGBE_READ_REG(hw, IXGBE_EEE_STAT) & IXGBE_EEE_STAT_NEG);
5065282289Serj
5066282289Serj	return (sysctl_handle_int(oidp, 0, status, req));
5067282289Serj}
5068282289Serj
5069282289Serj/*
5070282289Serj * Read-only sysctl indicating whether RX Link is in LPI state.
5071282289Serj */
5072282289Serjstatic int
5073282289Serjixgbe_sysctl_eee_rx_lpi_status(SYSCTL_HANDLER_ARGS)
5074282289Serj{
5075282289Serj	struct adapter *adapter = (struct adapter *) arg1;
5076282289Serj	struct ixgbe_hw *hw = &adapter->hw;
5077282289Serj	bool status;
5078282289Serj
5079282289Serj	status = !!(IXGBE_READ_REG(hw, IXGBE_EEE_STAT) &
5080282289Serj	    IXGBE_EEE_RX_LPI_STATUS);
5081282289Serj
5082282289Serj	return (sysctl_handle_int(oidp, 0, status, req));
5083282289Serj}
5084282289Serj
5085282289Serj/*
5086282289Serj * Read-only sysctl indicating whether TX Link is in LPI state.
5087282289Serj */
5088282289Serjstatic int
5089282289Serjixgbe_sysctl_eee_tx_lpi_status(SYSCTL_HANDLER_ARGS)
5090282289Serj{
5091282289Serj	struct adapter *adapter = (struct adapter *) arg1;
5092282289Serj	struct ixgbe_hw *hw = &adapter->hw;
5093282289Serj	bool status;
5094282289Serj
5095282289Serj	status = !!(IXGBE_READ_REG(hw, IXGBE_EEE_STAT) &
5096282289Serj	    IXGBE_EEE_TX_LPI_STATUS);
5097282289Serj
5098282289Serj	return (sysctl_handle_int(oidp, 0, status, req));
5099282289Serj}
5100282289Serj
5101282289Serj/*
5102292674Ssbruno * Read-only sysctl indicating TX Link LPI delay
5103292674Ssbruno */
5104292674Ssbrunostatic int
5105292674Ssbrunoixgbe_sysctl_eee_tx_lpi_delay(SYSCTL_HANDLER_ARGS)
5106292674Ssbruno{
5107292674Ssbruno	struct adapter *adapter = (struct adapter *) arg1;
5108292674Ssbruno	struct ixgbe_hw *hw = &adapter->hw;
5109292674Ssbruno	u32 reg;
5110292674Ssbruno
5111292674Ssbruno	reg = IXGBE_READ_REG(hw, IXGBE_EEE_SU);
5112292674Ssbruno
5113292674Ssbruno	return (sysctl_handle_int(oidp, 0, reg >> 26, req));
5114292674Ssbruno}
5115292674Ssbruno
5116292674Ssbruno/*
5117282289Serj * Sysctl to enable/disable the types of packets that the
5118282289Serj * adapter will wake up on upon receipt.
5119282289Serj * WUFC - Wake Up Filter Control
5120282289Serj * Flags:
5121282289Serj *	0x1  - Link Status Change
5122282289Serj *	0x2  - Magic Packet
5123282289Serj *	0x4  - Direct Exact
5124282289Serj *	0x8  - Directed Multicast
5125282289Serj *	0x10 - Broadcast
5126282289Serj *	0x20 - ARP/IPv4 Request Packet
5127282289Serj *	0x40 - Direct IPv4 Packet
5128282289Serj *	0x80 - Direct IPv6 Packet
5129282289Serj *
5130282289Serj * Setting another flag will cause the sysctl to return an
5131282289Serj * error.
5132282289Serj */
5133282289Serjstatic int
5134282289Serjixgbe_sysctl_wufc(SYSCTL_HANDLER_ARGS)
5135282289Serj{
5136282289Serj	struct adapter *adapter = (struct adapter *) arg1;
5137282289Serj	int error = 0;
5138282289Serj	u32 new_wufc;
5139282289Serj
5140282289Serj	new_wufc = adapter->wufc;
5141282289Serj
5142282289Serj	error = sysctl_handle_int(oidp, &new_wufc, 0, req);
5143282289Serj	if ((error) || (req->newptr == NULL))
5144282289Serj		return (error);
5145282289Serj	if (new_wufc == adapter->wufc)
5146282289Serj		return (0);
5147282289Serj
5148282289Serj	if (new_wufc & 0xffffff00)
5149282289Serj		return (EINVAL);
5150282289Serj	else {
5151282289Serj		new_wufc &= 0xff;
5152282289Serj		new_wufc |= (0xffffff & adapter->wufc);
5153282289Serj		adapter->wufc = new_wufc;
5154282289Serj	}
5155282289Serj
5156282289Serj	return (0);
5157282289Serj}
5158282289Serj
5159292674Ssbruno#ifdef IXGBE_DEBUG
5160292674Ssbrunostatic int
5161292674Ssbrunoixgbe_sysctl_print_rss_config(SYSCTL_HANDLER_ARGS)
5162292674Ssbruno{
5163292674Ssbruno	struct adapter *adapter = (struct adapter *)arg1;
5164292674Ssbruno	struct ixgbe_hw *hw = &adapter->hw;
5165292674Ssbruno	device_t dev = adapter->dev;
5166292674Ssbruno	int error = 0, reta_size;
5167292674Ssbruno	struct sbuf *buf;
5168292674Ssbruno	u32 reg;
5169292674Ssbruno
5170292674Ssbruno	buf = sbuf_new_for_sysctl(NULL, NULL, 128, req);
5171292674Ssbruno	if (!buf) {
5172292674Ssbruno		device_printf(dev, "Could not allocate sbuf for output.\n");
5173292674Ssbruno		return (ENOMEM);
5174292674Ssbruno	}
5175292674Ssbruno
5176292674Ssbruno	// TODO: use sbufs to make a string to print out
5177292674Ssbruno	/* Set multiplier for RETA setup and table size based on MAC */
5178292674Ssbruno	switch (adapter->hw.mac.type) {
5179292674Ssbruno	case ixgbe_mac_X550:
5180292674Ssbruno	case ixgbe_mac_X550EM_x:
5181292674Ssbruno		reta_size = 128;
5182292674Ssbruno		break;
5183292674Ssbruno	default:
5184292674Ssbruno		reta_size = 32;
5185292674Ssbruno		break;
5186292674Ssbruno	}
5187292674Ssbruno
5188292674Ssbruno	/* Print out the redirection table */
5189292674Ssbruno	sbuf_cat(buf, "\n");
5190292674Ssbruno	for (int i = 0; i < reta_size; i++) {
5191292674Ssbruno		if (i < 32) {
5192292674Ssbruno			reg = IXGBE_READ_REG(hw, IXGBE_RETA(i));
5193292674Ssbruno			sbuf_printf(buf, "RETA(%2d): 0x%08x\n", i, reg);
5194292674Ssbruno		} else {
5195292674Ssbruno			reg = IXGBE_READ_REG(hw, IXGBE_ERETA(i - 32));
5196292674Ssbruno			sbuf_printf(buf, "ERETA(%2d): 0x%08x\n", i - 32, reg);
5197292674Ssbruno		}
5198292674Ssbruno	}
5199292674Ssbruno
5200292674Ssbruno	// TODO: print more config
5201292674Ssbruno
5202292674Ssbruno	error = sbuf_finish(buf);
5203292674Ssbruno	if (error)
5204292674Ssbruno		device_printf(dev, "Error finishing sbuf: %d\n", error);
5205292674Ssbruno
5206292674Ssbruno	sbuf_delete(buf);
5207292674Ssbruno	return (0);
5208292674Ssbruno}
5209292674Ssbruno#endif /* IXGBE_DEBUG */
5210292674Ssbruno
5211282289Serj/*
5212280182Sjfv** Enable the hardware to drop packets when the buffer is
5213280182Sjfv** full. This is useful when multiqueue,so that no single
5214280182Sjfv** queue being full stalls the entire RX engine. We only
5215280182Sjfv** enable this when Multiqueue AND when Flow Control is
5216280182Sjfv** disabled.
5217280182Sjfv*/
5218280182Sjfvstatic void
5219280182Sjfvixgbe_enable_rx_drop(struct adapter *adapter)
5220280182Sjfv{
5221280182Sjfv        struct ixgbe_hw *hw = &adapter->hw;
5222280182Sjfv
5223280182Sjfv	for (int i = 0; i < adapter->num_queues; i++) {
5224283883Sjfv		struct rx_ring *rxr = &adapter->rx_rings[i];
5225283883Sjfv        	u32 srrctl = IXGBE_READ_REG(hw, IXGBE_SRRCTL(rxr->me));
5226280182Sjfv        	srrctl |= IXGBE_SRRCTL_DROP_EN;
5227283883Sjfv        	IXGBE_WRITE_REG(hw, IXGBE_SRRCTL(rxr->me), srrctl);
5228280182Sjfv	}
5229283883Sjfv#ifdef PCI_IOV
5230283883Sjfv	/* enable drop for each vf */
5231283883Sjfv	for (int i = 0; i < adapter->num_vfs; i++) {
5232283883Sjfv		IXGBE_WRITE_REG(hw, IXGBE_QDE,
5233283883Sjfv		    (IXGBE_QDE_WRITE | (i << IXGBE_QDE_IDX_SHIFT) |
5234283883Sjfv		    IXGBE_QDE_ENABLE));
5235283883Sjfv	}
5236283883Sjfv#endif
5237280182Sjfv}
5238280182Sjfv
5239280182Sjfvstatic void
5240280182Sjfvixgbe_disable_rx_drop(struct adapter *adapter)
5241280182Sjfv{
5242280182Sjfv        struct ixgbe_hw *hw = &adapter->hw;
5243280182Sjfv
5244280182Sjfv	for (int i = 0; i < adapter->num_queues; i++) {
5245283883Sjfv		struct rx_ring *rxr = &adapter->rx_rings[i];
5246283883Sjfv        	u32 srrctl = IXGBE_READ_REG(hw, IXGBE_SRRCTL(rxr->me));
5247280182Sjfv        	srrctl &= ~IXGBE_SRRCTL_DROP_EN;
5248283883Sjfv        	IXGBE_WRITE_REG(hw, IXGBE_SRRCTL(rxr->me), srrctl);
5249280182Sjfv	}
5250283883Sjfv#ifdef PCI_IOV
5251283883Sjfv	/* disable drop for each vf */
5252283883Sjfv	for (int i = 0; i < adapter->num_vfs; i++) {
5253283883Sjfv		IXGBE_WRITE_REG(hw, IXGBE_QDE,
5254283883Sjfv		    (IXGBE_QDE_WRITE | (i << IXGBE_QDE_IDX_SHIFT)));
5255283883Sjfv	}
5256283883Sjfv#endif
5257280182Sjfv}
5258280182Sjfv
5259280182Sjfvstatic void
5260280182Sjfvixgbe_rearm_queues(struct adapter *adapter, u64 queues)
5261280182Sjfv{
5262280182Sjfv	u32 mask;
5263280182Sjfv
5264280182Sjfv	switch (adapter->hw.mac.type) {
5265280182Sjfv	case ixgbe_mac_82598EB:
5266280182Sjfv		mask = (IXGBE_EIMS_RTX_QUEUE & queues);
5267280182Sjfv		IXGBE_WRITE_REG(&adapter->hw, IXGBE_EICS, mask);
5268280182Sjfv		break;
5269280182Sjfv	case ixgbe_mac_82599EB:
5270280182Sjfv	case ixgbe_mac_X540:
5271280182Sjfv	case ixgbe_mac_X550:
5272282289Serj	case ixgbe_mac_X550EM_x:
5273280182Sjfv		mask = (queues & 0xFFFFFFFF);
5274280182Sjfv		IXGBE_WRITE_REG(&adapter->hw, IXGBE_EICS_EX(0), mask);
5275280182Sjfv		mask = (queues >> 32);
5276280182Sjfv		IXGBE_WRITE_REG(&adapter->hw, IXGBE_EICS_EX(1), mask);
5277280182Sjfv		break;
5278280182Sjfv	default:
5279280182Sjfv		break;
5280280182Sjfv	}
5281280182Sjfv}
5282280182Sjfv
5283283883Sjfv#ifdef PCI_IOV
5284280182Sjfv
5285283883Sjfv/*
5286283883Sjfv** Support functions for SRIOV/VF management
5287283883Sjfv*/
5288283883Sjfv
5289283883Sjfvstatic void
5290283883Sjfvixgbe_ping_all_vfs(struct adapter *adapter)
5291283883Sjfv{
5292283883Sjfv	struct ixgbe_vf *vf;
5293283883Sjfv
5294283883Sjfv	for (int i = 0; i < adapter->num_vfs; i++) {
5295283883Sjfv		vf = &adapter->vfs[i];
5296283883Sjfv		if (vf->flags & IXGBE_VF_ACTIVE)
5297283883Sjfv			ixgbe_send_vf_msg(adapter, vf, IXGBE_PF_CONTROL_MSG);
5298283883Sjfv	}
5299283883Sjfv}
5300283883Sjfv
5301283883Sjfv
5302283883Sjfvstatic void
5303283883Sjfvixgbe_vf_set_default_vlan(struct adapter *adapter, struct ixgbe_vf *vf,
5304283883Sjfv    uint16_t tag)
5305283883Sjfv{
5306283883Sjfv	struct ixgbe_hw *hw;
5307283883Sjfv	uint32_t vmolr, vmvir;
5308283883Sjfv
5309283883Sjfv	hw = &adapter->hw;
5310283883Sjfv
5311283883Sjfv	vf->vlan_tag = tag;
5312283883Sjfv
5313283883Sjfv	vmolr = IXGBE_READ_REG(hw, IXGBE_VMOLR(vf->pool));
5314283883Sjfv
5315283883Sjfv	/* Do not receive packets that pass inexact filters. */
5316283883Sjfv	vmolr &= ~(IXGBE_VMOLR_ROMPE | IXGBE_VMOLR_ROPE);
5317283883Sjfv
5318283883Sjfv	/* Disable Multicast Promicuous Mode. */
5319283883Sjfv	vmolr &= ~IXGBE_VMOLR_MPE;
5320283883Sjfv
5321283883Sjfv	/* Accept broadcasts. */
5322283883Sjfv	vmolr |= IXGBE_VMOLR_BAM;
5323283883Sjfv
5324283883Sjfv	if (tag == 0) {
5325283883Sjfv		/* Accept non-vlan tagged traffic. */
5326283883Sjfv		//vmolr |= IXGBE_VMOLR_AUPE;
5327283883Sjfv
5328283883Sjfv		/* Allow VM to tag outgoing traffic; no default tag. */
5329283883Sjfv		vmvir = 0;
5330283883Sjfv	} else {
5331283883Sjfv		/* Require vlan-tagged traffic. */
5332283883Sjfv		vmolr &= ~IXGBE_VMOLR_AUPE;
5333283883Sjfv
5334283883Sjfv		/* Tag all traffic with provided vlan tag. */
5335283883Sjfv		vmvir = (tag | IXGBE_VMVIR_VLANA_DEFAULT);
5336283883Sjfv	}
5337283883Sjfv	IXGBE_WRITE_REG(hw, IXGBE_VMOLR(vf->pool), vmolr);
5338283883Sjfv	IXGBE_WRITE_REG(hw, IXGBE_VMVIR(vf->pool), vmvir);
5339283883Sjfv}
5340283883Sjfv
5341283883Sjfv
5342283883Sjfvstatic boolean_t
5343283883Sjfvixgbe_vf_frame_size_compatible(struct adapter *adapter, struct ixgbe_vf *vf)
5344283883Sjfv{
5345283883Sjfv
5346283883Sjfv	/*
5347283883Sjfv	 * Frame size compatibility between PF and VF is only a problem on
5348283883Sjfv	 * 82599-based cards.  X540 and later support any combination of jumbo
5349283883Sjfv	 * frames on PFs and VFs.
5350283883Sjfv	 */
5351283883Sjfv	if (adapter->hw.mac.type != ixgbe_mac_82599EB)
5352283883Sjfv		return (TRUE);
5353283883Sjfv
5354283883Sjfv	switch (vf->api_ver) {
5355283883Sjfv	case IXGBE_API_VER_1_0:
5356283883Sjfv	case IXGBE_API_VER_UNKNOWN:
5357283883Sjfv		/*
5358283883Sjfv		 * On legacy (1.0 and older) VF versions, we don't support jumbo
5359283883Sjfv		 * frames on either the PF or the VF.
5360283883Sjfv		 */
5361283883Sjfv		if (adapter->max_frame_size > ETHER_MAX_LEN ||
5362283883Sjfv		    vf->max_frame_size > ETHER_MAX_LEN)
5363283883Sjfv		    return (FALSE);
5364283883Sjfv
5365283883Sjfv		return (TRUE);
5366283883Sjfv
5367283883Sjfv		break;
5368283883Sjfv	case IXGBE_API_VER_1_1:
5369283883Sjfv	default:
5370283883Sjfv		/*
5371283883Sjfv		 * 1.1 or later VF versions always work if they aren't using
5372283883Sjfv		 * jumbo frames.
5373283883Sjfv		 */
5374283883Sjfv		if (vf->max_frame_size <= ETHER_MAX_LEN)
5375283883Sjfv			return (TRUE);
5376283883Sjfv
5377283883Sjfv		/*
5378283883Sjfv		 * Jumbo frames only work with VFs if the PF is also using jumbo
5379283883Sjfv		 * frames.
5380283883Sjfv		 */
5381283883Sjfv		if (adapter->max_frame_size <= ETHER_MAX_LEN)
5382283883Sjfv			return (TRUE);
5383283883Sjfv
5384283883Sjfv		return (FALSE);
5385283883Sjfv
5386283883Sjfv	}
5387283883Sjfv}
5388283883Sjfv
5389283883Sjfv
5390283883Sjfvstatic void
5391283883Sjfvixgbe_process_vf_reset(struct adapter *adapter, struct ixgbe_vf *vf)
5392283883Sjfv{
5393283883Sjfv	ixgbe_vf_set_default_vlan(adapter, vf, vf->default_vlan);
5394283883Sjfv
5395283883Sjfv	// XXX clear multicast addresses
5396283883Sjfv
5397283883Sjfv	ixgbe_clear_rar(&adapter->hw, vf->rar_index);
5398283883Sjfv
5399283883Sjfv	vf->api_ver = IXGBE_API_VER_UNKNOWN;
5400283883Sjfv}
5401283883Sjfv
5402283883Sjfv
5403283883Sjfvstatic void
5404283883Sjfvixgbe_vf_enable_transmit(struct adapter *adapter, struct ixgbe_vf *vf)
5405283883Sjfv{
5406283883Sjfv	struct ixgbe_hw *hw;
5407283883Sjfv	uint32_t vf_index, vfte;
5408283883Sjfv
5409283883Sjfv	hw = &adapter->hw;
5410283883Sjfv
5411283883Sjfv	vf_index = IXGBE_VF_INDEX(vf->pool);
5412283883Sjfv	vfte = IXGBE_READ_REG(hw, IXGBE_VFTE(vf_index));
5413283883Sjfv	vfte |= IXGBE_VF_BIT(vf->pool);
5414283883Sjfv	IXGBE_WRITE_REG(hw, IXGBE_VFTE(vf_index), vfte);
5415283883Sjfv}
5416283883Sjfv
5417283883Sjfv
5418283883Sjfvstatic void
5419283883Sjfvixgbe_vf_enable_receive(struct adapter *adapter, struct ixgbe_vf *vf)
5420283883Sjfv{
5421283883Sjfv	struct ixgbe_hw *hw;
5422283883Sjfv	uint32_t vf_index, vfre;
5423283883Sjfv
5424283883Sjfv	hw = &adapter->hw;
5425283883Sjfv
5426283883Sjfv	vf_index = IXGBE_VF_INDEX(vf->pool);
5427283883Sjfv	vfre = IXGBE_READ_REG(hw, IXGBE_VFRE(vf_index));
5428283883Sjfv	if (ixgbe_vf_frame_size_compatible(adapter, vf))
5429283883Sjfv		vfre |= IXGBE_VF_BIT(vf->pool);
5430283883Sjfv	else
5431283883Sjfv		vfre &= ~IXGBE_VF_BIT(vf->pool);
5432283883Sjfv	IXGBE_WRITE_REG(hw, IXGBE_VFRE(vf_index), vfre);
5433283883Sjfv}
5434283883Sjfv
5435283883Sjfv
5436283883Sjfvstatic void
5437283883Sjfvixgbe_vf_reset_msg(struct adapter *adapter, struct ixgbe_vf *vf, uint32_t *msg)
5438283883Sjfv{
5439283883Sjfv	struct ixgbe_hw *hw;
5440283883Sjfv	uint32_t ack;
5441283883Sjfv	uint32_t resp[IXGBE_VF_PERMADDR_MSG_LEN];
5442283883Sjfv
5443283883Sjfv	hw = &adapter->hw;
5444283883Sjfv
5445283883Sjfv	ixgbe_process_vf_reset(adapter, vf);
5446283883Sjfv
5447283883Sjfv	if (ixgbe_validate_mac_addr(vf->ether_addr) == 0) {
5448283883Sjfv		ixgbe_set_rar(&adapter->hw, vf->rar_index,
5449283883Sjfv		    vf->ether_addr, vf->pool, TRUE);
5450283883Sjfv		ack = IXGBE_VT_MSGTYPE_ACK;
5451283883Sjfv	} else
5452283883Sjfv		ack = IXGBE_VT_MSGTYPE_NACK;
5453283883Sjfv
5454283883Sjfv	ixgbe_vf_enable_transmit(adapter, vf);
5455283883Sjfv	ixgbe_vf_enable_receive(adapter, vf);
5456283883Sjfv
5457283883Sjfv	vf->flags |= IXGBE_VF_CTS;
5458283883Sjfv
5459283883Sjfv	resp[0] = IXGBE_VF_RESET | ack | IXGBE_VT_MSGTYPE_CTS;
5460283883Sjfv	bcopy(vf->ether_addr, &resp[1], ETHER_ADDR_LEN);
5461283883Sjfv	resp[3] = hw->mac.mc_filter_type;
5462283883Sjfv	ixgbe_write_mbx(hw, resp, IXGBE_VF_PERMADDR_MSG_LEN, vf->pool);
5463283883Sjfv}
5464283883Sjfv
5465283883Sjfv
5466283883Sjfvstatic void
5467283883Sjfvixgbe_vf_set_mac(struct adapter *adapter, struct ixgbe_vf *vf, uint32_t *msg)
5468283883Sjfv{
5469283883Sjfv	uint8_t *mac;
5470283883Sjfv
5471283883Sjfv	mac = (uint8_t*)&msg[1];
5472283883Sjfv
5473283883Sjfv	/* Check that the VF has permission to change the MAC address. */
5474283883Sjfv	if (!(vf->flags & IXGBE_VF_CAP_MAC) && ixgbe_vf_mac_changed(vf, mac)) {
5475283883Sjfv		ixgbe_send_vf_nack(adapter, vf, msg[0]);
5476283883Sjfv		return;
5477283883Sjfv	}
5478283883Sjfv
5479283883Sjfv	if (ixgbe_validate_mac_addr(mac) != 0) {
5480283883Sjfv		ixgbe_send_vf_nack(adapter, vf, msg[0]);
5481283883Sjfv		return;
5482283883Sjfv	}
5483283883Sjfv
5484283883Sjfv	bcopy(mac, vf->ether_addr, ETHER_ADDR_LEN);
5485283883Sjfv
5486283883Sjfv	ixgbe_set_rar(&adapter->hw, vf->rar_index, vf->ether_addr,
5487283883Sjfv	    vf->pool, TRUE);
5488283883Sjfv
5489283883Sjfv	ixgbe_send_vf_ack(adapter, vf, msg[0]);
5490283883Sjfv}
5491283883Sjfv
5492283883Sjfv
5493283883Sjfv/*
5494283883Sjfv** VF multicast addresses are set by using the appropriate bit in
5495283883Sjfv** 1 of 128 32 bit addresses (4096 possible).
5496283883Sjfv*/
5497283883Sjfvstatic void
5498283883Sjfvixgbe_vf_set_mc_addr(struct adapter *adapter, struct ixgbe_vf *vf, u32 *msg)
5499283883Sjfv{
5500283883Sjfv	u16	*list = (u16*)&msg[1];
5501283883Sjfv	int	entries;
5502283883Sjfv	u32	vmolr, vec_bit, vec_reg, mta_reg;
5503283883Sjfv
5504283883Sjfv	entries = (msg[0] & IXGBE_VT_MSGINFO_MASK) >> IXGBE_VT_MSGINFO_SHIFT;
5505283883Sjfv	entries = min(entries, IXGBE_MAX_VF_MC);
5506283883Sjfv
5507283883Sjfv	vmolr = IXGBE_READ_REG(&adapter->hw, IXGBE_VMOLR(vf->pool));
5508283883Sjfv
5509283883Sjfv	vf->num_mc_hashes = entries;
5510283883Sjfv
5511283883Sjfv	/* Set the appropriate MTA bit */
5512283883Sjfv	for (int i = 0; i < entries; i++) {
5513283883Sjfv		vf->mc_hash[i] = list[i];
5514283883Sjfv		vec_reg = (vf->mc_hash[i] >> 5) & 0x7F;
5515283883Sjfv                vec_bit = vf->mc_hash[i] & 0x1F;
5516283883Sjfv                mta_reg = IXGBE_READ_REG(&adapter->hw, IXGBE_MTA(vec_reg));
5517283883Sjfv                mta_reg |= (1 << vec_bit);
5518283883Sjfv                IXGBE_WRITE_REG(&adapter->hw, IXGBE_MTA(vec_reg), mta_reg);
5519283883Sjfv        }
5520283883Sjfv
5521283883Sjfv	vmolr |= IXGBE_VMOLR_ROMPE;
5522283883Sjfv	IXGBE_WRITE_REG(&adapter->hw, IXGBE_VMOLR(vf->pool), vmolr);
5523283883Sjfv	ixgbe_send_vf_ack(adapter, vf, msg[0]);
5524283883Sjfv	return;
5525283883Sjfv}
5526283883Sjfv
5527283883Sjfv
5528283883Sjfvstatic void
5529283883Sjfvixgbe_vf_set_vlan(struct adapter *adapter, struct ixgbe_vf *vf, uint32_t *msg)
5530283883Sjfv{
5531283883Sjfv	struct ixgbe_hw *hw;
5532283883Sjfv	int enable;
5533283883Sjfv	uint16_t tag;
5534283883Sjfv
5535283883Sjfv	hw = &adapter->hw;
5536283883Sjfv	enable = IXGBE_VT_MSGINFO(msg[0]);
5537283883Sjfv	tag = msg[1] & IXGBE_VLVF_VLANID_MASK;
5538283883Sjfv
5539283883Sjfv	if (!(vf->flags & IXGBE_VF_CAP_VLAN)) {
5540283883Sjfv		ixgbe_send_vf_nack(adapter, vf, msg[0]);
5541283883Sjfv		return;
5542283883Sjfv	}
5543283883Sjfv
5544283883Sjfv	/* It is illegal to enable vlan tag 0. */
5545283883Sjfv	if (tag == 0 && enable != 0){
5546283883Sjfv		ixgbe_send_vf_nack(adapter, vf, msg[0]);
5547283883Sjfv		return;
5548283883Sjfv	}
5549283883Sjfv
5550283883Sjfv	ixgbe_set_vfta(hw, tag, vf->pool, enable);
5551283883Sjfv	ixgbe_send_vf_ack(adapter, vf, msg[0]);
5552283883Sjfv}
5553283883Sjfv
5554283883Sjfv
5555283883Sjfvstatic void
5556283883Sjfvixgbe_vf_set_lpe(struct adapter *adapter, struct ixgbe_vf *vf, uint32_t *msg)
5557283883Sjfv{
5558283883Sjfv	struct ixgbe_hw *hw;
5559283883Sjfv	uint32_t vf_max_size, pf_max_size, mhadd;
5560283883Sjfv
5561283883Sjfv	hw = &adapter->hw;
5562283883Sjfv	vf_max_size = msg[1];
5563283883Sjfv
5564283883Sjfv	if (vf_max_size < ETHER_CRC_LEN) {
5565283883Sjfv		/* We intentionally ACK invalid LPE requests. */
5566283883Sjfv		ixgbe_send_vf_ack(adapter, vf, msg[0]);
5567283883Sjfv		return;
5568283883Sjfv	}
5569283883Sjfv
5570283883Sjfv	vf_max_size -= ETHER_CRC_LEN;
5571283883Sjfv
5572283883Sjfv	if (vf_max_size > IXGBE_MAX_FRAME_SIZE) {
5573283883Sjfv		/* We intentionally ACK invalid LPE requests. */
5574283883Sjfv		ixgbe_send_vf_ack(adapter, vf, msg[0]);
5575283883Sjfv		return;
5576283883Sjfv	}
5577283883Sjfv
5578283883Sjfv	vf->max_frame_size = vf_max_size;
5579283883Sjfv	ixgbe_update_max_frame(adapter, vf->max_frame_size);
5580283883Sjfv
5581283883Sjfv	/*
5582283883Sjfv	 * We might have to disable reception to this VF if the frame size is
5583283883Sjfv	 * not compatible with the config on the PF.
5584283883Sjfv	 */
5585283883Sjfv	ixgbe_vf_enable_receive(adapter, vf);
5586283883Sjfv
5587283883Sjfv	mhadd = IXGBE_READ_REG(hw, IXGBE_MHADD);
5588283883Sjfv	pf_max_size = (mhadd & IXGBE_MHADD_MFS_MASK) >> IXGBE_MHADD_MFS_SHIFT;
5589283883Sjfv
5590283883Sjfv	if (pf_max_size < adapter->max_frame_size) {
5591283883Sjfv		mhadd &= ~IXGBE_MHADD_MFS_MASK;
5592283883Sjfv		mhadd |= adapter->max_frame_size << IXGBE_MHADD_MFS_SHIFT;
5593283883Sjfv		IXGBE_WRITE_REG(hw, IXGBE_MHADD, mhadd);
5594283883Sjfv	}
5595283883Sjfv
5596283883Sjfv	ixgbe_send_vf_ack(adapter, vf, msg[0]);
5597283883Sjfv}
5598283883Sjfv
5599283883Sjfv
5600283883Sjfvstatic void
5601283883Sjfvixgbe_vf_set_macvlan(struct adapter *adapter, struct ixgbe_vf *vf,
5602283883Sjfv    uint32_t *msg)
5603283883Sjfv{
5604283883Sjfv	//XXX implement this
5605283883Sjfv	ixgbe_send_vf_nack(adapter, vf, msg[0]);
5606283883Sjfv}
5607283883Sjfv
5608283883Sjfv
5609283883Sjfvstatic void
5610283883Sjfvixgbe_vf_api_negotiate(struct adapter *adapter, struct ixgbe_vf *vf,
5611283883Sjfv    uint32_t *msg)
5612283883Sjfv{
5613283883Sjfv
5614285590Spkelsey	switch (msg[1]) {
5615283883Sjfv	case IXGBE_API_VER_1_0:
5616283883Sjfv	case IXGBE_API_VER_1_1:
5617285590Spkelsey		vf->api_ver = msg[1];
5618283883Sjfv		ixgbe_send_vf_ack(adapter, vf, msg[0]);
5619283883Sjfv		break;
5620283883Sjfv	default:
5621283883Sjfv		vf->api_ver = IXGBE_API_VER_UNKNOWN;
5622283883Sjfv		ixgbe_send_vf_nack(adapter, vf, msg[0]);
5623283883Sjfv		break;
5624283883Sjfv	}
5625283883Sjfv}
5626283883Sjfv
5627283883Sjfv
5628283883Sjfvstatic void
5629283883Sjfvixgbe_vf_get_queues(struct adapter *adapter, struct ixgbe_vf *vf,
5630283883Sjfv    uint32_t *msg)
5631283883Sjfv{
5632283883Sjfv	struct ixgbe_hw *hw;
5633283883Sjfv	uint32_t resp[IXGBE_VF_GET_QUEUES_RESP_LEN];
5634283883Sjfv	int num_queues;
5635283883Sjfv
5636283883Sjfv	hw = &adapter->hw;
5637283883Sjfv
5638283883Sjfv	/* GET_QUEUES is not supported on pre-1.1 APIs. */
5639283883Sjfv	switch (msg[0]) {
5640283883Sjfv	case IXGBE_API_VER_1_0:
5641283883Sjfv	case IXGBE_API_VER_UNKNOWN:
5642283883Sjfv		ixgbe_send_vf_nack(adapter, vf, msg[0]);
5643283883Sjfv		return;
5644283883Sjfv	}
5645283883Sjfv
5646283883Sjfv	resp[0] = IXGBE_VF_GET_QUEUES | IXGBE_VT_MSGTYPE_ACK |
5647283883Sjfv	    IXGBE_VT_MSGTYPE_CTS;
5648283883Sjfv
5649283883Sjfv	num_queues = ixgbe_vf_queues(ixgbe_get_iov_mode(adapter));
5650283883Sjfv	resp[IXGBE_VF_TX_QUEUES] = num_queues;
5651283883Sjfv	resp[IXGBE_VF_RX_QUEUES] = num_queues;
5652283883Sjfv	resp[IXGBE_VF_TRANS_VLAN] = (vf->default_vlan != 0);
5653283883Sjfv	resp[IXGBE_VF_DEF_QUEUE] = 0;
5654283883Sjfv
5655283883Sjfv	ixgbe_write_mbx(hw, resp, IXGBE_VF_GET_QUEUES_RESP_LEN, vf->pool);
5656283883Sjfv}
5657283883Sjfv
5658283883Sjfv
5659283883Sjfvstatic void
5660283883Sjfvixgbe_process_vf_msg(struct adapter *adapter, struct ixgbe_vf *vf)
5661283883Sjfv{
5662283883Sjfv	struct ixgbe_hw *hw;
5663283883Sjfv	uint32_t msg[IXGBE_VFMAILBOX_SIZE];
5664283883Sjfv	int error;
5665283883Sjfv
5666283883Sjfv	hw = &adapter->hw;
5667283883Sjfv
5668283883Sjfv	error = ixgbe_read_mbx(hw, msg, IXGBE_VFMAILBOX_SIZE, vf->pool);
5669283883Sjfv
5670283883Sjfv	if (error != 0)
5671283883Sjfv		return;
5672283883Sjfv
5673283883Sjfv	CTR3(KTR_MALLOC, "%s: received msg %x from %d",
5674283883Sjfv	    adapter->ifp->if_xname, msg[0], vf->pool);
5675283883Sjfv	if (msg[0] == IXGBE_VF_RESET) {
5676283883Sjfv		ixgbe_vf_reset_msg(adapter, vf, msg);
5677283883Sjfv		return;
5678283883Sjfv	}
5679283883Sjfv
5680283883Sjfv	if (!(vf->flags & IXGBE_VF_CTS)) {
5681283883Sjfv		ixgbe_send_vf_nack(adapter, vf, msg[0]);
5682283883Sjfv		return;
5683283883Sjfv	}
5684283883Sjfv
5685283883Sjfv	switch (msg[0] & IXGBE_VT_MSG_MASK) {
5686283883Sjfv	case IXGBE_VF_SET_MAC_ADDR:
5687283883Sjfv		ixgbe_vf_set_mac(adapter, vf, msg);
5688283883Sjfv		break;
5689283883Sjfv	case IXGBE_VF_SET_MULTICAST:
5690283883Sjfv		ixgbe_vf_set_mc_addr(adapter, vf, msg);
5691283883Sjfv		break;
5692283883Sjfv	case IXGBE_VF_SET_VLAN:
5693283883Sjfv		ixgbe_vf_set_vlan(adapter, vf, msg);
5694283883Sjfv		break;
5695283883Sjfv	case IXGBE_VF_SET_LPE:
5696283883Sjfv		ixgbe_vf_set_lpe(adapter, vf, msg);
5697283883Sjfv		break;
5698283883Sjfv	case IXGBE_VF_SET_MACVLAN:
5699283883Sjfv		ixgbe_vf_set_macvlan(adapter, vf, msg);
5700283883Sjfv		break;
5701283883Sjfv	case IXGBE_VF_API_NEGOTIATE:
5702283883Sjfv		ixgbe_vf_api_negotiate(adapter, vf, msg);
5703283883Sjfv		break;
5704283883Sjfv	case IXGBE_VF_GET_QUEUES:
5705283883Sjfv		ixgbe_vf_get_queues(adapter, vf, msg);
5706283883Sjfv		break;
5707283883Sjfv	default:
5708283883Sjfv		ixgbe_send_vf_nack(adapter, vf, msg[0]);
5709283883Sjfv	}
5710283883Sjfv}
5711283883Sjfv
5712283883Sjfv
5713283883Sjfv/*
5714283883Sjfv * Tasklet for handling VF -> PF mailbox messages.
5715283883Sjfv */
5716283883Sjfvstatic void
5717283883Sjfvixgbe_handle_mbx(void *context, int pending)
5718283883Sjfv{
5719283883Sjfv	struct adapter *adapter;
5720283883Sjfv	struct ixgbe_hw *hw;
5721283883Sjfv	struct ixgbe_vf *vf;
5722283883Sjfv	int i;
5723283883Sjfv
5724283883Sjfv	adapter = context;
5725283883Sjfv	hw = &adapter->hw;
5726283883Sjfv
5727283883Sjfv	IXGBE_CORE_LOCK(adapter);
5728283883Sjfv	for (i = 0; i < adapter->num_vfs; i++) {
5729283883Sjfv		vf = &adapter->vfs[i];
5730283883Sjfv
5731283883Sjfv		if (vf->flags & IXGBE_VF_ACTIVE) {
5732283883Sjfv			if (ixgbe_check_for_rst(hw, vf->pool) == 0)
5733283883Sjfv				ixgbe_process_vf_reset(adapter, vf);
5734283883Sjfv
5735283883Sjfv			if (ixgbe_check_for_msg(hw, vf->pool) == 0)
5736283883Sjfv				ixgbe_process_vf_msg(adapter, vf);
5737283883Sjfv
5738283883Sjfv			if (ixgbe_check_for_ack(hw, vf->pool) == 0)
5739283883Sjfv				ixgbe_process_vf_ack(adapter, vf);
5740283883Sjfv		}
5741283883Sjfv	}
5742283883Sjfv	IXGBE_CORE_UNLOCK(adapter);
5743283883Sjfv}
5744283883Sjfv
5745283883Sjfv
5746283883Sjfvstatic int
5747283883Sjfvixgbe_init_iov(device_t dev, u16 num_vfs, const nvlist_t *config)
5748283883Sjfv{
5749283883Sjfv	struct adapter *adapter;
5750283883Sjfv	enum ixgbe_iov_mode mode;
5751283883Sjfv
5752283883Sjfv	adapter = device_get_softc(dev);
5753283883Sjfv	adapter->num_vfs = num_vfs;
5754283883Sjfv	mode = ixgbe_get_iov_mode(adapter);
5755283883Sjfv
5756283883Sjfv	if (num_vfs > ixgbe_max_vfs(mode)) {
5757283883Sjfv		adapter->num_vfs = 0;
5758283883Sjfv		return (ENOSPC);
5759283883Sjfv	}
5760283883Sjfv
5761283883Sjfv	IXGBE_CORE_LOCK(adapter);
5762283883Sjfv
5763283883Sjfv	adapter->vfs = malloc(sizeof(*adapter->vfs) * num_vfs, M_IXGBE,
5764283883Sjfv	    M_NOWAIT | M_ZERO);
5765283883Sjfv
5766283883Sjfv	if (adapter->vfs == NULL) {
5767283883Sjfv		adapter->num_vfs = 0;
5768283883Sjfv		IXGBE_CORE_UNLOCK(adapter);
5769283883Sjfv		return (ENOMEM);
5770283883Sjfv	}
5771283883Sjfv
5772283883Sjfv	ixgbe_init_locked(adapter);
5773283883Sjfv
5774283883Sjfv	IXGBE_CORE_UNLOCK(adapter);
5775283883Sjfv
5776283883Sjfv	return (0);
5777283883Sjfv}
5778283883Sjfv
5779283883Sjfv
5780283883Sjfvstatic void
5781283883Sjfvixgbe_uninit_iov(device_t dev)
5782283883Sjfv{
5783283883Sjfv	struct ixgbe_hw *hw;
5784283883Sjfv	struct adapter *adapter;
5785283883Sjfv	uint32_t pf_reg, vf_reg;
5786283883Sjfv
5787283883Sjfv	adapter = device_get_softc(dev);
5788283883Sjfv	hw = &adapter->hw;
5789283883Sjfv
5790283883Sjfv	IXGBE_CORE_LOCK(adapter);
5791283883Sjfv
5792283883Sjfv	/* Enable rx/tx for the PF and disable it for all VFs. */
5793283883Sjfv	pf_reg = IXGBE_VF_INDEX(adapter->pool);
5794283883Sjfv	IXGBE_WRITE_REG(hw, IXGBE_VFRE(pf_reg),
5795283883Sjfv	    IXGBE_VF_BIT(adapter->pool));
5796283883Sjfv	IXGBE_WRITE_REG(hw, IXGBE_VFTE(pf_reg),
5797283883Sjfv	    IXGBE_VF_BIT(adapter->pool));
5798283883Sjfv
5799283883Sjfv	if (pf_reg == 0)
5800283883Sjfv		vf_reg = 1;
5801283883Sjfv	else
5802283883Sjfv		vf_reg = 0;
5803283883Sjfv	IXGBE_WRITE_REG(hw, IXGBE_VFRE(vf_reg), 0);
5804283883Sjfv	IXGBE_WRITE_REG(hw, IXGBE_VFTE(vf_reg), 0);
5805283883Sjfv
5806283883Sjfv	IXGBE_WRITE_REG(hw, IXGBE_VT_CTL, 0);
5807283883Sjfv
5808283883Sjfv	free(adapter->vfs, M_IXGBE);
5809283883Sjfv	adapter->vfs = NULL;
5810283883Sjfv	adapter->num_vfs = 0;
5811283883Sjfv
5812283883Sjfv	IXGBE_CORE_UNLOCK(adapter);
5813283883Sjfv}
5814283883Sjfv
5815283883Sjfv
5816283883Sjfvstatic void
5817283883Sjfvixgbe_initialize_iov(struct adapter *adapter)
5818283883Sjfv{
5819283883Sjfv	struct ixgbe_hw *hw = &adapter->hw;
5820283883Sjfv	uint32_t mrqc, mtqc, vt_ctl, vf_reg, gcr_ext, gpie;
5821283883Sjfv	enum ixgbe_iov_mode mode;
5822283883Sjfv	int i;
5823283883Sjfv
5824283883Sjfv	mode = ixgbe_get_iov_mode(adapter);
5825283883Sjfv	if (mode == IXGBE_NO_VM)
5826283883Sjfv		return;
5827283883Sjfv
5828283883Sjfv	IXGBE_CORE_LOCK_ASSERT(adapter);
5829283883Sjfv
5830283883Sjfv	mrqc = IXGBE_READ_REG(hw, IXGBE_MRQC);
5831283883Sjfv	mrqc &= ~IXGBE_MRQC_MRQE_MASK;
5832283883Sjfv
5833283883Sjfv	switch (mode) {
5834283883Sjfv	case IXGBE_64_VM:
5835283883Sjfv		mrqc |= IXGBE_MRQC_VMDQRSS64EN;
5836283883Sjfv		break;
5837283883Sjfv	case IXGBE_32_VM:
5838283883Sjfv		mrqc |= IXGBE_MRQC_VMDQRSS32EN;
5839283883Sjfv		break;
5840283883Sjfv	default:
5841283883Sjfv		panic("Unexpected SR-IOV mode %d", mode);
5842283883Sjfv	}
5843283883Sjfv	IXGBE_WRITE_REG(hw, IXGBE_MRQC, mrqc);
5844283883Sjfv
5845283883Sjfv	mtqc = IXGBE_MTQC_VT_ENA;
5846283883Sjfv	switch (mode) {
5847283883Sjfv	case IXGBE_64_VM:
5848283883Sjfv		mtqc |= IXGBE_MTQC_64VF;
5849283883Sjfv		break;
5850283883Sjfv	case IXGBE_32_VM:
5851283883Sjfv		mtqc |= IXGBE_MTQC_32VF;
5852283883Sjfv		break;
5853283883Sjfv	default:
5854283883Sjfv		panic("Unexpected SR-IOV mode %d", mode);
5855283883Sjfv	}
5856283883Sjfv	IXGBE_WRITE_REG(hw, IXGBE_MTQC, mtqc);
5857283883Sjfv
5858283883Sjfv
5859283883Sjfv	gcr_ext = IXGBE_READ_REG(hw, IXGBE_GCR_EXT);
5860283883Sjfv	gcr_ext |= IXGBE_GCR_EXT_MSIX_EN;
5861283883Sjfv	gcr_ext &= ~IXGBE_GCR_EXT_VT_MODE_MASK;
5862283883Sjfv	switch (mode) {
5863283883Sjfv	case IXGBE_64_VM:
5864283883Sjfv		gcr_ext |= IXGBE_GCR_EXT_VT_MODE_64;
5865283883Sjfv		break;
5866283883Sjfv	case IXGBE_32_VM:
5867283883Sjfv		gcr_ext |= IXGBE_GCR_EXT_VT_MODE_32;
5868283883Sjfv		break;
5869283883Sjfv	default:
5870283883Sjfv		panic("Unexpected SR-IOV mode %d", mode);
5871283883Sjfv	}
5872283883Sjfv	IXGBE_WRITE_REG(hw, IXGBE_GCR_EXT, gcr_ext);
5873283883Sjfv
5874283883Sjfv
5875283883Sjfv	gpie = IXGBE_READ_REG(hw, IXGBE_GPIE);
5876283883Sjfv	gcr_ext &= ~IXGBE_GPIE_VTMODE_MASK;
5877283883Sjfv	switch (mode) {
5878283883Sjfv	case IXGBE_64_VM:
5879283883Sjfv		gpie |= IXGBE_GPIE_VTMODE_64;
5880283883Sjfv		break;
5881283883Sjfv	case IXGBE_32_VM:
5882283883Sjfv		gpie |= IXGBE_GPIE_VTMODE_32;
5883283883Sjfv		break;
5884283883Sjfv	default:
5885283883Sjfv		panic("Unexpected SR-IOV mode %d", mode);
5886283883Sjfv	}
5887283883Sjfv	IXGBE_WRITE_REG(hw, IXGBE_GPIE, gpie);
5888283883Sjfv
5889283883Sjfv	/* Enable rx/tx for the PF. */
5890283883Sjfv	vf_reg = IXGBE_VF_INDEX(adapter->pool);
5891283883Sjfv	IXGBE_WRITE_REG(hw, IXGBE_VFRE(vf_reg),
5892283883Sjfv	    IXGBE_VF_BIT(adapter->pool));
5893283883Sjfv	IXGBE_WRITE_REG(hw, IXGBE_VFTE(vf_reg),
5894283883Sjfv	    IXGBE_VF_BIT(adapter->pool));
5895283883Sjfv
5896283883Sjfv	/* Allow VM-to-VM communication. */
5897283883Sjfv	IXGBE_WRITE_REG(hw, IXGBE_PFDTXGSWC, IXGBE_PFDTXGSWC_VT_LBEN);
5898283883Sjfv
5899283883Sjfv	vt_ctl = IXGBE_VT_CTL_VT_ENABLE | IXGBE_VT_CTL_REPLEN;
5900283883Sjfv	vt_ctl |= (adapter->pool << IXGBE_VT_CTL_POOL_SHIFT);
5901283883Sjfv	IXGBE_WRITE_REG(hw, IXGBE_VT_CTL, vt_ctl);
5902283883Sjfv
5903283883Sjfv	for (i = 0; i < adapter->num_vfs; i++)
5904283883Sjfv		ixgbe_init_vf(adapter, &adapter->vfs[i]);
5905283883Sjfv}
5906283883Sjfv
5907283883Sjfv
5908283883Sjfv/*
5909283883Sjfv** Check the max frame setting of all active VF's
5910283883Sjfv*/
5911283883Sjfvstatic void
5912283883Sjfvixgbe_recalculate_max_frame(struct adapter *adapter)
5913283883Sjfv{
5914283883Sjfv	struct ixgbe_vf *vf;
5915283883Sjfv
5916283883Sjfv	IXGBE_CORE_LOCK_ASSERT(adapter);
5917283883Sjfv
5918283883Sjfv	for (int i = 0; i < adapter->num_vfs; i++) {
5919283883Sjfv		vf = &adapter->vfs[i];
5920283883Sjfv		if (vf->flags & IXGBE_VF_ACTIVE)
5921283883Sjfv			ixgbe_update_max_frame(adapter, vf->max_frame_size);
5922283883Sjfv	}
5923283883Sjfv}
5924283883Sjfv
5925283883Sjfv
5926283883Sjfvstatic void
5927283883Sjfvixgbe_init_vf(struct adapter *adapter, struct ixgbe_vf *vf)
5928283883Sjfv{
5929283883Sjfv	struct ixgbe_hw *hw;
5930283883Sjfv	uint32_t vf_index, pfmbimr;
5931283883Sjfv
5932283883Sjfv	IXGBE_CORE_LOCK_ASSERT(adapter);
5933283883Sjfv
5934283883Sjfv	hw = &adapter->hw;
5935283883Sjfv
5936283883Sjfv	if (!(vf->flags & IXGBE_VF_ACTIVE))
5937283883Sjfv		return;
5938283883Sjfv
5939283883Sjfv	vf_index = IXGBE_VF_INDEX(vf->pool);
5940283883Sjfv	pfmbimr = IXGBE_READ_REG(hw, IXGBE_PFMBIMR(vf_index));
5941283883Sjfv	pfmbimr |= IXGBE_VF_BIT(vf->pool);
5942283883Sjfv	IXGBE_WRITE_REG(hw, IXGBE_PFMBIMR(vf_index), pfmbimr);
5943283883Sjfv
5944283883Sjfv	ixgbe_vf_set_default_vlan(adapter, vf, vf->vlan_tag);
5945283883Sjfv
5946283883Sjfv	// XXX multicast addresses
5947283883Sjfv
5948283883Sjfv	if (ixgbe_validate_mac_addr(vf->ether_addr) == 0) {
5949283883Sjfv		ixgbe_set_rar(&adapter->hw, vf->rar_index,
5950283883Sjfv		    vf->ether_addr, vf->pool, TRUE);
5951283883Sjfv	}
5952283883Sjfv
5953283883Sjfv	ixgbe_vf_enable_transmit(adapter, vf);
5954283883Sjfv	ixgbe_vf_enable_receive(adapter, vf);
5955283883Sjfv
5956283883Sjfv	ixgbe_send_vf_msg(adapter, vf, IXGBE_PF_CONTROL_MSG);
5957283883Sjfv}
5958283883Sjfv
5959283883Sjfvstatic int
5960283883Sjfvixgbe_add_vf(device_t dev, u16 vfnum, const nvlist_t *config)
5961283883Sjfv{
5962283883Sjfv	struct adapter *adapter;
5963283883Sjfv	struct ixgbe_vf *vf;
5964283883Sjfv	const void *mac;
5965283883Sjfv
5966283883Sjfv	adapter = device_get_softc(dev);
5967283883Sjfv
5968283883Sjfv	KASSERT(vfnum < adapter->num_vfs, ("VF index %d is out of range %d",
5969283883Sjfv	    vfnum, adapter->num_vfs));
5970283883Sjfv
5971283883Sjfv	IXGBE_CORE_LOCK(adapter);
5972283883Sjfv	vf = &adapter->vfs[vfnum];
5973283883Sjfv	vf->pool= vfnum;
5974283883Sjfv
5975283883Sjfv	/* RAR[0] is used by the PF so use vfnum + 1 for VF RAR. */
5976283883Sjfv	vf->rar_index = vfnum + 1;
5977283883Sjfv	vf->default_vlan = 0;
5978283883Sjfv	vf->max_frame_size = ETHER_MAX_LEN;
5979283883Sjfv	ixgbe_update_max_frame(adapter, vf->max_frame_size);
5980283883Sjfv
5981283883Sjfv	if (nvlist_exists_binary(config, "mac-addr")) {
5982283883Sjfv		mac = nvlist_get_binary(config, "mac-addr", NULL);
5983283883Sjfv		bcopy(mac, vf->ether_addr, ETHER_ADDR_LEN);
5984283883Sjfv		if (nvlist_get_bool(config, "allow-set-mac"))
5985283883Sjfv			vf->flags |= IXGBE_VF_CAP_MAC;
5986283883Sjfv	} else
5987283883Sjfv		/*
5988283883Sjfv		 * If the administrator has not specified a MAC address then
5989283883Sjfv		 * we must allow the VF to choose one.
5990283883Sjfv		 */
5991283883Sjfv		vf->flags |= IXGBE_VF_CAP_MAC;
5992283883Sjfv
5993283883Sjfv	vf->flags = IXGBE_VF_ACTIVE;
5994283883Sjfv
5995283883Sjfv	ixgbe_init_vf(adapter, vf);
5996283883Sjfv	IXGBE_CORE_UNLOCK(adapter);
5997283883Sjfv
5998283883Sjfv	return (0);
5999283883Sjfv}
6000283883Sjfv#endif /* PCI_IOV */
6001283883Sjfv
6002