ixgbe.c revision 1.5.2.2 1 1.5.2.2 jdolecek /* $NetBSD: ixgbe.c,v 1.5.2.2 2017/12/03 11:37:29 jdolecek Exp $ */
2 1.5.2.2 jdolecek
3 1.1 dyoung /******************************************************************************
4 1.1 dyoung
5 1.5.2.2 jdolecek Copyright (c) 2001-2017, Intel Corporation
6 1.1 dyoung All rights reserved.
7 1.5.2.2 jdolecek
8 1.5.2.2 jdolecek Redistribution and use in source and binary forms, with or without
9 1.1 dyoung modification, are permitted provided that the following conditions are met:
10 1.5.2.2 jdolecek
11 1.5.2.2 jdolecek 1. Redistributions of source code must retain the above copyright notice,
12 1.1 dyoung this list of conditions and the following disclaimer.
13 1.5.2.2 jdolecek
14 1.5.2.2 jdolecek 2. Redistributions in binary form must reproduce the above copyright
15 1.5.2.2 jdolecek notice, this list of conditions and the following disclaimer in the
16 1.1 dyoung documentation and/or other materials provided with the distribution.
17 1.5.2.2 jdolecek
18 1.5.2.2 jdolecek 3. Neither the name of the Intel Corporation nor the names of its
19 1.5.2.2 jdolecek contributors may be used to endorse or promote products derived from
20 1.1 dyoung this software without specific prior written permission.
21 1.5.2.2 jdolecek
22 1.1 dyoung THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
23 1.5.2.2 jdolecek AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 1.5.2.2 jdolecek IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 1.5.2.2 jdolecek ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
26 1.5.2.2 jdolecek LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
27 1.5.2.2 jdolecek CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
28 1.5.2.2 jdolecek SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
29 1.5.2.2 jdolecek INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
30 1.5.2.2 jdolecek CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
31 1.1 dyoung ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32 1.1 dyoung POSSIBILITY OF SUCH DAMAGE.
33 1.1 dyoung
34 1.1 dyoung ******************************************************************************/
35 1.5.2.2 jdolecek /*$FreeBSD: head/sys/dev/ixgbe/if_ix.c 320916 2017-07-12 17:35:32Z sbruno $*/
36 1.5.2.2 jdolecek
37 1.1 dyoung /*
38 1.1 dyoung * Copyright (c) 2011 The NetBSD Foundation, Inc.
39 1.1 dyoung * All rights reserved.
40 1.1 dyoung *
41 1.1 dyoung * This code is derived from software contributed to The NetBSD Foundation
42 1.1 dyoung * by Coyote Point Systems, Inc.
43 1.1 dyoung *
44 1.1 dyoung * Redistribution and use in source and binary forms, with or without
45 1.1 dyoung * modification, are permitted provided that the following conditions
46 1.1 dyoung * are met:
47 1.1 dyoung * 1. Redistributions of source code must retain the above copyright
48 1.1 dyoung * notice, this list of conditions and the following disclaimer.
49 1.1 dyoung * 2. Redistributions in binary form must reproduce the above copyright
50 1.1 dyoung * notice, this list of conditions and the following disclaimer in the
51 1.1 dyoung * documentation and/or other materials provided with the distribution.
52 1.1 dyoung *
53 1.1 dyoung * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
54 1.1 dyoung * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
55 1.1 dyoung * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
56 1.1 dyoung * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
57 1.1 dyoung * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
58 1.1 dyoung * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
59 1.1 dyoung * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
60 1.1 dyoung * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
61 1.1 dyoung * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
62 1.1 dyoung * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
63 1.1 dyoung * POSSIBILITY OF SUCH DAMAGE.
64 1.1 dyoung */
65 1.1 dyoung
66 1.5.2.2 jdolecek #ifdef _KERNEL_OPT
67 1.1 dyoung #include "opt_inet.h"
68 1.5.2.2 jdolecek #include "opt_inet6.h"
69 1.5.2.2 jdolecek #include "opt_net_mpsafe.h"
70 1.5.2.2 jdolecek #endif
71 1.1 dyoung
72 1.1 dyoung #include "ixgbe.h"
73 1.5.2.2 jdolecek #include "vlan.h"
74 1.1 dyoung
75 1.5.2.2 jdolecek #include <sys/cprng.h>
76 1.5.2.2 jdolecek #include <dev/mii/mii.h>
77 1.5.2.2 jdolecek #include <dev/mii/miivar.h>
78 1.5.2.2 jdolecek
79 1.5.2.2 jdolecek /************************************************************************
80 1.5.2.2 jdolecek * Driver version
81 1.5.2.2 jdolecek ************************************************************************/
82 1.5.2.2 jdolecek char ixgbe_driver_version[] = "3.2.12-k";
83 1.1 dyoung
84 1.5.2.2 jdolecek
85 1.5.2.2 jdolecek /************************************************************************
86 1.5.2.2 jdolecek * PCI Device ID Table
87 1.5.2.2 jdolecek *
88 1.5.2.2 jdolecek * Used by probe to select devices to load on
89 1.5.2.2 jdolecek * Last field stores an index into ixgbe_strings
90 1.5.2.2 jdolecek * Last entry must be all 0s
91 1.5.2.2 jdolecek *
92 1.5.2.2 jdolecek * { Vendor ID, Device ID, SubVendor ID, SubDevice ID, String Index }
93 1.5.2.2 jdolecek ************************************************************************/
94 1.1 dyoung static ixgbe_vendor_info_t ixgbe_vendor_info_array[] =
95 1.1 dyoung {
96 1.1 dyoung {IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82598AF_DUAL_PORT, 0, 0, 0},
97 1.1 dyoung {IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82598AF_SINGLE_PORT, 0, 0, 0},
98 1.1 dyoung {IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82598EB_CX4, 0, 0, 0},
99 1.1 dyoung {IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82598AT, 0, 0, 0},
100 1.1 dyoung {IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82598AT2, 0, 0, 0},
101 1.1 dyoung {IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82598, 0, 0, 0},
102 1.1 dyoung {IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82598_DA_DUAL_PORT, 0, 0, 0},
103 1.1 dyoung {IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82598_CX4_DUAL_PORT, 0, 0, 0},
104 1.1 dyoung {IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82598EB_XF_LR, 0, 0, 0},
105 1.1 dyoung {IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82598_SR_DUAL_PORT_EM, 0, 0, 0},
106 1.1 dyoung {IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82598EB_SFP_LOM, 0, 0, 0},
107 1.1 dyoung {IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82599_KX4, 0, 0, 0},
108 1.1 dyoung {IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82599_KX4_MEZZ, 0, 0, 0},
109 1.1 dyoung {IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82599_SFP, 0, 0, 0},
110 1.1 dyoung {IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82599_XAUI_LOM, 0, 0, 0},
111 1.1 dyoung {IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82599_CX4, 0, 0, 0},
112 1.1 dyoung {IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82599_T3_LOM, 0, 0, 0},
113 1.1 dyoung {IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82599_COMBO_BACKPLANE, 0, 0, 0},
114 1.1 dyoung {IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82599_BACKPLANE_FCOE, 0, 0, 0},
115 1.5.2.2 jdolecek {IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82599_SFP_SF2, 0, 0, 0},
116 1.1 dyoung {IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82599_SFP_FCOE, 0, 0, 0},
117 1.5.2.2 jdolecek {IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82599EN_SFP, 0, 0, 0},
118 1.5.2.2 jdolecek {IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82599_SFP_SF_QP, 0, 0, 0},
119 1.5.2.2 jdolecek {IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82599_QSFP_SF_QP, 0, 0, 0},
120 1.5.2.2 jdolecek {IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X540T, 0, 0, 0},
121 1.5.2.2 jdolecek {IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X540T1, 0, 0, 0},
122 1.5.2.2 jdolecek {IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X550T, 0, 0, 0},
123 1.5.2.2 jdolecek {IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X550T1, 0, 0, 0},
124 1.5.2.2 jdolecek {IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X550EM_X_KR, 0, 0, 0},
125 1.5.2.2 jdolecek {IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X550EM_X_KX4, 0, 0, 0},
126 1.5.2.2 jdolecek {IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X550EM_X_10G_T, 0, 0, 0},
127 1.5.2.2 jdolecek {IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X550EM_X_1G_T, 0, 0, 0},
128 1.5.2.2 jdolecek {IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X550EM_X_SFP, 0, 0, 0},
129 1.5.2.2 jdolecek {IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X550EM_A_KR, 0, 0, 0},
130 1.5.2.2 jdolecek {IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X550EM_A_KR_L, 0, 0, 0},
131 1.5.2.2 jdolecek {IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X550EM_A_SFP, 0, 0, 0},
132 1.5.2.2 jdolecek {IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X550EM_A_SFP_N, 0, 0, 0},
133 1.5.2.2 jdolecek {IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X550EM_A_SGMII, 0, 0, 0},
134 1.5.2.2 jdolecek {IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X550EM_A_SGMII_L, 0, 0, 0},
135 1.5.2.2 jdolecek {IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X550EM_A_10G_T, 0, 0, 0},
136 1.5.2.2 jdolecek {IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X550EM_A_1G_T, 0, 0, 0},
137 1.5.2.2 jdolecek {IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X550EM_A_1G_T_L, 0, 0, 0},
138 1.5.2.2 jdolecek {IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X540_BYPASS, 0, 0, 0},
139 1.5.2.2 jdolecek {IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82599_BYPASS, 0, 0, 0},
140 1.1 dyoung /* required last entry */
141 1.1 dyoung {0, 0, 0, 0, 0}
142 1.1 dyoung };
143 1.1 dyoung
144 1.5.2.2 jdolecek /************************************************************************
145 1.5.2.2 jdolecek * Table of branding strings
146 1.5.2.2 jdolecek ************************************************************************/
147 1.1 dyoung static const char *ixgbe_strings[] = {
148 1.1 dyoung "Intel(R) PRO/10GbE PCI-Express Network Driver"
149 1.1 dyoung };
150 1.1 dyoung
151 1.5.2.2 jdolecek /************************************************************************
152 1.5.2.2 jdolecek * Function prototypes
153 1.5.2.2 jdolecek ************************************************************************/
154 1.1 dyoung static int ixgbe_probe(device_t, cfdata_t, void *);
155 1.1 dyoung static void ixgbe_attach(device_t, device_t, void *);
156 1.1 dyoung static int ixgbe_detach(device_t, int);
157 1.1 dyoung #if 0
158 1.1 dyoung static int ixgbe_shutdown(device_t);
159 1.1 dyoung #endif
160 1.5.2.2 jdolecek static bool ixgbe_suspend(device_t, const pmf_qual_t *);
161 1.5.2.2 jdolecek static bool ixgbe_resume(device_t, const pmf_qual_t *);
162 1.5.2.2 jdolecek static int ixgbe_ifflags_cb(struct ethercom *);
163 1.1 dyoung static int ixgbe_ioctl(struct ifnet *, u_long, void *);
164 1.1 dyoung static void ixgbe_ifstop(struct ifnet *, int);
165 1.1 dyoung static int ixgbe_init(struct ifnet *);
166 1.1 dyoung static void ixgbe_init_locked(struct adapter *);
167 1.1 dyoung static void ixgbe_stop(void *);
168 1.5.2.2 jdolecek static void ixgbe_init_device_features(struct adapter *);
169 1.5.2.2 jdolecek static void ixgbe_check_fan_failure(struct adapter *, u32, bool);
170 1.5.2.2 jdolecek static void ixgbe_add_media_types(struct adapter *);
171 1.1 dyoung static void ixgbe_media_status(struct ifnet *, struct ifmediareq *);
172 1.1 dyoung static int ixgbe_media_change(struct ifnet *);
173 1.1 dyoung static int ixgbe_allocate_pci_resources(struct adapter *,
174 1.1 dyoung const struct pci_attach_args *);
175 1.5.2.2 jdolecek static void ixgbe_get_slot_info(struct adapter *);
176 1.1 dyoung static int ixgbe_allocate_msix(struct adapter *,
177 1.1 dyoung const struct pci_attach_args *);
178 1.1 dyoung static int ixgbe_allocate_legacy(struct adapter *,
179 1.1 dyoung const struct pci_attach_args *);
180 1.5.2.2 jdolecek static int ixgbe_configure_interrupts(struct adapter *);
181 1.1 dyoung static void ixgbe_free_pci_resources(struct adapter *);
182 1.1 dyoung static void ixgbe_local_timer(void *);
183 1.5.2.2 jdolecek static void ixgbe_local_timer1(void *);
184 1.1 dyoung static int ixgbe_setup_interface(device_t, struct adapter *);
185 1.5.2.2 jdolecek static void ixgbe_config_gpie(struct adapter *);
186 1.5.2.2 jdolecek static void ixgbe_config_dmac(struct adapter *);
187 1.5.2.2 jdolecek static void ixgbe_config_delay_values(struct adapter *);
188 1.1 dyoung static void ixgbe_config_link(struct adapter *);
189 1.5.2.2 jdolecek static void ixgbe_check_wol_support(struct adapter *);
190 1.5.2.2 jdolecek static int ixgbe_setup_low_power_mode(struct adapter *);
191 1.5.2.2 jdolecek static void ixgbe_rearm_queues(struct adapter *, u64);
192 1.1 dyoung
193 1.1 dyoung static void ixgbe_initialize_transmit_units(struct adapter *);
194 1.1 dyoung static void ixgbe_initialize_receive_units(struct adapter *);
195 1.5.2.2 jdolecek static void ixgbe_enable_rx_drop(struct adapter *);
196 1.5.2.2 jdolecek static void ixgbe_disable_rx_drop(struct adapter *);
197 1.5.2.2 jdolecek static void ixgbe_initialize_rss_mapping(struct adapter *);
198 1.1 dyoung
199 1.1 dyoung static void ixgbe_enable_intr(struct adapter *);
200 1.1 dyoung static void ixgbe_disable_intr(struct adapter *);
201 1.1 dyoung static void ixgbe_update_stats_counters(struct adapter *);
202 1.1 dyoung static void ixgbe_set_promisc(struct adapter *);
203 1.1 dyoung static void ixgbe_set_multi(struct adapter *);
204 1.1 dyoung static void ixgbe_update_link_status(struct adapter *);
205 1.1 dyoung static void ixgbe_set_ivar(struct adapter *, u8, u8, s8);
206 1.1 dyoung static void ixgbe_configure_ivars(struct adapter *);
207 1.1 dyoung static u8 * ixgbe_mc_array_itr(struct ixgbe_hw *, u8 **, u32 *);
208 1.1 dyoung
209 1.1 dyoung static void ixgbe_setup_vlan_hw_support(struct adapter *);
210 1.1 dyoung #if 0
211 1.1 dyoung static void ixgbe_register_vlan(void *, struct ifnet *, u16);
212 1.1 dyoung static void ixgbe_unregister_vlan(void *, struct ifnet *, u16);
213 1.1 dyoung #endif
214 1.1 dyoung
215 1.5.2.2 jdolecek static void ixgbe_add_device_sysctls(struct adapter *);
216 1.5.2.2 jdolecek static void ixgbe_add_hw_stats(struct adapter *);
217 1.5.2.2 jdolecek static void ixgbe_clear_evcnt(struct adapter *);
218 1.5.2.2 jdolecek static int ixgbe_set_flowcntl(struct adapter *, int);
219 1.5.2.2 jdolecek static int ixgbe_set_advertise(struct adapter *, int);
220 1.5.2.2 jdolecek static int ixgbe_get_advertise(struct adapter *);
221 1.5.2.2 jdolecek
222 1.5.2.2 jdolecek /* Sysctl handlers */
223 1.5.2.2 jdolecek static void ixgbe_set_sysctl_value(struct adapter *, const char *,
224 1.5.2.2 jdolecek const char *, int *, int);
225 1.5.2.2 jdolecek static int ixgbe_sysctl_flowcntl(SYSCTLFN_PROTO);
226 1.5.2.2 jdolecek static int ixgbe_sysctl_advertise(SYSCTLFN_PROTO);
227 1.5.2.2 jdolecek static int ixgbe_sysctl_interrupt_rate_handler(SYSCTLFN_PROTO);
228 1.5.2.2 jdolecek static int ixgbe_sysctl_dmac(SYSCTLFN_PROTO);
229 1.5.2.2 jdolecek static int ixgbe_sysctl_phy_temp(SYSCTLFN_PROTO);
230 1.5.2.2 jdolecek static int ixgbe_sysctl_phy_overtemp_occurred(SYSCTLFN_PROTO);
231 1.5.2.2 jdolecek #ifdef IXGBE_DEBUG
232 1.5.2.2 jdolecek static int ixgbe_sysctl_power_state(SYSCTLFN_PROTO);
233 1.5.2.2 jdolecek static int ixgbe_sysctl_print_rss_config(SYSCTLFN_PROTO);
234 1.5.2.2 jdolecek #endif
235 1.5.2.2 jdolecek static int ixgbe_sysctl_rdh_handler(SYSCTLFN_PROTO);
236 1.5.2.2 jdolecek static int ixgbe_sysctl_rdt_handler(SYSCTLFN_PROTO);
237 1.5.2.2 jdolecek static int ixgbe_sysctl_tdt_handler(SYSCTLFN_PROTO);
238 1.5.2.2 jdolecek static int ixgbe_sysctl_tdh_handler(SYSCTLFN_PROTO);
239 1.5.2.2 jdolecek static int ixgbe_sysctl_eee_state(SYSCTLFN_PROTO);
240 1.5.2.2 jdolecek static int ixgbe_sysctl_wol_enable(SYSCTLFN_PROTO);
241 1.5.2.2 jdolecek static int ixgbe_sysctl_wufc(SYSCTLFN_PROTO);
242 1.1 dyoung
243 1.1 dyoung /* Support for pluggable optic modules */
244 1.1 dyoung static bool ixgbe_sfp_probe(struct adapter *);
245 1.1 dyoung
246 1.5.2.2 jdolecek /* Legacy (single vector) interrupt handler */
247 1.1 dyoung static int ixgbe_legacy_irq(void *);
248 1.1 dyoung
249 1.5.2.2 jdolecek /* The MSI/MSI-X Interrupt handlers */
250 1.5.2.2 jdolecek static int ixgbe_msix_que(void *);
251 1.5.2.2 jdolecek static int ixgbe_msix_link(void *);
252 1.1 dyoung
253 1.1 dyoung /* Software interrupts for deferred work */
254 1.1 dyoung static void ixgbe_handle_que(void *);
255 1.1 dyoung static void ixgbe_handle_link(void *);
256 1.1 dyoung static void ixgbe_handle_msf(void *);
257 1.1 dyoung static void ixgbe_handle_mod(void *);
258 1.5.2.2 jdolecek static void ixgbe_handle_phy(void *);
259 1.1 dyoung
260 1.1 dyoung static ixgbe_vendor_info_t *ixgbe_lookup(const struct pci_attach_args *);
261 1.1 dyoung
262 1.5.2.2 jdolecek /************************************************************************
263 1.5.2.2 jdolecek * NetBSD Device Interface Entry Points
264 1.5.2.2 jdolecek ************************************************************************/
265 1.1 dyoung CFATTACH_DECL3_NEW(ixg, sizeof(struct adapter),
266 1.1 dyoung ixgbe_probe, ixgbe_attach, ixgbe_detach, NULL, NULL, NULL,
267 1.1 dyoung DVF_DETACH_SHUTDOWN);
268 1.1 dyoung
269 1.1 dyoung #if 0
270 1.5.2.2 jdolecek devclass_t ix_devclass;
271 1.5.2.2 jdolecek DRIVER_MODULE(ix, pci, ix_driver, ix_devclass, 0, 0);
272 1.1 dyoung
273 1.5.2.2 jdolecek MODULE_DEPEND(ix, pci, 1, 1, 1);
274 1.5.2.2 jdolecek MODULE_DEPEND(ix, ether, 1, 1, 1);
275 1.1 dyoung #endif
276 1.1 dyoung
277 1.1 dyoung /*
278 1.5.2.2 jdolecek * TUNEABLE PARAMETERS:
279 1.5.2.2 jdolecek */
280 1.1 dyoung
281 1.1 dyoung /*
282 1.5.2.2 jdolecek * AIM: Adaptive Interrupt Moderation
283 1.5.2.2 jdolecek * which means that the interrupt rate
284 1.5.2.2 jdolecek * is varied over time based on the
285 1.5.2.2 jdolecek * traffic for that interrupt vector
286 1.5.2.2 jdolecek */
287 1.5.2.2 jdolecek static bool ixgbe_enable_aim = true;
288 1.5.2.2 jdolecek #define SYSCTL_INT(_a1, _a2, _a3, _a4, _a5, _a6, _a7)
289 1.5.2.2 jdolecek SYSCTL_INT(_hw_ix, OID_AUTO, enable_aim, CTLFLAG_RDTUN, &ixgbe_enable_aim, 0,
290 1.5.2.2 jdolecek "Enable adaptive interrupt moderation");
291 1.5.2.2 jdolecek
292 1.5.2.2 jdolecek static int ixgbe_max_interrupt_rate = (4000000 / IXGBE_LOW_LATENCY);
293 1.5.2.2 jdolecek SYSCTL_INT(_hw_ix, OID_AUTO, max_interrupt_rate, CTLFLAG_RDTUN,
294 1.5.2.2 jdolecek &ixgbe_max_interrupt_rate, 0, "Maximum interrupts per second");
295 1.1 dyoung
296 1.1 dyoung /* How many packets rxeof tries to clean at a time */
297 1.1 dyoung static int ixgbe_rx_process_limit = 256;
298 1.5.2.2 jdolecek SYSCTL_INT(_hw_ix, OID_AUTO, rx_process_limit, CTLFLAG_RDTUN,
299 1.5.2.2 jdolecek &ixgbe_rx_process_limit, 0, "Maximum number of received packets to process at a time, -1 means unlimited");
300 1.5.2.2 jdolecek
301 1.5.2.2 jdolecek /* How many packets txeof tries to clean at a time */
302 1.5.2.2 jdolecek static int ixgbe_tx_process_limit = 256;
303 1.5.2.2 jdolecek SYSCTL_INT(_hw_ix, OID_AUTO, tx_process_limit, CTLFLAG_RDTUN,
304 1.5.2.2 jdolecek &ixgbe_tx_process_limit, 0,
305 1.5.2.2 jdolecek "Maximum number of sent packets to process at a time, -1 means unlimited");
306 1.1 dyoung
307 1.1 dyoung /* Flow control setting, default to full */
308 1.1 dyoung static int ixgbe_flow_control = ixgbe_fc_full;
309 1.5.2.2 jdolecek SYSCTL_INT(_hw_ix, OID_AUTO, flow_control, CTLFLAG_RDTUN,
310 1.5.2.2 jdolecek &ixgbe_flow_control, 0, "Default flow control used for all adapters");
311 1.1 dyoung
312 1.1 dyoung /*
313 1.5.2.2 jdolecek * Smart speed setting, default to on
314 1.5.2.2 jdolecek * this only works as a compile option
315 1.5.2.2 jdolecek * right now as its during attach, set
316 1.5.2.2 jdolecek * this to 'ixgbe_smart_speed_off' to
317 1.5.2.2 jdolecek * disable.
318 1.5.2.2 jdolecek */
319 1.1 dyoung static int ixgbe_smart_speed = ixgbe_smart_speed_on;
320 1.1 dyoung
321 1.1 dyoung /*
322 1.5.2.2 jdolecek * MSI-X should be the default for best performance,
323 1.1 dyoung * but this allows it to be forced off for testing.
324 1.1 dyoung */
325 1.1 dyoung static int ixgbe_enable_msix = 1;
326 1.5.2.2 jdolecek SYSCTL_INT(_hw_ix, OID_AUTO, enable_msix, CTLFLAG_RDTUN, &ixgbe_enable_msix, 0,
327 1.5.2.2 jdolecek "Enable MSI-X interrupts");
328 1.1 dyoung
329 1.1 dyoung /*
330 1.1 dyoung * Number of Queues, can be set to 0,
331 1.1 dyoung * it then autoconfigures based on the
332 1.1 dyoung * number of cpus with a max of 8. This
333 1.1 dyoung * can be overriden manually here.
334 1.1 dyoung */
335 1.1 dyoung static int ixgbe_num_queues = 0;
336 1.5.2.2 jdolecek SYSCTL_INT(_hw_ix, OID_AUTO, num_queues, CTLFLAG_RDTUN, &ixgbe_num_queues, 0,
337 1.5.2.2 jdolecek "Number of queues to configure, 0 indicates autoconfigure");
338 1.1 dyoung
339 1.1 dyoung /*
340 1.5.2.2 jdolecek * Number of TX descriptors per ring,
341 1.5.2.2 jdolecek * setting higher than RX as this seems
342 1.5.2.2 jdolecek * the better performing choice.
343 1.5.2.2 jdolecek */
344 1.1 dyoung static int ixgbe_txd = PERFORM_TXD;
345 1.5.2.2 jdolecek SYSCTL_INT(_hw_ix, OID_AUTO, txd, CTLFLAG_RDTUN, &ixgbe_txd, 0,
346 1.5.2.2 jdolecek "Number of transmit descriptors per queue");
347 1.1 dyoung
348 1.1 dyoung /* Number of RX descriptors per ring */
349 1.1 dyoung static int ixgbe_rxd = PERFORM_RXD;
350 1.5.2.2 jdolecek SYSCTL_INT(_hw_ix, OID_AUTO, rxd, CTLFLAG_RDTUN, &ixgbe_rxd, 0,
351 1.5.2.2 jdolecek "Number of receive descriptors per queue");
352 1.5.2.2 jdolecek
353 1.5.2.2 jdolecek /*
354 1.5.2.2 jdolecek * Defining this on will allow the use
355 1.5.2.2 jdolecek * of unsupported SFP+ modules, note that
356 1.5.2.2 jdolecek * doing so you are on your own :)
357 1.5.2.2 jdolecek */
358 1.5.2.2 jdolecek static int allow_unsupported_sfp = false;
359 1.5.2.2 jdolecek #define TUNABLE_INT(__x, __y)
360 1.5.2.2 jdolecek TUNABLE_INT("hw.ix.unsupported_sfp", &allow_unsupported_sfp);
361 1.5.2.2 jdolecek
362 1.5.2.2 jdolecek /*
363 1.5.2.2 jdolecek * Not sure if Flow Director is fully baked,
364 1.5.2.2 jdolecek * so we'll default to turning it off.
365 1.5.2.2 jdolecek */
366 1.5.2.2 jdolecek static int ixgbe_enable_fdir = 0;
367 1.5.2.2 jdolecek SYSCTL_INT(_hw_ix, OID_AUTO, enable_fdir, CTLFLAG_RDTUN, &ixgbe_enable_fdir, 0,
368 1.5.2.2 jdolecek "Enable Flow Director");
369 1.5.2.2 jdolecek
370 1.5.2.2 jdolecek /* Legacy Transmit (single queue) */
371 1.5.2.2 jdolecek static int ixgbe_enable_legacy_tx = 0;
372 1.5.2.2 jdolecek SYSCTL_INT(_hw_ix, OID_AUTO, enable_legacy_tx, CTLFLAG_RDTUN,
373 1.5.2.2 jdolecek &ixgbe_enable_legacy_tx, 0, "Enable Legacy TX flow");
374 1.5.2.2 jdolecek
375 1.5.2.2 jdolecek /* Receive-Side Scaling */
376 1.5.2.2 jdolecek static int ixgbe_enable_rss = 1;
377 1.5.2.2 jdolecek SYSCTL_INT(_hw_ix, OID_AUTO, enable_rss, CTLFLAG_RDTUN, &ixgbe_enable_rss, 0,
378 1.5.2.2 jdolecek "Enable Receive-Side Scaling (RSS)");
379 1.1 dyoung
380 1.1 dyoung /* Keep running tab on them for sanity check */
381 1.1 dyoung static int ixgbe_total_ports;
382 1.1 dyoung
383 1.5.2.2 jdolecek #if 0
384 1.5.2.2 jdolecek static int (*ixgbe_start_locked)(struct ifnet *, struct tx_ring *);
385 1.5.2.2 jdolecek static int (*ixgbe_ring_empty)(struct ifnet *, pcq_t *);
386 1.1 dyoung #endif
387 1.1 dyoung
388 1.5.2.2 jdolecek #ifdef NET_MPSAFE
389 1.5.2.2 jdolecek #define IXGBE_MPSAFE 1
390 1.5.2.2 jdolecek #define IXGBE_CALLOUT_FLAGS CALLOUT_MPSAFE
391 1.5.2.2 jdolecek #define IXGBE_SOFTINFT_FLAGS SOFTINT_MPSAFE
392 1.5.2.2 jdolecek #else
393 1.5.2.2 jdolecek #define IXGBE_CALLOUT_FLAGS 0
394 1.5.2.2 jdolecek #define IXGBE_SOFTINFT_FLAGS 0
395 1.5.2.2 jdolecek #endif
396 1.1 dyoung
397 1.5.2.2 jdolecek /************************************************************************
398 1.5.2.2 jdolecek * ixgbe_initialize_rss_mapping
399 1.5.2.2 jdolecek ************************************************************************/
400 1.5.2.2 jdolecek static void
401 1.5.2.2 jdolecek ixgbe_initialize_rss_mapping(struct adapter *adapter)
402 1.1 dyoung {
403 1.5.2.2 jdolecek struct ixgbe_hw *hw = &adapter->hw;
404 1.5.2.2 jdolecek u32 reta = 0, mrqc, rss_key[10];
405 1.5.2.2 jdolecek int queue_id, table_size, index_mult;
406 1.5.2.2 jdolecek int i, j;
407 1.5.2.2 jdolecek u32 rss_hash_config;
408 1.5.2.2 jdolecek
409 1.5.2.2 jdolecek if (adapter->feat_en & IXGBE_FEATURE_RSS) {
410 1.5.2.2 jdolecek /* Fetch the configured RSS key */
411 1.5.2.2 jdolecek rss_getkey((uint8_t *) &rss_key);
412 1.5.2.2 jdolecek } else {
413 1.5.2.2 jdolecek /* set up random bits */
414 1.5.2.2 jdolecek cprng_fast(&rss_key, sizeof(rss_key));
415 1.5.2.2 jdolecek }
416 1.1 dyoung
417 1.5.2.2 jdolecek /* Set multiplier for RETA setup and table size based on MAC */
418 1.5.2.2 jdolecek index_mult = 0x1;
419 1.5.2.2 jdolecek table_size = 128;
420 1.5.2.2 jdolecek switch (adapter->hw.mac.type) {
421 1.5.2.2 jdolecek case ixgbe_mac_82598EB:
422 1.5.2.2 jdolecek index_mult = 0x11;
423 1.5.2.2 jdolecek break;
424 1.5.2.2 jdolecek case ixgbe_mac_X550:
425 1.5.2.2 jdolecek case ixgbe_mac_X550EM_x:
426 1.5.2.2 jdolecek case ixgbe_mac_X550EM_a:
427 1.5.2.2 jdolecek table_size = 512;
428 1.5.2.2 jdolecek break;
429 1.5.2.2 jdolecek default:
430 1.5.2.2 jdolecek break;
431 1.5.2.2 jdolecek }
432 1.1 dyoung
433 1.5.2.2 jdolecek /* Set up the redirection table */
434 1.5.2.2 jdolecek for (i = 0, j = 0; i < table_size; i++, j++) {
435 1.5.2.2 jdolecek if (j == adapter->num_queues)
436 1.5.2.2 jdolecek j = 0;
437 1.5.2.2 jdolecek
438 1.5.2.2 jdolecek if (adapter->feat_en & IXGBE_FEATURE_RSS) {
439 1.5.2.2 jdolecek /*
440 1.5.2.2 jdolecek * Fetch the RSS bucket id for the given indirection
441 1.5.2.2 jdolecek * entry. Cap it at the number of configured buckets
442 1.5.2.2 jdolecek * (which is num_queues.)
443 1.5.2.2 jdolecek */
444 1.5.2.2 jdolecek queue_id = rss_get_indirection_to_bucket(i);
445 1.5.2.2 jdolecek queue_id = queue_id % adapter->num_queues;
446 1.5.2.2 jdolecek } else
447 1.5.2.2 jdolecek queue_id = (j * index_mult);
448 1.5.2.2 jdolecek
449 1.5.2.2 jdolecek /*
450 1.5.2.2 jdolecek * The low 8 bits are for hash value (n+0);
451 1.5.2.2 jdolecek * The next 8 bits are for hash value (n+1), etc.
452 1.5.2.2 jdolecek */
453 1.5.2.2 jdolecek reta = reta >> 8;
454 1.5.2.2 jdolecek reta = reta | (((uint32_t) queue_id) << 24);
455 1.5.2.2 jdolecek if ((i & 3) == 3) {
456 1.5.2.2 jdolecek if (i < 128)
457 1.5.2.2 jdolecek IXGBE_WRITE_REG(hw, IXGBE_RETA(i >> 2), reta);
458 1.5.2.2 jdolecek else
459 1.5.2.2 jdolecek IXGBE_WRITE_REG(hw, IXGBE_ERETA((i >> 2) - 32),
460 1.5.2.2 jdolecek reta);
461 1.5.2.2 jdolecek reta = 0;
462 1.5.2.2 jdolecek }
463 1.5.2.2 jdolecek }
464 1.5.2.2 jdolecek
465 1.5.2.2 jdolecek /* Now fill our hash function seeds */
466 1.5.2.2 jdolecek for (i = 0; i < 10; i++)
467 1.5.2.2 jdolecek IXGBE_WRITE_REG(hw, IXGBE_RSSRK(i), rss_key[i]);
468 1.5.2.2 jdolecek
469 1.5.2.2 jdolecek /* Perform hash on these packet types */
470 1.5.2.2 jdolecek if (adapter->feat_en & IXGBE_FEATURE_RSS)
471 1.5.2.2 jdolecek rss_hash_config = rss_gethashconfig();
472 1.5.2.2 jdolecek else {
473 1.5.2.2 jdolecek /*
474 1.5.2.2 jdolecek * Disable UDP - IP fragments aren't currently being handled
475 1.5.2.2 jdolecek * and so we end up with a mix of 2-tuple and 4-tuple
476 1.5.2.2 jdolecek * traffic.
477 1.5.2.2 jdolecek */
478 1.5.2.2 jdolecek rss_hash_config = RSS_HASHTYPE_RSS_IPV4
479 1.5.2.2 jdolecek | RSS_HASHTYPE_RSS_TCP_IPV4
480 1.5.2.2 jdolecek | RSS_HASHTYPE_RSS_IPV6
481 1.5.2.2 jdolecek | RSS_HASHTYPE_RSS_TCP_IPV6
482 1.5.2.2 jdolecek | RSS_HASHTYPE_RSS_IPV6_EX
483 1.5.2.2 jdolecek | RSS_HASHTYPE_RSS_TCP_IPV6_EX;
484 1.5.2.2 jdolecek }
485 1.5.2.2 jdolecek
486 1.5.2.2 jdolecek mrqc = IXGBE_MRQC_RSSEN;
487 1.5.2.2 jdolecek if (rss_hash_config & RSS_HASHTYPE_RSS_IPV4)
488 1.5.2.2 jdolecek mrqc |= IXGBE_MRQC_RSS_FIELD_IPV4;
489 1.5.2.2 jdolecek if (rss_hash_config & RSS_HASHTYPE_RSS_TCP_IPV4)
490 1.5.2.2 jdolecek mrqc |= IXGBE_MRQC_RSS_FIELD_IPV4_TCP;
491 1.5.2.2 jdolecek if (rss_hash_config & RSS_HASHTYPE_RSS_IPV6)
492 1.5.2.2 jdolecek mrqc |= IXGBE_MRQC_RSS_FIELD_IPV6;
493 1.5.2.2 jdolecek if (rss_hash_config & RSS_HASHTYPE_RSS_TCP_IPV6)
494 1.5.2.2 jdolecek mrqc |= IXGBE_MRQC_RSS_FIELD_IPV6_TCP;
495 1.5.2.2 jdolecek if (rss_hash_config & RSS_HASHTYPE_RSS_IPV6_EX)
496 1.5.2.2 jdolecek mrqc |= IXGBE_MRQC_RSS_FIELD_IPV6_EX;
497 1.5.2.2 jdolecek if (rss_hash_config & RSS_HASHTYPE_RSS_TCP_IPV6_EX)
498 1.5.2.2 jdolecek mrqc |= IXGBE_MRQC_RSS_FIELD_IPV6_EX_TCP;
499 1.5.2.2 jdolecek if (rss_hash_config & RSS_HASHTYPE_RSS_UDP_IPV4)
500 1.5.2.2 jdolecek mrqc |= IXGBE_MRQC_RSS_FIELD_IPV4_UDP;
501 1.5.2.2 jdolecek if (rss_hash_config & RSS_HASHTYPE_RSS_UDP_IPV4_EX)
502 1.5.2.2 jdolecek device_printf(adapter->dev, "%s: RSS_HASHTYPE_RSS_UDP_IPV4_EX defined, but not supported\n",
503 1.5.2.2 jdolecek __func__);
504 1.5.2.2 jdolecek if (rss_hash_config & RSS_HASHTYPE_RSS_UDP_IPV6)
505 1.5.2.2 jdolecek mrqc |= IXGBE_MRQC_RSS_FIELD_IPV6_UDP;
506 1.5.2.2 jdolecek if (rss_hash_config & RSS_HASHTYPE_RSS_UDP_IPV6_EX)
507 1.5.2.2 jdolecek mrqc |= IXGBE_MRQC_RSS_FIELD_IPV6_EX_UDP;
508 1.5.2.2 jdolecek mrqc |= ixgbe_get_mrqc(adapter->iov_mode);
509 1.5.2.2 jdolecek IXGBE_WRITE_REG(hw, IXGBE_MRQC, mrqc);
510 1.5.2.2 jdolecek } /* ixgbe_initialize_rss_mapping */
511 1.5.2.2 jdolecek
512 1.5.2.2 jdolecek /************************************************************************
513 1.5.2.2 jdolecek * ixgbe_initialize_receive_units - Setup receive registers and features.
514 1.5.2.2 jdolecek ************************************************************************/
515 1.5.2.2 jdolecek #define BSIZEPKT_ROUNDUP ((1<<IXGBE_SRRCTL_BSIZEPKT_SHIFT)-1)
516 1.5.2.2 jdolecek
517 1.5.2.2 jdolecek static void
518 1.5.2.2 jdolecek ixgbe_initialize_receive_units(struct adapter *adapter)
519 1.1 dyoung {
520 1.5.2.2 jdolecek struct rx_ring *rxr = adapter->rx_rings;
521 1.5.2.2 jdolecek struct ixgbe_hw *hw = &adapter->hw;
522 1.5.2.2 jdolecek struct ifnet *ifp = adapter->ifp;
523 1.5.2.2 jdolecek int i, j;
524 1.5.2.2 jdolecek u32 bufsz, fctrl, srrctl, rxcsum;
525 1.5.2.2 jdolecek u32 hlreg;
526 1.1 dyoung
527 1.5.2.2 jdolecek /*
528 1.5.2.2 jdolecek * Make sure receives are disabled while
529 1.5.2.2 jdolecek * setting up the descriptor ring
530 1.5.2.2 jdolecek */
531 1.5.2.2 jdolecek ixgbe_disable_rx(hw);
532 1.1 dyoung
533 1.5.2.2 jdolecek /* Enable broadcasts */
534 1.5.2.2 jdolecek fctrl = IXGBE_READ_REG(hw, IXGBE_FCTRL);
535 1.5.2.2 jdolecek fctrl |= IXGBE_FCTRL_BAM;
536 1.5.2.2 jdolecek if (adapter->hw.mac.type == ixgbe_mac_82598EB) {
537 1.5.2.2 jdolecek fctrl |= IXGBE_FCTRL_DPF;
538 1.5.2.2 jdolecek fctrl |= IXGBE_FCTRL_PMCF;
539 1.5.2.2 jdolecek }
540 1.5.2.2 jdolecek IXGBE_WRITE_REG(hw, IXGBE_FCTRL, fctrl);
541 1.1 dyoung
542 1.5.2.2 jdolecek /* Set for Jumbo Frames? */
543 1.5.2.2 jdolecek hlreg = IXGBE_READ_REG(hw, IXGBE_HLREG0);
544 1.5.2.2 jdolecek if (ifp->if_mtu > ETHERMTU)
545 1.5.2.2 jdolecek hlreg |= IXGBE_HLREG0_JUMBOEN;
546 1.5.2.2 jdolecek else
547 1.5.2.2 jdolecek hlreg &= ~IXGBE_HLREG0_JUMBOEN;
548 1.1 dyoung
549 1.5.2.2 jdolecek #ifdef DEV_NETMAP
550 1.5.2.2 jdolecek /* CRC stripping is conditional in Netmap */
551 1.5.2.2 jdolecek if ((adapter->feat_en & IXGBE_FEATURE_NETMAP) &&
552 1.5.2.2 jdolecek (ifp->if_capenable & IFCAP_NETMAP) &&
553 1.5.2.2 jdolecek !ix_crcstrip)
554 1.5.2.2 jdolecek hlreg &= ~IXGBE_HLREG0_RXCRCSTRP;
555 1.5.2.2 jdolecek else
556 1.5.2.2 jdolecek #endif /* DEV_NETMAP */
557 1.5.2.2 jdolecek hlreg |= IXGBE_HLREG0_RXCRCSTRP;
558 1.1 dyoung
559 1.5.2.2 jdolecek IXGBE_WRITE_REG(hw, IXGBE_HLREG0, hlreg);
560 1.1 dyoung
561 1.5.2.2 jdolecek bufsz = (adapter->rx_mbuf_sz + BSIZEPKT_ROUNDUP) >>
562 1.5.2.2 jdolecek IXGBE_SRRCTL_BSIZEPKT_SHIFT;
563 1.5.2.2 jdolecek
564 1.5.2.2 jdolecek for (i = 0; i < adapter->num_queues; i++, rxr++) {
565 1.5.2.2 jdolecek u64 rdba = rxr->rxdma.dma_paddr;
566 1.5.2.2 jdolecek u32 tqsmreg, reg;
567 1.5.2.2 jdolecek int regnum = i / 4; /* 1 register per 4 queues */
568 1.5.2.2 jdolecek int regshift = i % 4; /* 4 bits per 1 queue */
569 1.5.2.2 jdolecek j = rxr->me;
570 1.5.2.2 jdolecek
571 1.5.2.2 jdolecek /* Setup the Base and Length of the Rx Descriptor Ring */
572 1.5.2.2 jdolecek IXGBE_WRITE_REG(hw, IXGBE_RDBAL(j),
573 1.5.2.2 jdolecek (rdba & 0x00000000ffffffffULL));
574 1.5.2.2 jdolecek IXGBE_WRITE_REG(hw, IXGBE_RDBAH(j), (rdba >> 32));
575 1.5.2.2 jdolecek IXGBE_WRITE_REG(hw, IXGBE_RDLEN(j),
576 1.5.2.2 jdolecek adapter->num_rx_desc * sizeof(union ixgbe_adv_rx_desc));
577 1.5.2.2 jdolecek
578 1.5.2.2 jdolecek /* Set up the SRRCTL register */
579 1.5.2.2 jdolecek srrctl = IXGBE_READ_REG(hw, IXGBE_SRRCTL(j));
580 1.5.2.2 jdolecek srrctl &= ~IXGBE_SRRCTL_BSIZEHDR_MASK;
581 1.5.2.2 jdolecek srrctl &= ~IXGBE_SRRCTL_BSIZEPKT_MASK;
582 1.5.2.2 jdolecek srrctl |= bufsz;
583 1.5.2.2 jdolecek srrctl |= IXGBE_SRRCTL_DESCTYPE_ADV_ONEBUF;
584 1.5.2.2 jdolecek
585 1.5.2.2 jdolecek /* Set RQSMR (Receive Queue Statistic Mapping) register */
586 1.5.2.2 jdolecek reg = IXGBE_READ_REG(hw, IXGBE_RQSMR(regnum));
587 1.5.2.2 jdolecek reg &= ~(0x000000ff << (regshift * 8));
588 1.5.2.2 jdolecek reg |= i << (regshift * 8);
589 1.5.2.2 jdolecek IXGBE_WRITE_REG(hw, IXGBE_RQSMR(regnum), reg);
590 1.5.2.2 jdolecek
591 1.5.2.2 jdolecek /*
592 1.5.2.2 jdolecek * Set RQSMR (Receive Queue Statistic Mapping) register.
593 1.5.2.2 jdolecek * Register location for queue 0...7 are different between
594 1.5.2.2 jdolecek * 82598 and newer.
595 1.5.2.2 jdolecek */
596 1.5.2.2 jdolecek if (adapter->hw.mac.type == ixgbe_mac_82598EB)
597 1.5.2.2 jdolecek tqsmreg = IXGBE_TQSMR(regnum);
598 1.5.2.2 jdolecek else
599 1.5.2.2 jdolecek tqsmreg = IXGBE_TQSM(regnum);
600 1.5.2.2 jdolecek reg = IXGBE_READ_REG(hw, tqsmreg);
601 1.5.2.2 jdolecek reg &= ~(0x000000ff << (regshift * 8));
602 1.5.2.2 jdolecek reg |= i << (regshift * 8);
603 1.5.2.2 jdolecek IXGBE_WRITE_REG(hw, tqsmreg, reg);
604 1.5.2.2 jdolecek
605 1.5.2.2 jdolecek /*
606 1.5.2.2 jdolecek * Set DROP_EN iff we have no flow control and >1 queue.
607 1.5.2.2 jdolecek * Note that srrctl was cleared shortly before during reset,
608 1.5.2.2 jdolecek * so we do not need to clear the bit, but do it just in case
609 1.5.2.2 jdolecek * this code is moved elsewhere.
610 1.5.2.2 jdolecek */
611 1.5.2.2 jdolecek if (adapter->num_queues > 1 &&
612 1.5.2.2 jdolecek adapter->hw.fc.requested_mode == ixgbe_fc_none) {
613 1.5.2.2 jdolecek srrctl |= IXGBE_SRRCTL_DROP_EN;
614 1.5.2.2 jdolecek } else {
615 1.5.2.2 jdolecek srrctl &= ~IXGBE_SRRCTL_DROP_EN;
616 1.1 dyoung }
617 1.5.2.2 jdolecek
618 1.5.2.2 jdolecek IXGBE_WRITE_REG(hw, IXGBE_SRRCTL(j), srrctl);
619 1.5.2.2 jdolecek
620 1.5.2.2 jdolecek /* Setup the HW Rx Head and Tail Descriptor Pointers */
621 1.5.2.2 jdolecek IXGBE_WRITE_REG(hw, IXGBE_RDH(j), 0);
622 1.5.2.2 jdolecek IXGBE_WRITE_REG(hw, IXGBE_RDT(j), 0);
623 1.5.2.2 jdolecek
624 1.5.2.2 jdolecek /* Set the driver rx tail address */
625 1.5.2.2 jdolecek rxr->tail = IXGBE_RDT(rxr->me);
626 1.1 dyoung }
627 1.1 dyoung
628 1.5.2.2 jdolecek if (adapter->hw.mac.type != ixgbe_mac_82598EB) {
629 1.5.2.2 jdolecek u32 psrtype = IXGBE_PSRTYPE_TCPHDR
630 1.5.2.2 jdolecek | IXGBE_PSRTYPE_UDPHDR
631 1.5.2.2 jdolecek | IXGBE_PSRTYPE_IPV4HDR
632 1.5.2.2 jdolecek | IXGBE_PSRTYPE_IPV6HDR;
633 1.5.2.2 jdolecek IXGBE_WRITE_REG(hw, IXGBE_PSRTYPE(0), psrtype);
634 1.5.2.2 jdolecek }
635 1.5.2.2 jdolecek
636 1.5.2.2 jdolecek rxcsum = IXGBE_READ_REG(hw, IXGBE_RXCSUM);
637 1.5.2.2 jdolecek
638 1.5.2.2 jdolecek ixgbe_initialize_rss_mapping(adapter);
639 1.5.2.2 jdolecek
640 1.5.2.2 jdolecek if (adapter->num_queues > 1) {
641 1.5.2.2 jdolecek /* RSS and RX IPP Checksum are mutually exclusive */
642 1.5.2.2 jdolecek rxcsum |= IXGBE_RXCSUM_PCSD;
643 1.5.2.2 jdolecek }
644 1.5.2.2 jdolecek
645 1.5.2.2 jdolecek if (ifp->if_capenable & IFCAP_RXCSUM)
646 1.5.2.2 jdolecek rxcsum |= IXGBE_RXCSUM_PCSD;
647 1.5.2.2 jdolecek
648 1.5.2.2 jdolecek /* This is useful for calculating UDP/IP fragment checksums */
649 1.5.2.2 jdolecek if (!(rxcsum & IXGBE_RXCSUM_PCSD))
650 1.5.2.2 jdolecek rxcsum |= IXGBE_RXCSUM_IPPCSE;
651 1.5.2.2 jdolecek
652 1.5.2.2 jdolecek IXGBE_WRITE_REG(hw, IXGBE_RXCSUM, rxcsum);
653 1.5.2.2 jdolecek
654 1.5.2.2 jdolecek return;
655 1.5.2.2 jdolecek } /* ixgbe_initialize_receive_units */
656 1.1 dyoung
657 1.5.2.2 jdolecek /************************************************************************
658 1.5.2.2 jdolecek * ixgbe_initialize_transmit_units - Enable transmit units.
659 1.5.2.2 jdolecek ************************************************************************/
660 1.1 dyoung static void
661 1.5.2.2 jdolecek ixgbe_initialize_transmit_units(struct adapter *adapter)
662 1.1 dyoung {
663 1.5.2.2 jdolecek struct tx_ring *txr = adapter->tx_rings;
664 1.5.2.2 jdolecek struct ixgbe_hw *hw = &adapter->hw;
665 1.1 dyoung
666 1.5.2.2 jdolecek /* Setup the Base and Length of the Tx Descriptor Ring */
667 1.5.2.2 jdolecek for (int i = 0; i < adapter->num_queues; i++, txr++) {
668 1.5.2.2 jdolecek u64 tdba = txr->txdma.dma_paddr;
669 1.5.2.2 jdolecek u32 txctrl = 0;
670 1.5.2.2 jdolecek int j = txr->me;
671 1.5.2.2 jdolecek
672 1.5.2.2 jdolecek IXGBE_WRITE_REG(hw, IXGBE_TDBAL(j),
673 1.5.2.2 jdolecek (tdba & 0x00000000ffffffffULL));
674 1.5.2.2 jdolecek IXGBE_WRITE_REG(hw, IXGBE_TDBAH(j), (tdba >> 32));
675 1.5.2.2 jdolecek IXGBE_WRITE_REG(hw, IXGBE_TDLEN(j),
676 1.5.2.2 jdolecek adapter->num_tx_desc * sizeof(union ixgbe_adv_tx_desc));
677 1.1 dyoung
678 1.5.2.2 jdolecek /* Setup the HW Tx Head and Tail descriptor pointers */
679 1.5.2.2 jdolecek IXGBE_WRITE_REG(hw, IXGBE_TDH(j), 0);
680 1.5.2.2 jdolecek IXGBE_WRITE_REG(hw, IXGBE_TDT(j), 0);
681 1.1 dyoung
682 1.5.2.2 jdolecek /* Cache the tail address */
683 1.5.2.2 jdolecek txr->tail = IXGBE_TDT(j);
684 1.1 dyoung
685 1.5.2.2 jdolecek /* Disable Head Writeback */
686 1.5.2.2 jdolecek /*
687 1.5.2.2 jdolecek * Note: for X550 series devices, these registers are actually
688 1.5.2.2 jdolecek * prefixed with TPH_ isntead of DCA_, but the addresses and
689 1.5.2.2 jdolecek * fields remain the same.
690 1.5.2.2 jdolecek */
691 1.5.2.2 jdolecek switch (hw->mac.type) {
692 1.5.2.2 jdolecek case ixgbe_mac_82598EB:
693 1.5.2.2 jdolecek txctrl = IXGBE_READ_REG(hw, IXGBE_DCA_TXCTRL(j));
694 1.5.2.2 jdolecek break;
695 1.5.2.2 jdolecek default:
696 1.5.2.2 jdolecek txctrl = IXGBE_READ_REG(hw, IXGBE_DCA_TXCTRL_82599(j));
697 1.5.2.2 jdolecek break;
698 1.5.2.2 jdolecek }
699 1.5.2.2 jdolecek txctrl &= ~IXGBE_DCA_TXCTRL_DESC_WRO_EN;
700 1.5.2.2 jdolecek switch (hw->mac.type) {
701 1.5.2.2 jdolecek case ixgbe_mac_82598EB:
702 1.5.2.2 jdolecek IXGBE_WRITE_REG(hw, IXGBE_DCA_TXCTRL(j), txctrl);
703 1.5.2.2 jdolecek break;
704 1.5.2.2 jdolecek default:
705 1.5.2.2 jdolecek IXGBE_WRITE_REG(hw, IXGBE_DCA_TXCTRL_82599(j), txctrl);
706 1.5.2.2 jdolecek break;
707 1.5.2.2 jdolecek }
708 1.1 dyoung
709 1.5.2.2 jdolecek }
710 1.1 dyoung
711 1.5.2.2 jdolecek if (hw->mac.type != ixgbe_mac_82598EB) {
712 1.5.2.2 jdolecek u32 dmatxctl, rttdcs;
713 1.1 dyoung
714 1.5.2.2 jdolecek dmatxctl = IXGBE_READ_REG(hw, IXGBE_DMATXCTL);
715 1.5.2.2 jdolecek dmatxctl |= IXGBE_DMATXCTL_TE;
716 1.5.2.2 jdolecek IXGBE_WRITE_REG(hw, IXGBE_DMATXCTL, dmatxctl);
717 1.5.2.2 jdolecek /* Disable arbiter to set MTQC */
718 1.5.2.2 jdolecek rttdcs = IXGBE_READ_REG(hw, IXGBE_RTTDCS);
719 1.5.2.2 jdolecek rttdcs |= IXGBE_RTTDCS_ARBDIS;
720 1.5.2.2 jdolecek IXGBE_WRITE_REG(hw, IXGBE_RTTDCS, rttdcs);
721 1.5.2.2 jdolecek IXGBE_WRITE_REG(hw, IXGBE_MTQC,
722 1.5.2.2 jdolecek ixgbe_get_mtqc(adapter->iov_mode));
723 1.5.2.2 jdolecek rttdcs &= ~IXGBE_RTTDCS_ARBDIS;
724 1.5.2.2 jdolecek IXGBE_WRITE_REG(hw, IXGBE_RTTDCS, rttdcs);
725 1.5.2.2 jdolecek }
726 1.5.2.2 jdolecek
727 1.5.2.2 jdolecek return;
728 1.5.2.2 jdolecek } /* ixgbe_initialize_transmit_units */
729 1.1 dyoung
730 1.5.2.2 jdolecek /************************************************************************
731 1.5.2.2 jdolecek * ixgbe_attach - Device initialization routine
732 1.1 dyoung *
733 1.5.2.2 jdolecek * Called when the driver is being loaded.
734 1.5.2.2 jdolecek * Identifies the type of hardware, allocates all resources
735 1.5.2.2 jdolecek * and initializes the hardware.
736 1.1 dyoung *
737 1.5.2.2 jdolecek * return 0 on success, positive on failure
738 1.5.2.2 jdolecek ************************************************************************/
739 1.1 dyoung static void
740 1.1 dyoung ixgbe_attach(device_t parent, device_t dev, void *aux)
741 1.1 dyoung {
742 1.5.2.2 jdolecek struct adapter *adapter;
743 1.1 dyoung struct ixgbe_hw *hw;
744 1.5.2.2 jdolecek int error = -1;
745 1.1 dyoung u32 ctrl_ext;
746 1.5.2.2 jdolecek u16 high, low, nvmreg;
747 1.5.2.2 jdolecek pcireg_t id, subid;
748 1.1 dyoung ixgbe_vendor_info_t *ent;
749 1.5.2.2 jdolecek struct pci_attach_args *pa = aux;
750 1.5.2.2 jdolecek const char *str;
751 1.5.2.2 jdolecek char buf[256];
752 1.1 dyoung
753 1.1 dyoung INIT_DEBUGOUT("ixgbe_attach: begin");
754 1.1 dyoung
755 1.1 dyoung /* Allocate, clear, and link in our adapter structure */
756 1.1 dyoung adapter = device_private(dev);
757 1.5.2.2 jdolecek adapter->hw.back = adapter;
758 1.5.2.2 jdolecek adapter->dev = dev;
759 1.1 dyoung hw = &adapter->hw;
760 1.1 dyoung adapter->osdep.pc = pa->pa_pc;
761 1.1 dyoung adapter->osdep.tag = pa->pa_tag;
762 1.5.2.2 jdolecek if (pci_dma64_available(pa))
763 1.5.2.2 jdolecek adapter->osdep.dmat = pa->pa_dmat64;
764 1.5.2.2 jdolecek else
765 1.5.2.2 jdolecek adapter->osdep.dmat = pa->pa_dmat;
766 1.5.2.2 jdolecek adapter->osdep.attached = false;
767 1.1 dyoung
768 1.1 dyoung ent = ixgbe_lookup(pa);
769 1.1 dyoung
770 1.1 dyoung KASSERT(ent != NULL);
771 1.1 dyoung
772 1.1 dyoung aprint_normal(": %s, Version - %s\n",
773 1.1 dyoung ixgbe_strings[ent->index], ixgbe_driver_version);
774 1.1 dyoung
775 1.1 dyoung /* Core Lock Init*/
776 1.1 dyoung IXGBE_CORE_LOCK_INIT(adapter, device_xname(dev));
777 1.1 dyoung
778 1.1 dyoung /* Set up the timer callout */
779 1.5.2.2 jdolecek callout_init(&adapter->timer, IXGBE_CALLOUT_FLAGS);
780 1.1 dyoung
781 1.1 dyoung /* Determine hardware revision */
782 1.5.2.2 jdolecek id = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_ID_REG);
783 1.5.2.2 jdolecek subid = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_SUBSYS_ID_REG);
784 1.5.2.2 jdolecek
785 1.5.2.2 jdolecek hw->vendor_id = PCI_VENDOR(id);
786 1.5.2.2 jdolecek hw->device_id = PCI_PRODUCT(id);
787 1.5.2.2 jdolecek hw->revision_id =
788 1.5.2.2 jdolecek PCI_REVISION(pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_CLASS_REG));
789 1.5.2.2 jdolecek hw->subsystem_vendor_id = PCI_SUBSYS_VENDOR(subid);
790 1.5.2.2 jdolecek hw->subsystem_device_id = PCI_SUBSYS_ID(subid);
791 1.5.2.2 jdolecek
792 1.5.2.2 jdolecek /*
793 1.5.2.2 jdolecek * Make sure BUSMASTER is set
794 1.5.2.2 jdolecek */
795 1.5.2.2 jdolecek ixgbe_pci_enable_busmaster(pa->pa_pc, pa->pa_tag);
796 1.1 dyoung
797 1.1 dyoung /* Do base PCI setup - map BAR0 */
798 1.1 dyoung if (ixgbe_allocate_pci_resources(adapter, pa)) {
799 1.1 dyoung aprint_error_dev(dev, "Allocation of PCI resources failed\n");
800 1.1 dyoung error = ENXIO;
801 1.1 dyoung goto err_out;
802 1.1 dyoung }
803 1.1 dyoung
804 1.5.2.2 jdolecek /* let hardware know driver is loaded */
805 1.5.2.2 jdolecek ctrl_ext = IXGBE_READ_REG(hw, IXGBE_CTRL_EXT);
806 1.5.2.2 jdolecek ctrl_ext |= IXGBE_CTRL_EXT_DRV_LOAD;
807 1.5.2.2 jdolecek IXGBE_WRITE_REG(hw, IXGBE_CTRL_EXT, ctrl_ext);
808 1.1 dyoung
809 1.1 dyoung /*
810 1.5.2.2 jdolecek * Initialize the shared code
811 1.5.2.2 jdolecek */
812 1.5.2.2 jdolecek if (ixgbe_init_shared_code(hw)) {
813 1.5.2.2 jdolecek aprint_error_dev(dev, "Unable to initialize the shared code\n");
814 1.5.2.2 jdolecek error = ENXIO;
815 1.5.2.2 jdolecek goto err_out;
816 1.5.2.2 jdolecek }
817 1.5.2.2 jdolecek
818 1.5.2.2 jdolecek switch (hw->mac.type) {
819 1.5.2.2 jdolecek case ixgbe_mac_82598EB:
820 1.5.2.2 jdolecek str = "82598EB";
821 1.5.2.2 jdolecek break;
822 1.5.2.2 jdolecek case ixgbe_mac_82599EB:
823 1.5.2.2 jdolecek str = "82599EB";
824 1.5.2.2 jdolecek break;
825 1.5.2.2 jdolecek case ixgbe_mac_X540:
826 1.5.2.2 jdolecek str = "X540";
827 1.5.2.2 jdolecek break;
828 1.5.2.2 jdolecek case ixgbe_mac_X550:
829 1.5.2.2 jdolecek str = "X550";
830 1.5.2.2 jdolecek break;
831 1.5.2.2 jdolecek case ixgbe_mac_X550EM_x:
832 1.5.2.2 jdolecek str = "X550EM";
833 1.5.2.2 jdolecek break;
834 1.5.2.2 jdolecek case ixgbe_mac_X550EM_a:
835 1.5.2.2 jdolecek str = "X550EM A";
836 1.5.2.2 jdolecek break;
837 1.5.2.2 jdolecek default:
838 1.5.2.2 jdolecek str = "Unknown";
839 1.5.2.2 jdolecek break;
840 1.5.2.2 jdolecek }
841 1.5.2.2 jdolecek aprint_normal_dev(dev, "device %s\n", str);
842 1.5.2.2 jdolecek
843 1.5.2.2 jdolecek if (hw->mbx.ops.init_params)
844 1.5.2.2 jdolecek hw->mbx.ops.init_params(hw);
845 1.5.2.2 jdolecek
846 1.5.2.2 jdolecek hw->allow_unsupported_sfp = allow_unsupported_sfp;
847 1.5.2.2 jdolecek
848 1.5.2.2 jdolecek /* Pick up the 82599 settings */
849 1.5.2.2 jdolecek if (hw->mac.type != ixgbe_mac_82598EB) {
850 1.5.2.2 jdolecek hw->phy.smart_speed = ixgbe_smart_speed;
851 1.5.2.2 jdolecek adapter->num_segs = IXGBE_82599_SCATTER;
852 1.5.2.2 jdolecek } else
853 1.5.2.2 jdolecek adapter->num_segs = IXGBE_82598_SCATTER;
854 1.5.2.2 jdolecek
855 1.5.2.2 jdolecek hw->mac.ops.set_lan_id(hw);
856 1.5.2.2 jdolecek ixgbe_init_device_features(adapter);
857 1.5.2.2 jdolecek
858 1.5.2.2 jdolecek if (ixgbe_configure_interrupts(adapter)) {
859 1.5.2.2 jdolecek error = ENXIO;
860 1.5.2.2 jdolecek goto err_out;
861 1.5.2.2 jdolecek }
862 1.5.2.2 jdolecek
863 1.5.2.2 jdolecek /* Allocate multicast array memory. */
864 1.5.2.2 jdolecek adapter->mta = malloc(sizeof(*adapter->mta) *
865 1.5.2.2 jdolecek MAX_NUM_MULTICAST_ADDRESSES, M_DEVBUF, M_NOWAIT);
866 1.5.2.2 jdolecek if (adapter->mta == NULL) {
867 1.5.2.2 jdolecek aprint_error_dev(dev, "Cannot allocate multicast setup array\n");
868 1.5.2.2 jdolecek error = ENOMEM;
869 1.5.2.2 jdolecek goto err_out;
870 1.5.2.2 jdolecek }
871 1.5.2.2 jdolecek
872 1.5.2.2 jdolecek /* Enable WoL (if supported) */
873 1.5.2.2 jdolecek ixgbe_check_wol_support(adapter);
874 1.5.2.2 jdolecek
875 1.5.2.2 jdolecek /* Verify adapter fan is still functional (if applicable) */
876 1.5.2.2 jdolecek if (adapter->feat_en & IXGBE_FEATURE_FAN_FAIL) {
877 1.5.2.2 jdolecek u32 esdp = IXGBE_READ_REG(hw, IXGBE_ESDP);
878 1.5.2.2 jdolecek ixgbe_check_fan_failure(adapter, esdp, FALSE);
879 1.5.2.2 jdolecek }
880 1.5.2.2 jdolecek
881 1.5.2.2 jdolecek /* Ensure SW/FW semaphore is free */
882 1.5.2.2 jdolecek ixgbe_init_swfw_semaphore(hw);
883 1.5.2.2 jdolecek
884 1.5.2.2 jdolecek /* Enable EEE power saving */
885 1.5.2.2 jdolecek if (adapter->feat_en & IXGBE_FEATURE_EEE)
886 1.5.2.2 jdolecek hw->mac.ops.setup_eee(hw, TRUE);
887 1.5.2.2 jdolecek
888 1.5.2.2 jdolecek /* Set an initial default flow control value */
889 1.5.2.2 jdolecek hw->fc.requested_mode = ixgbe_flow_control;
890 1.5.2.2 jdolecek
891 1.5.2.2 jdolecek /* Sysctls for limiting the amount of work done in the taskqueues */
892 1.5.2.2 jdolecek ixgbe_set_sysctl_value(adapter, "rx_processing_limit",
893 1.5.2.2 jdolecek "max number of rx packets to process",
894 1.5.2.2 jdolecek &adapter->rx_process_limit, ixgbe_rx_process_limit);
895 1.5.2.2 jdolecek
896 1.5.2.2 jdolecek ixgbe_set_sysctl_value(adapter, "tx_processing_limit",
897 1.5.2.2 jdolecek "max number of tx packets to process",
898 1.5.2.2 jdolecek &adapter->tx_process_limit, ixgbe_tx_process_limit);
899 1.5.2.2 jdolecek
900 1.5.2.2 jdolecek /* Do descriptor calc and sanity checks */
901 1.5.2.2 jdolecek if (((ixgbe_txd * sizeof(union ixgbe_adv_tx_desc)) % DBA_ALIGN) != 0 ||
902 1.5.2.2 jdolecek ixgbe_txd < MIN_TXD || ixgbe_txd > MAX_TXD) {
903 1.5.2.2 jdolecek aprint_error_dev(dev, "TXD config issue, using default!\n");
904 1.5.2.2 jdolecek adapter->num_tx_desc = DEFAULT_TXD;
905 1.5.2.2 jdolecek } else
906 1.5.2.2 jdolecek adapter->num_tx_desc = ixgbe_txd;
907 1.5.2.2 jdolecek
908 1.5.2.2 jdolecek /*
909 1.5.2.2 jdolecek * With many RX rings it is easy to exceed the
910 1.5.2.2 jdolecek * system mbuf allocation. Tuning nmbclusters
911 1.5.2.2 jdolecek * can alleviate this.
912 1.5.2.2 jdolecek */
913 1.5.2.2 jdolecek if (nmbclusters > 0) {
914 1.5.2.2 jdolecek int s;
915 1.5.2.2 jdolecek s = (ixgbe_rxd * adapter->num_queues) * ixgbe_total_ports;
916 1.5.2.2 jdolecek if (s > nmbclusters) {
917 1.5.2.2 jdolecek aprint_error_dev(dev, "RX Descriptors exceed "
918 1.5.2.2 jdolecek "system mbuf max, using default instead!\n");
919 1.1 dyoung ixgbe_rxd = DEFAULT_RXD;
920 1.1 dyoung }
921 1.1 dyoung }
922 1.1 dyoung
923 1.1 dyoung if (((ixgbe_rxd * sizeof(union ixgbe_adv_rx_desc)) % DBA_ALIGN) != 0 ||
924 1.5.2.2 jdolecek ixgbe_rxd < MIN_RXD || ixgbe_rxd > MAX_RXD) {
925 1.1 dyoung aprint_error_dev(dev, "RXD config issue, using default!\n");
926 1.1 dyoung adapter->num_rx_desc = DEFAULT_RXD;
927 1.1 dyoung } else
928 1.1 dyoung adapter->num_rx_desc = ixgbe_rxd;
929 1.1 dyoung
930 1.1 dyoung /* Allocate our TX/RX Queues */
931 1.1 dyoung if (ixgbe_allocate_queues(adapter)) {
932 1.1 dyoung error = ENOMEM;
933 1.1 dyoung goto err_out;
934 1.1 dyoung }
935 1.1 dyoung
936 1.5.2.2 jdolecek hw->phy.reset_if_overtemp = TRUE;
937 1.5.2.2 jdolecek error = ixgbe_reset_hw(hw);
938 1.5.2.2 jdolecek hw->phy.reset_if_overtemp = FALSE;
939 1.1 dyoung if (error == IXGBE_ERR_SFP_NOT_PRESENT) {
940 1.1 dyoung /*
941 1.5.2.2 jdolecek * No optics in this port, set up
942 1.5.2.2 jdolecek * so the timer routine will probe
943 1.5.2.2 jdolecek * for later insertion.
944 1.5.2.2 jdolecek */
945 1.1 dyoung adapter->sfp_probe = TRUE;
946 1.5.2.2 jdolecek error = IXGBE_SUCCESS;
947 1.1 dyoung } else if (error == IXGBE_ERR_SFP_NOT_SUPPORTED) {
948 1.5.2.2 jdolecek aprint_error_dev(dev, "Unsupported SFP+ module detected!\n");
949 1.1 dyoung error = EIO;
950 1.1 dyoung goto err_late;
951 1.1 dyoung } else if (error) {
952 1.5.2.2 jdolecek aprint_error_dev(dev, "Hardware initialization failed\n");
953 1.1 dyoung error = EIO;
954 1.1 dyoung goto err_late;
955 1.1 dyoung }
956 1.1 dyoung
957 1.1 dyoung /* Make sure we have a good EEPROM before we read from it */
958 1.5.2.2 jdolecek if (ixgbe_validate_eeprom_checksum(&adapter->hw, NULL) < 0) {
959 1.5.2.2 jdolecek aprint_error_dev(dev, "The EEPROM Checksum Is Not Valid\n");
960 1.1 dyoung error = EIO;
961 1.1 dyoung goto err_late;
962 1.1 dyoung }
963 1.1 dyoung
964 1.5.2.2 jdolecek aprint_normal("%s:", device_xname(dev));
965 1.5.2.2 jdolecek /* NVM Image Version */
966 1.5.2.2 jdolecek switch (hw->mac.type) {
967 1.5.2.2 jdolecek case ixgbe_mac_X540:
968 1.5.2.2 jdolecek case ixgbe_mac_X550EM_a:
969 1.5.2.2 jdolecek hw->eeprom.ops.read(hw, IXGBE_NVM_IMAGE_VER, &nvmreg);
970 1.5.2.2 jdolecek if (nvmreg == 0xffff)
971 1.5.2.2 jdolecek break;
972 1.5.2.2 jdolecek high = (nvmreg >> 12) & 0x0f;
973 1.5.2.2 jdolecek low = (nvmreg >> 4) & 0xff;
974 1.5.2.2 jdolecek id = nvmreg & 0x0f;
975 1.5.2.2 jdolecek aprint_normal(" NVM Image Version %u.", high);
976 1.5.2.2 jdolecek if (hw->mac.type == ixgbe_mac_X540)
977 1.5.2.2 jdolecek str = "%x";
978 1.5.2.2 jdolecek else
979 1.5.2.2 jdolecek str = "%02x";
980 1.5.2.2 jdolecek aprint_normal(str, low);
981 1.5.2.2 jdolecek aprint_normal(" ID 0x%x,", id);
982 1.5.2.2 jdolecek break;
983 1.5.2.2 jdolecek case ixgbe_mac_X550EM_x:
984 1.5.2.2 jdolecek case ixgbe_mac_X550:
985 1.5.2.2 jdolecek hw->eeprom.ops.read(hw, IXGBE_NVM_IMAGE_VER, &nvmreg);
986 1.5.2.2 jdolecek if (nvmreg == 0xffff)
987 1.5.2.2 jdolecek break;
988 1.5.2.2 jdolecek high = (nvmreg >> 12) & 0x0f;
989 1.5.2.2 jdolecek low = nvmreg & 0xff;
990 1.5.2.2 jdolecek aprint_normal(" NVM Image Version %u.%02x,", high, low);
991 1.5.2.2 jdolecek break;
992 1.5.2.2 jdolecek default:
993 1.5.2.2 jdolecek break;
994 1.5.2.2 jdolecek }
995 1.1 dyoung
996 1.5.2.2 jdolecek /* PHY firmware revision */
997 1.5.2.2 jdolecek switch (hw->mac.type) {
998 1.5.2.2 jdolecek case ixgbe_mac_X540:
999 1.5.2.2 jdolecek case ixgbe_mac_X550:
1000 1.5.2.2 jdolecek hw->eeprom.ops.read(hw, IXGBE_PHYFW_REV, &nvmreg);
1001 1.5.2.2 jdolecek if (nvmreg == 0xffff)
1002 1.5.2.2 jdolecek break;
1003 1.5.2.2 jdolecek high = (nvmreg >> 12) & 0x0f;
1004 1.5.2.2 jdolecek low = (nvmreg >> 4) & 0xff;
1005 1.5.2.2 jdolecek id = nvmreg & 0x000f;
1006 1.5.2.2 jdolecek aprint_normal(" PHY FW Revision %u.", high);
1007 1.5.2.2 jdolecek if (hw->mac.type == ixgbe_mac_X540)
1008 1.5.2.2 jdolecek str = "%x";
1009 1.5.2.2 jdolecek else
1010 1.5.2.2 jdolecek str = "%02x";
1011 1.5.2.2 jdolecek aprint_normal(str, low);
1012 1.5.2.2 jdolecek aprint_normal(" ID 0x%x,", id);
1013 1.5.2.2 jdolecek break;
1014 1.5.2.2 jdolecek default:
1015 1.5.2.2 jdolecek break;
1016 1.5.2.2 jdolecek }
1017 1.1 dyoung
1018 1.5.2.2 jdolecek /* NVM Map version & OEM NVM Image version */
1019 1.5.2.2 jdolecek switch (hw->mac.type) {
1020 1.5.2.2 jdolecek case ixgbe_mac_X550:
1021 1.5.2.2 jdolecek case ixgbe_mac_X550EM_x:
1022 1.5.2.2 jdolecek case ixgbe_mac_X550EM_a:
1023 1.5.2.2 jdolecek hw->eeprom.ops.read(hw, IXGBE_NVM_MAP_VER, &nvmreg);
1024 1.5.2.2 jdolecek if (nvmreg != 0xffff) {
1025 1.5.2.2 jdolecek high = (nvmreg >> 12) & 0x0f;
1026 1.5.2.2 jdolecek low = nvmreg & 0x00ff;
1027 1.5.2.2 jdolecek aprint_normal(" NVM Map version %u.%02x,", high, low);
1028 1.5.2.2 jdolecek }
1029 1.5.2.2 jdolecek hw->eeprom.ops.read(hw, IXGBE_OEM_NVM_IMAGE_VER, &nvmreg);
1030 1.5.2.2 jdolecek if (nvmreg != 0xffff) {
1031 1.5.2.2 jdolecek high = (nvmreg >> 12) & 0x0f;
1032 1.5.2.2 jdolecek low = nvmreg & 0x00ff;
1033 1.5.2.2 jdolecek aprint_verbose(" OEM NVM Image version %u.%02x,", high,
1034 1.5.2.2 jdolecek low);
1035 1.5.2.2 jdolecek }
1036 1.5.2.2 jdolecek break;
1037 1.5.2.2 jdolecek default:
1038 1.5.2.2 jdolecek break;
1039 1.1 dyoung }
1040 1.1 dyoung
1041 1.5.2.2 jdolecek /* Print the ETrackID */
1042 1.5.2.2 jdolecek hw->eeprom.ops.read(hw, IXGBE_ETRACKID_H, &high);
1043 1.5.2.2 jdolecek hw->eeprom.ops.read(hw, IXGBE_ETRACKID_L, &low);
1044 1.5.2.2 jdolecek aprint_normal(" ETrackID %08x\n", ((uint32_t)high << 16) | low);
1045 1.5.2.2 jdolecek
1046 1.5.2.2 jdolecek /* Setup OS specific network interface */
1047 1.5.2.2 jdolecek if (ixgbe_setup_interface(dev, adapter) != 0)
1048 1.5.2.2 jdolecek goto err_late;
1049 1.1 dyoung
1050 1.5.2.2 jdolecek if (adapter->feat_en & IXGBE_FEATURE_MSIX)
1051 1.5.2.2 jdolecek error = ixgbe_allocate_msix(adapter, pa);
1052 1.1 dyoung else
1053 1.5.2.2 jdolecek error = ixgbe_allocate_legacy(adapter, pa);
1054 1.1 dyoung if (error)
1055 1.1 dyoung goto err_late;
1056 1.1 dyoung
1057 1.5.2.2 jdolecek error = ixgbe_start_hw(hw);
1058 1.5.2.2 jdolecek switch (error) {
1059 1.5.2.2 jdolecek case IXGBE_ERR_EEPROM_VERSION:
1060 1.5.2.2 jdolecek aprint_error_dev(dev, "This device is a pre-production adapter/"
1061 1.5.2.2 jdolecek "LOM. Please be aware there may be issues associated "
1062 1.5.2.2 jdolecek "with your hardware.\nIf you are experiencing problems "
1063 1.5.2.2 jdolecek "please contact your Intel or hardware representative "
1064 1.5.2.2 jdolecek "who provided you with this hardware.\n");
1065 1.5.2.2 jdolecek break;
1066 1.5.2.2 jdolecek case IXGBE_ERR_SFP_NOT_SUPPORTED:
1067 1.5.2.2 jdolecek aprint_error_dev(dev, "Unsupported SFP+ Module\n");
1068 1.5.2.2 jdolecek error = EIO;
1069 1.1 dyoung goto err_late;
1070 1.5.2.2 jdolecek case IXGBE_ERR_SFP_NOT_PRESENT:
1071 1.5.2.2 jdolecek aprint_error_dev(dev, "No SFP+ Module found\n");
1072 1.5.2.2 jdolecek /* falls thru */
1073 1.5.2.2 jdolecek default:
1074 1.5.2.2 jdolecek break;
1075 1.5.2.2 jdolecek }
1076 1.5.2.2 jdolecek
1077 1.5.2.2 jdolecek /*
1078 1.5.2.2 jdolecek * Print PHY ID only for copper PHY. On device which has SFP(+) cage
1079 1.5.2.2 jdolecek * and a module is inserted, phy.id is not MII PHY id but SFF 8024 ID.
1080 1.5.2.2 jdolecek */
1081 1.5.2.2 jdolecek if (hw->phy.media_type == ixgbe_media_type_copper) {
1082 1.5.2.2 jdolecek uint16_t id1, id2;
1083 1.5.2.2 jdolecek int oui, model, rev;
1084 1.5.2.2 jdolecek const char *descr;
1085 1.5.2.2 jdolecek
1086 1.5.2.2 jdolecek id1 = hw->phy.id >> 16;
1087 1.5.2.2 jdolecek id2 = hw->phy.id & 0xffff;
1088 1.5.2.2 jdolecek oui = MII_OUI(id1, id2);
1089 1.5.2.2 jdolecek model = MII_MODEL(id2);
1090 1.5.2.2 jdolecek rev = MII_REV(id2);
1091 1.5.2.2 jdolecek if ((descr = mii_get_descr(oui, model)) != NULL)
1092 1.5.2.2 jdolecek aprint_normal_dev(dev,
1093 1.5.2.2 jdolecek "PHY: %s (OUI 0x%06x, model 0x%04x), rev. %d\n",
1094 1.5.2.2 jdolecek descr, oui, model, rev);
1095 1.5.2.2 jdolecek else
1096 1.5.2.2 jdolecek aprint_normal_dev(dev,
1097 1.5.2.2 jdolecek "PHY OUI 0x%06x, model 0x%04x, rev. %d\n",
1098 1.5.2.2 jdolecek oui, model, rev);
1099 1.5.2.2 jdolecek }
1100 1.5.2.2 jdolecek
1101 1.5.2.2 jdolecek /* Enable the optics for 82599 SFP+ fiber */
1102 1.5.2.2 jdolecek ixgbe_enable_tx_laser(hw);
1103 1.1 dyoung
1104 1.5.2.2 jdolecek /* Enable power to the phy. */
1105 1.5.2.2 jdolecek ixgbe_set_phy_power(hw, TRUE);
1106 1.1 dyoung
1107 1.1 dyoung /* Initialize statistics */
1108 1.1 dyoung ixgbe_update_stats_counters(adapter);
1109 1.1 dyoung
1110 1.5.2.2 jdolecek /* Check PCIE slot type/speed/width */
1111 1.5.2.2 jdolecek ixgbe_get_slot_info(adapter);
1112 1.1 dyoung
1113 1.5.2.2 jdolecek /*
1114 1.5.2.2 jdolecek * Do time init and sysctl init here, but
1115 1.5.2.2 jdolecek * only on the first port of a bypass adapter.
1116 1.5.2.2 jdolecek */
1117 1.5.2.2 jdolecek ixgbe_bypass_init(adapter);
1118 1.5.2.2 jdolecek
1119 1.5.2.2 jdolecek /* Set an initial dmac value */
1120 1.5.2.2 jdolecek adapter->dmac = 0;
1121 1.5.2.2 jdolecek /* Set initial advertised speeds (if applicable) */
1122 1.5.2.2 jdolecek adapter->advertise = ixgbe_get_advertise(adapter);
1123 1.1 dyoung
1124 1.5.2.2 jdolecek if (adapter->feat_cap & IXGBE_FEATURE_SRIOV)
1125 1.5.2.2 jdolecek ixgbe_define_iov_schemas(dev, &error);
1126 1.5.2.2 jdolecek
1127 1.5.2.2 jdolecek /* Add sysctls */
1128 1.5.2.2 jdolecek ixgbe_add_device_sysctls(adapter);
1129 1.1 dyoung ixgbe_add_hw_stats(adapter);
1130 1.1 dyoung
1131 1.5.2.2 jdolecek /* For Netmap */
1132 1.5.2.2 jdolecek adapter->init_locked = ixgbe_init_locked;
1133 1.5.2.2 jdolecek adapter->stop_locked = ixgbe_stop;
1134 1.5.2.2 jdolecek
1135 1.5.2.2 jdolecek if (adapter->feat_en & IXGBE_FEATURE_NETMAP)
1136 1.5.2.2 jdolecek ixgbe_netmap_attach(adapter);
1137 1.5.2.2 jdolecek
1138 1.5.2.2 jdolecek snprintb(buf, sizeof(buf), IXGBE_FEATURE_FLAGS, adapter->feat_cap);
1139 1.5.2.2 jdolecek aprint_verbose_dev(dev, "feature cap %s\n", buf);
1140 1.5.2.2 jdolecek snprintb(buf, sizeof(buf), IXGBE_FEATURE_FLAGS, adapter->feat_en);
1141 1.5.2.2 jdolecek aprint_verbose_dev(dev, "feature ena %s\n", buf);
1142 1.5.2.2 jdolecek
1143 1.5.2.2 jdolecek if (pmf_device_register(dev, ixgbe_suspend, ixgbe_resume))
1144 1.5.2.2 jdolecek pmf_class_network_register(dev, adapter->ifp);
1145 1.5.2.2 jdolecek else
1146 1.5.2.2 jdolecek aprint_error_dev(dev, "couldn't establish power handler\n");
1147 1.5.2.2 jdolecek
1148 1.1 dyoung INIT_DEBUGOUT("ixgbe_attach: end");
1149 1.5.2.2 jdolecek adapter->osdep.attached = true;
1150 1.5.2.2 jdolecek
1151 1.1 dyoung return;
1152 1.5.2.2 jdolecek
1153 1.1 dyoung err_late:
1154 1.1 dyoung ixgbe_free_transmit_structures(adapter);
1155 1.1 dyoung ixgbe_free_receive_structures(adapter);
1156 1.5.2.2 jdolecek free(adapter->queues, M_DEVBUF);
1157 1.1 dyoung err_out:
1158 1.1 dyoung if (adapter->ifp != NULL)
1159 1.1 dyoung if_free(adapter->ifp);
1160 1.5.2.2 jdolecek ctrl_ext = IXGBE_READ_REG(&adapter->hw, IXGBE_CTRL_EXT);
1161 1.5.2.2 jdolecek ctrl_ext &= ~IXGBE_CTRL_EXT_DRV_LOAD;
1162 1.5.2.2 jdolecek IXGBE_WRITE_REG(&adapter->hw, IXGBE_CTRL_EXT, ctrl_ext);
1163 1.1 dyoung ixgbe_free_pci_resources(adapter);
1164 1.1 dyoung if (adapter->mta != NULL)
1165 1.1 dyoung free(adapter->mta, M_DEVBUF);
1166 1.5.2.2 jdolecek IXGBE_CORE_LOCK_DESTROY(adapter);
1167 1.1 dyoung
1168 1.5.2.2 jdolecek return;
1169 1.5.2.2 jdolecek } /* ixgbe_attach */
1170 1.1 dyoung
1171 1.5.2.2 jdolecek /************************************************************************
1172 1.5.2.2 jdolecek * ixgbe_check_wol_support
1173 1.1 dyoung *
1174 1.5.2.2 jdolecek * Checks whether the adapter's ports are capable of
1175 1.5.2.2 jdolecek * Wake On LAN by reading the adapter's NVM.
1176 1.1 dyoung *
1177 1.5.2.2 jdolecek * Sets each port's hw->wol_enabled value depending
1178 1.5.2.2 jdolecek * on the value read here.
1179 1.5.2.2 jdolecek ************************************************************************/
1180 1.5.2.2 jdolecek static void
1181 1.5.2.2 jdolecek ixgbe_check_wol_support(struct adapter *adapter)
1182 1.5.2.2 jdolecek {
1183 1.5.2.2 jdolecek struct ixgbe_hw *hw = &adapter->hw;
1184 1.5.2.2 jdolecek u16 dev_caps = 0;
1185 1.5.2.2 jdolecek
1186 1.5.2.2 jdolecek /* Find out WoL support for port */
1187 1.5.2.2 jdolecek adapter->wol_support = hw->wol_enabled = 0;
1188 1.5.2.2 jdolecek ixgbe_get_device_caps(hw, &dev_caps);
1189 1.5.2.2 jdolecek if ((dev_caps & IXGBE_DEVICE_CAPS_WOL_PORT0_1) ||
1190 1.5.2.2 jdolecek ((dev_caps & IXGBE_DEVICE_CAPS_WOL_PORT0) &&
1191 1.5.2.2 jdolecek hw->bus.func == 0))
1192 1.5.2.2 jdolecek adapter->wol_support = hw->wol_enabled = 1;
1193 1.1 dyoung
1194 1.5.2.2 jdolecek /* Save initial wake up filter configuration */
1195 1.5.2.2 jdolecek adapter->wufc = IXGBE_READ_REG(hw, IXGBE_WUFC);
1196 1.5.2.2 jdolecek
1197 1.5.2.2 jdolecek return;
1198 1.5.2.2 jdolecek } /* ixgbe_check_wol_support */
1199 1.5.2.2 jdolecek
1200 1.5.2.2 jdolecek /************************************************************************
1201 1.5.2.2 jdolecek * ixgbe_setup_interface
1202 1.5.2.2 jdolecek *
1203 1.5.2.2 jdolecek * Setup networking device structure and register an interface.
1204 1.5.2.2 jdolecek ************************************************************************/
1205 1.1 dyoung static int
1206 1.5.2.2 jdolecek ixgbe_setup_interface(device_t dev, struct adapter *adapter)
1207 1.1 dyoung {
1208 1.5.2.2 jdolecek struct ethercom *ec = &adapter->osdep.ec;
1209 1.5.2.2 jdolecek struct ifnet *ifp;
1210 1.5.2.2 jdolecek int rv;
1211 1.1 dyoung
1212 1.5.2.2 jdolecek INIT_DEBUGOUT("ixgbe_setup_interface: begin");
1213 1.1 dyoung
1214 1.5.2.2 jdolecek ifp = adapter->ifp = &ec->ec_if;
1215 1.5.2.2 jdolecek strlcpy(ifp->if_xname, device_xname(dev), IFNAMSIZ);
1216 1.5.2.2 jdolecek ifp->if_baudrate = IF_Gbps(10);
1217 1.5.2.2 jdolecek ifp->if_init = ixgbe_init;
1218 1.5.2.2 jdolecek ifp->if_stop = ixgbe_ifstop;
1219 1.5.2.2 jdolecek ifp->if_softc = adapter;
1220 1.5.2.2 jdolecek ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
1221 1.5.2.2 jdolecek #ifdef IXGBE_MPSAFE
1222 1.5.2.2 jdolecek ifp->if_extflags = IFEF_MPSAFE;
1223 1.5.2.2 jdolecek #endif
1224 1.5.2.2 jdolecek ifp->if_ioctl = ixgbe_ioctl;
1225 1.5.2.2 jdolecek #if __FreeBSD_version >= 1100045
1226 1.5.2.2 jdolecek /* TSO parameters */
1227 1.5.2.2 jdolecek ifp->if_hw_tsomax = 65518;
1228 1.5.2.2 jdolecek ifp->if_hw_tsomaxsegcount = IXGBE_82599_SCATTER;
1229 1.5.2.2 jdolecek ifp->if_hw_tsomaxsegsize = 2048;
1230 1.5.2.2 jdolecek #endif
1231 1.5.2.2 jdolecek if (adapter->feat_en & IXGBE_FEATURE_LEGACY_TX) {
1232 1.5.2.2 jdolecek #if 0
1233 1.5.2.2 jdolecek ixgbe_start_locked = ixgbe_legacy_start_locked;
1234 1.5.2.2 jdolecek #endif
1235 1.5.2.2 jdolecek } else {
1236 1.5.2.2 jdolecek ifp->if_transmit = ixgbe_mq_start;
1237 1.5.2.2 jdolecek #if 0
1238 1.5.2.2 jdolecek ixgbe_start_locked = ixgbe_mq_start_locked;
1239 1.5.2.2 jdolecek #endif
1240 1.1 dyoung }
1241 1.5.2.2 jdolecek ifp->if_start = ixgbe_legacy_start;
1242 1.5.2.2 jdolecek IFQ_SET_MAXLEN(&ifp->if_snd, adapter->num_tx_desc - 2);
1243 1.5.2.2 jdolecek IFQ_SET_READY(&ifp->if_snd);
1244 1.1 dyoung
1245 1.5.2.2 jdolecek rv = if_initialize(ifp);
1246 1.5.2.2 jdolecek if (rv != 0) {
1247 1.5.2.2 jdolecek aprint_error_dev(dev, "if_initialize failed(%d)\n", rv);
1248 1.5.2.2 jdolecek return rv;
1249 1.1 dyoung }
1250 1.5.2.2 jdolecek adapter->ipq = if_percpuq_create(&adapter->osdep.ec.ec_if);
1251 1.5.2.2 jdolecek ether_ifattach(ifp, adapter->hw.mac.addr);
1252 1.5.2.2 jdolecek /*
1253 1.5.2.2 jdolecek * We use per TX queue softint, so if_deferred_start_init() isn't
1254 1.5.2.2 jdolecek * used.
1255 1.5.2.2 jdolecek */
1256 1.5.2.2 jdolecek if_register(ifp);
1257 1.5.2.2 jdolecek ether_set_ifflags_cb(ec, ixgbe_ifflags_cb);
1258 1.1 dyoung
1259 1.5.2.2 jdolecek adapter->max_frame_size = ifp->if_mtu + ETHER_HDR_LEN + ETHER_CRC_LEN;
1260 1.1 dyoung
1261 1.5.2.2 jdolecek /*
1262 1.5.2.2 jdolecek * Tell the upper layer(s) we support long frames.
1263 1.5.2.2 jdolecek */
1264 1.5.2.2 jdolecek ifp->if_hdrlen = sizeof(struct ether_vlan_header);
1265 1.1 dyoung
1266 1.5.2.2 jdolecek /* Set capability flags */
1267 1.5.2.2 jdolecek ifp->if_capabilities |= IFCAP_RXCSUM
1268 1.5.2.2 jdolecek | IFCAP_TXCSUM
1269 1.5.2.2 jdolecek | IFCAP_TSOv4
1270 1.5.2.2 jdolecek | IFCAP_TSOv6
1271 1.5.2.2 jdolecek | IFCAP_LRO;
1272 1.5.2.2 jdolecek ifp->if_capenable = 0;
1273 1.1 dyoung
1274 1.5.2.2 jdolecek ec->ec_capabilities |= ETHERCAP_VLAN_HWTAGGING
1275 1.5.2.2 jdolecek | ETHERCAP_VLAN_HWCSUM
1276 1.5.2.2 jdolecek | ETHERCAP_JUMBO_MTU
1277 1.5.2.2 jdolecek | ETHERCAP_VLAN_MTU;
1278 1.1 dyoung
1279 1.5.2.2 jdolecek /* Enable the above capabilities by default */
1280 1.5.2.2 jdolecek ec->ec_capenable = ec->ec_capabilities;
1281 1.1 dyoung
1282 1.5.2.2 jdolecek /*
1283 1.5.2.2 jdolecek * Don't turn this on by default, if vlans are
1284 1.5.2.2 jdolecek * created on another pseudo device (eg. lagg)
1285 1.5.2.2 jdolecek * then vlan events are not passed thru, breaking
1286 1.5.2.2 jdolecek * operation, but with HW FILTER off it works. If
1287 1.5.2.2 jdolecek * using vlans directly on the ixgbe driver you can
1288 1.5.2.2 jdolecek * enable this and get full hardware tag filtering.
1289 1.5.2.2 jdolecek */
1290 1.5.2.2 jdolecek ec->ec_capabilities |= ETHERCAP_VLAN_HWFILTER;
1291 1.1 dyoung
1292 1.5.2.2 jdolecek /*
1293 1.5.2.2 jdolecek * Specify the media types supported by this adapter and register
1294 1.5.2.2 jdolecek * callbacks to update media and link information
1295 1.5.2.2 jdolecek */
1296 1.5.2.2 jdolecek ifmedia_init(&adapter->media, IFM_IMASK, ixgbe_media_change,
1297 1.5.2.2 jdolecek ixgbe_media_status);
1298 1.1 dyoung
1299 1.5.2.2 jdolecek adapter->phy_layer = ixgbe_get_supported_physical_layer(&adapter->hw);
1300 1.5.2.2 jdolecek ixgbe_add_media_types(adapter);
1301 1.1 dyoung
1302 1.5.2.2 jdolecek /* Set autoselect media by default */
1303 1.5.2.2 jdolecek ifmedia_set(&adapter->media, IFM_ETHER | IFM_AUTO);
1304 1.1 dyoung
1305 1.1 dyoung return (0);
1306 1.5.2.2 jdolecek } /* ixgbe_setup_interface */
1307 1.1 dyoung
1308 1.5.2.2 jdolecek /************************************************************************
1309 1.5.2.2 jdolecek * ixgbe_add_media_types
1310 1.5.2.2 jdolecek ************************************************************************/
1311 1.1 dyoung static void
1312 1.5.2.2 jdolecek ixgbe_add_media_types(struct adapter *adapter)
1313 1.1 dyoung {
1314 1.5.2.2 jdolecek struct ixgbe_hw *hw = &adapter->hw;
1315 1.5.2.2 jdolecek device_t dev = adapter->dev;
1316 1.5.2.2 jdolecek u64 layer;
1317 1.1 dyoung
1318 1.5.2.2 jdolecek layer = adapter->phy_layer;
1319 1.1 dyoung
1320 1.5.2.2 jdolecek #define ADD(mm, dd) \
1321 1.5.2.2 jdolecek ifmedia_add(&adapter->media, IFM_ETHER | (mm), (dd), NULL);
1322 1.1 dyoung
1323 1.5.2.2 jdolecek /* Media types with matching NetBSD media defines */
1324 1.5.2.2 jdolecek if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_T) {
1325 1.5.2.2 jdolecek ADD(IFM_10G_T | IFM_FDX, 0);
1326 1.5.2.2 jdolecek }
1327 1.5.2.2 jdolecek if (layer & IXGBE_PHYSICAL_LAYER_1000BASE_T) {
1328 1.5.2.2 jdolecek ADD(IFM_1000_T | IFM_FDX, 0);
1329 1.5.2.2 jdolecek }
1330 1.5.2.2 jdolecek if (layer & IXGBE_PHYSICAL_LAYER_100BASE_TX) {
1331 1.5.2.2 jdolecek ADD(IFM_100_TX | IFM_FDX, 0);
1332 1.5.2.2 jdolecek }
1333 1.5.2.2 jdolecek if (layer & IXGBE_PHYSICAL_LAYER_10BASE_T) {
1334 1.5.2.2 jdolecek ADD(IFM_10_T | IFM_FDX, 0);
1335 1.5.2.2 jdolecek }
1336 1.1 dyoung
1337 1.5.2.2 jdolecek if (layer & IXGBE_PHYSICAL_LAYER_SFP_PLUS_CU ||
1338 1.5.2.2 jdolecek layer & IXGBE_PHYSICAL_LAYER_SFP_ACTIVE_DA) {
1339 1.5.2.2 jdolecek ADD(IFM_10G_TWINAX | IFM_FDX, 0);
1340 1.5.2.2 jdolecek }
1341 1.1 dyoung
1342 1.5.2.2 jdolecek if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_LR) {
1343 1.5.2.2 jdolecek ADD(IFM_10G_LR | IFM_FDX, 0);
1344 1.5.2.2 jdolecek if (hw->phy.multispeed_fiber) {
1345 1.5.2.2 jdolecek ADD(IFM_1000_LX | IFM_FDX, 0);
1346 1.1 dyoung }
1347 1.5.2.2 jdolecek }
1348 1.5.2.2 jdolecek if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_SR) {
1349 1.5.2.2 jdolecek ADD(IFM_10G_SR | IFM_FDX, 0);
1350 1.5.2.2 jdolecek if (hw->phy.multispeed_fiber) {
1351 1.5.2.2 jdolecek ADD(IFM_1000_SX | IFM_FDX, 0);
1352 1.1 dyoung }
1353 1.5.2.2 jdolecek } else if (layer & IXGBE_PHYSICAL_LAYER_1000BASE_SX) {
1354 1.5.2.2 jdolecek ADD(IFM_1000_SX | IFM_FDX, 0);
1355 1.5.2.2 jdolecek }
1356 1.5.2.2 jdolecek if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_CX4) {
1357 1.5.2.2 jdolecek ADD(IFM_10G_CX4 | IFM_FDX, 0);
1358 1.5.2.2 jdolecek }
1359 1.1 dyoung
1360 1.5.2.2 jdolecek #ifdef IFM_ETH_XTYPE
1361 1.5.2.2 jdolecek if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_KR) {
1362 1.5.2.2 jdolecek ADD(IFM_10G_KR | IFM_FDX, 0);
1363 1.5.2.2 jdolecek }
1364 1.5.2.2 jdolecek if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_KX4) {
1365 1.5.2.2 jdolecek ADD(AIFM_10G_KX4 | IFM_FDX, 0);
1366 1.5.2.2 jdolecek }
1367 1.5.2.2 jdolecek #else
1368 1.5.2.2 jdolecek if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_KR) {
1369 1.5.2.2 jdolecek device_printf(dev, "Media supported: 10GbaseKR\n");
1370 1.5.2.2 jdolecek device_printf(dev, "10GbaseKR mapped to 10GbaseSR\n");
1371 1.5.2.2 jdolecek ADD(IFM_10G_SR | IFM_FDX, 0);
1372 1.5.2.2 jdolecek }
1373 1.5.2.2 jdolecek if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_KX4) {
1374 1.5.2.2 jdolecek device_printf(dev, "Media supported: 10GbaseKX4\n");
1375 1.5.2.2 jdolecek device_printf(dev, "10GbaseKX4 mapped to 10GbaseCX4\n");
1376 1.5.2.2 jdolecek ADD(IFM_10G_CX4 | IFM_FDX, 0);
1377 1.5.2.2 jdolecek }
1378 1.5.2.2 jdolecek #endif
1379 1.5.2.2 jdolecek if (layer & IXGBE_PHYSICAL_LAYER_1000BASE_KX) {
1380 1.5.2.2 jdolecek ADD(IFM_1000_KX | IFM_FDX, 0);
1381 1.5.2.2 jdolecek }
1382 1.5.2.2 jdolecek if (layer & IXGBE_PHYSICAL_LAYER_2500BASE_KX) {
1383 1.5.2.2 jdolecek ADD(IFM_2500_KX | IFM_FDX, 0);
1384 1.5.2.2 jdolecek }
1385 1.5.2.2 jdolecek if (layer & IXGBE_PHYSICAL_LAYER_2500BASE_T) {
1386 1.5.2.2 jdolecek ADD(IFM_2500_T | IFM_FDX, 0);
1387 1.5.2.2 jdolecek }
1388 1.5.2.2 jdolecek if (layer & IXGBE_PHYSICAL_LAYER_5GBASE_T) {
1389 1.5.2.2 jdolecek ADD(IFM_5000_T | IFM_FDX, 0);
1390 1.5.2.2 jdolecek }
1391 1.5.2.2 jdolecek if (layer & IXGBE_PHYSICAL_LAYER_1000BASE_BX)
1392 1.5.2.2 jdolecek device_printf(dev, "Media supported: 1000baseBX\n");
1393 1.5.2.2 jdolecek /* XXX no ifmedia_set? */
1394 1.5.2.2 jdolecek
1395 1.5.2.2 jdolecek ADD(IFM_AUTO, 0);
1396 1.1 dyoung
1397 1.5.2.2 jdolecek #undef ADD
1398 1.5.2.2 jdolecek } /* ixgbe_add_media_types */
1399 1.1 dyoung
1400 1.5.2.2 jdolecek /************************************************************************
1401 1.5.2.2 jdolecek * ixgbe_is_sfp
1402 1.5.2.2 jdolecek ************************************************************************/
1403 1.5.2.2 jdolecek static inline bool
1404 1.5.2.2 jdolecek ixgbe_is_sfp(struct ixgbe_hw *hw)
1405 1.5.2.2 jdolecek {
1406 1.5.2.2 jdolecek switch (hw->mac.type) {
1407 1.5.2.2 jdolecek case ixgbe_mac_82598EB:
1408 1.5.2.2 jdolecek if (hw->phy.type == ixgbe_phy_nl)
1409 1.5.2.2 jdolecek return TRUE;
1410 1.5.2.2 jdolecek return FALSE;
1411 1.5.2.2 jdolecek case ixgbe_mac_82599EB:
1412 1.5.2.2 jdolecek switch (hw->mac.ops.get_media_type(hw)) {
1413 1.5.2.2 jdolecek case ixgbe_media_type_fiber:
1414 1.5.2.2 jdolecek case ixgbe_media_type_fiber_qsfp:
1415 1.5.2.2 jdolecek return TRUE;
1416 1.5.2.2 jdolecek default:
1417 1.5.2.2 jdolecek return FALSE;
1418 1.5.2.2 jdolecek }
1419 1.5.2.2 jdolecek case ixgbe_mac_X550EM_x:
1420 1.5.2.2 jdolecek case ixgbe_mac_X550EM_a:
1421 1.5.2.2 jdolecek if (hw->mac.ops.get_media_type(hw) == ixgbe_media_type_fiber)
1422 1.5.2.2 jdolecek return TRUE;
1423 1.5.2.2 jdolecek return FALSE;
1424 1.5.2.2 jdolecek default:
1425 1.5.2.2 jdolecek return FALSE;
1426 1.1 dyoung }
1427 1.5.2.2 jdolecek } /* ixgbe_is_sfp */
1428 1.1 dyoung
1429 1.5.2.2 jdolecek /************************************************************************
1430 1.5.2.2 jdolecek * ixgbe_config_link
1431 1.5.2.2 jdolecek ************************************************************************/
1432 1.1 dyoung static void
1433 1.5.2.2 jdolecek ixgbe_config_link(struct adapter *adapter)
1434 1.1 dyoung {
1435 1.5.2.2 jdolecek struct ixgbe_hw *hw = &adapter->hw;
1436 1.5.2.2 jdolecek u32 autoneg, err = 0;
1437 1.5.2.2 jdolecek bool sfp, negotiate = false;
1438 1.1 dyoung
1439 1.5.2.2 jdolecek sfp = ixgbe_is_sfp(hw);
1440 1.5.2.2 jdolecek
1441 1.5.2.2 jdolecek if (sfp) {
1442 1.5.2.2 jdolecek if (hw->phy.multispeed_fiber) {
1443 1.5.2.2 jdolecek hw->mac.ops.setup_sfp(hw);
1444 1.5.2.2 jdolecek ixgbe_enable_tx_laser(hw);
1445 1.5.2.2 jdolecek kpreempt_disable();
1446 1.5.2.2 jdolecek softint_schedule(adapter->msf_si);
1447 1.5.2.2 jdolecek kpreempt_enable();
1448 1.5.2.2 jdolecek } else {
1449 1.5.2.2 jdolecek kpreempt_disable();
1450 1.5.2.2 jdolecek softint_schedule(adapter->mod_si);
1451 1.5.2.2 jdolecek kpreempt_enable();
1452 1.5.2.2 jdolecek }
1453 1.5.2.2 jdolecek } else {
1454 1.5.2.2 jdolecek if (hw->mac.ops.check_link)
1455 1.5.2.2 jdolecek err = ixgbe_check_link(hw, &adapter->link_speed,
1456 1.5.2.2 jdolecek &adapter->link_up, FALSE);
1457 1.5.2.2 jdolecek if (err)
1458 1.5.2.2 jdolecek goto out;
1459 1.5.2.2 jdolecek autoneg = hw->phy.autoneg_advertised;
1460 1.5.2.2 jdolecek if ((!autoneg) && (hw->mac.ops.get_link_capabilities))
1461 1.5.2.2 jdolecek err = hw->mac.ops.get_link_capabilities(hw, &autoneg,
1462 1.5.2.2 jdolecek &negotiate);
1463 1.5.2.2 jdolecek if (err)
1464 1.5.2.2 jdolecek goto out;
1465 1.5.2.2 jdolecek if (hw->mac.ops.setup_link)
1466 1.5.2.2 jdolecek err = hw->mac.ops.setup_link(hw, autoneg,
1467 1.5.2.2 jdolecek adapter->link_up);
1468 1.1 dyoung }
1469 1.5.2.2 jdolecek out:
1470 1.5.2.2 jdolecek
1471 1.1 dyoung return;
1472 1.5.2.2 jdolecek } /* ixgbe_config_link */
1473 1.1 dyoung
1474 1.5.2.2 jdolecek /************************************************************************
1475 1.5.2.2 jdolecek * ixgbe_update_stats_counters - Update board statistics counters.
1476 1.5.2.2 jdolecek ************************************************************************/
1477 1.5.2.2 jdolecek static void
1478 1.5.2.2 jdolecek ixgbe_update_stats_counters(struct adapter *adapter)
1479 1.1 dyoung {
1480 1.5.2.2 jdolecek struct ifnet *ifp = adapter->ifp;
1481 1.5.2.2 jdolecek struct ixgbe_hw *hw = &adapter->hw;
1482 1.5.2.2 jdolecek struct ixgbe_hw_stats *stats = &adapter->stats.pf;
1483 1.5.2.2 jdolecek u32 missed_rx = 0, bprc, lxon, lxoff, total;
1484 1.5.2.2 jdolecek u64 total_missed_rx = 0;
1485 1.5.2.2 jdolecek uint64_t crcerrs, rlec;
1486 1.5.2.2 jdolecek
1487 1.5.2.2 jdolecek crcerrs = IXGBE_READ_REG(hw, IXGBE_CRCERRS);
1488 1.5.2.2 jdolecek stats->crcerrs.ev_count += crcerrs;
1489 1.5.2.2 jdolecek stats->illerrc.ev_count += IXGBE_READ_REG(hw, IXGBE_ILLERRC);
1490 1.5.2.2 jdolecek stats->errbc.ev_count += IXGBE_READ_REG(hw, IXGBE_ERRBC);
1491 1.5.2.2 jdolecek stats->mspdc.ev_count += IXGBE_READ_REG(hw, IXGBE_MSPDC);
1492 1.5.2.2 jdolecek if (hw->mac.type == ixgbe_mac_X550)
1493 1.5.2.2 jdolecek stats->mbsdc.ev_count += IXGBE_READ_REG(hw, IXGBE_MBSDC);
1494 1.1 dyoung
1495 1.5.2.2 jdolecek for (int i = 0; i < __arraycount(stats->qprc); i++) {
1496 1.5.2.2 jdolecek int j = i % adapter->num_queues;
1497 1.5.2.2 jdolecek stats->qprc[j].ev_count += IXGBE_READ_REG(hw, IXGBE_QPRC(i));
1498 1.5.2.2 jdolecek stats->qptc[j].ev_count += IXGBE_READ_REG(hw, IXGBE_QPTC(i));
1499 1.5.2.2 jdolecek stats->qprdc[j].ev_count += IXGBE_READ_REG(hw, IXGBE_QPRDC(i));
1500 1.5.2.2 jdolecek }
1501 1.5.2.2 jdolecek for (int i = 0; i < __arraycount(stats->mpc); i++) {
1502 1.5.2.2 jdolecek uint32_t mp;
1503 1.5.2.2 jdolecek int j = i % adapter->num_queues;
1504 1.1 dyoung
1505 1.5.2.2 jdolecek mp = IXGBE_READ_REG(hw, IXGBE_MPC(i));
1506 1.5.2.2 jdolecek /* global total per queue */
1507 1.5.2.2 jdolecek stats->mpc[j].ev_count += mp;
1508 1.5.2.2 jdolecek /* running comprehensive total for stats display */
1509 1.5.2.2 jdolecek total_missed_rx += mp;
1510 1.5.2.2 jdolecek
1511 1.5.2.2 jdolecek if (hw->mac.type == ixgbe_mac_82598EB)
1512 1.5.2.2 jdolecek stats->rnbc[j].ev_count
1513 1.5.2.2 jdolecek += IXGBE_READ_REG(hw, IXGBE_RNBC(i));
1514 1.5.2.2 jdolecek
1515 1.5.2.2 jdolecek }
1516 1.5.2.2 jdolecek stats->mpctotal.ev_count += total_missed_rx;
1517 1.5.2.2 jdolecek
1518 1.5.2.2 jdolecek /* Document says M[LR]FC are valid when link is up and 10Gbps */
1519 1.5.2.2 jdolecek if ((adapter->link_active == TRUE)
1520 1.5.2.2 jdolecek && (adapter->link_speed == IXGBE_LINK_SPEED_10GB_FULL)) {
1521 1.5.2.2 jdolecek stats->mlfc.ev_count += IXGBE_READ_REG(hw, IXGBE_MLFC);
1522 1.5.2.2 jdolecek stats->mrfc.ev_count += IXGBE_READ_REG(hw, IXGBE_MRFC);
1523 1.1 dyoung }
1524 1.5.2.2 jdolecek rlec = IXGBE_READ_REG(hw, IXGBE_RLEC);
1525 1.5.2.2 jdolecek stats->rlec.ev_count += rlec;
1526 1.1 dyoung
1527 1.5.2.2 jdolecek /* Hardware workaround, gprc counts missed packets */
1528 1.5.2.2 jdolecek stats->gprc.ev_count += IXGBE_READ_REG(hw, IXGBE_GPRC) - missed_rx;
1529 1.1 dyoung
1530 1.5.2.2 jdolecek lxon = IXGBE_READ_REG(hw, IXGBE_LXONTXC);
1531 1.5.2.2 jdolecek stats->lxontxc.ev_count += lxon;
1532 1.5.2.2 jdolecek lxoff = IXGBE_READ_REG(hw, IXGBE_LXOFFTXC);
1533 1.5.2.2 jdolecek stats->lxofftxc.ev_count += lxoff;
1534 1.5.2.2 jdolecek total = lxon + lxoff;
1535 1.1 dyoung
1536 1.5.2.2 jdolecek if (hw->mac.type != ixgbe_mac_82598EB) {
1537 1.5.2.2 jdolecek stats->gorc.ev_count += IXGBE_READ_REG(hw, IXGBE_GORCL) +
1538 1.5.2.2 jdolecek ((u64)IXGBE_READ_REG(hw, IXGBE_GORCH) << 32);
1539 1.5.2.2 jdolecek stats->gotc.ev_count += IXGBE_READ_REG(hw, IXGBE_GOTCL) +
1540 1.5.2.2 jdolecek ((u64)IXGBE_READ_REG(hw, IXGBE_GOTCH) << 32) - total * ETHER_MIN_LEN;
1541 1.5.2.2 jdolecek stats->tor.ev_count += IXGBE_READ_REG(hw, IXGBE_TORL) +
1542 1.5.2.2 jdolecek ((u64)IXGBE_READ_REG(hw, IXGBE_TORH) << 32);
1543 1.5.2.2 jdolecek stats->lxonrxc.ev_count += IXGBE_READ_REG(hw, IXGBE_LXONRXCNT);
1544 1.5.2.2 jdolecek stats->lxoffrxc.ev_count += IXGBE_READ_REG(hw, IXGBE_LXOFFRXCNT);
1545 1.5.2.2 jdolecek } else {
1546 1.5.2.2 jdolecek stats->lxonrxc.ev_count += IXGBE_READ_REG(hw, IXGBE_LXONRXC);
1547 1.5.2.2 jdolecek stats->lxoffrxc.ev_count += IXGBE_READ_REG(hw, IXGBE_LXOFFRXC);
1548 1.5.2.2 jdolecek /* 82598 only has a counter in the high register */
1549 1.5.2.2 jdolecek stats->gorc.ev_count += IXGBE_READ_REG(hw, IXGBE_GORCH);
1550 1.5.2.2 jdolecek stats->gotc.ev_count += IXGBE_READ_REG(hw, IXGBE_GOTCH) - total * ETHER_MIN_LEN;
1551 1.5.2.2 jdolecek stats->tor.ev_count += IXGBE_READ_REG(hw, IXGBE_TORH);
1552 1.1 dyoung }
1553 1.1 dyoung
1554 1.5.2.2 jdolecek /*
1555 1.5.2.2 jdolecek * Workaround: mprc hardware is incorrectly counting
1556 1.5.2.2 jdolecek * broadcasts, so for now we subtract those.
1557 1.5.2.2 jdolecek */
1558 1.5.2.2 jdolecek bprc = IXGBE_READ_REG(hw, IXGBE_BPRC);
1559 1.5.2.2 jdolecek stats->bprc.ev_count += bprc;
1560 1.5.2.2 jdolecek stats->mprc.ev_count += IXGBE_READ_REG(hw, IXGBE_MPRC)
1561 1.5.2.2 jdolecek - ((hw->mac.type == ixgbe_mac_82598EB) ? bprc : 0);
1562 1.5.2.2 jdolecek
1563 1.5.2.2 jdolecek stats->prc64.ev_count += IXGBE_READ_REG(hw, IXGBE_PRC64);
1564 1.5.2.2 jdolecek stats->prc127.ev_count += IXGBE_READ_REG(hw, IXGBE_PRC127);
1565 1.5.2.2 jdolecek stats->prc255.ev_count += IXGBE_READ_REG(hw, IXGBE_PRC255);
1566 1.5.2.2 jdolecek stats->prc511.ev_count += IXGBE_READ_REG(hw, IXGBE_PRC511);
1567 1.5.2.2 jdolecek stats->prc1023.ev_count += IXGBE_READ_REG(hw, IXGBE_PRC1023);
1568 1.5.2.2 jdolecek stats->prc1522.ev_count += IXGBE_READ_REG(hw, IXGBE_PRC1522);
1569 1.5.2.2 jdolecek
1570 1.5.2.2 jdolecek stats->gptc.ev_count += IXGBE_READ_REG(hw, IXGBE_GPTC) - total;
1571 1.5.2.2 jdolecek stats->mptc.ev_count += IXGBE_READ_REG(hw, IXGBE_MPTC) - total;
1572 1.5.2.2 jdolecek stats->ptc64.ev_count += IXGBE_READ_REG(hw, IXGBE_PTC64) - total;
1573 1.5.2.2 jdolecek
1574 1.5.2.2 jdolecek stats->ruc.ev_count += IXGBE_READ_REG(hw, IXGBE_RUC);
1575 1.5.2.2 jdolecek stats->rfc.ev_count += IXGBE_READ_REG(hw, IXGBE_RFC);
1576 1.5.2.2 jdolecek stats->roc.ev_count += IXGBE_READ_REG(hw, IXGBE_ROC);
1577 1.5.2.2 jdolecek stats->rjc.ev_count += IXGBE_READ_REG(hw, IXGBE_RJC);
1578 1.5.2.2 jdolecek stats->mngprc.ev_count += IXGBE_READ_REG(hw, IXGBE_MNGPRC);
1579 1.5.2.2 jdolecek stats->mngpdc.ev_count += IXGBE_READ_REG(hw, IXGBE_MNGPDC);
1580 1.5.2.2 jdolecek stats->mngptc.ev_count += IXGBE_READ_REG(hw, IXGBE_MNGPTC);
1581 1.5.2.2 jdolecek stats->tpr.ev_count += IXGBE_READ_REG(hw, IXGBE_TPR);
1582 1.5.2.2 jdolecek stats->tpt.ev_count += IXGBE_READ_REG(hw, IXGBE_TPT);
1583 1.5.2.2 jdolecek stats->ptc127.ev_count += IXGBE_READ_REG(hw, IXGBE_PTC127);
1584 1.5.2.2 jdolecek stats->ptc255.ev_count += IXGBE_READ_REG(hw, IXGBE_PTC255);
1585 1.5.2.2 jdolecek stats->ptc511.ev_count += IXGBE_READ_REG(hw, IXGBE_PTC511);
1586 1.5.2.2 jdolecek stats->ptc1023.ev_count += IXGBE_READ_REG(hw, IXGBE_PTC1023);
1587 1.5.2.2 jdolecek stats->ptc1522.ev_count += IXGBE_READ_REG(hw, IXGBE_PTC1522);
1588 1.5.2.2 jdolecek stats->bptc.ev_count += IXGBE_READ_REG(hw, IXGBE_BPTC);
1589 1.5.2.2 jdolecek stats->xec.ev_count += IXGBE_READ_REG(hw, IXGBE_XEC);
1590 1.5.2.2 jdolecek stats->fccrc.ev_count += IXGBE_READ_REG(hw, IXGBE_FCCRC);
1591 1.5.2.2 jdolecek stats->fclast.ev_count += IXGBE_READ_REG(hw, IXGBE_FCLAST);
1592 1.5.2.2 jdolecek /* Only read FCOE on 82599 */
1593 1.5.2.2 jdolecek if (hw->mac.type != ixgbe_mac_82598EB) {
1594 1.5.2.2 jdolecek stats->fcoerpdc.ev_count += IXGBE_READ_REG(hw, IXGBE_FCOERPDC);
1595 1.5.2.2 jdolecek stats->fcoeprc.ev_count += IXGBE_READ_REG(hw, IXGBE_FCOEPRC);
1596 1.5.2.2 jdolecek stats->fcoeptc.ev_count += IXGBE_READ_REG(hw, IXGBE_FCOEPTC);
1597 1.5.2.2 jdolecek stats->fcoedwrc.ev_count += IXGBE_READ_REG(hw, IXGBE_FCOEDWRC);
1598 1.5.2.2 jdolecek stats->fcoedwtc.ev_count += IXGBE_READ_REG(hw, IXGBE_FCOEDWTC);
1599 1.1 dyoung }
1600 1.1 dyoung
1601 1.5.2.2 jdolecek /* Fill out the OS statistics structure */
1602 1.5.2.2 jdolecek /*
1603 1.5.2.2 jdolecek * NetBSD: Don't override if_{i|o}{packets|bytes|mcasts} with
1604 1.5.2.2 jdolecek * adapter->stats counters. It's required to make ifconfig -z
1605 1.5.2.2 jdolecek * (SOICZIFDATA) work.
1606 1.5.2.2 jdolecek */
1607 1.5.2.2 jdolecek ifp->if_collisions = 0;
1608 1.1 dyoung
1609 1.5.2.2 jdolecek /* Rx Errors */
1610 1.5.2.2 jdolecek ifp->if_iqdrops += total_missed_rx;
1611 1.5.2.2 jdolecek ifp->if_ierrors += crcerrs + rlec;
1612 1.5.2.2 jdolecek } /* ixgbe_update_stats_counters */
1613 1.1 dyoung
1614 1.5.2.2 jdolecek /************************************************************************
1615 1.5.2.2 jdolecek * ixgbe_add_hw_stats
1616 1.5.2.2 jdolecek *
1617 1.5.2.2 jdolecek * Add sysctl variables, one per statistic, to the system.
1618 1.5.2.2 jdolecek ************************************************************************/
1619 1.5.2.2 jdolecek static void
1620 1.5.2.2 jdolecek ixgbe_add_hw_stats(struct adapter *adapter)
1621 1.1 dyoung {
1622 1.5.2.2 jdolecek device_t dev = adapter->dev;
1623 1.5.2.2 jdolecek const struct sysctlnode *rnode, *cnode;
1624 1.5.2.2 jdolecek struct sysctllog **log = &adapter->sysctllog;
1625 1.5.2.2 jdolecek struct tx_ring *txr = adapter->tx_rings;
1626 1.5.2.2 jdolecek struct rx_ring *rxr = adapter->rx_rings;
1627 1.5.2.2 jdolecek struct ixgbe_hw *hw = &adapter->hw;
1628 1.5.2.2 jdolecek struct ixgbe_hw_stats *stats = &adapter->stats.pf;
1629 1.5.2.2 jdolecek const char *xname = device_xname(dev);
1630 1.1 dyoung
1631 1.5.2.2 jdolecek /* Driver Statistics */
1632 1.5.2.2 jdolecek evcnt_attach_dynamic(&adapter->handleq, EVCNT_TYPE_MISC,
1633 1.5.2.2 jdolecek NULL, xname, "Handled queue in softint");
1634 1.5.2.2 jdolecek evcnt_attach_dynamic(&adapter->req, EVCNT_TYPE_MISC,
1635 1.5.2.2 jdolecek NULL, xname, "Requeued in softint");
1636 1.5.2.2 jdolecek evcnt_attach_dynamic(&adapter->efbig_tx_dma_setup, EVCNT_TYPE_MISC,
1637 1.5.2.2 jdolecek NULL, xname, "Driver tx dma soft fail EFBIG");
1638 1.5.2.2 jdolecek evcnt_attach_dynamic(&adapter->mbuf_defrag_failed, EVCNT_TYPE_MISC,
1639 1.5.2.2 jdolecek NULL, xname, "m_defrag() failed");
1640 1.5.2.2 jdolecek evcnt_attach_dynamic(&adapter->efbig2_tx_dma_setup, EVCNT_TYPE_MISC,
1641 1.5.2.2 jdolecek NULL, xname, "Driver tx dma hard fail EFBIG");
1642 1.5.2.2 jdolecek evcnt_attach_dynamic(&adapter->einval_tx_dma_setup, EVCNT_TYPE_MISC,
1643 1.5.2.2 jdolecek NULL, xname, "Driver tx dma hard fail EINVAL");
1644 1.5.2.2 jdolecek evcnt_attach_dynamic(&adapter->other_tx_dma_setup, EVCNT_TYPE_MISC,
1645 1.5.2.2 jdolecek NULL, xname, "Driver tx dma hard fail other");
1646 1.5.2.2 jdolecek evcnt_attach_dynamic(&adapter->eagain_tx_dma_setup, EVCNT_TYPE_MISC,
1647 1.5.2.2 jdolecek NULL, xname, "Driver tx dma soft fail EAGAIN");
1648 1.5.2.2 jdolecek evcnt_attach_dynamic(&adapter->enomem_tx_dma_setup, EVCNT_TYPE_MISC,
1649 1.5.2.2 jdolecek NULL, xname, "Driver tx dma soft fail ENOMEM");
1650 1.5.2.2 jdolecek evcnt_attach_dynamic(&adapter->watchdog_events, EVCNT_TYPE_MISC,
1651 1.5.2.2 jdolecek NULL, xname, "Watchdog timeouts");
1652 1.5.2.2 jdolecek evcnt_attach_dynamic(&adapter->tso_err, EVCNT_TYPE_MISC,
1653 1.5.2.2 jdolecek NULL, xname, "TSO errors");
1654 1.5.2.2 jdolecek evcnt_attach_dynamic(&adapter->link_irq, EVCNT_TYPE_INTR,
1655 1.5.2.2 jdolecek NULL, xname, "Link MSI-X IRQ Handled");
1656 1.1 dyoung
1657 1.5.2.2 jdolecek for (int i = 0; i < adapter->num_queues; i++, rxr++, txr++) {
1658 1.5.2.2 jdolecek snprintf(adapter->queues[i].evnamebuf,
1659 1.5.2.2 jdolecek sizeof(adapter->queues[i].evnamebuf), "%s q%d",
1660 1.5.2.2 jdolecek xname, i);
1661 1.5.2.2 jdolecek snprintf(adapter->queues[i].namebuf,
1662 1.5.2.2 jdolecek sizeof(adapter->queues[i].namebuf), "q%d", i);
1663 1.1 dyoung
1664 1.5.2.2 jdolecek if ((rnode = ixgbe_sysctl_instance(adapter)) == NULL) {
1665 1.5.2.2 jdolecek aprint_error_dev(dev, "could not create sysctl root\n");
1666 1.5.2.2 jdolecek break;
1667 1.5.2.2 jdolecek }
1668 1.1 dyoung
1669 1.5.2.2 jdolecek if (sysctl_createv(log, 0, &rnode, &rnode,
1670 1.5.2.2 jdolecek 0, CTLTYPE_NODE,
1671 1.5.2.2 jdolecek adapter->queues[i].namebuf, SYSCTL_DESCR("Queue Name"),
1672 1.5.2.2 jdolecek NULL, 0, NULL, 0, CTL_CREATE, CTL_EOL) != 0)
1673 1.5.2.2 jdolecek break;
1674 1.1 dyoung
1675 1.5.2.2 jdolecek if (sysctl_createv(log, 0, &rnode, &cnode,
1676 1.5.2.2 jdolecek CTLFLAG_READWRITE, CTLTYPE_INT,
1677 1.5.2.2 jdolecek "interrupt_rate", SYSCTL_DESCR("Interrupt Rate"),
1678 1.5.2.2 jdolecek ixgbe_sysctl_interrupt_rate_handler, 0,
1679 1.5.2.2 jdolecek (void *)&adapter->queues[i], 0, CTL_CREATE, CTL_EOL) != 0)
1680 1.5.2.2 jdolecek break;
1681 1.1 dyoung
1682 1.5.2.2 jdolecek #if 0 /* XXX msaitoh */
1683 1.5.2.2 jdolecek if (sysctl_createv(log, 0, &rnode, &cnode,
1684 1.5.2.2 jdolecek CTLFLAG_READONLY, CTLTYPE_QUAD,
1685 1.5.2.2 jdolecek "irqs", SYSCTL_DESCR("irqs on this queue"),
1686 1.5.2.2 jdolecek NULL, 0, &(adapter->queues[i].irqs),
1687 1.5.2.2 jdolecek 0, CTL_CREATE, CTL_EOL) != 0)
1688 1.5.2.2 jdolecek break;
1689 1.5.2.2 jdolecek #endif
1690 1.1 dyoung
1691 1.5.2.2 jdolecek if (sysctl_createv(log, 0, &rnode, &cnode,
1692 1.5.2.2 jdolecek CTLFLAG_READONLY, CTLTYPE_INT,
1693 1.5.2.2 jdolecek "txd_head", SYSCTL_DESCR("Transmit Descriptor Head"),
1694 1.5.2.2 jdolecek ixgbe_sysctl_tdh_handler, 0, (void *)txr,
1695 1.5.2.2 jdolecek 0, CTL_CREATE, CTL_EOL) != 0)
1696 1.5.2.2 jdolecek break;
1697 1.1 dyoung
1698 1.5.2.2 jdolecek if (sysctl_createv(log, 0, &rnode, &cnode,
1699 1.5.2.2 jdolecek CTLFLAG_READONLY, CTLTYPE_INT,
1700 1.5.2.2 jdolecek "txd_tail", SYSCTL_DESCR("Transmit Descriptor Tail"),
1701 1.5.2.2 jdolecek ixgbe_sysctl_tdt_handler, 0, (void *)txr,
1702 1.5.2.2 jdolecek 0, CTL_CREATE, CTL_EOL) != 0)
1703 1.5.2.2 jdolecek break;
1704 1.1 dyoung
1705 1.5.2.2 jdolecek evcnt_attach_dynamic(&adapter->queues[i].irqs, EVCNT_TYPE_INTR,
1706 1.5.2.2 jdolecek NULL, adapter->queues[i].evnamebuf, "IRQs on queue");
1707 1.5.2.2 jdolecek evcnt_attach_dynamic(&txr->tso_tx, EVCNT_TYPE_MISC,
1708 1.5.2.2 jdolecek NULL, adapter->queues[i].evnamebuf, "TSO");
1709 1.5.2.2 jdolecek evcnt_attach_dynamic(&txr->no_desc_avail, EVCNT_TYPE_MISC,
1710 1.5.2.2 jdolecek NULL, adapter->queues[i].evnamebuf,
1711 1.5.2.2 jdolecek "Queue No Descriptor Available");
1712 1.5.2.2 jdolecek evcnt_attach_dynamic(&txr->total_packets, EVCNT_TYPE_MISC,
1713 1.5.2.2 jdolecek NULL, adapter->queues[i].evnamebuf,
1714 1.5.2.2 jdolecek "Queue Packets Transmitted");
1715 1.5.2.2 jdolecek #ifndef IXGBE_LEGACY_TX
1716 1.5.2.2 jdolecek evcnt_attach_dynamic(&txr->pcq_drops, EVCNT_TYPE_MISC,
1717 1.5.2.2 jdolecek NULL, adapter->queues[i].evnamebuf,
1718 1.5.2.2 jdolecek "Packets dropped in pcq");
1719 1.5.2.2 jdolecek #endif
1720 1.1 dyoung
1721 1.5.2.2 jdolecek #ifdef LRO
1722 1.5.2.2 jdolecek struct lro_ctrl *lro = &rxr->lro;
1723 1.5.2.2 jdolecek #endif /* LRO */
1724 1.1 dyoung
1725 1.5.2.2 jdolecek if (sysctl_createv(log, 0, &rnode, &cnode,
1726 1.5.2.2 jdolecek CTLFLAG_READONLY,
1727 1.5.2.2 jdolecek CTLTYPE_INT,
1728 1.5.2.2 jdolecek "rxd_head", SYSCTL_DESCR("Receive Descriptor Head"),
1729 1.5.2.2 jdolecek ixgbe_sysctl_rdh_handler, 0, (void *)rxr, 0,
1730 1.5.2.2 jdolecek CTL_CREATE, CTL_EOL) != 0)
1731 1.5.2.2 jdolecek break;
1732 1.1 dyoung
1733 1.5.2.2 jdolecek if (sysctl_createv(log, 0, &rnode, &cnode,
1734 1.5.2.2 jdolecek CTLFLAG_READONLY,
1735 1.5.2.2 jdolecek CTLTYPE_INT,
1736 1.5.2.2 jdolecek "rxd_tail", SYSCTL_DESCR("Receive Descriptor Tail"),
1737 1.5.2.2 jdolecek ixgbe_sysctl_rdt_handler, 0, (void *)rxr, 0,
1738 1.5.2.2 jdolecek CTL_CREATE, CTL_EOL) != 0)
1739 1.5.2.2 jdolecek break;
1740 1.1 dyoung
1741 1.5.2.2 jdolecek if (i < __arraycount(stats->mpc)) {
1742 1.5.2.2 jdolecek evcnt_attach_dynamic(&stats->mpc[i],
1743 1.5.2.2 jdolecek EVCNT_TYPE_MISC, NULL, adapter->queues[i].evnamebuf,
1744 1.5.2.2 jdolecek "RX Missed Packet Count");
1745 1.5.2.2 jdolecek if (hw->mac.type == ixgbe_mac_82598EB)
1746 1.5.2.2 jdolecek evcnt_attach_dynamic(&stats->rnbc[i],
1747 1.5.2.2 jdolecek EVCNT_TYPE_MISC, NULL,
1748 1.5.2.2 jdolecek adapter->queues[i].evnamebuf,
1749 1.5.2.2 jdolecek "Receive No Buffers");
1750 1.1 dyoung }
1751 1.5.2.2 jdolecek if (i < __arraycount(stats->pxontxc)) {
1752 1.5.2.2 jdolecek evcnt_attach_dynamic(&stats->pxontxc[i],
1753 1.5.2.2 jdolecek EVCNT_TYPE_MISC, NULL, adapter->queues[i].evnamebuf,
1754 1.5.2.2 jdolecek "pxontxc");
1755 1.5.2.2 jdolecek evcnt_attach_dynamic(&stats->pxonrxc[i],
1756 1.5.2.2 jdolecek EVCNT_TYPE_MISC, NULL, adapter->queues[i].evnamebuf,
1757 1.5.2.2 jdolecek "pxonrxc");
1758 1.5.2.2 jdolecek evcnt_attach_dynamic(&stats->pxofftxc[i],
1759 1.5.2.2 jdolecek EVCNT_TYPE_MISC, NULL, adapter->queues[i].evnamebuf,
1760 1.5.2.2 jdolecek "pxofftxc");
1761 1.5.2.2 jdolecek evcnt_attach_dynamic(&stats->pxoffrxc[i],
1762 1.5.2.2 jdolecek EVCNT_TYPE_MISC, NULL, adapter->queues[i].evnamebuf,
1763 1.5.2.2 jdolecek "pxoffrxc");
1764 1.5.2.2 jdolecek evcnt_attach_dynamic(&stats->pxon2offc[i],
1765 1.5.2.2 jdolecek EVCNT_TYPE_MISC, NULL, adapter->queues[i].evnamebuf,
1766 1.5.2.2 jdolecek "pxon2offc");
1767 1.1 dyoung }
1768 1.5.2.2 jdolecek if (i < __arraycount(stats->qprc)) {
1769 1.5.2.2 jdolecek evcnt_attach_dynamic(&stats->qprc[i],
1770 1.5.2.2 jdolecek EVCNT_TYPE_MISC, NULL, adapter->queues[i].evnamebuf,
1771 1.5.2.2 jdolecek "qprc");
1772 1.5.2.2 jdolecek evcnt_attach_dynamic(&stats->qptc[i],
1773 1.5.2.2 jdolecek EVCNT_TYPE_MISC, NULL, adapter->queues[i].evnamebuf,
1774 1.5.2.2 jdolecek "qptc");
1775 1.5.2.2 jdolecek evcnt_attach_dynamic(&stats->qbrc[i],
1776 1.5.2.2 jdolecek EVCNT_TYPE_MISC, NULL, adapter->queues[i].evnamebuf,
1777 1.5.2.2 jdolecek "qbrc");
1778 1.5.2.2 jdolecek evcnt_attach_dynamic(&stats->qbtc[i],
1779 1.5.2.2 jdolecek EVCNT_TYPE_MISC, NULL, adapter->queues[i].evnamebuf,
1780 1.5.2.2 jdolecek "qbtc");
1781 1.5.2.2 jdolecek evcnt_attach_dynamic(&stats->qprdc[i],
1782 1.5.2.2 jdolecek EVCNT_TYPE_MISC, NULL, adapter->queues[i].evnamebuf,
1783 1.5.2.2 jdolecek "qprdc");
1784 1.5.2.2 jdolecek }
1785 1.5.2.2 jdolecek
1786 1.5.2.2 jdolecek evcnt_attach_dynamic(&rxr->rx_packets, EVCNT_TYPE_MISC,
1787 1.5.2.2 jdolecek NULL, adapter->queues[i].evnamebuf, "Queue Packets Received");
1788 1.5.2.2 jdolecek evcnt_attach_dynamic(&rxr->rx_bytes, EVCNT_TYPE_MISC,
1789 1.5.2.2 jdolecek NULL, adapter->queues[i].evnamebuf, "Queue Bytes Received");
1790 1.5.2.2 jdolecek evcnt_attach_dynamic(&rxr->rx_copies, EVCNT_TYPE_MISC,
1791 1.5.2.2 jdolecek NULL, adapter->queues[i].evnamebuf, "Copied RX Frames");
1792 1.5.2.2 jdolecek evcnt_attach_dynamic(&rxr->no_jmbuf, EVCNT_TYPE_MISC,
1793 1.5.2.2 jdolecek NULL, adapter->queues[i].evnamebuf, "Rx no jumbo mbuf");
1794 1.5.2.2 jdolecek evcnt_attach_dynamic(&rxr->rx_discarded, EVCNT_TYPE_MISC,
1795 1.5.2.2 jdolecek NULL, adapter->queues[i].evnamebuf, "Rx discarded");
1796 1.5.2.2 jdolecek #ifdef LRO
1797 1.5.2.2 jdolecek SYSCTL_ADD_INT(ctx, queue_list, OID_AUTO, "lro_queued",
1798 1.5.2.2 jdolecek CTLFLAG_RD, &lro->lro_queued, 0,
1799 1.5.2.2 jdolecek "LRO Queued");
1800 1.5.2.2 jdolecek SYSCTL_ADD_INT(ctx, queue_list, OID_AUTO, "lro_flushed",
1801 1.5.2.2 jdolecek CTLFLAG_RD, &lro->lro_flushed, 0,
1802 1.5.2.2 jdolecek "LRO Flushed");
1803 1.5.2.2 jdolecek #endif /* LRO */
1804 1.1 dyoung }
1805 1.1 dyoung
1806 1.5.2.2 jdolecek /* MAC stats get their own sub node */
1807 1.1 dyoung
1808 1.5.2.2 jdolecek snprintf(stats->namebuf,
1809 1.5.2.2 jdolecek sizeof(stats->namebuf), "%s MAC Statistics", xname);
1810 1.1 dyoung
1811 1.5.2.2 jdolecek evcnt_attach_dynamic(&stats->ipcs, EVCNT_TYPE_MISC, NULL,
1812 1.5.2.2 jdolecek stats->namebuf, "rx csum offload - IP");
1813 1.5.2.2 jdolecek evcnt_attach_dynamic(&stats->l4cs, EVCNT_TYPE_MISC, NULL,
1814 1.5.2.2 jdolecek stats->namebuf, "rx csum offload - L4");
1815 1.5.2.2 jdolecek evcnt_attach_dynamic(&stats->ipcs_bad, EVCNT_TYPE_MISC, NULL,
1816 1.5.2.2 jdolecek stats->namebuf, "rx csum offload - IP bad");
1817 1.5.2.2 jdolecek evcnt_attach_dynamic(&stats->l4cs_bad, EVCNT_TYPE_MISC, NULL,
1818 1.5.2.2 jdolecek stats->namebuf, "rx csum offload - L4 bad");
1819 1.5.2.2 jdolecek evcnt_attach_dynamic(&stats->intzero, EVCNT_TYPE_MISC, NULL,
1820 1.5.2.2 jdolecek stats->namebuf, "Interrupt conditions zero");
1821 1.5.2.2 jdolecek evcnt_attach_dynamic(&stats->legint, EVCNT_TYPE_MISC, NULL,
1822 1.5.2.2 jdolecek stats->namebuf, "Legacy interrupts");
1823 1.1 dyoung
1824 1.5.2.2 jdolecek evcnt_attach_dynamic(&stats->crcerrs, EVCNT_TYPE_MISC, NULL,
1825 1.5.2.2 jdolecek stats->namebuf, "CRC Errors");
1826 1.5.2.2 jdolecek evcnt_attach_dynamic(&stats->illerrc, EVCNT_TYPE_MISC, NULL,
1827 1.5.2.2 jdolecek stats->namebuf, "Illegal Byte Errors");
1828 1.5.2.2 jdolecek evcnt_attach_dynamic(&stats->errbc, EVCNT_TYPE_MISC, NULL,
1829 1.5.2.2 jdolecek stats->namebuf, "Byte Errors");
1830 1.5.2.2 jdolecek evcnt_attach_dynamic(&stats->mspdc, EVCNT_TYPE_MISC, NULL,
1831 1.5.2.2 jdolecek stats->namebuf, "MAC Short Packets Discarded");
1832 1.5.2.2 jdolecek if (hw->mac.type >= ixgbe_mac_X550)
1833 1.5.2.2 jdolecek evcnt_attach_dynamic(&stats->mbsdc, EVCNT_TYPE_MISC, NULL,
1834 1.5.2.2 jdolecek stats->namebuf, "Bad SFD");
1835 1.5.2.2 jdolecek evcnt_attach_dynamic(&stats->mpctotal, EVCNT_TYPE_MISC, NULL,
1836 1.5.2.2 jdolecek stats->namebuf, "Total Packets Missed");
1837 1.5.2.2 jdolecek evcnt_attach_dynamic(&stats->mlfc, EVCNT_TYPE_MISC, NULL,
1838 1.5.2.2 jdolecek stats->namebuf, "MAC Local Faults");
1839 1.5.2.2 jdolecek evcnt_attach_dynamic(&stats->mrfc, EVCNT_TYPE_MISC, NULL,
1840 1.5.2.2 jdolecek stats->namebuf, "MAC Remote Faults");
1841 1.5.2.2 jdolecek evcnt_attach_dynamic(&stats->rlec, EVCNT_TYPE_MISC, NULL,
1842 1.5.2.2 jdolecek stats->namebuf, "Receive Length Errors");
1843 1.5.2.2 jdolecek evcnt_attach_dynamic(&stats->lxontxc, EVCNT_TYPE_MISC, NULL,
1844 1.5.2.2 jdolecek stats->namebuf, "Link XON Transmitted");
1845 1.5.2.2 jdolecek evcnt_attach_dynamic(&stats->lxonrxc, EVCNT_TYPE_MISC, NULL,
1846 1.5.2.2 jdolecek stats->namebuf, "Link XON Received");
1847 1.5.2.2 jdolecek evcnt_attach_dynamic(&stats->lxofftxc, EVCNT_TYPE_MISC, NULL,
1848 1.5.2.2 jdolecek stats->namebuf, "Link XOFF Transmitted");
1849 1.5.2.2 jdolecek evcnt_attach_dynamic(&stats->lxoffrxc, EVCNT_TYPE_MISC, NULL,
1850 1.5.2.2 jdolecek stats->namebuf, "Link XOFF Received");
1851 1.1 dyoung
1852 1.5.2.2 jdolecek /* Packet Reception Stats */
1853 1.5.2.2 jdolecek evcnt_attach_dynamic(&stats->tor, EVCNT_TYPE_MISC, NULL,
1854 1.5.2.2 jdolecek stats->namebuf, "Total Octets Received");
1855 1.5.2.2 jdolecek evcnt_attach_dynamic(&stats->gorc, EVCNT_TYPE_MISC, NULL,
1856 1.5.2.2 jdolecek stats->namebuf, "Good Octets Received");
1857 1.5.2.2 jdolecek evcnt_attach_dynamic(&stats->tpr, EVCNT_TYPE_MISC, NULL,
1858 1.5.2.2 jdolecek stats->namebuf, "Total Packets Received");
1859 1.5.2.2 jdolecek evcnt_attach_dynamic(&stats->gprc, EVCNT_TYPE_MISC, NULL,
1860 1.5.2.2 jdolecek stats->namebuf, "Good Packets Received");
1861 1.5.2.2 jdolecek evcnt_attach_dynamic(&stats->mprc, EVCNT_TYPE_MISC, NULL,
1862 1.5.2.2 jdolecek stats->namebuf, "Multicast Packets Received");
1863 1.5.2.2 jdolecek evcnt_attach_dynamic(&stats->bprc, EVCNT_TYPE_MISC, NULL,
1864 1.5.2.2 jdolecek stats->namebuf, "Broadcast Packets Received");
1865 1.5.2.2 jdolecek evcnt_attach_dynamic(&stats->prc64, EVCNT_TYPE_MISC, NULL,
1866 1.5.2.2 jdolecek stats->namebuf, "64 byte frames received ");
1867 1.5.2.2 jdolecek evcnt_attach_dynamic(&stats->prc127, EVCNT_TYPE_MISC, NULL,
1868 1.5.2.2 jdolecek stats->namebuf, "65-127 byte frames received");
1869 1.5.2.2 jdolecek evcnt_attach_dynamic(&stats->prc255, EVCNT_TYPE_MISC, NULL,
1870 1.5.2.2 jdolecek stats->namebuf, "128-255 byte frames received");
1871 1.5.2.2 jdolecek evcnt_attach_dynamic(&stats->prc511, EVCNT_TYPE_MISC, NULL,
1872 1.5.2.2 jdolecek stats->namebuf, "256-511 byte frames received");
1873 1.5.2.2 jdolecek evcnt_attach_dynamic(&stats->prc1023, EVCNT_TYPE_MISC, NULL,
1874 1.5.2.2 jdolecek stats->namebuf, "512-1023 byte frames received");
1875 1.5.2.2 jdolecek evcnt_attach_dynamic(&stats->prc1522, EVCNT_TYPE_MISC, NULL,
1876 1.5.2.2 jdolecek stats->namebuf, "1023-1522 byte frames received");
1877 1.5.2.2 jdolecek evcnt_attach_dynamic(&stats->ruc, EVCNT_TYPE_MISC, NULL,
1878 1.5.2.2 jdolecek stats->namebuf, "Receive Undersized");
1879 1.5.2.2 jdolecek evcnt_attach_dynamic(&stats->rfc, EVCNT_TYPE_MISC, NULL,
1880 1.5.2.2 jdolecek stats->namebuf, "Fragmented Packets Received ");
1881 1.5.2.2 jdolecek evcnt_attach_dynamic(&stats->roc, EVCNT_TYPE_MISC, NULL,
1882 1.5.2.2 jdolecek stats->namebuf, "Oversized Packets Received");
1883 1.5.2.2 jdolecek evcnt_attach_dynamic(&stats->rjc, EVCNT_TYPE_MISC, NULL,
1884 1.5.2.2 jdolecek stats->namebuf, "Received Jabber");
1885 1.5.2.2 jdolecek evcnt_attach_dynamic(&stats->mngprc, EVCNT_TYPE_MISC, NULL,
1886 1.5.2.2 jdolecek stats->namebuf, "Management Packets Received");
1887 1.5.2.2 jdolecek evcnt_attach_dynamic(&stats->mngpdc, EVCNT_TYPE_MISC, NULL,
1888 1.5.2.2 jdolecek stats->namebuf, "Management Packets Dropped");
1889 1.5.2.2 jdolecek evcnt_attach_dynamic(&stats->xec, EVCNT_TYPE_MISC, NULL,
1890 1.5.2.2 jdolecek stats->namebuf, "Checksum Errors");
1891 1.1 dyoung
1892 1.5.2.2 jdolecek /* Packet Transmission Stats */
1893 1.5.2.2 jdolecek evcnt_attach_dynamic(&stats->gotc, EVCNT_TYPE_MISC, NULL,
1894 1.5.2.2 jdolecek stats->namebuf, "Good Octets Transmitted");
1895 1.5.2.2 jdolecek evcnt_attach_dynamic(&stats->tpt, EVCNT_TYPE_MISC, NULL,
1896 1.5.2.2 jdolecek stats->namebuf, "Total Packets Transmitted");
1897 1.5.2.2 jdolecek evcnt_attach_dynamic(&stats->gptc, EVCNT_TYPE_MISC, NULL,
1898 1.5.2.2 jdolecek stats->namebuf, "Good Packets Transmitted");
1899 1.5.2.2 jdolecek evcnt_attach_dynamic(&stats->bptc, EVCNT_TYPE_MISC, NULL,
1900 1.5.2.2 jdolecek stats->namebuf, "Broadcast Packets Transmitted");
1901 1.5.2.2 jdolecek evcnt_attach_dynamic(&stats->mptc, EVCNT_TYPE_MISC, NULL,
1902 1.5.2.2 jdolecek stats->namebuf, "Multicast Packets Transmitted");
1903 1.5.2.2 jdolecek evcnt_attach_dynamic(&stats->mngptc, EVCNT_TYPE_MISC, NULL,
1904 1.5.2.2 jdolecek stats->namebuf, "Management Packets Transmitted");
1905 1.5.2.2 jdolecek evcnt_attach_dynamic(&stats->ptc64, EVCNT_TYPE_MISC, NULL,
1906 1.5.2.2 jdolecek stats->namebuf, "64 byte frames transmitted ");
1907 1.5.2.2 jdolecek evcnt_attach_dynamic(&stats->ptc127, EVCNT_TYPE_MISC, NULL,
1908 1.5.2.2 jdolecek stats->namebuf, "65-127 byte frames transmitted");
1909 1.5.2.2 jdolecek evcnt_attach_dynamic(&stats->ptc255, EVCNT_TYPE_MISC, NULL,
1910 1.5.2.2 jdolecek stats->namebuf, "128-255 byte frames transmitted");
1911 1.5.2.2 jdolecek evcnt_attach_dynamic(&stats->ptc511, EVCNT_TYPE_MISC, NULL,
1912 1.5.2.2 jdolecek stats->namebuf, "256-511 byte frames transmitted");
1913 1.5.2.2 jdolecek evcnt_attach_dynamic(&stats->ptc1023, EVCNT_TYPE_MISC, NULL,
1914 1.5.2.2 jdolecek stats->namebuf, "512-1023 byte frames transmitted");
1915 1.5.2.2 jdolecek evcnt_attach_dynamic(&stats->ptc1522, EVCNT_TYPE_MISC, NULL,
1916 1.5.2.2 jdolecek stats->namebuf, "1024-1522 byte frames transmitted");
1917 1.5.2.2 jdolecek } /* ixgbe_add_hw_stats */
1918 1.1 dyoung
1919 1.5.2.2 jdolecek static void
1920 1.5.2.2 jdolecek ixgbe_clear_evcnt(struct adapter *adapter)
1921 1.5.2.2 jdolecek {
1922 1.5.2.2 jdolecek struct tx_ring *txr = adapter->tx_rings;
1923 1.5.2.2 jdolecek struct rx_ring *rxr = adapter->rx_rings;
1924 1.5.2.2 jdolecek struct ixgbe_hw *hw = &adapter->hw;
1925 1.5.2.2 jdolecek struct ixgbe_hw_stats *stats = &adapter->stats.pf;
1926 1.1 dyoung
1927 1.5.2.2 jdolecek adapter->handleq.ev_count = 0;
1928 1.5.2.2 jdolecek adapter->req.ev_count = 0;
1929 1.5.2.2 jdolecek adapter->efbig_tx_dma_setup.ev_count = 0;
1930 1.5.2.2 jdolecek adapter->mbuf_defrag_failed.ev_count = 0;
1931 1.5.2.2 jdolecek adapter->efbig2_tx_dma_setup.ev_count = 0;
1932 1.5.2.2 jdolecek adapter->einval_tx_dma_setup.ev_count = 0;
1933 1.5.2.2 jdolecek adapter->other_tx_dma_setup.ev_count = 0;
1934 1.5.2.2 jdolecek adapter->eagain_tx_dma_setup.ev_count = 0;
1935 1.5.2.2 jdolecek adapter->enomem_tx_dma_setup.ev_count = 0;
1936 1.5.2.2 jdolecek adapter->watchdog_events.ev_count = 0;
1937 1.5.2.2 jdolecek adapter->tso_err.ev_count = 0;
1938 1.5.2.2 jdolecek adapter->link_irq.ev_count = 0;
1939 1.1 dyoung
1940 1.5.2.2 jdolecek txr = adapter->tx_rings;
1941 1.5.2.2 jdolecek for (int i = 0; i < adapter->num_queues; i++, rxr++, txr++) {
1942 1.5.2.2 jdolecek adapter->queues[i].irqs.ev_count = 0;
1943 1.5.2.2 jdolecek txr->no_desc_avail.ev_count = 0;
1944 1.5.2.2 jdolecek txr->total_packets.ev_count = 0;
1945 1.5.2.2 jdolecek txr->tso_tx.ev_count = 0;
1946 1.5.2.2 jdolecek #ifndef IXGBE_LEGACY_TX
1947 1.5.2.2 jdolecek txr->pcq_drops.ev_count = 0;
1948 1.5.2.2 jdolecek #endif
1949 1.5.2.2 jdolecek
1950 1.5.2.2 jdolecek if (i < __arraycount(stats->mpc)) {
1951 1.5.2.2 jdolecek stats->mpc[i].ev_count = 0;
1952 1.5.2.2 jdolecek if (hw->mac.type == ixgbe_mac_82598EB)
1953 1.5.2.2 jdolecek stats->rnbc[i].ev_count = 0;
1954 1.5.2.2 jdolecek }
1955 1.5.2.2 jdolecek if (i < __arraycount(stats->pxontxc)) {
1956 1.5.2.2 jdolecek stats->pxontxc[i].ev_count = 0;
1957 1.5.2.2 jdolecek stats->pxonrxc[i].ev_count = 0;
1958 1.5.2.2 jdolecek stats->pxofftxc[i].ev_count = 0;
1959 1.5.2.2 jdolecek stats->pxoffrxc[i].ev_count = 0;
1960 1.5.2.2 jdolecek stats->pxon2offc[i].ev_count = 0;
1961 1.5.2.2 jdolecek }
1962 1.5.2.2 jdolecek if (i < __arraycount(stats->qprc)) {
1963 1.5.2.2 jdolecek stats->qprc[i].ev_count = 0;
1964 1.5.2.2 jdolecek stats->qptc[i].ev_count = 0;
1965 1.5.2.2 jdolecek stats->qbrc[i].ev_count = 0;
1966 1.5.2.2 jdolecek stats->qbtc[i].ev_count = 0;
1967 1.5.2.2 jdolecek stats->qprdc[i].ev_count = 0;
1968 1.5.2.2 jdolecek }
1969 1.5.2.2 jdolecek
1970 1.5.2.2 jdolecek rxr->rx_packets.ev_count = 0;
1971 1.5.2.2 jdolecek rxr->rx_bytes.ev_count = 0;
1972 1.5.2.2 jdolecek rxr->rx_copies.ev_count = 0;
1973 1.5.2.2 jdolecek rxr->no_jmbuf.ev_count = 0;
1974 1.5.2.2 jdolecek rxr->rx_discarded.ev_count = 0;
1975 1.5.2.2 jdolecek }
1976 1.5.2.2 jdolecek stats->ipcs.ev_count = 0;
1977 1.5.2.2 jdolecek stats->l4cs.ev_count = 0;
1978 1.5.2.2 jdolecek stats->ipcs_bad.ev_count = 0;
1979 1.5.2.2 jdolecek stats->l4cs_bad.ev_count = 0;
1980 1.5.2.2 jdolecek stats->intzero.ev_count = 0;
1981 1.5.2.2 jdolecek stats->legint.ev_count = 0;
1982 1.5.2.2 jdolecek stats->crcerrs.ev_count = 0;
1983 1.5.2.2 jdolecek stats->illerrc.ev_count = 0;
1984 1.5.2.2 jdolecek stats->errbc.ev_count = 0;
1985 1.5.2.2 jdolecek stats->mspdc.ev_count = 0;
1986 1.5.2.2 jdolecek stats->mbsdc.ev_count = 0;
1987 1.5.2.2 jdolecek stats->mpctotal.ev_count = 0;
1988 1.5.2.2 jdolecek stats->mlfc.ev_count = 0;
1989 1.5.2.2 jdolecek stats->mrfc.ev_count = 0;
1990 1.5.2.2 jdolecek stats->rlec.ev_count = 0;
1991 1.5.2.2 jdolecek stats->lxontxc.ev_count = 0;
1992 1.5.2.2 jdolecek stats->lxonrxc.ev_count = 0;
1993 1.5.2.2 jdolecek stats->lxofftxc.ev_count = 0;
1994 1.5.2.2 jdolecek stats->lxoffrxc.ev_count = 0;
1995 1.1 dyoung
1996 1.5.2.2 jdolecek /* Packet Reception Stats */
1997 1.5.2.2 jdolecek stats->tor.ev_count = 0;
1998 1.5.2.2 jdolecek stats->gorc.ev_count = 0;
1999 1.5.2.2 jdolecek stats->tpr.ev_count = 0;
2000 1.5.2.2 jdolecek stats->gprc.ev_count = 0;
2001 1.5.2.2 jdolecek stats->mprc.ev_count = 0;
2002 1.5.2.2 jdolecek stats->bprc.ev_count = 0;
2003 1.5.2.2 jdolecek stats->prc64.ev_count = 0;
2004 1.5.2.2 jdolecek stats->prc127.ev_count = 0;
2005 1.5.2.2 jdolecek stats->prc255.ev_count = 0;
2006 1.5.2.2 jdolecek stats->prc511.ev_count = 0;
2007 1.5.2.2 jdolecek stats->prc1023.ev_count = 0;
2008 1.5.2.2 jdolecek stats->prc1522.ev_count = 0;
2009 1.5.2.2 jdolecek stats->ruc.ev_count = 0;
2010 1.5.2.2 jdolecek stats->rfc.ev_count = 0;
2011 1.5.2.2 jdolecek stats->roc.ev_count = 0;
2012 1.5.2.2 jdolecek stats->rjc.ev_count = 0;
2013 1.5.2.2 jdolecek stats->mngprc.ev_count = 0;
2014 1.5.2.2 jdolecek stats->mngpdc.ev_count = 0;
2015 1.5.2.2 jdolecek stats->xec.ev_count = 0;
2016 1.1 dyoung
2017 1.5.2.2 jdolecek /* Packet Transmission Stats */
2018 1.5.2.2 jdolecek stats->gotc.ev_count = 0;
2019 1.5.2.2 jdolecek stats->tpt.ev_count = 0;
2020 1.5.2.2 jdolecek stats->gptc.ev_count = 0;
2021 1.5.2.2 jdolecek stats->bptc.ev_count = 0;
2022 1.5.2.2 jdolecek stats->mptc.ev_count = 0;
2023 1.5.2.2 jdolecek stats->mngptc.ev_count = 0;
2024 1.5.2.2 jdolecek stats->ptc64.ev_count = 0;
2025 1.5.2.2 jdolecek stats->ptc127.ev_count = 0;
2026 1.5.2.2 jdolecek stats->ptc255.ev_count = 0;
2027 1.5.2.2 jdolecek stats->ptc511.ev_count = 0;
2028 1.5.2.2 jdolecek stats->ptc1023.ev_count = 0;
2029 1.5.2.2 jdolecek stats->ptc1522.ev_count = 0;
2030 1.1 dyoung }
2031 1.1 dyoung
2032 1.5.2.2 jdolecek /************************************************************************
2033 1.5.2.2 jdolecek * ixgbe_sysctl_tdh_handler - Transmit Descriptor Head handler function
2034 1.5.2.2 jdolecek *
2035 1.5.2.2 jdolecek * Retrieves the TDH value from the hardware
2036 1.5.2.2 jdolecek ************************************************************************/
2037 1.5.2.2 jdolecek static int
2038 1.5.2.2 jdolecek ixgbe_sysctl_tdh_handler(SYSCTLFN_ARGS)
2039 1.1 dyoung {
2040 1.5.2.2 jdolecek struct sysctlnode node = *rnode;
2041 1.5.2.2 jdolecek struct tx_ring *txr = (struct tx_ring *)node.sysctl_data;
2042 1.5.2.2 jdolecek uint32_t val;
2043 1.1 dyoung
2044 1.5.2.2 jdolecek if (!txr)
2045 1.5.2.2 jdolecek return (0);
2046 1.1 dyoung
2047 1.5.2.2 jdolecek val = IXGBE_READ_REG(&txr->adapter->hw, IXGBE_TDH(txr->me));
2048 1.5.2.2 jdolecek node.sysctl_data = &val;
2049 1.5.2.2 jdolecek return sysctl_lookup(SYSCTLFN_CALL(&node));
2050 1.5.2.2 jdolecek } /* ixgbe_sysctl_tdh_handler */
2051 1.1 dyoung
2052 1.5.2.2 jdolecek /************************************************************************
2053 1.5.2.2 jdolecek * ixgbe_sysctl_tdt_handler - Transmit Descriptor Tail handler function
2054 1.5.2.2 jdolecek *
2055 1.5.2.2 jdolecek * Retrieves the TDT value from the hardware
2056 1.5.2.2 jdolecek ************************************************************************/
2057 1.5.2.2 jdolecek static int
2058 1.5.2.2 jdolecek ixgbe_sysctl_tdt_handler(SYSCTLFN_ARGS)
2059 1.1 dyoung {
2060 1.5.2.2 jdolecek struct sysctlnode node = *rnode;
2061 1.5.2.2 jdolecek struct tx_ring *txr = (struct tx_ring *)node.sysctl_data;
2062 1.5.2.2 jdolecek uint32_t val;
2063 1.1 dyoung
2064 1.5.2.2 jdolecek if (!txr)
2065 1.5.2.2 jdolecek return (0);
2066 1.5.2.2 jdolecek
2067 1.5.2.2 jdolecek val = IXGBE_READ_REG(&txr->adapter->hw, IXGBE_TDT(txr->me));
2068 1.5.2.2 jdolecek node.sysctl_data = &val;
2069 1.5.2.2 jdolecek return sysctl_lookup(SYSCTLFN_CALL(&node));
2070 1.5.2.2 jdolecek } /* ixgbe_sysctl_tdt_handler */
2071 1.1 dyoung
2072 1.5.2.2 jdolecek /************************************************************************
2073 1.5.2.2 jdolecek * ixgbe_sysctl_rdh_handler - Receive Descriptor Head handler function
2074 1.5.2.2 jdolecek *
2075 1.5.2.2 jdolecek * Retrieves the RDH value from the hardware
2076 1.5.2.2 jdolecek ************************************************************************/
2077 1.5.2.2 jdolecek static int
2078 1.5.2.2 jdolecek ixgbe_sysctl_rdh_handler(SYSCTLFN_ARGS)
2079 1.1 dyoung {
2080 1.5.2.2 jdolecek struct sysctlnode node = *rnode;
2081 1.5.2.2 jdolecek struct rx_ring *rxr = (struct rx_ring *)node.sysctl_data;
2082 1.5.2.2 jdolecek uint32_t val;
2083 1.1 dyoung
2084 1.5.2.2 jdolecek if (!rxr)
2085 1.5.2.2 jdolecek return (0);
2086 1.1 dyoung
2087 1.5.2.2 jdolecek val = IXGBE_READ_REG(&rxr->adapter->hw, IXGBE_RDH(rxr->me));
2088 1.5.2.2 jdolecek node.sysctl_data = &val;
2089 1.5.2.2 jdolecek return sysctl_lookup(SYSCTLFN_CALL(&node));
2090 1.5.2.2 jdolecek } /* ixgbe_sysctl_rdh_handler */
2091 1.5.2.2 jdolecek
2092 1.5.2.2 jdolecek /************************************************************************
2093 1.5.2.2 jdolecek * ixgbe_sysctl_rdt_handler - Receive Descriptor Tail handler function
2094 1.5.2.2 jdolecek *
2095 1.5.2.2 jdolecek * Retrieves the RDT value from the hardware
2096 1.5.2.2 jdolecek ************************************************************************/
2097 1.5.2.2 jdolecek static int
2098 1.5.2.2 jdolecek ixgbe_sysctl_rdt_handler(SYSCTLFN_ARGS)
2099 1.1 dyoung {
2100 1.5.2.2 jdolecek struct sysctlnode node = *rnode;
2101 1.5.2.2 jdolecek struct rx_ring *rxr = (struct rx_ring *)node.sysctl_data;
2102 1.5.2.2 jdolecek uint32_t val;
2103 1.1 dyoung
2104 1.5.2.2 jdolecek if (!rxr)
2105 1.5.2.2 jdolecek return (0);
2106 1.1 dyoung
2107 1.5.2.2 jdolecek val = IXGBE_READ_REG(&rxr->adapter->hw, IXGBE_RDT(rxr->me));
2108 1.5.2.2 jdolecek node.sysctl_data = &val;
2109 1.5.2.2 jdolecek return sysctl_lookup(SYSCTLFN_CALL(&node));
2110 1.5.2.2 jdolecek } /* ixgbe_sysctl_rdt_handler */
2111 1.1 dyoung
2112 1.5.2.2 jdolecek #if 0 /* XXX Badly need to overhaul vlan(4) on NetBSD. */
2113 1.5.2.2 jdolecek /************************************************************************
2114 1.5.2.2 jdolecek * ixgbe_register_vlan
2115 1.5.2.2 jdolecek *
2116 1.5.2.2 jdolecek * Run via vlan config EVENT, it enables us to use the
2117 1.5.2.2 jdolecek * HW Filter table since we can get the vlan id. This
2118 1.5.2.2 jdolecek * just creates the entry in the soft version of the
2119 1.5.2.2 jdolecek * VFTA, init will repopulate the real table.
2120 1.5.2.2 jdolecek ************************************************************************/
2121 1.1 dyoung static void
2122 1.5.2.2 jdolecek ixgbe_register_vlan(void *arg, struct ifnet *ifp, u16 vtag)
2123 1.1 dyoung {
2124 1.5.2.2 jdolecek struct adapter *adapter = ifp->if_softc;
2125 1.5.2.2 jdolecek u16 index, bit;
2126 1.1 dyoung
2127 1.5.2.2 jdolecek if (ifp->if_softc != arg) /* Not our event */
2128 1.5.2.2 jdolecek return;
2129 1.1 dyoung
2130 1.5.2.2 jdolecek if ((vtag == 0) || (vtag > 4095)) /* Invalid */
2131 1.5.2.2 jdolecek return;
2132 1.5.2.2 jdolecek
2133 1.5.2.2 jdolecek IXGBE_CORE_LOCK(adapter);
2134 1.5.2.2 jdolecek index = (vtag >> 5) & 0x7F;
2135 1.5.2.2 jdolecek bit = vtag & 0x1F;
2136 1.5.2.2 jdolecek adapter->shadow_vfta[index] |= (1 << bit);
2137 1.5.2.2 jdolecek ixgbe_setup_vlan_hw_support(adapter);
2138 1.5.2.2 jdolecek IXGBE_CORE_UNLOCK(adapter);
2139 1.5.2.2 jdolecek } /* ixgbe_register_vlan */
2140 1.1 dyoung
2141 1.5.2.2 jdolecek /************************************************************************
2142 1.5.2.2 jdolecek * ixgbe_unregister_vlan
2143 1.5.2.2 jdolecek *
2144 1.5.2.2 jdolecek * Run via vlan unconfig EVENT, remove our entry in the soft vfta.
2145 1.5.2.2 jdolecek ************************************************************************/
2146 1.5.2.2 jdolecek static void
2147 1.5.2.2 jdolecek ixgbe_unregister_vlan(void *arg, struct ifnet *ifp, u16 vtag)
2148 1.5.2.2 jdolecek {
2149 1.5.2.2 jdolecek struct adapter *adapter = ifp->if_softc;
2150 1.5.2.2 jdolecek u16 index, bit;
2151 1.1 dyoung
2152 1.5.2.2 jdolecek if (ifp->if_softc != arg)
2153 1.5.2.2 jdolecek return;
2154 1.1 dyoung
2155 1.5.2.2 jdolecek if ((vtag == 0) || (vtag > 4095)) /* Invalid */
2156 1.5.2.2 jdolecek return;
2157 1.1 dyoung
2158 1.5.2.2 jdolecek IXGBE_CORE_LOCK(adapter);
2159 1.5.2.2 jdolecek index = (vtag >> 5) & 0x7F;
2160 1.5.2.2 jdolecek bit = vtag & 0x1F;
2161 1.5.2.2 jdolecek adapter->shadow_vfta[index] &= ~(1 << bit);
2162 1.5.2.2 jdolecek /* Re-init to load the changes */
2163 1.5.2.2 jdolecek ixgbe_setup_vlan_hw_support(adapter);
2164 1.5.2.2 jdolecek IXGBE_CORE_UNLOCK(adapter);
2165 1.5.2.2 jdolecek } /* ixgbe_unregister_vlan */
2166 1.5.2.2 jdolecek #endif
2167 1.1 dyoung
2168 1.5.2.2 jdolecek static void
2169 1.5.2.2 jdolecek ixgbe_setup_vlan_hw_support(struct adapter *adapter)
2170 1.1 dyoung {
2171 1.5.2.2 jdolecek struct ethercom *ec = &adapter->osdep.ec;
2172 1.5.2.2 jdolecek struct ixgbe_hw *hw = &adapter->hw;
2173 1.5.2.2 jdolecek struct rx_ring *rxr;
2174 1.5.2.2 jdolecek int i;
2175 1.5.2.2 jdolecek u32 ctrl;
2176 1.1 dyoung
2177 1.1 dyoung
2178 1.5.2.2 jdolecek /*
2179 1.5.2.2 jdolecek * We get here thru init_locked, meaning
2180 1.5.2.2 jdolecek * a soft reset, this has already cleared
2181 1.5.2.2 jdolecek * the VFTA and other state, so if there
2182 1.5.2.2 jdolecek * have been no vlan's registered do nothing.
2183 1.5.2.2 jdolecek */
2184 1.5.2.2 jdolecek if (!VLAN_ATTACHED(&adapter->osdep.ec))
2185 1.5.2.2 jdolecek return;
2186 1.1 dyoung
2187 1.5.2.2 jdolecek /* Setup the queues for vlans */
2188 1.5.2.2 jdolecek for (i = 0; i < adapter->num_queues; i++) {
2189 1.5.2.2 jdolecek rxr = &adapter->rx_rings[i];
2190 1.5.2.2 jdolecek /* On 82599 the VLAN enable is per/queue in RXDCTL */
2191 1.5.2.2 jdolecek if (hw->mac.type != ixgbe_mac_82598EB) {
2192 1.5.2.2 jdolecek ctrl = IXGBE_READ_REG(hw, IXGBE_RXDCTL(rxr->me));
2193 1.5.2.2 jdolecek ctrl |= IXGBE_RXDCTL_VME;
2194 1.5.2.2 jdolecek IXGBE_WRITE_REG(hw, IXGBE_RXDCTL(rxr->me), ctrl);
2195 1.5.2.2 jdolecek }
2196 1.5.2.2 jdolecek rxr->vtag_strip = TRUE;
2197 1.1 dyoung }
2198 1.1 dyoung
2199 1.5.2.2 jdolecek if ((ec->ec_capenable & ETHERCAP_VLAN_HWFILTER) == 0)
2200 1.5.2.2 jdolecek return;
2201 1.5.2.2 jdolecek /*
2202 1.5.2.2 jdolecek * A soft reset zero's out the VFTA, so
2203 1.5.2.2 jdolecek * we need to repopulate it now.
2204 1.5.2.2 jdolecek */
2205 1.5.2.2 jdolecek for (i = 0; i < IXGBE_VFTA_SIZE; i++)
2206 1.5.2.2 jdolecek if (adapter->shadow_vfta[i] != 0)
2207 1.5.2.2 jdolecek IXGBE_WRITE_REG(hw, IXGBE_VFTA(i),
2208 1.5.2.2 jdolecek adapter->shadow_vfta[i]);
2209 1.1 dyoung
2210 1.5.2.2 jdolecek ctrl = IXGBE_READ_REG(hw, IXGBE_VLNCTRL);
2211 1.5.2.2 jdolecek /* Enable the Filter Table if enabled */
2212 1.5.2.2 jdolecek if (ec->ec_capenable & ETHERCAP_VLAN_HWFILTER) {
2213 1.5.2.2 jdolecek ctrl &= ~IXGBE_VLNCTRL_CFIEN;
2214 1.5.2.2 jdolecek ctrl |= IXGBE_VLNCTRL_VFE;
2215 1.5.2.2 jdolecek }
2216 1.5.2.2 jdolecek if (hw->mac.type == ixgbe_mac_82598EB)
2217 1.5.2.2 jdolecek ctrl |= IXGBE_VLNCTRL_VME;
2218 1.5.2.2 jdolecek IXGBE_WRITE_REG(hw, IXGBE_VLNCTRL, ctrl);
2219 1.5.2.2 jdolecek } /* ixgbe_setup_vlan_hw_support */
2220 1.1 dyoung
2221 1.5.2.2 jdolecek /************************************************************************
2222 1.5.2.2 jdolecek * ixgbe_get_slot_info
2223 1.5.2.2 jdolecek *
2224 1.5.2.2 jdolecek * Get the width and transaction speed of
2225 1.5.2.2 jdolecek * the slot this adapter is plugged into.
2226 1.5.2.2 jdolecek ************************************************************************/
2227 1.5.2.2 jdolecek static void
2228 1.5.2.2 jdolecek ixgbe_get_slot_info(struct adapter *adapter)
2229 1.5.2.2 jdolecek {
2230 1.5.2.2 jdolecek device_t dev = adapter->dev;
2231 1.5.2.2 jdolecek struct ixgbe_hw *hw = &adapter->hw;
2232 1.5.2.2 jdolecek u32 offset;
2233 1.5.2.2 jdolecek // struct ixgbe_mac_info *mac = &hw->mac;
2234 1.5.2.2 jdolecek u16 link;
2235 1.5.2.2 jdolecek int bus_info_valid = TRUE;
2236 1.5.2.2 jdolecek
2237 1.5.2.2 jdolecek /* Some devices are behind an internal bridge */
2238 1.5.2.2 jdolecek switch (hw->device_id) {
2239 1.5.2.2 jdolecek case IXGBE_DEV_ID_82599_SFP_SF_QP:
2240 1.5.2.2 jdolecek case IXGBE_DEV_ID_82599_QSFP_SF_QP:
2241 1.5.2.2 jdolecek goto get_parent_info;
2242 1.5.2.2 jdolecek default:
2243 1.5.2.2 jdolecek break;
2244 1.1 dyoung }
2245 1.1 dyoung
2246 1.5.2.2 jdolecek ixgbe_get_bus_info(hw);
2247 1.5.2.2 jdolecek
2248 1.5.2.2 jdolecek /*
2249 1.5.2.2 jdolecek * Some devices don't use PCI-E, but there is no need
2250 1.5.2.2 jdolecek * to display "Unknown" for bus speed and width.
2251 1.5.2.2 jdolecek */
2252 1.5.2.2 jdolecek switch (hw->mac.type) {
2253 1.5.2.2 jdolecek case ixgbe_mac_X550EM_x:
2254 1.5.2.2 jdolecek case ixgbe_mac_X550EM_a:
2255 1.5.2.2 jdolecek return;
2256 1.5.2.2 jdolecek default:
2257 1.5.2.2 jdolecek goto display;
2258 1.1 dyoung }
2259 1.1 dyoung
2260 1.5.2.2 jdolecek get_parent_info:
2261 1.5.2.2 jdolecek /*
2262 1.5.2.2 jdolecek * For the Quad port adapter we need to parse back
2263 1.5.2.2 jdolecek * up the PCI tree to find the speed of the expansion
2264 1.5.2.2 jdolecek * slot into which this adapter is plugged. A bit more work.
2265 1.5.2.2 jdolecek */
2266 1.5.2.2 jdolecek dev = device_parent(device_parent(dev));
2267 1.5.2.2 jdolecek #if 0
2268 1.5.2.2 jdolecek #ifdef IXGBE_DEBUG
2269 1.5.2.2 jdolecek device_printf(dev, "parent pcib = %x,%x,%x\n", pci_get_bus(dev),
2270 1.5.2.2 jdolecek pci_get_slot(dev), pci_get_function(dev));
2271 1.5.2.2 jdolecek #endif
2272 1.5.2.2 jdolecek dev = device_parent(device_parent(dev));
2273 1.5.2.2 jdolecek #ifdef IXGBE_DEBUG
2274 1.5.2.2 jdolecek device_printf(dev, "slot pcib = %x,%x,%x\n", pci_get_bus(dev),
2275 1.5.2.2 jdolecek pci_get_slot(dev), pci_get_function(dev));
2276 1.5.2.2 jdolecek #endif
2277 1.5.2.2 jdolecek #endif
2278 1.5.2.2 jdolecek /* Now get the PCI Express Capabilities offset */
2279 1.5.2.2 jdolecek if (pci_get_capability(adapter->osdep.pc, adapter->osdep.tag,
2280 1.5.2.2 jdolecek PCI_CAP_PCIEXPRESS, &offset, NULL)) {
2281 1.5.2.2 jdolecek /*
2282 1.5.2.2 jdolecek * Hmm...can't get PCI-Express capabilities.
2283 1.5.2.2 jdolecek * Falling back to default method.
2284 1.5.2.2 jdolecek */
2285 1.5.2.2 jdolecek bus_info_valid = FALSE;
2286 1.5.2.2 jdolecek ixgbe_get_bus_info(hw);
2287 1.5.2.2 jdolecek goto display;
2288 1.5.2.2 jdolecek }
2289 1.5.2.2 jdolecek /* ...and read the Link Status Register */
2290 1.5.2.2 jdolecek link = pci_conf_read(adapter->osdep.pc, adapter->osdep.tag,
2291 1.5.2.2 jdolecek offset + PCIE_LCSR);
2292 1.5.2.2 jdolecek ixgbe_set_pci_config_data_generic(hw, link >> 16);
2293 1.5.2.2 jdolecek
2294 1.5.2.2 jdolecek display:
2295 1.5.2.2 jdolecek device_printf(dev, "PCI Express Bus: Speed %s Width %s\n",
2296 1.5.2.2 jdolecek ((hw->bus.speed == ixgbe_bus_speed_8000) ? "8.0GT/s" :
2297 1.5.2.2 jdolecek (hw->bus.speed == ixgbe_bus_speed_5000) ? "5.0GT/s" :
2298 1.5.2.2 jdolecek (hw->bus.speed == ixgbe_bus_speed_2500) ? "2.5GT/s" :
2299 1.5.2.2 jdolecek "Unknown"),
2300 1.5.2.2 jdolecek ((hw->bus.width == ixgbe_bus_width_pcie_x8) ? "x8" :
2301 1.5.2.2 jdolecek (hw->bus.width == ixgbe_bus_width_pcie_x4) ? "x4" :
2302 1.5.2.2 jdolecek (hw->bus.width == ixgbe_bus_width_pcie_x1) ? "x1" :
2303 1.5.2.2 jdolecek "Unknown"));
2304 1.5.2.2 jdolecek
2305 1.5.2.2 jdolecek if (bus_info_valid) {
2306 1.5.2.2 jdolecek if ((hw->device_id != IXGBE_DEV_ID_82599_SFP_SF_QP) &&
2307 1.5.2.2 jdolecek ((hw->bus.width <= ixgbe_bus_width_pcie_x4) &&
2308 1.5.2.2 jdolecek (hw->bus.speed == ixgbe_bus_speed_2500))) {
2309 1.5.2.2 jdolecek device_printf(dev, "PCI-Express bandwidth available"
2310 1.5.2.2 jdolecek " for this card\n is not sufficient for"
2311 1.5.2.2 jdolecek " optimal performance.\n");
2312 1.5.2.2 jdolecek device_printf(dev, "For optimal performance a x8 "
2313 1.5.2.2 jdolecek "PCIE, or x4 PCIE Gen2 slot is required.\n");
2314 1.5.2.2 jdolecek }
2315 1.5.2.2 jdolecek if ((hw->device_id == IXGBE_DEV_ID_82599_SFP_SF_QP) &&
2316 1.5.2.2 jdolecek ((hw->bus.width <= ixgbe_bus_width_pcie_x8) &&
2317 1.5.2.2 jdolecek (hw->bus.speed < ixgbe_bus_speed_8000))) {
2318 1.5.2.2 jdolecek device_printf(dev, "PCI-Express bandwidth available"
2319 1.5.2.2 jdolecek " for this card\n is not sufficient for"
2320 1.5.2.2 jdolecek " optimal performance.\n");
2321 1.5.2.2 jdolecek device_printf(dev, "For optimal performance a x8 "
2322 1.5.2.2 jdolecek "PCIE Gen3 slot is required.\n");
2323 1.5.2.2 jdolecek }
2324 1.5.2.2 jdolecek } else
2325 1.5.2.2 jdolecek device_printf(dev, "Unable to determine slot speed/width. The speed/width reported are that of the internal switch.\n");
2326 1.1 dyoung
2327 1.5.2.2 jdolecek return;
2328 1.5.2.2 jdolecek } /* ixgbe_get_slot_info */
2329 1.1 dyoung
2330 1.5.2.2 jdolecek /************************************************************************
2331 1.5.2.2 jdolecek * ixgbe_enable_queue - MSI-X Interrupt Handlers and Tasklets
2332 1.5.2.2 jdolecek ************************************************************************/
2333 1.5.2.2 jdolecek static inline void
2334 1.5.2.2 jdolecek ixgbe_enable_queue(struct adapter *adapter, u32 vector)
2335 1.5.2.2 jdolecek {
2336 1.5.2.2 jdolecek struct ixgbe_hw *hw = &adapter->hw;
2337 1.5.2.2 jdolecek u64 queue = (u64)(1ULL << vector);
2338 1.5.2.2 jdolecek u32 mask;
2339 1.1 dyoung
2340 1.5.2.2 jdolecek if (hw->mac.type == ixgbe_mac_82598EB) {
2341 1.5.2.2 jdolecek mask = (IXGBE_EIMS_RTX_QUEUE & queue);
2342 1.5.2.2 jdolecek IXGBE_WRITE_REG(hw, IXGBE_EIMS, mask);
2343 1.5.2.2 jdolecek } else {
2344 1.5.2.2 jdolecek mask = (queue & 0xFFFFFFFF);
2345 1.5.2.2 jdolecek if (mask)
2346 1.5.2.2 jdolecek IXGBE_WRITE_REG(hw, IXGBE_EIMS_EX(0), mask);
2347 1.5.2.2 jdolecek mask = (queue >> 32);
2348 1.5.2.2 jdolecek if (mask)
2349 1.5.2.2 jdolecek IXGBE_WRITE_REG(hw, IXGBE_EIMS_EX(1), mask);
2350 1.5.2.2 jdolecek }
2351 1.5.2.2 jdolecek } /* ixgbe_enable_queue */
2352 1.5.2.2 jdolecek
2353 1.5.2.2 jdolecek /************************************************************************
2354 1.5.2.2 jdolecek * ixgbe_disable_queue
2355 1.5.2.2 jdolecek ************************************************************************/
2356 1.5.2.2 jdolecek static inline void
2357 1.5.2.2 jdolecek ixgbe_disable_queue(struct adapter *adapter, u32 vector)
2358 1.5.2.2 jdolecek {
2359 1.5.2.2 jdolecek struct ixgbe_hw *hw = &adapter->hw;
2360 1.5.2.2 jdolecek u64 queue = (u64)(1ULL << vector);
2361 1.5.2.2 jdolecek u32 mask;
2362 1.5.2.2 jdolecek
2363 1.5.2.2 jdolecek if (hw->mac.type == ixgbe_mac_82598EB) {
2364 1.5.2.2 jdolecek mask = (IXGBE_EIMS_RTX_QUEUE & queue);
2365 1.5.2.2 jdolecek IXGBE_WRITE_REG(hw, IXGBE_EIMC, mask);
2366 1.5.2.2 jdolecek } else {
2367 1.5.2.2 jdolecek mask = (queue & 0xFFFFFFFF);
2368 1.5.2.2 jdolecek if (mask)
2369 1.5.2.2 jdolecek IXGBE_WRITE_REG(hw, IXGBE_EIMC_EX(0), mask);
2370 1.5.2.2 jdolecek mask = (queue >> 32);
2371 1.5.2.2 jdolecek if (mask)
2372 1.5.2.2 jdolecek IXGBE_WRITE_REG(hw, IXGBE_EIMC_EX(1), mask);
2373 1.5.2.2 jdolecek }
2374 1.5.2.2 jdolecek } /* ixgbe_disable_queue */
2375 1.5.2.2 jdolecek
2376 1.5.2.2 jdolecek /************************************************************************
2377 1.5.2.2 jdolecek * ixgbe_msix_que - MSI-X Queue Interrupt Service routine
2378 1.5.2.2 jdolecek ************************************************************************/
2379 1.5.2.2 jdolecek static int
2380 1.1 dyoung ixgbe_msix_que(void *arg)
2381 1.1 dyoung {
2382 1.1 dyoung struct ix_queue *que = arg;
2383 1.1 dyoung struct adapter *adapter = que->adapter;
2384 1.5.2.2 jdolecek struct ifnet *ifp = adapter->ifp;
2385 1.1 dyoung struct tx_ring *txr = que->txr;
2386 1.1 dyoung struct rx_ring *rxr = que->rxr;
2387 1.5.2.2 jdolecek bool more;
2388 1.1 dyoung u32 newitr = 0;
2389 1.1 dyoung
2390 1.5.2.2 jdolecek /* Protect against spurious interrupts */
2391 1.5.2.2 jdolecek if ((ifp->if_flags & IFF_RUNNING) == 0)
2392 1.5.2.2 jdolecek return 0;
2393 1.5.2.2 jdolecek
2394 1.5.2.2 jdolecek ixgbe_disable_queue(adapter, que->msix);
2395 1.5.2.2 jdolecek ++que->irqs.ev_count;
2396 1.1 dyoung
2397 1.5.2.2 jdolecek #ifdef __NetBSD__
2398 1.5.2.2 jdolecek /* Don't run ixgbe_rxeof in interrupt context */
2399 1.5.2.2 jdolecek more = true;
2400 1.5.2.2 jdolecek #else
2401 1.5.2.2 jdolecek more = ixgbe_rxeof(que);
2402 1.5.2.2 jdolecek #endif
2403 1.1 dyoung
2404 1.1 dyoung IXGBE_TX_LOCK(txr);
2405 1.5.2.2 jdolecek ixgbe_txeof(txr);
2406 1.1 dyoung IXGBE_TX_UNLOCK(txr);
2407 1.1 dyoung
2408 1.1 dyoung /* Do AIM now? */
2409 1.1 dyoung
2410 1.5.2.2 jdolecek if (adapter->enable_aim == false)
2411 1.1 dyoung goto no_calc;
2412 1.1 dyoung /*
2413 1.5.2.2 jdolecek * Do Adaptive Interrupt Moderation:
2414 1.5.2.2 jdolecek * - Write out last calculated setting
2415 1.5.2.2 jdolecek * - Calculate based on average size over
2416 1.5.2.2 jdolecek * the last interval.
2417 1.5.2.2 jdolecek */
2418 1.5.2.2 jdolecek if (que->eitr_setting)
2419 1.5.2.2 jdolecek IXGBE_WRITE_REG(&adapter->hw, IXGBE_EITR(que->msix),
2420 1.5.2.2 jdolecek que->eitr_setting);
2421 1.5.2.2 jdolecek
2422 1.5.2.2 jdolecek que->eitr_setting = 0;
2423 1.1 dyoung
2424 1.5.2.2 jdolecek /* Idle, do nothing */
2425 1.1 dyoung if ((txr->bytes == 0) && (rxr->bytes == 0))
2426 1.1 dyoung goto no_calc;
2427 1.1 dyoung
2428 1.1 dyoung if ((txr->bytes) && (txr->packets))
2429 1.5.2.2 jdolecek newitr = txr->bytes/txr->packets;
2430 1.1 dyoung if ((rxr->bytes) && (rxr->packets))
2431 1.5.2.2 jdolecek newitr = max(newitr, (rxr->bytes / rxr->packets));
2432 1.1 dyoung newitr += 24; /* account for hardware frame, crc */
2433 1.1 dyoung
2434 1.1 dyoung /* set an upper boundary */
2435 1.1 dyoung newitr = min(newitr, 3000);
2436 1.1 dyoung
2437 1.1 dyoung /* Be nice to the mid range */
2438 1.1 dyoung if ((newitr > 300) && (newitr < 1200))
2439 1.1 dyoung newitr = (newitr / 3);
2440 1.1 dyoung else
2441 1.1 dyoung newitr = (newitr / 2);
2442 1.1 dyoung
2443 1.1 dyoung if (adapter->hw.mac.type == ixgbe_mac_82598EB)
2444 1.1 dyoung newitr |= newitr << 16;
2445 1.1 dyoung else
2446 1.1 dyoung newitr |= IXGBE_EITR_CNT_WDIS;
2447 1.1 dyoung
2448 1.1 dyoung /* save for next interrupt */
2449 1.1 dyoung que->eitr_setting = newitr;
2450 1.1 dyoung
2451 1.5.2.2 jdolecek /* Reset state */
2452 1.5.2.2 jdolecek txr->bytes = 0;
2453 1.5.2.2 jdolecek txr->packets = 0;
2454 1.5.2.2 jdolecek rxr->bytes = 0;
2455 1.5.2.2 jdolecek rxr->packets = 0;
2456 1.1 dyoung
2457 1.1 dyoung no_calc:
2458 1.5.2.2 jdolecek if (more)
2459 1.1 dyoung softint_schedule(que->que_si);
2460 1.5.2.2 jdolecek else
2461 1.1 dyoung ixgbe_enable_queue(adapter, que->msix);
2462 1.1 dyoung
2463 1.5.2.2 jdolecek return 1;
2464 1.5.2.2 jdolecek } /* ixgbe_msix_que */
2465 1.1 dyoung
2466 1.5.2.2 jdolecek /************************************************************************
2467 1.5.2.2 jdolecek * ixgbe_media_status - Media Ioctl callback
2468 1.1 dyoung *
2469 1.5.2.2 jdolecek * Called whenever the user queries the status of
2470 1.5.2.2 jdolecek * the interface using ifconfig.
2471 1.5.2.2 jdolecek ************************************************************************/
2472 1.1 dyoung static void
2473 1.5.2.2 jdolecek ixgbe_media_status(struct ifnet *ifp, struct ifmediareq *ifmr)
2474 1.1 dyoung {
2475 1.1 dyoung struct adapter *adapter = ifp->if_softc;
2476 1.5.2.2 jdolecek struct ixgbe_hw *hw = &adapter->hw;
2477 1.5.2.2 jdolecek int layer;
2478 1.1 dyoung
2479 1.1 dyoung INIT_DEBUGOUT("ixgbe_media_status: begin");
2480 1.1 dyoung IXGBE_CORE_LOCK(adapter);
2481 1.1 dyoung ixgbe_update_link_status(adapter);
2482 1.1 dyoung
2483 1.1 dyoung ifmr->ifm_status = IFM_AVALID;
2484 1.1 dyoung ifmr->ifm_active = IFM_ETHER;
2485 1.1 dyoung
2486 1.1 dyoung if (!adapter->link_active) {
2487 1.5.2.2 jdolecek ifmr->ifm_active |= IFM_NONE;
2488 1.1 dyoung IXGBE_CORE_UNLOCK(adapter);
2489 1.1 dyoung return;
2490 1.1 dyoung }
2491 1.1 dyoung
2492 1.1 dyoung ifmr->ifm_status |= IFM_ACTIVE;
2493 1.5.2.2 jdolecek layer = adapter->phy_layer;
2494 1.1 dyoung
2495 1.5.2.2 jdolecek if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_T ||
2496 1.5.2.2 jdolecek layer & IXGBE_PHYSICAL_LAYER_5GBASE_T ||
2497 1.5.2.2 jdolecek layer & IXGBE_PHYSICAL_LAYER_2500BASE_T ||
2498 1.5.2.2 jdolecek layer & IXGBE_PHYSICAL_LAYER_1000BASE_T ||
2499 1.5.2.2 jdolecek layer & IXGBE_PHYSICAL_LAYER_100BASE_TX ||
2500 1.5.2.2 jdolecek layer & IXGBE_PHYSICAL_LAYER_10BASE_T)
2501 1.5.2.2 jdolecek switch (adapter->link_speed) {
2502 1.5.2.2 jdolecek case IXGBE_LINK_SPEED_10GB_FULL:
2503 1.5.2.2 jdolecek ifmr->ifm_active |= IFM_10G_T | IFM_FDX;
2504 1.5.2.2 jdolecek break;
2505 1.5.2.2 jdolecek case IXGBE_LINK_SPEED_5GB_FULL:
2506 1.5.2.2 jdolecek ifmr->ifm_active |= IFM_5000_T | IFM_FDX;
2507 1.5.2.2 jdolecek break;
2508 1.5.2.2 jdolecek case IXGBE_LINK_SPEED_2_5GB_FULL:
2509 1.5.2.2 jdolecek ifmr->ifm_active |= IFM_2500_T | IFM_FDX;
2510 1.5.2.2 jdolecek break;
2511 1.1 dyoung case IXGBE_LINK_SPEED_1GB_FULL:
2512 1.1 dyoung ifmr->ifm_active |= IFM_1000_T | IFM_FDX;
2513 1.1 dyoung break;
2514 1.5.2.2 jdolecek case IXGBE_LINK_SPEED_100_FULL:
2515 1.5.2.2 jdolecek ifmr->ifm_active |= IFM_100_TX | IFM_FDX;
2516 1.5.2.2 jdolecek break;
2517 1.5.2.2 jdolecek case IXGBE_LINK_SPEED_10_FULL:
2518 1.5.2.2 jdolecek ifmr->ifm_active |= IFM_10_T | IFM_FDX;
2519 1.5.2.2 jdolecek break;
2520 1.5.2.2 jdolecek }
2521 1.5.2.2 jdolecek if (layer & IXGBE_PHYSICAL_LAYER_SFP_PLUS_CU ||
2522 1.5.2.2 jdolecek layer & IXGBE_PHYSICAL_LAYER_SFP_ACTIVE_DA)
2523 1.5.2.2 jdolecek switch (adapter->link_speed) {
2524 1.5.2.2 jdolecek case IXGBE_LINK_SPEED_10GB_FULL:
2525 1.5.2.2 jdolecek ifmr->ifm_active |= IFM_10G_TWINAX | IFM_FDX;
2526 1.5.2.2 jdolecek break;
2527 1.5.2.2 jdolecek }
2528 1.5.2.2 jdolecek if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_LR)
2529 1.5.2.2 jdolecek switch (adapter->link_speed) {
2530 1.5.2.2 jdolecek case IXGBE_LINK_SPEED_10GB_FULL:
2531 1.5.2.2 jdolecek ifmr->ifm_active |= IFM_10G_LR | IFM_FDX;
2532 1.5.2.2 jdolecek break;
2533 1.5.2.2 jdolecek case IXGBE_LINK_SPEED_1GB_FULL:
2534 1.5.2.2 jdolecek ifmr->ifm_active |= IFM_1000_LX | IFM_FDX;
2535 1.5.2.2 jdolecek break;
2536 1.5.2.2 jdolecek }
2537 1.5.2.2 jdolecek if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_LRM)
2538 1.5.2.2 jdolecek switch (adapter->link_speed) {
2539 1.5.2.2 jdolecek case IXGBE_LINK_SPEED_10GB_FULL:
2540 1.5.2.2 jdolecek ifmr->ifm_active |= IFM_10G_LRM | IFM_FDX;
2541 1.5.2.2 jdolecek break;
2542 1.5.2.2 jdolecek case IXGBE_LINK_SPEED_1GB_FULL:
2543 1.5.2.2 jdolecek ifmr->ifm_active |= IFM_1000_LX | IFM_FDX;
2544 1.5.2.2 jdolecek break;
2545 1.5.2.2 jdolecek }
2546 1.5.2.2 jdolecek if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_SR ||
2547 1.5.2.2 jdolecek layer & IXGBE_PHYSICAL_LAYER_1000BASE_SX)
2548 1.5.2.2 jdolecek switch (adapter->link_speed) {
2549 1.5.2.2 jdolecek case IXGBE_LINK_SPEED_10GB_FULL:
2550 1.5.2.2 jdolecek ifmr->ifm_active |= IFM_10G_SR | IFM_FDX;
2551 1.5.2.2 jdolecek break;
2552 1.5.2.2 jdolecek case IXGBE_LINK_SPEED_1GB_FULL:
2553 1.5.2.2 jdolecek ifmr->ifm_active |= IFM_1000_SX | IFM_FDX;
2554 1.5.2.2 jdolecek break;
2555 1.5.2.2 jdolecek }
2556 1.5.2.2 jdolecek if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_CX4)
2557 1.5.2.2 jdolecek switch (adapter->link_speed) {
2558 1.5.2.2 jdolecek case IXGBE_LINK_SPEED_10GB_FULL:
2559 1.5.2.2 jdolecek ifmr->ifm_active |= IFM_10G_CX4 | IFM_FDX;
2560 1.5.2.2 jdolecek break;
2561 1.5.2.2 jdolecek }
2562 1.5.2.2 jdolecek /*
2563 1.5.2.2 jdolecek * XXX: These need to use the proper media types once
2564 1.5.2.2 jdolecek * they're added.
2565 1.5.2.2 jdolecek */
2566 1.5.2.2 jdolecek if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_KR)
2567 1.5.2.2 jdolecek switch (adapter->link_speed) {
2568 1.5.2.2 jdolecek case IXGBE_LINK_SPEED_10GB_FULL:
2569 1.5.2.2 jdolecek #ifndef IFM_ETH_XTYPE
2570 1.5.2.2 jdolecek ifmr->ifm_active |= IFM_10G_SR | IFM_FDX;
2571 1.5.2.2 jdolecek #else
2572 1.5.2.2 jdolecek ifmr->ifm_active |= IFM_10G_KR | IFM_FDX;
2573 1.5.2.2 jdolecek #endif
2574 1.5.2.2 jdolecek break;
2575 1.5.2.2 jdolecek case IXGBE_LINK_SPEED_2_5GB_FULL:
2576 1.5.2.2 jdolecek ifmr->ifm_active |= IFM_2500_KX | IFM_FDX;
2577 1.5.2.2 jdolecek break;
2578 1.5.2.2 jdolecek case IXGBE_LINK_SPEED_1GB_FULL:
2579 1.5.2.2 jdolecek ifmr->ifm_active |= IFM_1000_KX | IFM_FDX;
2580 1.5.2.2 jdolecek break;
2581 1.5.2.2 jdolecek }
2582 1.5.2.2 jdolecek else if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_KX4 ||
2583 1.5.2.2 jdolecek layer & IXGBE_PHYSICAL_LAYER_2500BASE_KX ||
2584 1.5.2.2 jdolecek layer & IXGBE_PHYSICAL_LAYER_1000BASE_KX)
2585 1.5.2.2 jdolecek switch (adapter->link_speed) {
2586 1.1 dyoung case IXGBE_LINK_SPEED_10GB_FULL:
2587 1.5.2.2 jdolecek #ifndef IFM_ETH_XTYPE
2588 1.5.2.2 jdolecek ifmr->ifm_active |= IFM_10G_CX4 | IFM_FDX;
2589 1.5.2.2 jdolecek #else
2590 1.5.2.2 jdolecek ifmr->ifm_active |= IFM_10G_KX4 | IFM_FDX;
2591 1.5.2.2 jdolecek #endif
2592 1.1 dyoung break;
2593 1.5.2.2 jdolecek case IXGBE_LINK_SPEED_2_5GB_FULL:
2594 1.5.2.2 jdolecek ifmr->ifm_active |= IFM_2500_KX | IFM_FDX;
2595 1.5.2.2 jdolecek break;
2596 1.5.2.2 jdolecek case IXGBE_LINK_SPEED_1GB_FULL:
2597 1.5.2.2 jdolecek ifmr->ifm_active |= IFM_1000_KX | IFM_FDX;
2598 1.5.2.2 jdolecek break;
2599 1.5.2.2 jdolecek }
2600 1.5.2.2 jdolecek
2601 1.5.2.2 jdolecek /* If nothing is recognized... */
2602 1.5.2.2 jdolecek #if 0
2603 1.5.2.2 jdolecek if (IFM_SUBTYPE(ifmr->ifm_active) == 0)
2604 1.5.2.2 jdolecek ifmr->ifm_active |= IFM_UNKNOWN;
2605 1.5.2.2 jdolecek #endif
2606 1.5.2.2 jdolecek
2607 1.5.2.2 jdolecek ifp->if_baudrate = ifmedia_baudrate(ifmr->ifm_active);
2608 1.5.2.2 jdolecek
2609 1.5.2.2 jdolecek /* Display current flow control setting used on link */
2610 1.5.2.2 jdolecek if (hw->fc.current_mode == ixgbe_fc_rx_pause ||
2611 1.5.2.2 jdolecek hw->fc.current_mode == ixgbe_fc_full)
2612 1.5.2.2 jdolecek ifmr->ifm_active |= IFM_ETH_RXPAUSE;
2613 1.5.2.2 jdolecek if (hw->fc.current_mode == ixgbe_fc_tx_pause ||
2614 1.5.2.2 jdolecek hw->fc.current_mode == ixgbe_fc_full)
2615 1.5.2.2 jdolecek ifmr->ifm_active |= IFM_ETH_TXPAUSE;
2616 1.1 dyoung
2617 1.1 dyoung IXGBE_CORE_UNLOCK(adapter);
2618 1.1 dyoung
2619 1.1 dyoung return;
2620 1.5.2.2 jdolecek } /* ixgbe_media_status */
2621 1.1 dyoung
2622 1.5.2.2 jdolecek /************************************************************************
2623 1.5.2.2 jdolecek * ixgbe_media_change - Media Ioctl callback
2624 1.1 dyoung *
2625 1.5.2.2 jdolecek * Called when the user changes speed/duplex using
2626 1.5.2.2 jdolecek * media/mediopt option with ifconfig.
2627 1.5.2.2 jdolecek ************************************************************************/
2628 1.1 dyoung static int
2629 1.5.2.2 jdolecek ixgbe_media_change(struct ifnet *ifp)
2630 1.1 dyoung {
2631 1.5.2.2 jdolecek struct adapter *adapter = ifp->if_softc;
2632 1.5.2.2 jdolecek struct ifmedia *ifm = &adapter->media;
2633 1.5.2.2 jdolecek struct ixgbe_hw *hw = &adapter->hw;
2634 1.5.2.2 jdolecek ixgbe_link_speed speed = 0;
2635 1.5.2.2 jdolecek ixgbe_link_speed link_caps = 0;
2636 1.5.2.2 jdolecek bool negotiate = false;
2637 1.5.2.2 jdolecek s32 err = IXGBE_NOT_IMPLEMENTED;
2638 1.1 dyoung
2639 1.1 dyoung INIT_DEBUGOUT("ixgbe_media_change: begin");
2640 1.1 dyoung
2641 1.1 dyoung if (IFM_TYPE(ifm->ifm_media) != IFM_ETHER)
2642 1.1 dyoung return (EINVAL);
2643 1.1 dyoung
2644 1.5.2.2 jdolecek if (hw->phy.media_type == ixgbe_media_type_backplane)
2645 1.5.2.2 jdolecek return (ENODEV);
2646 1.1 dyoung
2647 1.1 dyoung /*
2648 1.5.2.2 jdolecek * We don't actually need to check against the supported
2649 1.5.2.2 jdolecek * media types of the adapter; ifmedia will take care of
2650 1.5.2.2 jdolecek * that for us.
2651 1.1 dyoung */
2652 1.5.2.2 jdolecek switch (IFM_SUBTYPE(ifm->ifm_media)) {
2653 1.5.2.2 jdolecek case IFM_AUTO:
2654 1.5.2.2 jdolecek err = hw->mac.ops.get_link_capabilities(hw, &link_caps,
2655 1.5.2.2 jdolecek &negotiate);
2656 1.5.2.2 jdolecek if (err != IXGBE_SUCCESS) {
2657 1.5.2.2 jdolecek device_printf(adapter->dev, "Unable to determine "
2658 1.5.2.2 jdolecek "supported advertise speeds\n");
2659 1.5.2.2 jdolecek return (ENODEV);
2660 1.5.2.2 jdolecek }
2661 1.5.2.2 jdolecek speed |= link_caps;
2662 1.5.2.2 jdolecek break;
2663 1.5.2.2 jdolecek case IFM_10G_T:
2664 1.5.2.2 jdolecek case IFM_10G_LRM:
2665 1.5.2.2 jdolecek case IFM_10G_LR:
2666 1.5.2.2 jdolecek case IFM_10G_TWINAX:
2667 1.5.2.2 jdolecek #ifndef IFM_ETH_XTYPE
2668 1.5.2.2 jdolecek case IFM_10G_SR: /* KR, too */
2669 1.5.2.2 jdolecek case IFM_10G_CX4: /* KX4 */
2670 1.5.2.2 jdolecek #else
2671 1.5.2.2 jdolecek case IFM_10G_KR:
2672 1.5.2.2 jdolecek case IFM_10G_KX4:
2673 1.5.2.2 jdolecek #endif
2674 1.5.2.2 jdolecek speed |= IXGBE_LINK_SPEED_10GB_FULL;
2675 1.5.2.2 jdolecek break;
2676 1.5.2.2 jdolecek case IFM_5000_T:
2677 1.5.2.2 jdolecek speed |= IXGBE_LINK_SPEED_5GB_FULL;
2678 1.5.2.2 jdolecek break;
2679 1.5.2.2 jdolecek case IFM_2500_T:
2680 1.5.2.2 jdolecek case IFM_2500_KX:
2681 1.5.2.2 jdolecek speed |= IXGBE_LINK_SPEED_2_5GB_FULL;
2682 1.1 dyoung break;
2683 1.5.2.2 jdolecek case IFM_1000_T:
2684 1.5.2.2 jdolecek case IFM_1000_LX:
2685 1.5.2.2 jdolecek case IFM_1000_SX:
2686 1.5.2.2 jdolecek case IFM_1000_KX:
2687 1.5.2.2 jdolecek speed |= IXGBE_LINK_SPEED_1GB_FULL;
2688 1.5.2.2 jdolecek break;
2689 1.5.2.2 jdolecek case IFM_100_TX:
2690 1.5.2.2 jdolecek speed |= IXGBE_LINK_SPEED_100_FULL;
2691 1.5.2.2 jdolecek break;
2692 1.5.2.2 jdolecek case IFM_10_T:
2693 1.5.2.2 jdolecek speed |= IXGBE_LINK_SPEED_10_FULL;
2694 1.5.2.2 jdolecek break;
2695 1.5.2.2 jdolecek default:
2696 1.5.2.2 jdolecek goto invalid;
2697 1.1 dyoung }
2698 1.1 dyoung
2699 1.5.2.2 jdolecek hw->mac.autotry_restart = TRUE;
2700 1.5.2.2 jdolecek hw->mac.ops.setup_link(hw, speed, TRUE);
2701 1.5.2.2 jdolecek adapter->advertise = 0;
2702 1.5.2.2 jdolecek if (IFM_SUBTYPE(ifm->ifm_media) != IFM_AUTO) {
2703 1.5.2.2 jdolecek if ((speed & IXGBE_LINK_SPEED_10GB_FULL) != 0)
2704 1.5.2.2 jdolecek adapter->advertise |= 1 << 2;
2705 1.5.2.2 jdolecek if ((speed & IXGBE_LINK_SPEED_1GB_FULL) != 0)
2706 1.5.2.2 jdolecek adapter->advertise |= 1 << 1;
2707 1.5.2.2 jdolecek if ((speed & IXGBE_LINK_SPEED_100_FULL) != 0)
2708 1.5.2.2 jdolecek adapter->advertise |= 1 << 0;
2709 1.5.2.2 jdolecek if ((speed & IXGBE_LINK_SPEED_10_FULL) != 0)
2710 1.5.2.2 jdolecek adapter->advertise |= 1 << 3;
2711 1.5.2.2 jdolecek if ((speed & IXGBE_LINK_SPEED_2_5GB_FULL) != 0)
2712 1.5.2.2 jdolecek adapter->advertise |= 1 << 4;
2713 1.5.2.2 jdolecek if ((speed & IXGBE_LINK_SPEED_5GB_FULL) != 0)
2714 1.5.2.2 jdolecek adapter->advertise |= 1 << 5;
2715 1.1 dyoung }
2716 1.1 dyoung
2717 1.5.2.2 jdolecek return (0);
2718 1.1 dyoung
2719 1.5.2.2 jdolecek invalid:
2720 1.5.2.2 jdolecek device_printf(adapter->dev, "Invalid media type!\n");
2721 1.1 dyoung
2722 1.5.2.2 jdolecek return (EINVAL);
2723 1.5.2.2 jdolecek } /* ixgbe_media_change */
2724 1.1 dyoung
2725 1.5.2.2 jdolecek /************************************************************************
2726 1.5.2.2 jdolecek * ixgbe_set_promisc
2727 1.5.2.2 jdolecek ************************************************************************/
2728 1.1 dyoung static void
2729 1.1 dyoung ixgbe_set_promisc(struct adapter *adapter)
2730 1.1 dyoung {
2731 1.5.2.2 jdolecek struct ifnet *ifp = adapter->ifp;
2732 1.5.2.2 jdolecek int mcnt = 0;
2733 1.5.2.2 jdolecek u32 rctl;
2734 1.1 dyoung struct ether_multi *enm;
2735 1.1 dyoung struct ether_multistep step;
2736 1.1 dyoung struct ethercom *ec = &adapter->osdep.ec;
2737 1.1 dyoung
2738 1.5.2.2 jdolecek KASSERT(mutex_owned(&adapter->core_mtx));
2739 1.5.2.2 jdolecek rctl = IXGBE_READ_REG(&adapter->hw, IXGBE_FCTRL);
2740 1.5.2.2 jdolecek rctl &= (~IXGBE_FCTRL_UPE);
2741 1.5.2.2 jdolecek if (ifp->if_flags & IFF_ALLMULTI)
2742 1.5.2.2 jdolecek mcnt = MAX_NUM_MULTICAST_ADDRESSES;
2743 1.5.2.2 jdolecek else {
2744 1.5.2.2 jdolecek ETHER_LOCK(ec);
2745 1.5.2.2 jdolecek ETHER_FIRST_MULTI(step, ec, enm);
2746 1.5.2.2 jdolecek while (enm != NULL) {
2747 1.5.2.2 jdolecek if (mcnt == MAX_NUM_MULTICAST_ADDRESSES)
2748 1.5.2.2 jdolecek break;
2749 1.5.2.2 jdolecek mcnt++;
2750 1.5.2.2 jdolecek ETHER_NEXT_MULTI(step, enm);
2751 1.1 dyoung }
2752 1.5.2.2 jdolecek ETHER_UNLOCK(ec);
2753 1.1 dyoung }
2754 1.5.2.2 jdolecek if (mcnt < MAX_NUM_MULTICAST_ADDRESSES)
2755 1.5.2.2 jdolecek rctl &= (~IXGBE_FCTRL_MPE);
2756 1.5.2.2 jdolecek IXGBE_WRITE_REG(&adapter->hw, IXGBE_FCTRL, rctl);
2757 1.1 dyoung
2758 1.5.2.2 jdolecek if (ifp->if_flags & IFF_PROMISC) {
2759 1.5.2.2 jdolecek rctl |= (IXGBE_FCTRL_UPE | IXGBE_FCTRL_MPE);
2760 1.5.2.2 jdolecek IXGBE_WRITE_REG(&adapter->hw, IXGBE_FCTRL, rctl);
2761 1.5.2.2 jdolecek } else if (ifp->if_flags & IFF_ALLMULTI) {
2762 1.5.2.2 jdolecek rctl |= IXGBE_FCTRL_MPE;
2763 1.5.2.2 jdolecek rctl &= ~IXGBE_FCTRL_UPE;
2764 1.5.2.2 jdolecek IXGBE_WRITE_REG(&adapter->hw, IXGBE_FCTRL, rctl);
2765 1.5.2.2 jdolecek }
2766 1.5.2.2 jdolecek } /* ixgbe_set_promisc */
2767 1.5.2.2 jdolecek
2768 1.5.2.2 jdolecek /************************************************************************
2769 1.5.2.2 jdolecek * ixgbe_msix_link - Link status change ISR (MSI/MSI-X)
2770 1.5.2.2 jdolecek ************************************************************************/
2771 1.5.2.2 jdolecek static int
2772 1.5.2.2 jdolecek ixgbe_msix_link(void *arg)
2773 1.1 dyoung {
2774 1.5.2.2 jdolecek struct adapter *adapter = arg;
2775 1.5.2.2 jdolecek struct ixgbe_hw *hw = &adapter->hw;
2776 1.5.2.2 jdolecek u32 eicr, eicr_mask;
2777 1.5.2.2 jdolecek s32 retval;
2778 1.1 dyoung
2779 1.5.2.2 jdolecek ++adapter->link_irq.ev_count;
2780 1.1 dyoung
2781 1.5.2.2 jdolecek /* Pause other interrupts */
2782 1.5.2.2 jdolecek IXGBE_WRITE_REG(hw, IXGBE_EIMC, IXGBE_EIMC_OTHER);
2783 1.1 dyoung
2784 1.5.2.2 jdolecek /* First get the cause */
2785 1.5.2.2 jdolecek eicr = IXGBE_READ_REG(hw, IXGBE_EICS);
2786 1.5.2.2 jdolecek /* Be sure the queue bits are not cleared */
2787 1.5.2.2 jdolecek eicr &= ~IXGBE_EICR_RTX_QUEUE;
2788 1.5.2.2 jdolecek /* Clear interrupt with write */
2789 1.5.2.2 jdolecek IXGBE_WRITE_REG(hw, IXGBE_EICR, eicr);
2790 1.1 dyoung
2791 1.5.2.2 jdolecek /* Link status change */
2792 1.5.2.2 jdolecek if (eicr & IXGBE_EICR_LSC) {
2793 1.5.2.2 jdolecek IXGBE_WRITE_REG(hw, IXGBE_EIMC, IXGBE_EIMC_LSC);
2794 1.5.2.2 jdolecek softint_schedule(adapter->link_si);
2795 1.5.2.2 jdolecek }
2796 1.1 dyoung
2797 1.5.2.2 jdolecek if (adapter->hw.mac.type != ixgbe_mac_82598EB) {
2798 1.5.2.2 jdolecek if ((adapter->feat_en & IXGBE_FEATURE_FDIR) &&
2799 1.5.2.2 jdolecek (eicr & IXGBE_EICR_FLOW_DIR)) {
2800 1.5.2.2 jdolecek /* This is probably overkill :) */
2801 1.5.2.2 jdolecek if (!atomic_cas_uint(&adapter->fdir_reinit, 0, 1))
2802 1.5.2.2 jdolecek return 1;
2803 1.5.2.2 jdolecek /* Disable the interrupt */
2804 1.5.2.2 jdolecek IXGBE_WRITE_REG(hw, IXGBE_EIMC, IXGBE_EIMC_FLOW_DIR);
2805 1.5.2.2 jdolecek softint_schedule(adapter->fdir_si);
2806 1.5.2.2 jdolecek }
2807 1.1 dyoung
2808 1.5.2.2 jdolecek if (eicr & IXGBE_EICR_ECC) {
2809 1.5.2.2 jdolecek device_printf(adapter->dev,
2810 1.5.2.2 jdolecek "CRITICAL: ECC ERROR!! Please Reboot!!\n");
2811 1.5.2.2 jdolecek IXGBE_WRITE_REG(hw, IXGBE_EICR, IXGBE_EICR_ECC);
2812 1.5.2.2 jdolecek }
2813 1.1 dyoung
2814 1.5.2.2 jdolecek /* Check for over temp condition */
2815 1.5.2.2 jdolecek if (adapter->feat_en & IXGBE_FEATURE_TEMP_SENSOR) {
2816 1.5.2.2 jdolecek switch (adapter->hw.mac.type) {
2817 1.5.2.2 jdolecek case ixgbe_mac_X550EM_a:
2818 1.5.2.2 jdolecek if (!(eicr & IXGBE_EICR_GPI_SDP0_X550EM_a))
2819 1.5.2.2 jdolecek break;
2820 1.5.2.2 jdolecek IXGBE_WRITE_REG(hw, IXGBE_EIMC,
2821 1.5.2.2 jdolecek IXGBE_EICR_GPI_SDP0_X550EM_a);
2822 1.5.2.2 jdolecek IXGBE_WRITE_REG(hw, IXGBE_EICR,
2823 1.5.2.2 jdolecek IXGBE_EICR_GPI_SDP0_X550EM_a);
2824 1.5.2.2 jdolecek retval = hw->phy.ops.check_overtemp(hw);
2825 1.5.2.2 jdolecek if (retval != IXGBE_ERR_OVERTEMP)
2826 1.5.2.2 jdolecek break;
2827 1.5.2.2 jdolecek device_printf(adapter->dev, "CRITICAL: OVER TEMP!! PHY IS SHUT DOWN!!\n");
2828 1.5.2.2 jdolecek device_printf(adapter->dev, "System shutdown required!\n");
2829 1.5.2.2 jdolecek break;
2830 1.5.2.2 jdolecek default:
2831 1.5.2.2 jdolecek if (!(eicr & IXGBE_EICR_TS))
2832 1.5.2.2 jdolecek break;
2833 1.5.2.2 jdolecek retval = hw->phy.ops.check_overtemp(hw);
2834 1.5.2.2 jdolecek if (retval != IXGBE_ERR_OVERTEMP)
2835 1.5.2.2 jdolecek break;
2836 1.5.2.2 jdolecek device_printf(adapter->dev, "CRITICAL: OVER TEMP!! PHY IS SHUT DOWN!!\n");
2837 1.5.2.2 jdolecek device_printf(adapter->dev, "System shutdown required!\n");
2838 1.5.2.2 jdolecek IXGBE_WRITE_REG(hw, IXGBE_EICR, IXGBE_EICR_TS);
2839 1.5.2.2 jdolecek break;
2840 1.5.2.2 jdolecek }
2841 1.5.2.2 jdolecek }
2842 1.1 dyoung
2843 1.5.2.2 jdolecek /* Check for VF message */
2844 1.5.2.2 jdolecek if ((adapter->feat_en & IXGBE_FEATURE_SRIOV) &&
2845 1.5.2.2 jdolecek (eicr & IXGBE_EICR_MAILBOX))
2846 1.5.2.2 jdolecek softint_schedule(adapter->mbx_si);
2847 1.5.2.2 jdolecek }
2848 1.1 dyoung
2849 1.5.2.2 jdolecek if (ixgbe_is_sfp(hw)) {
2850 1.5.2.2 jdolecek /* Pluggable optics-related interrupt */
2851 1.5.2.2 jdolecek if (hw->mac.type >= ixgbe_mac_X540)
2852 1.5.2.2 jdolecek eicr_mask = IXGBE_EICR_GPI_SDP0_X540;
2853 1.5.2.2 jdolecek else
2854 1.5.2.2 jdolecek eicr_mask = IXGBE_EICR_GPI_SDP2_BY_MAC(hw);
2855 1.1 dyoung
2856 1.5.2.2 jdolecek if (eicr & eicr_mask) {
2857 1.5.2.2 jdolecek IXGBE_WRITE_REG(hw, IXGBE_EICR, eicr_mask);
2858 1.5.2.2 jdolecek softint_schedule(adapter->mod_si);
2859 1.1 dyoung }
2860 1.5.2.2 jdolecek
2861 1.5.2.2 jdolecek if ((hw->mac.type == ixgbe_mac_82599EB) &&
2862 1.5.2.2 jdolecek (eicr & IXGBE_EICR_GPI_SDP1_BY_MAC(hw))) {
2863 1.5.2.2 jdolecek IXGBE_WRITE_REG(hw, IXGBE_EICR,
2864 1.5.2.2 jdolecek IXGBE_EICR_GPI_SDP1_BY_MAC(hw));
2865 1.5.2.2 jdolecek softint_schedule(adapter->msf_si);
2866 1.1 dyoung }
2867 1.1 dyoung }
2868 1.1 dyoung
2869 1.5.2.2 jdolecek /* Check for fan failure */
2870 1.5.2.2 jdolecek if (adapter->feat_en & IXGBE_FEATURE_FAN_FAIL) {
2871 1.5.2.2 jdolecek ixgbe_check_fan_failure(adapter, eicr, TRUE);
2872 1.5.2.2 jdolecek IXGBE_WRITE_REG(hw, IXGBE_EICR, IXGBE_EICR_GPI_SDP1_BY_MAC(hw));
2873 1.5.2.2 jdolecek }
2874 1.1 dyoung
2875 1.5.2.2 jdolecek /* External PHY interrupt */
2876 1.5.2.2 jdolecek if ((hw->phy.type == ixgbe_phy_x550em_ext_t) &&
2877 1.5.2.2 jdolecek (eicr & IXGBE_EICR_GPI_SDP0_X540)) {
2878 1.5.2.2 jdolecek IXGBE_WRITE_REG(hw, IXGBE_EICR, IXGBE_EICR_GPI_SDP0_X540);
2879 1.5.2.2 jdolecek softint_schedule(adapter->phy_si);
2880 1.5.2.2 jdolecek }
2881 1.1 dyoung
2882 1.5.2.2 jdolecek /* Re-enable other interrupts */
2883 1.5.2.2 jdolecek IXGBE_WRITE_REG(hw, IXGBE_EIMS, IXGBE_EIMS_OTHER);
2884 1.5.2.2 jdolecek return 1;
2885 1.5.2.2 jdolecek } /* ixgbe_msix_link */
2886 1.5.2.2 jdolecek
2887 1.5.2.2 jdolecek /************************************************************************
2888 1.5.2.2 jdolecek * ixgbe_sysctl_interrupt_rate_handler
2889 1.5.2.2 jdolecek ************************************************************************/
2890 1.5.2.2 jdolecek static int
2891 1.5.2.2 jdolecek ixgbe_sysctl_interrupt_rate_handler(SYSCTLFN_ARGS)
2892 1.1 dyoung {
2893 1.5.2.2 jdolecek struct sysctlnode node = *rnode;
2894 1.5.2.2 jdolecek struct ix_queue *que = (struct ix_queue *)node.sysctl_data;
2895 1.5.2.2 jdolecek uint32_t reg, usec, rate;
2896 1.5.2.2 jdolecek int error;
2897 1.1 dyoung
2898 1.5.2.2 jdolecek if (que == NULL)
2899 1.5.2.2 jdolecek return 0;
2900 1.5.2.2 jdolecek reg = IXGBE_READ_REG(&que->adapter->hw, IXGBE_EITR(que->msix));
2901 1.5.2.2 jdolecek usec = ((reg & 0x0FF8) >> 3);
2902 1.5.2.2 jdolecek if (usec > 0)
2903 1.5.2.2 jdolecek rate = 500000 / usec;
2904 1.5.2.2 jdolecek else
2905 1.5.2.2 jdolecek rate = 0;
2906 1.5.2.2 jdolecek node.sysctl_data = &rate;
2907 1.5.2.2 jdolecek error = sysctl_lookup(SYSCTLFN_CALL(&node));
2908 1.5.2.2 jdolecek if (error || newp == NULL)
2909 1.5.2.2 jdolecek return error;
2910 1.5.2.2 jdolecek reg &= ~0xfff; /* default, no limitation */
2911 1.5.2.2 jdolecek ixgbe_max_interrupt_rate = 0;
2912 1.5.2.2 jdolecek if (rate > 0 && rate < 500000) {
2913 1.5.2.2 jdolecek if (rate < 1000)
2914 1.5.2.2 jdolecek rate = 1000;
2915 1.5.2.2 jdolecek ixgbe_max_interrupt_rate = rate;
2916 1.5.2.2 jdolecek reg |= ((4000000/rate) & 0xff8);
2917 1.5.2.2 jdolecek }
2918 1.5.2.2 jdolecek IXGBE_WRITE_REG(&que->adapter->hw, IXGBE_EITR(que->msix), reg);
2919 1.1 dyoung
2920 1.5.2.2 jdolecek return (0);
2921 1.5.2.2 jdolecek } /* ixgbe_sysctl_interrupt_rate_handler */
2922 1.1 dyoung
2923 1.5.2.2 jdolecek const struct sysctlnode *
2924 1.5.2.2 jdolecek ixgbe_sysctl_instance(struct adapter *adapter)
2925 1.1 dyoung {
2926 1.5.2.2 jdolecek const char *dvname;
2927 1.5.2.2 jdolecek struct sysctllog **log;
2928 1.5.2.2 jdolecek int rc;
2929 1.5.2.2 jdolecek const struct sysctlnode *rnode;
2930 1.1 dyoung
2931 1.5.2.2 jdolecek if (adapter->sysctltop != NULL)
2932 1.5.2.2 jdolecek return adapter->sysctltop;
2933 1.1 dyoung
2934 1.5.2.2 jdolecek log = &adapter->sysctllog;
2935 1.5.2.2 jdolecek dvname = device_xname(adapter->dev);
2936 1.1 dyoung
2937 1.5.2.2 jdolecek if ((rc = sysctl_createv(log, 0, NULL, &rnode,
2938 1.5.2.2 jdolecek 0, CTLTYPE_NODE, dvname,
2939 1.5.2.2 jdolecek SYSCTL_DESCR("ixgbe information and settings"),
2940 1.5.2.2 jdolecek NULL, 0, NULL, 0, CTL_HW, CTL_CREATE, CTL_EOL)) != 0)
2941 1.5.2.2 jdolecek goto err;
2942 1.1 dyoung
2943 1.5.2.2 jdolecek return rnode;
2944 1.5.2.2 jdolecek err:
2945 1.5.2.2 jdolecek printf("%s: sysctl_createv failed, rc = %d\n", __func__, rc);
2946 1.5.2.2 jdolecek return NULL;
2947 1.1 dyoung }
2948 1.1 dyoung
2949 1.5.2.2 jdolecek /************************************************************************
2950 1.5.2.2 jdolecek * ixgbe_add_device_sysctls
2951 1.5.2.2 jdolecek ************************************************************************/
2952 1.1 dyoung static void
2953 1.5.2.2 jdolecek ixgbe_add_device_sysctls(struct adapter *adapter)
2954 1.1 dyoung {
2955 1.5.2.2 jdolecek device_t dev = adapter->dev;
2956 1.5.2.2 jdolecek struct ixgbe_hw *hw = &adapter->hw;
2957 1.5.2.2 jdolecek struct sysctllog **log;
2958 1.5.2.2 jdolecek const struct sysctlnode *rnode, *cnode;
2959 1.1 dyoung
2960 1.5.2.2 jdolecek log = &adapter->sysctllog;
2961 1.1 dyoung
2962 1.5.2.2 jdolecek if ((rnode = ixgbe_sysctl_instance(adapter)) == NULL) {
2963 1.5.2.2 jdolecek aprint_error_dev(dev, "could not create sysctl root\n");
2964 1.5.2.2 jdolecek return;
2965 1.5.2.2 jdolecek }
2966 1.1 dyoung
2967 1.5.2.2 jdolecek if (sysctl_createv(log, 0, &rnode, &cnode,
2968 1.5.2.2 jdolecek CTLFLAG_READONLY, CTLTYPE_INT,
2969 1.5.2.2 jdolecek "num_rx_desc", SYSCTL_DESCR("Number of rx descriptors"),
2970 1.5.2.2 jdolecek NULL, 0, &adapter->num_rx_desc, 0, CTL_CREATE, CTL_EOL) != 0)
2971 1.5.2.2 jdolecek aprint_error_dev(dev, "could not create sysctl\n");
2972 1.1 dyoung
2973 1.5.2.2 jdolecek if (sysctl_createv(log, 0, &rnode, &cnode,
2974 1.5.2.2 jdolecek CTLFLAG_READONLY, CTLTYPE_INT,
2975 1.5.2.2 jdolecek "num_queues", SYSCTL_DESCR("Number of queues"),
2976 1.5.2.2 jdolecek NULL, 0, &adapter->num_queues, 0, CTL_CREATE, CTL_EOL) != 0)
2977 1.5.2.2 jdolecek aprint_error_dev(dev, "could not create sysctl\n");
2978 1.1 dyoung
2979 1.5.2.2 jdolecek /* Sysctls for all devices */
2980 1.5.2.2 jdolecek if (sysctl_createv(log, 0, &rnode, &cnode, CTLFLAG_READWRITE,
2981 1.5.2.2 jdolecek CTLTYPE_INT, "fc", SYSCTL_DESCR(IXGBE_SYSCTL_DESC_SET_FC),
2982 1.5.2.2 jdolecek ixgbe_sysctl_flowcntl, 0, (void *)adapter, 0, CTL_CREATE,
2983 1.5.2.2 jdolecek CTL_EOL) != 0)
2984 1.5.2.2 jdolecek aprint_error_dev(dev, "could not create sysctl\n");
2985 1.1 dyoung
2986 1.5.2.2 jdolecek adapter->enable_aim = ixgbe_enable_aim;
2987 1.5.2.2 jdolecek if (sysctl_createv(log, 0, &rnode, &cnode, CTLFLAG_READWRITE,
2988 1.5.2.2 jdolecek CTLTYPE_BOOL, "enable_aim", SYSCTL_DESCR("Interrupt Moderation"),
2989 1.5.2.2 jdolecek NULL, 0, &adapter->enable_aim, 0, CTL_CREATE, CTL_EOL) != 0)
2990 1.5.2.2 jdolecek aprint_error_dev(dev, "could not create sysctl\n");
2991 1.1 dyoung
2992 1.5.2.2 jdolecek if (sysctl_createv(log, 0, &rnode, &cnode,
2993 1.5.2.2 jdolecek CTLFLAG_READWRITE, CTLTYPE_INT,
2994 1.5.2.2 jdolecek "advertise_speed", SYSCTL_DESCR(IXGBE_SYSCTL_DESC_ADV_SPEED),
2995 1.5.2.2 jdolecek ixgbe_sysctl_advertise, 0, (void *)adapter, 0, CTL_CREATE,
2996 1.5.2.2 jdolecek CTL_EOL) != 0)
2997 1.5.2.2 jdolecek aprint_error_dev(dev, "could not create sysctl\n");
2998 1.5.2.2 jdolecek
2999 1.5.2.2 jdolecek #ifdef IXGBE_DEBUG
3000 1.5.2.2 jdolecek /* testing sysctls (for all devices) */
3001 1.5.2.2 jdolecek if (sysctl_createv(log, 0, &rnode, &cnode, CTLFLAG_READWRITE,
3002 1.5.2.2 jdolecek CTLTYPE_INT, "power_state", SYSCTL_DESCR("PCI Power State"),
3003 1.5.2.2 jdolecek ixgbe_sysctl_power_state, 0, (void *)adapter, 0, CTL_CREATE,
3004 1.5.2.2 jdolecek CTL_EOL) != 0)
3005 1.5.2.2 jdolecek aprint_error_dev(dev, "could not create sysctl\n");
3006 1.5.2.2 jdolecek
3007 1.5.2.2 jdolecek if (sysctl_createv(log, 0, &rnode, &cnode, CTLFLAG_READONLY,
3008 1.5.2.2 jdolecek CTLTYPE_STRING, "print_rss_config",
3009 1.5.2.2 jdolecek SYSCTL_DESCR("Prints RSS Configuration"),
3010 1.5.2.2 jdolecek ixgbe_sysctl_print_rss_config, 0, (void *)adapter, 0, CTL_CREATE,
3011 1.5.2.2 jdolecek CTL_EOL) != 0)
3012 1.5.2.2 jdolecek aprint_error_dev(dev, "could not create sysctl\n");
3013 1.5.2.2 jdolecek #endif
3014 1.5.2.2 jdolecek /* for X550 series devices */
3015 1.5.2.2 jdolecek if (hw->mac.type >= ixgbe_mac_X550)
3016 1.5.2.2 jdolecek if (sysctl_createv(log, 0, &rnode, &cnode, CTLFLAG_READWRITE,
3017 1.5.2.2 jdolecek CTLTYPE_INT, "dmac", SYSCTL_DESCR("DMA Coalesce"),
3018 1.5.2.2 jdolecek ixgbe_sysctl_dmac, 0, (void *)adapter, 0, CTL_CREATE,
3019 1.5.2.2 jdolecek CTL_EOL) != 0)
3020 1.5.2.2 jdolecek aprint_error_dev(dev, "could not create sysctl\n");
3021 1.5.2.2 jdolecek
3022 1.5.2.2 jdolecek /* for WoL-capable devices */
3023 1.5.2.2 jdolecek if (hw->device_id == IXGBE_DEV_ID_X550EM_X_10G_T) {
3024 1.5.2.2 jdolecek if (sysctl_createv(log, 0, &rnode, &cnode, CTLFLAG_READWRITE,
3025 1.5.2.2 jdolecek CTLTYPE_BOOL, "wol_enable",
3026 1.5.2.2 jdolecek SYSCTL_DESCR("Enable/Disable Wake on LAN"),
3027 1.5.2.2 jdolecek ixgbe_sysctl_wol_enable, 0, (void *)adapter, 0, CTL_CREATE,
3028 1.5.2.2 jdolecek CTL_EOL) != 0)
3029 1.5.2.2 jdolecek aprint_error_dev(dev, "could not create sysctl\n");
3030 1.5.2.2 jdolecek
3031 1.5.2.2 jdolecek if (sysctl_createv(log, 0, &rnode, &cnode, CTLFLAG_READWRITE,
3032 1.5.2.2 jdolecek CTLTYPE_INT, "wufc",
3033 1.5.2.2 jdolecek SYSCTL_DESCR("Enable/Disable Wake Up Filters"),
3034 1.5.2.2 jdolecek ixgbe_sysctl_wufc, 0, (void *)adapter, 0, CTL_CREATE,
3035 1.5.2.2 jdolecek CTL_EOL) != 0)
3036 1.5.2.2 jdolecek aprint_error_dev(dev, "could not create sysctl\n");
3037 1.5.2.2 jdolecek }
3038 1.5.2.2 jdolecek
3039 1.5.2.2 jdolecek /* for X552/X557-AT devices */
3040 1.5.2.2 jdolecek if (hw->device_id == IXGBE_DEV_ID_X550EM_X_10G_T) {
3041 1.5.2.2 jdolecek const struct sysctlnode *phy_node;
3042 1.5.2.2 jdolecek
3043 1.5.2.2 jdolecek if (sysctl_createv(log, 0, &rnode, &phy_node, 0, CTLTYPE_NODE,
3044 1.5.2.2 jdolecek "phy", SYSCTL_DESCR("External PHY sysctls"),
3045 1.5.2.2 jdolecek NULL, 0, NULL, 0, CTL_CREATE, CTL_EOL) != 0) {
3046 1.5.2.2 jdolecek aprint_error_dev(dev, "could not create sysctl\n");
3047 1.5.2.2 jdolecek return;
3048 1.5.2.2 jdolecek }
3049 1.5.2.2 jdolecek
3050 1.5.2.2 jdolecek if (sysctl_createv(log, 0, &phy_node, &cnode, CTLFLAG_READONLY,
3051 1.5.2.2 jdolecek CTLTYPE_INT, "temp",
3052 1.5.2.2 jdolecek SYSCTL_DESCR("Current External PHY Temperature (Celsius)"),
3053 1.5.2.2 jdolecek ixgbe_sysctl_phy_temp, 0, (void *)adapter, 0, CTL_CREATE,
3054 1.5.2.2 jdolecek CTL_EOL) != 0)
3055 1.5.2.2 jdolecek aprint_error_dev(dev, "could not create sysctl\n");
3056 1.5.2.2 jdolecek
3057 1.5.2.2 jdolecek if (sysctl_createv(log, 0, &phy_node, &cnode, CTLFLAG_READONLY,
3058 1.5.2.2 jdolecek CTLTYPE_INT, "overtemp_occurred",
3059 1.5.2.2 jdolecek SYSCTL_DESCR("External PHY High Temperature Event Occurred"),
3060 1.5.2.2 jdolecek ixgbe_sysctl_phy_overtemp_occurred, 0, (void *)adapter, 0,
3061 1.5.2.2 jdolecek CTL_CREATE, CTL_EOL) != 0)
3062 1.5.2.2 jdolecek aprint_error_dev(dev, "could not create sysctl\n");
3063 1.1 dyoung }
3064 1.1 dyoung
3065 1.5.2.2 jdolecek if (adapter->feat_cap & IXGBE_FEATURE_EEE) {
3066 1.5.2.2 jdolecek if (sysctl_createv(log, 0, &rnode, &cnode, CTLFLAG_READWRITE,
3067 1.5.2.2 jdolecek CTLTYPE_INT, "eee_state",
3068 1.5.2.2 jdolecek SYSCTL_DESCR("EEE Power Save State"),
3069 1.5.2.2 jdolecek ixgbe_sysctl_eee_state, 0, (void *)adapter, 0, CTL_CREATE,
3070 1.5.2.2 jdolecek CTL_EOL) != 0)
3071 1.5.2.2 jdolecek aprint_error_dev(dev, "could not create sysctl\n");
3072 1.5.2.2 jdolecek }
3073 1.5.2.2 jdolecek } /* ixgbe_add_device_sysctls */
3074 1.5.2.2 jdolecek
3075 1.5.2.2 jdolecek /************************************************************************
3076 1.5.2.2 jdolecek * ixgbe_allocate_pci_resources
3077 1.5.2.2 jdolecek ************************************************************************/
3078 1.1 dyoung static int
3079 1.5.2.2 jdolecek ixgbe_allocate_pci_resources(struct adapter *adapter,
3080 1.5.2.2 jdolecek const struct pci_attach_args *pa)
3081 1.1 dyoung {
3082 1.5.2.2 jdolecek pcireg_t memtype;
3083 1.1 dyoung device_t dev = adapter->dev;
3084 1.5.2.2 jdolecek bus_addr_t addr;
3085 1.5.2.2 jdolecek int flags;
3086 1.1 dyoung
3087 1.5.2.2 jdolecek memtype = pci_mapreg_type(pa->pa_pc, pa->pa_tag, PCI_BAR(0));
3088 1.5.2.2 jdolecek switch (memtype) {
3089 1.5.2.2 jdolecek case PCI_MAPREG_TYPE_MEM | PCI_MAPREG_MEM_TYPE_32BIT:
3090 1.5.2.2 jdolecek case PCI_MAPREG_TYPE_MEM | PCI_MAPREG_MEM_TYPE_64BIT:
3091 1.5.2.2 jdolecek adapter->osdep.mem_bus_space_tag = pa->pa_memt;
3092 1.5.2.2 jdolecek if (pci_mapreg_info(pa->pa_pc, pa->pa_tag, PCI_BAR(0),
3093 1.5.2.2 jdolecek memtype, &addr, &adapter->osdep.mem_size, &flags) != 0)
3094 1.5.2.2 jdolecek goto map_err;
3095 1.5.2.2 jdolecek if ((flags & BUS_SPACE_MAP_PREFETCHABLE) != 0) {
3096 1.5.2.2 jdolecek aprint_normal_dev(dev, "clearing prefetchable bit\n");
3097 1.5.2.2 jdolecek flags &= ~BUS_SPACE_MAP_PREFETCHABLE;
3098 1.5.2.2 jdolecek }
3099 1.5.2.2 jdolecek if (bus_space_map(adapter->osdep.mem_bus_space_tag, addr,
3100 1.5.2.2 jdolecek adapter->osdep.mem_size, flags,
3101 1.5.2.2 jdolecek &adapter->osdep.mem_bus_space_handle) != 0) {
3102 1.5.2.2 jdolecek map_err:
3103 1.5.2.2 jdolecek adapter->osdep.mem_size = 0;
3104 1.5.2.2 jdolecek aprint_error_dev(dev, "unable to map BAR0\n");
3105 1.5.2.2 jdolecek return ENXIO;
3106 1.5.2.2 jdolecek }
3107 1.5.2.2 jdolecek break;
3108 1.5.2.2 jdolecek default:
3109 1.5.2.2 jdolecek aprint_error_dev(dev, "unexpected type on BAR0\n");
3110 1.1 dyoung return ENXIO;
3111 1.1 dyoung }
3112 1.1 dyoung
3113 1.5.2.2 jdolecek return (0);
3114 1.5.2.2 jdolecek } /* ixgbe_allocate_pci_resources */
3115 1.1 dyoung
3116 1.5.2.2 jdolecek /************************************************************************
3117 1.5.2.2 jdolecek * ixgbe_detach - Device removal routine
3118 1.5.2.2 jdolecek *
3119 1.5.2.2 jdolecek * Called when the driver is being removed.
3120 1.5.2.2 jdolecek * Stops the adapter and deallocates all the resources
3121 1.5.2.2 jdolecek * that were allocated for driver operation.
3122 1.5.2.2 jdolecek *
3123 1.5.2.2 jdolecek * return 0 on success, positive on failure
3124 1.5.2.2 jdolecek ************************************************************************/
3125 1.5.2.2 jdolecek static int
3126 1.5.2.2 jdolecek ixgbe_detach(device_t dev, int flags)
3127 1.5.2.2 jdolecek {
3128 1.5.2.2 jdolecek struct adapter *adapter = device_private(dev);
3129 1.5.2.2 jdolecek struct ix_queue *que = adapter->queues;
3130 1.5.2.2 jdolecek struct rx_ring *rxr = adapter->rx_rings;
3131 1.5.2.2 jdolecek struct tx_ring *txr = adapter->tx_rings;
3132 1.5.2.2 jdolecek struct ixgbe_hw *hw = &adapter->hw;
3133 1.5.2.2 jdolecek struct ixgbe_hw_stats *stats = &adapter->stats.pf;
3134 1.5.2.2 jdolecek u32 ctrl_ext;
3135 1.5.2.2 jdolecek
3136 1.5.2.2 jdolecek INIT_DEBUGOUT("ixgbe_detach: begin");
3137 1.5.2.2 jdolecek if (adapter->osdep.attached == false)
3138 1.5.2.2 jdolecek return 0;
3139 1.5.2.2 jdolecek
3140 1.5.2.2 jdolecek if (ixgbe_pci_iov_detach(dev) != 0) {
3141 1.5.2.2 jdolecek device_printf(dev, "SR-IOV in use; detach first.\n");
3142 1.5.2.2 jdolecek return (EBUSY);
3143 1.1 dyoung }
3144 1.1 dyoung
3145 1.5.2.2 jdolecek /* Stop the interface. Callouts are stopped in it. */
3146 1.5.2.2 jdolecek ixgbe_ifstop(adapter->ifp, 1);
3147 1.5.2.2 jdolecek #if NVLAN > 0
3148 1.5.2.2 jdolecek /* Make sure VLANs are not using driver */
3149 1.5.2.2 jdolecek if (!VLAN_ATTACHED(&adapter->osdep.ec))
3150 1.5.2.2 jdolecek ; /* nothing to do: no VLANs */
3151 1.5.2.2 jdolecek else if ((flags & (DETACH_SHUTDOWN|DETACH_FORCE)) != 0)
3152 1.5.2.2 jdolecek vlan_ifdetach(adapter->ifp);
3153 1.5.2.2 jdolecek else {
3154 1.5.2.2 jdolecek aprint_error_dev(dev, "VLANs in use, detach first\n");
3155 1.5.2.2 jdolecek return (EBUSY);
3156 1.5.2.2 jdolecek }
3157 1.1 dyoung #endif
3158 1.5.2.2 jdolecek
3159 1.5.2.2 jdolecek pmf_device_deregister(dev);
3160 1.5.2.2 jdolecek
3161 1.5.2.2 jdolecek ether_ifdetach(adapter->ifp);
3162 1.5.2.2 jdolecek /* Stop the adapter */
3163 1.5.2.2 jdolecek IXGBE_CORE_LOCK(adapter);
3164 1.5.2.2 jdolecek ixgbe_setup_low_power_mode(adapter);
3165 1.5.2.2 jdolecek IXGBE_CORE_UNLOCK(adapter);
3166 1.5.2.2 jdolecek
3167 1.5.2.2 jdolecek for (int i = 0; i < adapter->num_queues; i++, que++, txr++) {
3168 1.5.2.2 jdolecek if (!(adapter->feat_en & IXGBE_FEATURE_LEGACY_TX))
3169 1.5.2.2 jdolecek softint_disestablish(txr->txr_si);
3170 1.5.2.2 jdolecek softint_disestablish(que->que_si);
3171 1.1 dyoung }
3172 1.1 dyoung
3173 1.5.2.2 jdolecek /* Drain the Link queue */
3174 1.5.2.2 jdolecek softint_disestablish(adapter->link_si);
3175 1.5.2.2 jdolecek softint_disestablish(adapter->mod_si);
3176 1.5.2.2 jdolecek softint_disestablish(adapter->msf_si);
3177 1.5.2.2 jdolecek if (adapter->feat_cap & IXGBE_FEATURE_SRIOV)
3178 1.5.2.2 jdolecek softint_disestablish(adapter->mbx_si);
3179 1.5.2.2 jdolecek softint_disestablish(adapter->phy_si);
3180 1.5.2.2 jdolecek if (adapter->feat_en & IXGBE_FEATURE_FDIR)
3181 1.5.2.2 jdolecek softint_disestablish(adapter->fdir_si);
3182 1.1 dyoung
3183 1.5.2.2 jdolecek /* let hardware know driver is unloading */
3184 1.5.2.2 jdolecek ctrl_ext = IXGBE_READ_REG(&adapter->hw, IXGBE_CTRL_EXT);
3185 1.5.2.2 jdolecek ctrl_ext &= ~IXGBE_CTRL_EXT_DRV_LOAD;
3186 1.5.2.2 jdolecek IXGBE_WRITE_REG(&adapter->hw, IXGBE_CTRL_EXT, ctrl_ext);
3187 1.1 dyoung
3188 1.5.2.2 jdolecek callout_halt(&adapter->timer, NULL);
3189 1.1 dyoung
3190 1.5.2.2 jdolecek if (adapter->feat_en & IXGBE_FEATURE_NETMAP)
3191 1.5.2.2 jdolecek netmap_detach(adapter->ifp);
3192 1.5.2.2 jdolecek
3193 1.5.2.2 jdolecek ixgbe_free_pci_resources(adapter);
3194 1.5.2.2 jdolecek #if 0 /* XXX the NetBSD port is probably missing something here */
3195 1.5.2.2 jdolecek bus_generic_detach(dev);
3196 1.1 dyoung #endif
3197 1.5.2.2 jdolecek if_detach(adapter->ifp);
3198 1.5.2.2 jdolecek if_percpuq_destroy(adapter->ipq);
3199 1.1 dyoung
3200 1.5.2.2 jdolecek sysctl_teardown(&adapter->sysctllog);
3201 1.5.2.2 jdolecek evcnt_detach(&adapter->handleq);
3202 1.5.2.2 jdolecek evcnt_detach(&adapter->req);
3203 1.5.2.2 jdolecek evcnt_detach(&adapter->efbig_tx_dma_setup);
3204 1.5.2.2 jdolecek evcnt_detach(&adapter->mbuf_defrag_failed);
3205 1.5.2.2 jdolecek evcnt_detach(&adapter->efbig2_tx_dma_setup);
3206 1.5.2.2 jdolecek evcnt_detach(&adapter->einval_tx_dma_setup);
3207 1.5.2.2 jdolecek evcnt_detach(&adapter->other_tx_dma_setup);
3208 1.5.2.2 jdolecek evcnt_detach(&adapter->eagain_tx_dma_setup);
3209 1.5.2.2 jdolecek evcnt_detach(&adapter->enomem_tx_dma_setup);
3210 1.5.2.2 jdolecek evcnt_detach(&adapter->watchdog_events);
3211 1.5.2.2 jdolecek evcnt_detach(&adapter->tso_err);
3212 1.5.2.2 jdolecek evcnt_detach(&adapter->link_irq);
3213 1.5.2.2 jdolecek
3214 1.5.2.2 jdolecek txr = adapter->tx_rings;
3215 1.5.2.2 jdolecek for (int i = 0; i < adapter->num_queues; i++, rxr++, txr++) {
3216 1.5.2.2 jdolecek evcnt_detach(&adapter->queues[i].irqs);
3217 1.5.2.2 jdolecek evcnt_detach(&txr->no_desc_avail);
3218 1.5.2.2 jdolecek evcnt_detach(&txr->total_packets);
3219 1.5.2.2 jdolecek evcnt_detach(&txr->tso_tx);
3220 1.5.2.2 jdolecek #ifndef IXGBE_LEGACY_TX
3221 1.5.2.2 jdolecek evcnt_detach(&txr->pcq_drops);
3222 1.5.2.2 jdolecek #endif
3223 1.5.2.2 jdolecek
3224 1.5.2.2 jdolecek if (i < __arraycount(stats->mpc)) {
3225 1.5.2.2 jdolecek evcnt_detach(&stats->mpc[i]);
3226 1.5.2.2 jdolecek if (hw->mac.type == ixgbe_mac_82598EB)
3227 1.5.2.2 jdolecek evcnt_detach(&stats->rnbc[i]);
3228 1.5.2.2 jdolecek }
3229 1.5.2.2 jdolecek if (i < __arraycount(stats->pxontxc)) {
3230 1.5.2.2 jdolecek evcnt_detach(&stats->pxontxc[i]);
3231 1.5.2.2 jdolecek evcnt_detach(&stats->pxonrxc[i]);
3232 1.5.2.2 jdolecek evcnt_detach(&stats->pxofftxc[i]);
3233 1.5.2.2 jdolecek evcnt_detach(&stats->pxoffrxc[i]);
3234 1.5.2.2 jdolecek evcnt_detach(&stats->pxon2offc[i]);
3235 1.5.2.2 jdolecek }
3236 1.5.2.2 jdolecek if (i < __arraycount(stats->qprc)) {
3237 1.5.2.2 jdolecek evcnt_detach(&stats->qprc[i]);
3238 1.5.2.2 jdolecek evcnt_detach(&stats->qptc[i]);
3239 1.5.2.2 jdolecek evcnt_detach(&stats->qbrc[i]);
3240 1.5.2.2 jdolecek evcnt_detach(&stats->qbtc[i]);
3241 1.5.2.2 jdolecek evcnt_detach(&stats->qprdc[i]);
3242 1.1 dyoung }
3243 1.1 dyoung
3244 1.5.2.2 jdolecek evcnt_detach(&rxr->rx_packets);
3245 1.5.2.2 jdolecek evcnt_detach(&rxr->rx_bytes);
3246 1.5.2.2 jdolecek evcnt_detach(&rxr->rx_copies);
3247 1.5.2.2 jdolecek evcnt_detach(&rxr->no_jmbuf);
3248 1.5.2.2 jdolecek evcnt_detach(&rxr->rx_discarded);
3249 1.1 dyoung }
3250 1.5.2.2 jdolecek evcnt_detach(&stats->ipcs);
3251 1.5.2.2 jdolecek evcnt_detach(&stats->l4cs);
3252 1.5.2.2 jdolecek evcnt_detach(&stats->ipcs_bad);
3253 1.5.2.2 jdolecek evcnt_detach(&stats->l4cs_bad);
3254 1.5.2.2 jdolecek evcnt_detach(&stats->intzero);
3255 1.5.2.2 jdolecek evcnt_detach(&stats->legint);
3256 1.5.2.2 jdolecek evcnt_detach(&stats->crcerrs);
3257 1.5.2.2 jdolecek evcnt_detach(&stats->illerrc);
3258 1.5.2.2 jdolecek evcnt_detach(&stats->errbc);
3259 1.5.2.2 jdolecek evcnt_detach(&stats->mspdc);
3260 1.5.2.2 jdolecek if (hw->mac.type >= ixgbe_mac_X550)
3261 1.5.2.2 jdolecek evcnt_detach(&stats->mbsdc);
3262 1.5.2.2 jdolecek evcnt_detach(&stats->mpctotal);
3263 1.5.2.2 jdolecek evcnt_detach(&stats->mlfc);
3264 1.5.2.2 jdolecek evcnt_detach(&stats->mrfc);
3265 1.5.2.2 jdolecek evcnt_detach(&stats->rlec);
3266 1.5.2.2 jdolecek evcnt_detach(&stats->lxontxc);
3267 1.5.2.2 jdolecek evcnt_detach(&stats->lxonrxc);
3268 1.5.2.2 jdolecek evcnt_detach(&stats->lxofftxc);
3269 1.5.2.2 jdolecek evcnt_detach(&stats->lxoffrxc);
3270 1.5.2.2 jdolecek
3271 1.5.2.2 jdolecek /* Packet Reception Stats */
3272 1.5.2.2 jdolecek evcnt_detach(&stats->tor);
3273 1.5.2.2 jdolecek evcnt_detach(&stats->gorc);
3274 1.5.2.2 jdolecek evcnt_detach(&stats->tpr);
3275 1.5.2.2 jdolecek evcnt_detach(&stats->gprc);
3276 1.5.2.2 jdolecek evcnt_detach(&stats->mprc);
3277 1.5.2.2 jdolecek evcnt_detach(&stats->bprc);
3278 1.5.2.2 jdolecek evcnt_detach(&stats->prc64);
3279 1.5.2.2 jdolecek evcnt_detach(&stats->prc127);
3280 1.5.2.2 jdolecek evcnt_detach(&stats->prc255);
3281 1.5.2.2 jdolecek evcnt_detach(&stats->prc511);
3282 1.5.2.2 jdolecek evcnt_detach(&stats->prc1023);
3283 1.5.2.2 jdolecek evcnt_detach(&stats->prc1522);
3284 1.5.2.2 jdolecek evcnt_detach(&stats->ruc);
3285 1.5.2.2 jdolecek evcnt_detach(&stats->rfc);
3286 1.5.2.2 jdolecek evcnt_detach(&stats->roc);
3287 1.5.2.2 jdolecek evcnt_detach(&stats->rjc);
3288 1.5.2.2 jdolecek evcnt_detach(&stats->mngprc);
3289 1.5.2.2 jdolecek evcnt_detach(&stats->mngpdc);
3290 1.5.2.2 jdolecek evcnt_detach(&stats->xec);
3291 1.5.2.2 jdolecek
3292 1.5.2.2 jdolecek /* Packet Transmission Stats */
3293 1.5.2.2 jdolecek evcnt_detach(&stats->gotc);
3294 1.5.2.2 jdolecek evcnt_detach(&stats->tpt);
3295 1.5.2.2 jdolecek evcnt_detach(&stats->gptc);
3296 1.5.2.2 jdolecek evcnt_detach(&stats->bptc);
3297 1.5.2.2 jdolecek evcnt_detach(&stats->mptc);
3298 1.5.2.2 jdolecek evcnt_detach(&stats->mngptc);
3299 1.5.2.2 jdolecek evcnt_detach(&stats->ptc64);
3300 1.5.2.2 jdolecek evcnt_detach(&stats->ptc127);
3301 1.5.2.2 jdolecek evcnt_detach(&stats->ptc255);
3302 1.5.2.2 jdolecek evcnt_detach(&stats->ptc511);
3303 1.5.2.2 jdolecek evcnt_detach(&stats->ptc1023);
3304 1.5.2.2 jdolecek evcnt_detach(&stats->ptc1522);
3305 1.5.2.2 jdolecek
3306 1.5.2.2 jdolecek ixgbe_free_transmit_structures(adapter);
3307 1.5.2.2 jdolecek ixgbe_free_receive_structures(adapter);
3308 1.5.2.2 jdolecek free(adapter->queues, M_DEVBUF);
3309 1.5.2.2 jdolecek free(adapter->mta, M_DEVBUF);
3310 1.5.2.2 jdolecek
3311 1.5.2.2 jdolecek IXGBE_CORE_LOCK_DESTROY(adapter);
3312 1.1 dyoung
3313 1.1 dyoung return (0);
3314 1.5.2.2 jdolecek } /* ixgbe_detach */
3315 1.1 dyoung
3316 1.5.2.2 jdolecek /************************************************************************
3317 1.5.2.2 jdolecek * ixgbe_setup_low_power_mode - LPLU/WoL preparation
3318 1.5.2.2 jdolecek *
3319 1.5.2.2 jdolecek * Prepare the adapter/port for LPLU and/or WoL
3320 1.5.2.2 jdolecek ************************************************************************/
3321 1.1 dyoung static int
3322 1.5.2.2 jdolecek ixgbe_setup_low_power_mode(struct adapter *adapter)
3323 1.1 dyoung {
3324 1.5.2.2 jdolecek struct ixgbe_hw *hw = &adapter->hw;
3325 1.5.2.2 jdolecek device_t dev = adapter->dev;
3326 1.5.2.2 jdolecek s32 error = 0;
3327 1.1 dyoung
3328 1.5.2.2 jdolecek KASSERT(mutex_owned(&adapter->core_mtx));
3329 1.1 dyoung
3330 1.5.2.2 jdolecek /* Limit power management flow to X550EM baseT */
3331 1.5.2.2 jdolecek if (hw->device_id == IXGBE_DEV_ID_X550EM_X_10G_T &&
3332 1.5.2.2 jdolecek hw->phy.ops.enter_lplu) {
3333 1.5.2.2 jdolecek /* X550EM baseT adapters need a special LPLU flow */
3334 1.5.2.2 jdolecek hw->phy.reset_disable = true;
3335 1.5.2.2 jdolecek ixgbe_stop(adapter);
3336 1.5.2.2 jdolecek error = hw->phy.ops.enter_lplu(hw);
3337 1.5.2.2 jdolecek if (error)
3338 1.5.2.2 jdolecek device_printf(dev,
3339 1.5.2.2 jdolecek "Error entering LPLU: %d\n", error);
3340 1.5.2.2 jdolecek hw->phy.reset_disable = false;
3341 1.5.2.2 jdolecek } else {
3342 1.5.2.2 jdolecek /* Just stop for other adapters */
3343 1.5.2.2 jdolecek ixgbe_stop(adapter);
3344 1.1 dyoung }
3345 1.1 dyoung
3346 1.5.2.2 jdolecek if (!hw->wol_enabled) {
3347 1.5.2.2 jdolecek ixgbe_set_phy_power(hw, FALSE);
3348 1.5.2.2 jdolecek IXGBE_WRITE_REG(hw, IXGBE_WUFC, 0);
3349 1.5.2.2 jdolecek IXGBE_WRITE_REG(hw, IXGBE_WUC, 0);
3350 1.5.2.2 jdolecek } else {
3351 1.5.2.2 jdolecek /* Turn off support for APM wakeup. (Using ACPI instead) */
3352 1.5.2.2 jdolecek IXGBE_WRITE_REG(hw, IXGBE_GRC,
3353 1.5.2.2 jdolecek IXGBE_READ_REG(hw, IXGBE_GRC) & ~(u32)2);
3354 1.1 dyoung
3355 1.5.2.2 jdolecek /*
3356 1.5.2.2 jdolecek * Clear Wake Up Status register to prevent any previous wakeup
3357 1.5.2.2 jdolecek * events from waking us up immediately after we suspend.
3358 1.5.2.2 jdolecek */
3359 1.5.2.2 jdolecek IXGBE_WRITE_REG(hw, IXGBE_WUS, 0xffffffff);
3360 1.1 dyoung
3361 1.5.2.2 jdolecek /*
3362 1.5.2.2 jdolecek * Program the Wakeup Filter Control register with user filter
3363 1.5.2.2 jdolecek * settings
3364 1.5.2.2 jdolecek */
3365 1.5.2.2 jdolecek IXGBE_WRITE_REG(hw, IXGBE_WUFC, adapter->wufc);
3366 1.5.2.2 jdolecek
3367 1.5.2.2 jdolecek /* Enable wakeups and power management in Wakeup Control */
3368 1.5.2.2 jdolecek IXGBE_WRITE_REG(hw, IXGBE_WUC,
3369 1.5.2.2 jdolecek IXGBE_WUC_WKEN | IXGBE_WUC_PME_EN);
3370 1.1 dyoung
3371 1.1 dyoung }
3372 1.1 dyoung
3373 1.5.2.2 jdolecek return error;
3374 1.5.2.2 jdolecek } /* ixgbe_setup_low_power_mode */
3375 1.1 dyoung
3376 1.5.2.2 jdolecek /************************************************************************
3377 1.5.2.2 jdolecek * ixgbe_shutdown - Shutdown entry point
3378 1.5.2.2 jdolecek ************************************************************************/
3379 1.5.2.2 jdolecek #if 0 /* XXX NetBSD ought to register something like this through pmf(9) */
3380 1.1 dyoung static int
3381 1.5.2.2 jdolecek ixgbe_shutdown(device_t dev)
3382 1.1 dyoung {
3383 1.5.2.2 jdolecek struct adapter *adapter = device_private(dev);
3384 1.5.2.2 jdolecek int error = 0;
3385 1.1 dyoung
3386 1.5.2.2 jdolecek INIT_DEBUGOUT("ixgbe_shutdown: begin");
3387 1.1 dyoung
3388 1.5.2.2 jdolecek IXGBE_CORE_LOCK(adapter);
3389 1.5.2.2 jdolecek error = ixgbe_setup_low_power_mode(adapter);
3390 1.5.2.2 jdolecek IXGBE_CORE_UNLOCK(adapter);
3391 1.1 dyoung
3392 1.5.2.2 jdolecek return (error);
3393 1.5.2.2 jdolecek } /* ixgbe_shutdown */
3394 1.5.2.2 jdolecek #endif
3395 1.1 dyoung
3396 1.5.2.2 jdolecek /************************************************************************
3397 1.5.2.2 jdolecek * ixgbe_suspend
3398 1.5.2.2 jdolecek *
3399 1.5.2.2 jdolecek * From D0 to D3
3400 1.5.2.2 jdolecek ************************************************************************/
3401 1.5.2.2 jdolecek static bool
3402 1.5.2.2 jdolecek ixgbe_suspend(device_t dev, const pmf_qual_t *qual)
3403 1.1 dyoung {
3404 1.5.2.2 jdolecek struct adapter *adapter = device_private(dev);
3405 1.5.2.2 jdolecek int error = 0;
3406 1.1 dyoung
3407 1.5.2.2 jdolecek INIT_DEBUGOUT("ixgbe_suspend: begin");
3408 1.1 dyoung
3409 1.5.2.2 jdolecek IXGBE_CORE_LOCK(adapter);
3410 1.1 dyoung
3411 1.5.2.2 jdolecek error = ixgbe_setup_low_power_mode(adapter);
3412 1.1 dyoung
3413 1.5.2.2 jdolecek IXGBE_CORE_UNLOCK(adapter);
3414 1.5.2.2 jdolecek
3415 1.5.2.2 jdolecek return (error);
3416 1.5.2.2 jdolecek } /* ixgbe_suspend */
3417 1.1 dyoung
3418 1.5.2.2 jdolecek /************************************************************************
3419 1.5.2.2 jdolecek * ixgbe_resume
3420 1.5.2.2 jdolecek *
3421 1.5.2.2 jdolecek * From D3 to D0
3422 1.5.2.2 jdolecek ************************************************************************/
3423 1.5.2.2 jdolecek static bool
3424 1.5.2.2 jdolecek ixgbe_resume(device_t dev, const pmf_qual_t *qual)
3425 1.5.2.2 jdolecek {
3426 1.5.2.2 jdolecek struct adapter *adapter = device_private(dev);
3427 1.5.2.2 jdolecek struct ifnet *ifp = adapter->ifp;
3428 1.5.2.2 jdolecek struct ixgbe_hw *hw = &adapter->hw;
3429 1.5.2.2 jdolecek u32 wus;
3430 1.1 dyoung
3431 1.5.2.2 jdolecek INIT_DEBUGOUT("ixgbe_resume: begin");
3432 1.1 dyoung
3433 1.5.2.2 jdolecek IXGBE_CORE_LOCK(adapter);
3434 1.1 dyoung
3435 1.5.2.2 jdolecek /* Read & clear WUS register */
3436 1.5.2.2 jdolecek wus = IXGBE_READ_REG(hw, IXGBE_WUS);
3437 1.5.2.2 jdolecek if (wus)
3438 1.5.2.2 jdolecek device_printf(dev, "Woken up by (WUS): %#010x\n",
3439 1.5.2.2 jdolecek IXGBE_READ_REG(hw, IXGBE_WUS));
3440 1.5.2.2 jdolecek IXGBE_WRITE_REG(hw, IXGBE_WUS, 0xffffffff);
3441 1.5.2.2 jdolecek /* And clear WUFC until next low-power transition */
3442 1.5.2.2 jdolecek IXGBE_WRITE_REG(hw, IXGBE_WUFC, 0);
3443 1.5.2.2 jdolecek
3444 1.5.2.2 jdolecek /*
3445 1.5.2.2 jdolecek * Required after D3->D0 transition;
3446 1.5.2.2 jdolecek * will re-advertise all previous advertised speeds
3447 1.5.2.2 jdolecek */
3448 1.5.2.2 jdolecek if (ifp->if_flags & IFF_UP)
3449 1.5.2.2 jdolecek ixgbe_init_locked(adapter);
3450 1.5.2.2 jdolecek
3451 1.5.2.2 jdolecek IXGBE_CORE_UNLOCK(adapter);
3452 1.5.2.2 jdolecek
3453 1.5.2.2 jdolecek return true;
3454 1.5.2.2 jdolecek } /* ixgbe_resume */
3455 1.5.2.2 jdolecek
3456 1.5.2.2 jdolecek /*
3457 1.5.2.2 jdolecek * Set the various hardware offload abilities.
3458 1.5.2.2 jdolecek *
3459 1.5.2.2 jdolecek * This takes the ifnet's if_capenable flags (e.g. set by the user using
3460 1.5.2.2 jdolecek * ifconfig) and indicates to the OS via the ifnet's if_hwassist field what
3461 1.5.2.2 jdolecek * mbuf offload flags the driver will understand.
3462 1.5.2.2 jdolecek */
3463 1.5.2.2 jdolecek static void
3464 1.5.2.2 jdolecek ixgbe_set_if_hwassist(struct adapter *adapter)
3465 1.5.2.2 jdolecek {
3466 1.5.2.2 jdolecek /* XXX */
3467 1.1 dyoung }
3468 1.1 dyoung
3469 1.5.2.2 jdolecek /************************************************************************
3470 1.5.2.2 jdolecek * ixgbe_init_locked - Init entry point
3471 1.1 dyoung *
3472 1.5.2.2 jdolecek * Used in two ways: It is used by the stack as an init
3473 1.5.2.2 jdolecek * entry point in network interface structure. It is also
3474 1.5.2.2 jdolecek * used by the driver as a hw/sw initialization routine to
3475 1.5.2.2 jdolecek * get to a consistent state.
3476 1.1 dyoung *
3477 1.5.2.2 jdolecek * return 0 on success, positive on failure
3478 1.5.2.2 jdolecek ************************************************************************/
3479 1.5.2.2 jdolecek static void
3480 1.5.2.2 jdolecek ixgbe_init_locked(struct adapter *adapter)
3481 1.1 dyoung {
3482 1.5.2.2 jdolecek struct ifnet *ifp = adapter->ifp;
3483 1.5.2.2 jdolecek device_t dev = adapter->dev;
3484 1.1 dyoung struct ixgbe_hw *hw = &adapter->hw;
3485 1.5.2.2 jdolecek struct tx_ring *txr;
3486 1.5.2.2 jdolecek struct rx_ring *rxr;
3487 1.5.2.2 jdolecek u32 txdctl, mhadd;
3488 1.5.2.2 jdolecek u32 rxdctl, rxctrl;
3489 1.5.2.2 jdolecek u32 ctrl_ext;
3490 1.5.2.2 jdolecek int err = 0;
3491 1.1 dyoung
3492 1.5.2.2 jdolecek /* XXX check IFF_UP and IFF_RUNNING, power-saving state! */
3493 1.1 dyoung
3494 1.5.2.2 jdolecek KASSERT(mutex_owned(&adapter->core_mtx));
3495 1.5.2.2 jdolecek INIT_DEBUGOUT("ixgbe_init_locked: begin");
3496 1.1 dyoung
3497 1.5.2.2 jdolecek hw->adapter_stopped = FALSE;
3498 1.5.2.2 jdolecek ixgbe_stop_adapter(hw);
3499 1.5.2.2 jdolecek callout_stop(&adapter->timer);
3500 1.1 dyoung
3501 1.5.2.2 jdolecek /* XXX I moved this here from the SIOCSIFMTU case in ixgbe_ioctl(). */
3502 1.1 dyoung adapter->max_frame_size =
3503 1.5.2.2 jdolecek ifp->if_mtu + ETHER_HDR_LEN + ETHER_CRC_LEN;
3504 1.1 dyoung
3505 1.5.2.2 jdolecek /* Queue indices may change with IOV mode */
3506 1.5.2.2 jdolecek ixgbe_align_all_queue_indices(adapter);
3507 1.1 dyoung
3508 1.5.2.2 jdolecek /* reprogram the RAR[0] in case user changed it. */
3509 1.5.2.2 jdolecek ixgbe_set_rar(hw, 0, hw->mac.addr, adapter->pool, IXGBE_RAH_AV);
3510 1.1 dyoung
3511 1.5.2.2 jdolecek /* Get the latest mac address, User can use a LAA */
3512 1.5.2.2 jdolecek memcpy(hw->mac.addr, CLLADDR(ifp->if_sadl),
3513 1.5.2.2 jdolecek IXGBE_ETH_LENGTH_OF_ADDRESS);
3514 1.5.2.2 jdolecek ixgbe_set_rar(hw, 0, hw->mac.addr, adapter->pool, 1);
3515 1.5.2.2 jdolecek hw->addr_ctrl.rar_used_count = 1;
3516 1.5.2.2 jdolecek
3517 1.5.2.2 jdolecek /* Set hardware offload abilities from ifnet flags */
3518 1.5.2.2 jdolecek ixgbe_set_if_hwassist(adapter);
3519 1.5.2.2 jdolecek
3520 1.5.2.2 jdolecek /* Prepare transmit descriptors and buffers */
3521 1.5.2.2 jdolecek if (ixgbe_setup_transmit_structures(adapter)) {
3522 1.5.2.2 jdolecek device_printf(dev, "Could not setup transmit structures\n");
3523 1.5.2.2 jdolecek ixgbe_stop(adapter);
3524 1.5.2.2 jdolecek return;
3525 1.5.2.2 jdolecek }
3526 1.5.2.2 jdolecek
3527 1.5.2.2 jdolecek ixgbe_init_hw(hw);
3528 1.5.2.2 jdolecek ixgbe_initialize_iov(adapter);
3529 1.5.2.2 jdolecek ixgbe_initialize_transmit_units(adapter);
3530 1.5.2.2 jdolecek
3531 1.5.2.2 jdolecek /* Setup Multicast table */
3532 1.5.2.2 jdolecek ixgbe_set_multi(adapter);
3533 1.5.2.2 jdolecek
3534 1.5.2.2 jdolecek /* Determine the correct mbuf pool, based on frame size */
3535 1.5.2.2 jdolecek if (adapter->max_frame_size <= MCLBYTES)
3536 1.5.2.2 jdolecek adapter->rx_mbuf_sz = MCLBYTES;
3537 1.5.2.2 jdolecek else
3538 1.5.2.2 jdolecek adapter->rx_mbuf_sz = MJUMPAGESIZE;
3539 1.5.2.2 jdolecek
3540 1.5.2.2 jdolecek /* Prepare receive descriptors and buffers */
3541 1.5.2.2 jdolecek if (ixgbe_setup_receive_structures(adapter)) {
3542 1.5.2.2 jdolecek device_printf(dev, "Could not setup receive structures\n");
3543 1.5.2.2 jdolecek ixgbe_stop(adapter);
3544 1.5.2.2 jdolecek return;
3545 1.5.2.2 jdolecek }
3546 1.5.2.2 jdolecek
3547 1.5.2.2 jdolecek /* Configure RX settings */
3548 1.5.2.2 jdolecek ixgbe_initialize_receive_units(adapter);
3549 1.5.2.2 jdolecek
3550 1.5.2.2 jdolecek /* Enable SDP & MSI-X interrupts based on adapter */
3551 1.5.2.2 jdolecek ixgbe_config_gpie(adapter);
3552 1.5.2.2 jdolecek
3553 1.5.2.2 jdolecek /* Set MTU size */
3554 1.5.2.2 jdolecek if (ifp->if_mtu > ETHERMTU) {
3555 1.5.2.2 jdolecek /* aka IXGBE_MAXFRS on 82599 and newer */
3556 1.5.2.2 jdolecek mhadd = IXGBE_READ_REG(hw, IXGBE_MHADD);
3557 1.5.2.2 jdolecek mhadd &= ~IXGBE_MHADD_MFS_MASK;
3558 1.5.2.2 jdolecek mhadd |= adapter->max_frame_size << IXGBE_MHADD_MFS_SHIFT;
3559 1.5.2.2 jdolecek IXGBE_WRITE_REG(hw, IXGBE_MHADD, mhadd);
3560 1.5.2.2 jdolecek }
3561 1.5.2.2 jdolecek
3562 1.5.2.2 jdolecek /* Now enable all the queues */
3563 1.5.2.2 jdolecek for (int i = 0; i < adapter->num_queues; i++) {
3564 1.5.2.2 jdolecek txr = &adapter->tx_rings[i];
3565 1.5.2.2 jdolecek txdctl = IXGBE_READ_REG(hw, IXGBE_TXDCTL(txr->me));
3566 1.5.2.2 jdolecek txdctl |= IXGBE_TXDCTL_ENABLE;
3567 1.5.2.2 jdolecek /* Set WTHRESH to 8, burst writeback */
3568 1.5.2.2 jdolecek txdctl |= (8 << 16);
3569 1.5.2.2 jdolecek /*
3570 1.5.2.2 jdolecek * When the internal queue falls below PTHRESH (32),
3571 1.5.2.2 jdolecek * start prefetching as long as there are at least
3572 1.5.2.2 jdolecek * HTHRESH (1) buffers ready. The values are taken
3573 1.5.2.2 jdolecek * from the Intel linux driver 3.8.21.
3574 1.5.2.2 jdolecek * Prefetching enables tx line rate even with 1 queue.
3575 1.5.2.2 jdolecek */
3576 1.5.2.2 jdolecek txdctl |= (32 << 0) | (1 << 8);
3577 1.5.2.2 jdolecek IXGBE_WRITE_REG(hw, IXGBE_TXDCTL(txr->me), txdctl);
3578 1.5.2.2 jdolecek }
3579 1.5.2.2 jdolecek
3580 1.5.2.2 jdolecek for (int i = 0, j = 0; i < adapter->num_queues; i++) {
3581 1.5.2.2 jdolecek rxr = &adapter->rx_rings[i];
3582 1.5.2.2 jdolecek rxdctl = IXGBE_READ_REG(hw, IXGBE_RXDCTL(rxr->me));
3583 1.5.2.2 jdolecek if (hw->mac.type == ixgbe_mac_82598EB) {
3584 1.5.2.2 jdolecek /*
3585 1.5.2.2 jdolecek * PTHRESH = 21
3586 1.5.2.2 jdolecek * HTHRESH = 4
3587 1.5.2.2 jdolecek * WTHRESH = 8
3588 1.5.2.2 jdolecek */
3589 1.5.2.2 jdolecek rxdctl &= ~0x3FFFFF;
3590 1.5.2.2 jdolecek rxdctl |= 0x080420;
3591 1.5.2.2 jdolecek }
3592 1.5.2.2 jdolecek rxdctl |= IXGBE_RXDCTL_ENABLE;
3593 1.5.2.2 jdolecek IXGBE_WRITE_REG(hw, IXGBE_RXDCTL(rxr->me), rxdctl);
3594 1.5.2.2 jdolecek for (; j < 10; j++) {
3595 1.5.2.2 jdolecek if (IXGBE_READ_REG(hw, IXGBE_RXDCTL(rxr->me)) &
3596 1.5.2.2 jdolecek IXGBE_RXDCTL_ENABLE)
3597 1.5.2.2 jdolecek break;
3598 1.5.2.2 jdolecek else
3599 1.5.2.2 jdolecek msec_delay(1);
3600 1.5.2.2 jdolecek }
3601 1.5.2.2 jdolecek wmb();
3602 1.5.2.2 jdolecek
3603 1.5.2.2 jdolecek /*
3604 1.5.2.2 jdolecek * In netmap mode, we must preserve the buffers made
3605 1.5.2.2 jdolecek * available to userspace before the if_init()
3606 1.5.2.2 jdolecek * (this is true by default on the TX side, because
3607 1.5.2.2 jdolecek * init makes all buffers available to userspace).
3608 1.5.2.2 jdolecek *
3609 1.5.2.2 jdolecek * netmap_reset() and the device specific routines
3610 1.5.2.2 jdolecek * (e.g. ixgbe_setup_receive_rings()) map these
3611 1.5.2.2 jdolecek * buffers at the end of the NIC ring, so here we
3612 1.5.2.2 jdolecek * must set the RDT (tail) register to make sure
3613 1.5.2.2 jdolecek * they are not overwritten.
3614 1.5.2.2 jdolecek *
3615 1.5.2.2 jdolecek * In this driver the NIC ring starts at RDH = 0,
3616 1.5.2.2 jdolecek * RDT points to the last slot available for reception (?),
3617 1.5.2.2 jdolecek * so RDT = num_rx_desc - 1 means the whole ring is available.
3618 1.5.2.2 jdolecek */
3619 1.5.2.2 jdolecek #ifdef DEV_NETMAP
3620 1.5.2.2 jdolecek if ((adapter->feat_en & IXGBE_FEATURE_NETMAP) &&
3621 1.5.2.2 jdolecek (ifp->if_capenable & IFCAP_NETMAP)) {
3622 1.5.2.2 jdolecek struct netmap_adapter *na = NA(adapter->ifp);
3623 1.5.2.2 jdolecek struct netmap_kring *kring = &na->rx_rings[i];
3624 1.5.2.2 jdolecek int t = na->num_rx_desc - 1 - nm_kr_rxspace(kring);
3625 1.5.2.2 jdolecek
3626 1.5.2.2 jdolecek IXGBE_WRITE_REG(hw, IXGBE_RDT(rxr->me), t);
3627 1.5.2.2 jdolecek } else
3628 1.5.2.2 jdolecek #endif /* DEV_NETMAP */
3629 1.5.2.2 jdolecek IXGBE_WRITE_REG(hw, IXGBE_RDT(rxr->me),
3630 1.5.2.2 jdolecek adapter->num_rx_desc - 1);
3631 1.5.2.2 jdolecek }
3632 1.5.2.2 jdolecek
3633 1.5.2.2 jdolecek /* Enable Receive engine */
3634 1.5.2.2 jdolecek rxctrl = IXGBE_READ_REG(hw, IXGBE_RXCTRL);
3635 1.5.2.2 jdolecek if (hw->mac.type == ixgbe_mac_82598EB)
3636 1.5.2.2 jdolecek rxctrl |= IXGBE_RXCTRL_DMBYPS;
3637 1.5.2.2 jdolecek rxctrl |= IXGBE_RXCTRL_RXEN;
3638 1.5.2.2 jdolecek ixgbe_enable_rx_dma(hw, rxctrl);
3639 1.5.2.2 jdolecek
3640 1.5.2.2 jdolecek callout_reset(&adapter->timer, hz, ixgbe_local_timer, adapter);
3641 1.1 dyoung
3642 1.5.2.2 jdolecek /* Set up MSI-X routing */
3643 1.5.2.2 jdolecek if (adapter->feat_en & IXGBE_FEATURE_MSIX) {
3644 1.5.2.2 jdolecek ixgbe_configure_ivars(adapter);
3645 1.5.2.2 jdolecek /* Set up auto-mask */
3646 1.5.2.2 jdolecek if (hw->mac.type == ixgbe_mac_82598EB)
3647 1.5.2.2 jdolecek IXGBE_WRITE_REG(hw, IXGBE_EIAM, IXGBE_EICS_RTX_QUEUE);
3648 1.5.2.2 jdolecek else {
3649 1.5.2.2 jdolecek IXGBE_WRITE_REG(hw, IXGBE_EIAM_EX(0), 0xFFFFFFFF);
3650 1.5.2.2 jdolecek IXGBE_WRITE_REG(hw, IXGBE_EIAM_EX(1), 0xFFFFFFFF);
3651 1.5.2.2 jdolecek }
3652 1.5.2.2 jdolecek } else { /* Simple settings for Legacy/MSI */
3653 1.5.2.2 jdolecek ixgbe_set_ivar(adapter, 0, 0, 0);
3654 1.5.2.2 jdolecek ixgbe_set_ivar(adapter, 0, 0, 1);
3655 1.5.2.2 jdolecek IXGBE_WRITE_REG(hw, IXGBE_EIAM, IXGBE_EICS_RTX_QUEUE);
3656 1.5.2.2 jdolecek }
3657 1.1 dyoung
3658 1.5.2.2 jdolecek ixgbe_init_fdir(adapter);
3659 1.1 dyoung
3660 1.1 dyoung /*
3661 1.5.2.2 jdolecek * Check on any SFP devices that
3662 1.5.2.2 jdolecek * need to be kick-started
3663 1.1 dyoung */
3664 1.5.2.2 jdolecek if (hw->phy.type == ixgbe_phy_none) {
3665 1.5.2.2 jdolecek err = hw->phy.ops.identify(hw);
3666 1.5.2.2 jdolecek if (err == IXGBE_ERR_SFP_NOT_SUPPORTED) {
3667 1.5.2.2 jdolecek device_printf(dev,
3668 1.5.2.2 jdolecek "Unsupported SFP+ module type was detected.\n");
3669 1.5.2.2 jdolecek return;
3670 1.5.2.2 jdolecek }
3671 1.1 dyoung }
3672 1.1 dyoung
3673 1.5.2.2 jdolecek /* Set moderation on the Link interrupt */
3674 1.5.2.2 jdolecek IXGBE_WRITE_REG(hw, IXGBE_EITR(adapter->vector), IXGBE_LINK_ITR);
3675 1.1 dyoung
3676 1.5.2.2 jdolecek /* Config/Enable Link */
3677 1.5.2.2 jdolecek ixgbe_config_link(adapter);
3678 1.1 dyoung
3679 1.5.2.2 jdolecek /* Hardware Packet Buffer & Flow Control setup */
3680 1.5.2.2 jdolecek ixgbe_config_delay_values(adapter);
3681 1.1 dyoung
3682 1.5.2.2 jdolecek /* Initialize the FC settings */
3683 1.5.2.2 jdolecek ixgbe_start_hw(hw);
3684 1.1 dyoung
3685 1.5.2.2 jdolecek /* Set up VLAN support and filter */
3686 1.5.2.2 jdolecek ixgbe_setup_vlan_hw_support(adapter);
3687 1.1 dyoung
3688 1.5.2.2 jdolecek /* Setup DMA Coalescing */
3689 1.5.2.2 jdolecek ixgbe_config_dmac(adapter);
3690 1.1 dyoung
3691 1.5.2.2 jdolecek /* And now turn on interrupts */
3692 1.5.2.2 jdolecek ixgbe_enable_intr(adapter);
3693 1.1 dyoung
3694 1.5.2.2 jdolecek /* Enable the use of the MBX by the VF's */
3695 1.5.2.2 jdolecek if (adapter->feat_en & IXGBE_FEATURE_SRIOV) {
3696 1.5.2.2 jdolecek ctrl_ext = IXGBE_READ_REG(hw, IXGBE_CTRL_EXT);
3697 1.5.2.2 jdolecek ctrl_ext |= IXGBE_CTRL_EXT_PFRSTD;
3698 1.5.2.2 jdolecek IXGBE_WRITE_REG(hw, IXGBE_CTRL_EXT, ctrl_ext);
3699 1.1 dyoung }
3700 1.1 dyoung
3701 1.5.2.2 jdolecek /* Now inform the stack we're ready */
3702 1.5.2.2 jdolecek ifp->if_flags |= IFF_RUNNING;
3703 1.1 dyoung
3704 1.5.2.2 jdolecek return;
3705 1.5.2.2 jdolecek } /* ixgbe_init_locked */
3706 1.1 dyoung
3707 1.5.2.2 jdolecek /************************************************************************
3708 1.5.2.2 jdolecek * ixgbe_init
3709 1.5.2.2 jdolecek ************************************************************************/
3710 1.1 dyoung static int
3711 1.5.2.2 jdolecek ixgbe_init(struct ifnet *ifp)
3712 1.1 dyoung {
3713 1.5.2.2 jdolecek struct adapter *adapter = ifp->if_softc;
3714 1.1 dyoung
3715 1.5.2.2 jdolecek IXGBE_CORE_LOCK(adapter);
3716 1.5.2.2 jdolecek ixgbe_init_locked(adapter);
3717 1.5.2.2 jdolecek IXGBE_CORE_UNLOCK(adapter);
3718 1.1 dyoung
3719 1.5.2.2 jdolecek return 0; /* XXX ixgbe_init_locked cannot fail? really? */
3720 1.5.2.2 jdolecek } /* ixgbe_init */
3721 1.5.2.2 jdolecek
3722 1.5.2.2 jdolecek /************************************************************************
3723 1.5.2.2 jdolecek * ixgbe_set_ivar
3724 1.5.2.2 jdolecek *
3725 1.5.2.2 jdolecek * Setup the correct IVAR register for a particular MSI-X interrupt
3726 1.5.2.2 jdolecek * (yes this is all very magic and confusing :)
3727 1.5.2.2 jdolecek * - entry is the register array entry
3728 1.5.2.2 jdolecek * - vector is the MSI-X vector for this queue
3729 1.5.2.2 jdolecek * - type is RX/TX/MISC
3730 1.5.2.2 jdolecek ************************************************************************/
3731 1.5.2.2 jdolecek static void
3732 1.5.2.2 jdolecek ixgbe_set_ivar(struct adapter *adapter, u8 entry, u8 vector, s8 type)
3733 1.5.2.2 jdolecek {
3734 1.5.2.2 jdolecek struct ixgbe_hw *hw = &adapter->hw;
3735 1.5.2.2 jdolecek u32 ivar, index;
3736 1.1 dyoung
3737 1.5.2.2 jdolecek vector |= IXGBE_IVAR_ALLOC_VAL;
3738 1.1 dyoung
3739 1.5.2.2 jdolecek switch (hw->mac.type) {
3740 1.1 dyoung
3741 1.5.2.2 jdolecek case ixgbe_mac_82598EB:
3742 1.5.2.2 jdolecek if (type == -1)
3743 1.5.2.2 jdolecek entry = IXGBE_IVAR_OTHER_CAUSES_INDEX;
3744 1.5.2.2 jdolecek else
3745 1.5.2.2 jdolecek entry += (type * 64);
3746 1.5.2.2 jdolecek index = (entry >> 2) & 0x1F;
3747 1.5.2.2 jdolecek ivar = IXGBE_READ_REG(hw, IXGBE_IVAR(index));
3748 1.5.2.2 jdolecek ivar &= ~(0xFF << (8 * (entry & 0x3)));
3749 1.5.2.2 jdolecek ivar |= (vector << (8 * (entry & 0x3)));
3750 1.5.2.2 jdolecek IXGBE_WRITE_REG(&adapter->hw, IXGBE_IVAR(index), ivar);
3751 1.5.2.2 jdolecek break;
3752 1.1 dyoung
3753 1.5.2.2 jdolecek case ixgbe_mac_82599EB:
3754 1.5.2.2 jdolecek case ixgbe_mac_X540:
3755 1.5.2.2 jdolecek case ixgbe_mac_X550:
3756 1.5.2.2 jdolecek case ixgbe_mac_X550EM_x:
3757 1.5.2.2 jdolecek case ixgbe_mac_X550EM_a:
3758 1.5.2.2 jdolecek if (type == -1) { /* MISC IVAR */
3759 1.5.2.2 jdolecek index = (entry & 1) * 8;
3760 1.5.2.2 jdolecek ivar = IXGBE_READ_REG(hw, IXGBE_IVAR_MISC);
3761 1.5.2.2 jdolecek ivar &= ~(0xFF << index);
3762 1.5.2.2 jdolecek ivar |= (vector << index);
3763 1.5.2.2 jdolecek IXGBE_WRITE_REG(hw, IXGBE_IVAR_MISC, ivar);
3764 1.5.2.2 jdolecek } else { /* RX/TX IVARS */
3765 1.5.2.2 jdolecek index = (16 * (entry & 1)) + (8 * type);
3766 1.5.2.2 jdolecek ivar = IXGBE_READ_REG(hw, IXGBE_IVAR(entry >> 1));
3767 1.5.2.2 jdolecek ivar &= ~(0xFF << index);
3768 1.5.2.2 jdolecek ivar |= (vector << index);
3769 1.5.2.2 jdolecek IXGBE_WRITE_REG(hw, IXGBE_IVAR(entry >> 1), ivar);
3770 1.1 dyoung }
3771 1.1 dyoung
3772 1.5.2.2 jdolecek default:
3773 1.5.2.2 jdolecek break;
3774 1.1 dyoung }
3775 1.5.2.2 jdolecek } /* ixgbe_set_ivar */
3776 1.1 dyoung
3777 1.5.2.2 jdolecek /************************************************************************
3778 1.5.2.2 jdolecek * ixgbe_configure_ivars
3779 1.5.2.2 jdolecek ************************************************************************/
3780 1.5.2.2 jdolecek static void
3781 1.5.2.2 jdolecek ixgbe_configure_ivars(struct adapter *adapter)
3782 1.5.2.2 jdolecek {
3783 1.5.2.2 jdolecek struct ix_queue *que = adapter->queues;
3784 1.5.2.2 jdolecek u32 newitr;
3785 1.1 dyoung
3786 1.5.2.2 jdolecek if (ixgbe_max_interrupt_rate > 0)
3787 1.5.2.2 jdolecek newitr = (4000000 / ixgbe_max_interrupt_rate) & 0x0FF8;
3788 1.5.2.2 jdolecek else {
3789 1.5.2.2 jdolecek /*
3790 1.5.2.2 jdolecek * Disable DMA coalescing if interrupt moderation is
3791 1.5.2.2 jdolecek * disabled.
3792 1.5.2.2 jdolecek */
3793 1.5.2.2 jdolecek adapter->dmac = 0;
3794 1.5.2.2 jdolecek newitr = 0;
3795 1.1 dyoung }
3796 1.1 dyoung
3797 1.5.2.2 jdolecek for (int i = 0; i < adapter->num_queues; i++, que++) {
3798 1.5.2.2 jdolecek struct rx_ring *rxr = &adapter->rx_rings[i];
3799 1.5.2.2 jdolecek struct tx_ring *txr = &adapter->tx_rings[i];
3800 1.5.2.2 jdolecek /* First the RX queue entry */
3801 1.5.2.2 jdolecek ixgbe_set_ivar(adapter, rxr->me, que->msix, 0);
3802 1.5.2.2 jdolecek /* ... and the TX */
3803 1.5.2.2 jdolecek ixgbe_set_ivar(adapter, txr->me, que->msix, 1);
3804 1.5.2.2 jdolecek /* Set an Initial EITR value */
3805 1.5.2.2 jdolecek IXGBE_WRITE_REG(&adapter->hw, IXGBE_EITR(que->msix), newitr);
3806 1.1 dyoung }
3807 1.1 dyoung
3808 1.5.2.2 jdolecek /* For the Link interrupt */
3809 1.5.2.2 jdolecek ixgbe_set_ivar(adapter, 1, adapter->vector, -1);
3810 1.5.2.2 jdolecek } /* ixgbe_configure_ivars */
3811 1.1 dyoung
3812 1.5.2.2 jdolecek /************************************************************************
3813 1.5.2.2 jdolecek * ixgbe_config_gpie
3814 1.5.2.2 jdolecek ************************************************************************/
3815 1.5.2.2 jdolecek static void
3816 1.5.2.2 jdolecek ixgbe_config_gpie(struct adapter *adapter)
3817 1.1 dyoung {
3818 1.5.2.2 jdolecek struct ixgbe_hw *hw = &adapter->hw;
3819 1.5.2.2 jdolecek u32 gpie;
3820 1.1 dyoung
3821 1.5.2.2 jdolecek gpie = IXGBE_READ_REG(hw, IXGBE_GPIE);
3822 1.1 dyoung
3823 1.5.2.2 jdolecek if (adapter->feat_en & IXGBE_FEATURE_MSIX) {
3824 1.5.2.2 jdolecek /* Enable Enhanced MSI-X mode */
3825 1.5.2.2 jdolecek gpie |= IXGBE_GPIE_MSIX_MODE
3826 1.5.2.2 jdolecek | IXGBE_GPIE_EIAME
3827 1.5.2.2 jdolecek | IXGBE_GPIE_PBA_SUPPORT
3828 1.5.2.2 jdolecek | IXGBE_GPIE_OCD;
3829 1.1 dyoung }
3830 1.1 dyoung
3831 1.5.2.2 jdolecek /* Fan Failure Interrupt */
3832 1.5.2.2 jdolecek if (adapter->feat_en & IXGBE_FEATURE_FAN_FAIL)
3833 1.5.2.2 jdolecek gpie |= IXGBE_SDP1_GPIEN;
3834 1.5.2.2 jdolecek
3835 1.5.2.2 jdolecek /* Thermal Sensor Interrupt */
3836 1.5.2.2 jdolecek if (adapter->feat_en & IXGBE_FEATURE_TEMP_SENSOR)
3837 1.5.2.2 jdolecek gpie |= IXGBE_SDP0_GPIEN_X540;
3838 1.5.2.2 jdolecek
3839 1.5.2.2 jdolecek /* Link detection */
3840 1.5.2.2 jdolecek switch (hw->mac.type) {
3841 1.5.2.2 jdolecek case ixgbe_mac_82599EB:
3842 1.5.2.2 jdolecek gpie |= IXGBE_SDP1_GPIEN | IXGBE_SDP2_GPIEN;
3843 1.5.2.2 jdolecek break;
3844 1.5.2.2 jdolecek case ixgbe_mac_X550EM_x:
3845 1.5.2.2 jdolecek case ixgbe_mac_X550EM_a:
3846 1.5.2.2 jdolecek gpie |= IXGBE_SDP0_GPIEN_X540;
3847 1.5.2.2 jdolecek break;
3848 1.5.2.2 jdolecek default:
3849 1.5.2.2 jdolecek break;
3850 1.1 dyoung }
3851 1.1 dyoung
3852 1.5.2.2 jdolecek IXGBE_WRITE_REG(hw, IXGBE_GPIE, gpie);
3853 1.1 dyoung
3854 1.5.2.2 jdolecek return;
3855 1.5.2.2 jdolecek } /* ixgbe_config_gpie */
3856 1.5.2.2 jdolecek
3857 1.5.2.2 jdolecek /************************************************************************
3858 1.5.2.2 jdolecek * ixgbe_config_delay_values
3859 1.1 dyoung *
3860 1.5.2.2 jdolecek * Requires adapter->max_frame_size to be set.
3861 1.5.2.2 jdolecek ************************************************************************/
3862 1.1 dyoung static void
3863 1.5.2.2 jdolecek ixgbe_config_delay_values(struct adapter *adapter)
3864 1.1 dyoung {
3865 1.5.2.2 jdolecek struct ixgbe_hw *hw = &adapter->hw;
3866 1.5.2.2 jdolecek u32 rxpb, frame, size, tmp;
3867 1.1 dyoung
3868 1.5.2.2 jdolecek frame = adapter->max_frame_size;
3869 1.1 dyoung
3870 1.5.2.2 jdolecek /* Calculate High Water */
3871 1.5.2.2 jdolecek switch (hw->mac.type) {
3872 1.5.2.2 jdolecek case ixgbe_mac_X540:
3873 1.5.2.2 jdolecek case ixgbe_mac_X550:
3874 1.5.2.2 jdolecek case ixgbe_mac_X550EM_x:
3875 1.5.2.2 jdolecek case ixgbe_mac_X550EM_a:
3876 1.5.2.2 jdolecek tmp = IXGBE_DV_X540(frame, frame);
3877 1.5.2.2 jdolecek break;
3878 1.5.2.2 jdolecek default:
3879 1.5.2.2 jdolecek tmp = IXGBE_DV(frame, frame);
3880 1.5.2.2 jdolecek break;
3881 1.5.2.2 jdolecek }
3882 1.5.2.2 jdolecek size = IXGBE_BT2KB(tmp);
3883 1.5.2.2 jdolecek rxpb = IXGBE_READ_REG(hw, IXGBE_RXPBSIZE(0)) >> 10;
3884 1.5.2.2 jdolecek hw->fc.high_water[0] = rxpb - size;
3885 1.1 dyoung
3886 1.5.2.2 jdolecek /* Now calculate Low Water */
3887 1.5.2.2 jdolecek switch (hw->mac.type) {
3888 1.5.2.2 jdolecek case ixgbe_mac_X540:
3889 1.5.2.2 jdolecek case ixgbe_mac_X550:
3890 1.5.2.2 jdolecek case ixgbe_mac_X550EM_x:
3891 1.5.2.2 jdolecek case ixgbe_mac_X550EM_a:
3892 1.5.2.2 jdolecek tmp = IXGBE_LOW_DV_X540(frame);
3893 1.5.2.2 jdolecek break;
3894 1.5.2.2 jdolecek default:
3895 1.5.2.2 jdolecek tmp = IXGBE_LOW_DV(frame);
3896 1.5.2.2 jdolecek break;
3897 1.5.2.2 jdolecek }
3898 1.5.2.2 jdolecek hw->fc.low_water[0] = IXGBE_BT2KB(tmp);
3899 1.1 dyoung
3900 1.5.2.2 jdolecek hw->fc.pause_time = IXGBE_FC_PAUSE;
3901 1.5.2.2 jdolecek hw->fc.send_xon = TRUE;
3902 1.5.2.2 jdolecek } /* ixgbe_config_delay_values */
3903 1.1 dyoung
3904 1.5.2.2 jdolecek /************************************************************************
3905 1.5.2.2 jdolecek * ixgbe_set_multi - Multicast Update
3906 1.1 dyoung *
3907 1.5.2.2 jdolecek * Called whenever multicast address list is updated.
3908 1.5.2.2 jdolecek ************************************************************************/
3909 1.1 dyoung static void
3910 1.5.2.2 jdolecek ixgbe_set_multi(struct adapter *adapter)
3911 1.1 dyoung {
3912 1.5.2.2 jdolecek struct ixgbe_mc_addr *mta;
3913 1.5.2.2 jdolecek struct ifnet *ifp = adapter->ifp;
3914 1.5.2.2 jdolecek u8 *update_ptr;
3915 1.5.2.2 jdolecek int mcnt = 0;
3916 1.5.2.2 jdolecek u32 fctrl;
3917 1.5.2.2 jdolecek struct ethercom *ec = &adapter->osdep.ec;
3918 1.5.2.2 jdolecek struct ether_multi *enm;
3919 1.5.2.2 jdolecek struct ether_multistep step;
3920 1.1 dyoung
3921 1.5.2.2 jdolecek KASSERT(mutex_owned(&adapter->core_mtx));
3922 1.5.2.2 jdolecek IOCTL_DEBUGOUT("ixgbe_set_multi: begin");
3923 1.1 dyoung
3924 1.5.2.2 jdolecek mta = adapter->mta;
3925 1.5.2.2 jdolecek bzero(mta, sizeof(*mta) * MAX_NUM_MULTICAST_ADDRESSES);
3926 1.1 dyoung
3927 1.5.2.2 jdolecek ifp->if_flags &= ~IFF_ALLMULTI;
3928 1.5.2.2 jdolecek ETHER_LOCK(ec);
3929 1.5.2.2 jdolecek ETHER_FIRST_MULTI(step, ec, enm);
3930 1.5.2.2 jdolecek while (enm != NULL) {
3931 1.5.2.2 jdolecek if ((mcnt == MAX_NUM_MULTICAST_ADDRESSES) ||
3932 1.5.2.2 jdolecek (memcmp(enm->enm_addrlo, enm->enm_addrhi,
3933 1.5.2.2 jdolecek ETHER_ADDR_LEN) != 0)) {
3934 1.5.2.2 jdolecek ifp->if_flags |= IFF_ALLMULTI;
3935 1.1 dyoung break;
3936 1.1 dyoung }
3937 1.5.2.2 jdolecek bcopy(enm->enm_addrlo,
3938 1.5.2.2 jdolecek mta[mcnt].addr, IXGBE_ETH_LENGTH_OF_ADDRESS);
3939 1.5.2.2 jdolecek mta[mcnt].vmdq = adapter->pool;
3940 1.5.2.2 jdolecek mcnt++;
3941 1.5.2.2 jdolecek ETHER_NEXT_MULTI(step, enm);
3942 1.1 dyoung }
3943 1.5.2.2 jdolecek ETHER_UNLOCK(ec);
3944 1.1 dyoung
3945 1.5.2.2 jdolecek fctrl = IXGBE_READ_REG(&adapter->hw, IXGBE_FCTRL);
3946 1.5.2.2 jdolecek fctrl &= ~(IXGBE_FCTRL_UPE | IXGBE_FCTRL_MPE);
3947 1.5.2.2 jdolecek if (ifp->if_flags & IFF_PROMISC)
3948 1.5.2.2 jdolecek fctrl |= (IXGBE_FCTRL_UPE | IXGBE_FCTRL_MPE);
3949 1.5.2.2 jdolecek else if (ifp->if_flags & IFF_ALLMULTI) {
3950 1.5.2.2 jdolecek fctrl |= IXGBE_FCTRL_MPE;
3951 1.5.2.2 jdolecek }
3952 1.5.2.2 jdolecek
3953 1.5.2.2 jdolecek IXGBE_WRITE_REG(&adapter->hw, IXGBE_FCTRL, fctrl);
3954 1.5.2.2 jdolecek
3955 1.5.2.2 jdolecek if (mcnt < MAX_NUM_MULTICAST_ADDRESSES) {
3956 1.5.2.2 jdolecek update_ptr = (u8 *)mta;
3957 1.5.2.2 jdolecek ixgbe_update_mc_addr_list(&adapter->hw, update_ptr, mcnt,
3958 1.5.2.2 jdolecek ixgbe_mc_array_itr, TRUE);
3959 1.1 dyoung }
3960 1.1 dyoung
3961 1.1 dyoung return;
3962 1.5.2.2 jdolecek } /* ixgbe_set_multi */
3963 1.1 dyoung
3964 1.5.2.2 jdolecek /************************************************************************
3965 1.5.2.2 jdolecek * ixgbe_mc_array_itr
3966 1.1 dyoung *
3967 1.5.2.2 jdolecek * An iterator function needed by the multicast shared code.
3968 1.5.2.2 jdolecek * It feeds the shared code routine the addresses in the
3969 1.5.2.2 jdolecek * array of ixgbe_set_multi() one by one.
3970 1.5.2.2 jdolecek ************************************************************************/
3971 1.5.2.2 jdolecek static u8 *
3972 1.5.2.2 jdolecek ixgbe_mc_array_itr(struct ixgbe_hw *hw, u8 **update_ptr, u32 *vmdq)
3973 1.1 dyoung {
3974 1.5.2.2 jdolecek struct ixgbe_mc_addr *mta;
3975 1.1 dyoung
3976 1.5.2.2 jdolecek mta = (struct ixgbe_mc_addr *)*update_ptr;
3977 1.5.2.2 jdolecek *vmdq = mta->vmdq;
3978 1.1 dyoung
3979 1.5.2.2 jdolecek *update_ptr = (u8*)(mta + 1);
3980 1.5.2.2 jdolecek
3981 1.5.2.2 jdolecek return (mta->addr);
3982 1.5.2.2 jdolecek } /* ixgbe_mc_array_itr */
3983 1.5.2.2 jdolecek
3984 1.5.2.2 jdolecek /************************************************************************
3985 1.5.2.2 jdolecek * ixgbe_local_timer - Timer routine
3986 1.1 dyoung *
3987 1.5.2.2 jdolecek * Checks for link status, updates statistics,
3988 1.5.2.2 jdolecek * and runs the watchdog check.
3989 1.5.2.2 jdolecek ************************************************************************/
3990 1.1 dyoung static void
3991 1.5.2.2 jdolecek ixgbe_local_timer(void *arg)
3992 1.1 dyoung {
3993 1.5.2.2 jdolecek struct adapter *adapter = arg;
3994 1.1 dyoung
3995 1.5.2.2 jdolecek IXGBE_CORE_LOCK(adapter);
3996 1.5.2.2 jdolecek ixgbe_local_timer1(adapter);
3997 1.5.2.2 jdolecek IXGBE_CORE_UNLOCK(adapter);
3998 1.1 dyoung }
3999 1.1 dyoung
4000 1.5.2.2 jdolecek static void
4001 1.5.2.2 jdolecek ixgbe_local_timer1(void *arg)
4002 1.1 dyoung {
4003 1.5.2.2 jdolecek struct adapter *adapter = arg;
4004 1.5.2.2 jdolecek device_t dev = adapter->dev;
4005 1.5.2.2 jdolecek struct ix_queue *que = adapter->queues;
4006 1.5.2.2 jdolecek u64 queues = 0;
4007 1.5.2.2 jdolecek int hung = 0;
4008 1.1 dyoung
4009 1.5.2.2 jdolecek KASSERT(mutex_owned(&adapter->core_mtx));
4010 1.1 dyoung
4011 1.5.2.2 jdolecek /* Check for pluggable optics */
4012 1.5.2.2 jdolecek if (adapter->sfp_probe)
4013 1.5.2.2 jdolecek if (!ixgbe_sfp_probe(adapter))
4014 1.5.2.2 jdolecek goto out; /* Nothing to do */
4015 1.1 dyoung
4016 1.5.2.2 jdolecek ixgbe_update_link_status(adapter);
4017 1.5.2.2 jdolecek ixgbe_update_stats_counters(adapter);
4018 1.1 dyoung
4019 1.1 dyoung /*
4020 1.5.2.2 jdolecek * Check the TX queues status
4021 1.5.2.2 jdolecek * - mark hung queues so we don't schedule on them
4022 1.5.2.2 jdolecek * - watchdog only if all queues show hung
4023 1.1 dyoung */
4024 1.5.2.2 jdolecek for (int i = 0; i < adapter->num_queues; i++, que++) {
4025 1.5.2.2 jdolecek /* Keep track of queues with work for soft irq */
4026 1.5.2.2 jdolecek if (que->txr->busy)
4027 1.5.2.2 jdolecek queues |= ((u64)1 << que->me);
4028 1.5.2.2 jdolecek /*
4029 1.5.2.2 jdolecek * Each time txeof runs without cleaning, but there
4030 1.5.2.2 jdolecek * are uncleaned descriptors it increments busy. If
4031 1.5.2.2 jdolecek * we get to the MAX we declare it hung.
4032 1.5.2.2 jdolecek */
4033 1.5.2.2 jdolecek if (que->busy == IXGBE_QUEUE_HUNG) {
4034 1.5.2.2 jdolecek ++hung;
4035 1.5.2.2 jdolecek /* Mark the queue as inactive */
4036 1.5.2.2 jdolecek adapter->active_queues &= ~((u64)1 << que->me);
4037 1.5.2.2 jdolecek continue;
4038 1.5.2.2 jdolecek } else {
4039 1.5.2.2 jdolecek /* Check if we've come back from hung */
4040 1.5.2.2 jdolecek if ((adapter->active_queues & ((u64)1 << que->me)) == 0)
4041 1.5.2.2 jdolecek adapter->active_queues |= ((u64)1 << que->me);
4042 1.5.2.2 jdolecek }
4043 1.5.2.2 jdolecek if (que->busy >= IXGBE_MAX_TX_BUSY) {
4044 1.5.2.2 jdolecek device_printf(dev,
4045 1.5.2.2 jdolecek "Warning queue %d appears to be hung!\n", i);
4046 1.5.2.2 jdolecek que->txr->busy = IXGBE_QUEUE_HUNG;
4047 1.5.2.2 jdolecek ++hung;
4048 1.5.2.2 jdolecek }
4049 1.1 dyoung }
4050 1.1 dyoung
4051 1.5.2.2 jdolecek /* Only truely watchdog if all queues show hung */
4052 1.5.2.2 jdolecek if (hung == adapter->num_queues)
4053 1.5.2.2 jdolecek goto watchdog;
4054 1.5.2.2 jdolecek else if (queues != 0) { /* Force an IRQ on queues with work */
4055 1.5.2.2 jdolecek ixgbe_rearm_queues(adapter, queues);
4056 1.1 dyoung }
4057 1.1 dyoung
4058 1.5.2.2 jdolecek out:
4059 1.5.2.2 jdolecek callout_reset(&adapter->timer, hz, ixgbe_local_timer, adapter);
4060 1.5.2.2 jdolecek return;
4061 1.1 dyoung
4062 1.5.2.2 jdolecek watchdog:
4063 1.5.2.2 jdolecek device_printf(adapter->dev, "Watchdog timeout -- resetting\n");
4064 1.5.2.2 jdolecek adapter->ifp->if_flags &= ~IFF_RUNNING;
4065 1.5.2.2 jdolecek adapter->watchdog_events.ev_count++;
4066 1.5.2.2 jdolecek ixgbe_init_locked(adapter);
4067 1.5.2.2 jdolecek } /* ixgbe_local_timer */
4068 1.1 dyoung
4069 1.5.2.2 jdolecek /************************************************************************
4070 1.5.2.2 jdolecek * ixgbe_sfp_probe
4071 1.1 dyoung *
4072 1.5.2.2 jdolecek * Determine if a port had optics inserted.
4073 1.5.2.2 jdolecek ************************************************************************/
4074 1.1 dyoung static bool
4075 1.5.2.2 jdolecek ixgbe_sfp_probe(struct adapter *adapter)
4076 1.1 dyoung {
4077 1.5.2.2 jdolecek struct ixgbe_hw *hw = &adapter->hw;
4078 1.5.2.2 jdolecek device_t dev = adapter->dev;
4079 1.5.2.2 jdolecek bool result = FALSE;
4080 1.1 dyoung
4081 1.5.2.2 jdolecek if ((hw->phy.type == ixgbe_phy_nl) &&
4082 1.5.2.2 jdolecek (hw->phy.sfp_type == ixgbe_sfp_type_not_present)) {
4083 1.5.2.2 jdolecek s32 ret = hw->phy.ops.identify_sfp(hw);
4084 1.5.2.2 jdolecek if (ret)
4085 1.5.2.2 jdolecek goto out;
4086 1.5.2.2 jdolecek ret = hw->phy.ops.reset(hw);
4087 1.5.2.2 jdolecek adapter->sfp_probe = FALSE;
4088 1.5.2.2 jdolecek if (ret == IXGBE_ERR_SFP_NOT_SUPPORTED) {
4089 1.5.2.2 jdolecek device_printf(dev,"Unsupported SFP+ module detected!");
4090 1.5.2.2 jdolecek device_printf(dev,
4091 1.5.2.2 jdolecek "Reload driver with supported module.\n");
4092 1.5.2.2 jdolecek goto out;
4093 1.5.2.2 jdolecek } else
4094 1.5.2.2 jdolecek device_printf(dev, "SFP+ module detected!\n");
4095 1.5.2.2 jdolecek /* We now have supported optics */
4096 1.5.2.2 jdolecek result = TRUE;
4097 1.5.2.2 jdolecek }
4098 1.5.2.2 jdolecek out:
4099 1.1 dyoung
4100 1.5.2.2 jdolecek return (result);
4101 1.5.2.2 jdolecek } /* ixgbe_sfp_probe */
4102 1.1 dyoung
4103 1.5.2.2 jdolecek /************************************************************************
4104 1.5.2.2 jdolecek * ixgbe_handle_mod - Tasklet for SFP module interrupts
4105 1.5.2.2 jdolecek ************************************************************************/
4106 1.5.2.2 jdolecek static void
4107 1.5.2.2 jdolecek ixgbe_handle_mod(void *context)
4108 1.5.2.2 jdolecek {
4109 1.5.2.2 jdolecek struct adapter *adapter = context;
4110 1.5.2.2 jdolecek struct ixgbe_hw *hw = &adapter->hw;
4111 1.5.2.2 jdolecek device_t dev = adapter->dev;
4112 1.5.2.2 jdolecek u32 err, cage_full = 0;
4113 1.1 dyoung
4114 1.5.2.2 jdolecek if (adapter->hw.need_crosstalk_fix) {
4115 1.5.2.2 jdolecek switch (hw->mac.type) {
4116 1.5.2.2 jdolecek case ixgbe_mac_82599EB:
4117 1.5.2.2 jdolecek cage_full = IXGBE_READ_REG(hw, IXGBE_ESDP) &
4118 1.5.2.2 jdolecek IXGBE_ESDP_SDP2;
4119 1.5.2.2 jdolecek break;
4120 1.5.2.2 jdolecek case ixgbe_mac_X550EM_x:
4121 1.5.2.2 jdolecek case ixgbe_mac_X550EM_a:
4122 1.5.2.2 jdolecek cage_full = IXGBE_READ_REG(hw, IXGBE_ESDP) &
4123 1.5.2.2 jdolecek IXGBE_ESDP_SDP0;
4124 1.5.2.2 jdolecek break;
4125 1.5.2.2 jdolecek default:
4126 1.5.2.2 jdolecek break;
4127 1.5.2.2 jdolecek }
4128 1.1 dyoung
4129 1.5.2.2 jdolecek if (!cage_full)
4130 1.5.2.2 jdolecek return;
4131 1.1 dyoung }
4132 1.1 dyoung
4133 1.5.2.2 jdolecek err = hw->phy.ops.identify_sfp(hw);
4134 1.5.2.2 jdolecek if (err == IXGBE_ERR_SFP_NOT_SUPPORTED) {
4135 1.5.2.2 jdolecek device_printf(dev,
4136 1.5.2.2 jdolecek "Unsupported SFP+ module type was detected.\n");
4137 1.1 dyoung return;
4138 1.5.2.2 jdolecek }
4139 1.1 dyoung
4140 1.5.2.2 jdolecek err = hw->mac.ops.setup_sfp(hw);
4141 1.5.2.2 jdolecek if (err == IXGBE_ERR_SFP_NOT_SUPPORTED) {
4142 1.5.2.2 jdolecek device_printf(dev,
4143 1.5.2.2 jdolecek "Setup failure - unsupported SFP+ module type.\n");
4144 1.1 dyoung return;
4145 1.1 dyoung }
4146 1.5.2.2 jdolecek softint_schedule(adapter->msf_si);
4147 1.5.2.2 jdolecek } /* ixgbe_handle_mod */
4148 1.1 dyoung
4149 1.1 dyoung
4150 1.5.2.2 jdolecek /************************************************************************
4151 1.5.2.2 jdolecek * ixgbe_handle_msf - Tasklet for MSF (multispeed fiber) interrupts
4152 1.5.2.2 jdolecek ************************************************************************/
4153 1.5.2.2 jdolecek static void
4154 1.5.2.2 jdolecek ixgbe_handle_msf(void *context)
4155 1.1 dyoung {
4156 1.5.2.2 jdolecek struct adapter *adapter = context;
4157 1.5.2.2 jdolecek struct ixgbe_hw *hw = &adapter->hw;
4158 1.5.2.2 jdolecek u32 autoneg;
4159 1.5.2.2 jdolecek bool negotiate;
4160 1.1 dyoung
4161 1.5.2.2 jdolecek /* get_supported_phy_layer will call hw->phy.ops.identify_sfp() */
4162 1.5.2.2 jdolecek adapter->phy_layer = ixgbe_get_supported_physical_layer(hw);
4163 1.1 dyoung
4164 1.5.2.2 jdolecek autoneg = hw->phy.autoneg_advertised;
4165 1.5.2.2 jdolecek if ((!autoneg) && (hw->mac.ops.get_link_capabilities))
4166 1.5.2.2 jdolecek hw->mac.ops.get_link_capabilities(hw, &autoneg, &negotiate);
4167 1.5.2.2 jdolecek else
4168 1.5.2.2 jdolecek negotiate = 0;
4169 1.5.2.2 jdolecek if (hw->mac.ops.setup_link)
4170 1.5.2.2 jdolecek hw->mac.ops.setup_link(hw, autoneg, TRUE);
4171 1.1 dyoung
4172 1.5.2.2 jdolecek /* Adjust media types shown in ifconfig */
4173 1.5.2.2 jdolecek ifmedia_removeall(&adapter->media);
4174 1.5.2.2 jdolecek ixgbe_add_media_types(adapter);
4175 1.5.2.2 jdolecek ifmedia_set(&adapter->media, IFM_ETHER | IFM_AUTO);
4176 1.5.2.2 jdolecek } /* ixgbe_handle_msf */
4177 1.1 dyoung
4178 1.5.2.2 jdolecek /************************************************************************
4179 1.5.2.2 jdolecek * ixgbe_handle_phy - Tasklet for external PHY interrupts
4180 1.5.2.2 jdolecek ************************************************************************/
4181 1.5.2.2 jdolecek static void
4182 1.5.2.2 jdolecek ixgbe_handle_phy(void *context)
4183 1.5.2.2 jdolecek {
4184 1.5.2.2 jdolecek struct adapter *adapter = context;
4185 1.5.2.2 jdolecek struct ixgbe_hw *hw = &adapter->hw;
4186 1.5.2.2 jdolecek int error;
4187 1.1 dyoung
4188 1.5.2.2 jdolecek error = hw->phy.ops.handle_lasi(hw);
4189 1.5.2.2 jdolecek if (error == IXGBE_ERR_OVERTEMP)
4190 1.5.2.2 jdolecek device_printf(adapter->dev,
4191 1.5.2.2 jdolecek "CRITICAL: EXTERNAL PHY OVER TEMP!! "
4192 1.5.2.2 jdolecek " PHY will downshift to lower power state!\n");
4193 1.5.2.2 jdolecek else if (error)
4194 1.5.2.2 jdolecek device_printf(adapter->dev,
4195 1.5.2.2 jdolecek "Error handling LASI interrupt: %d\n", error);
4196 1.5.2.2 jdolecek } /* ixgbe_handle_phy */
4197 1.1 dyoung
4198 1.5.2.2 jdolecek static void
4199 1.5.2.2 jdolecek ixgbe_ifstop(struct ifnet *ifp, int disable)
4200 1.5.2.2 jdolecek {
4201 1.5.2.2 jdolecek struct adapter *adapter = ifp->if_softc;
4202 1.1 dyoung
4203 1.5.2.2 jdolecek IXGBE_CORE_LOCK(adapter);
4204 1.5.2.2 jdolecek ixgbe_stop(adapter);
4205 1.5.2.2 jdolecek IXGBE_CORE_UNLOCK(adapter);
4206 1.1 dyoung }
4207 1.1 dyoung
4208 1.5.2.2 jdolecek /************************************************************************
4209 1.5.2.2 jdolecek * ixgbe_stop - Stop the hardware
4210 1.1 dyoung *
4211 1.5.2.2 jdolecek * Disables all traffic on the adapter by issuing a
4212 1.5.2.2 jdolecek * global reset on the MAC and deallocates TX/RX buffers.
4213 1.5.2.2 jdolecek ************************************************************************/
4214 1.5.2.2 jdolecek static void
4215 1.5.2.2 jdolecek ixgbe_stop(void *arg)
4216 1.5.2.2 jdolecek {
4217 1.5.2.2 jdolecek struct ifnet *ifp;
4218 1.5.2.2 jdolecek struct adapter *adapter = arg;
4219 1.5.2.2 jdolecek struct ixgbe_hw *hw = &adapter->hw;
4220 1.1 dyoung
4221 1.5.2.2 jdolecek ifp = adapter->ifp;
4222 1.1 dyoung
4223 1.5.2.2 jdolecek KASSERT(mutex_owned(&adapter->core_mtx));
4224 1.1 dyoung
4225 1.5.2.2 jdolecek INIT_DEBUGOUT("ixgbe_stop: begin\n");
4226 1.5.2.2 jdolecek ixgbe_disable_intr(adapter);
4227 1.5.2.2 jdolecek callout_stop(&adapter->timer);
4228 1.1 dyoung
4229 1.5.2.2 jdolecek /* Let the stack know...*/
4230 1.5.2.2 jdolecek ifp->if_flags &= ~IFF_RUNNING;
4231 1.1 dyoung
4232 1.5.2.2 jdolecek ixgbe_reset_hw(hw);
4233 1.5.2.2 jdolecek hw->adapter_stopped = FALSE;
4234 1.5.2.2 jdolecek ixgbe_stop_adapter(hw);
4235 1.5.2.2 jdolecek if (hw->mac.type == ixgbe_mac_82599EB)
4236 1.5.2.2 jdolecek ixgbe_stop_mac_link_on_d3_82599(hw);
4237 1.5.2.2 jdolecek /* Turn off the laser - noop with no optics */
4238 1.5.2.2 jdolecek ixgbe_disable_tx_laser(hw);
4239 1.1 dyoung
4240 1.5.2.2 jdolecek /* Update the stack */
4241 1.5.2.2 jdolecek adapter->link_up = FALSE;
4242 1.5.2.2 jdolecek ixgbe_update_link_status(adapter);
4243 1.1 dyoung
4244 1.5.2.2 jdolecek /* reprogram the RAR[0] in case user changed it. */
4245 1.5.2.2 jdolecek ixgbe_set_rar(&adapter->hw, 0, adapter->hw.mac.addr, 0, IXGBE_RAH_AV);
4246 1.1 dyoung
4247 1.5.2.2 jdolecek return;
4248 1.5.2.2 jdolecek } /* ixgbe_stop */
4249 1.5.2.2 jdolecek
4250 1.5.2.2 jdolecek /************************************************************************
4251 1.5.2.2 jdolecek * ixgbe_update_link_status - Update OS on link state
4252 1.1 dyoung *
4253 1.5.2.2 jdolecek * Note: Only updates the OS on the cached link state.
4254 1.5.2.2 jdolecek * The real check of the hardware only happens with
4255 1.5.2.2 jdolecek * a link interrupt.
4256 1.5.2.2 jdolecek ************************************************************************/
4257 1.1 dyoung static void
4258 1.5.2.2 jdolecek ixgbe_update_link_status(struct adapter *adapter)
4259 1.1 dyoung {
4260 1.5.2.2 jdolecek struct ifnet *ifp = adapter->ifp;
4261 1.5.2.2 jdolecek device_t dev = adapter->dev;
4262 1.5.2.2 jdolecek struct ixgbe_hw *hw = &adapter->hw;
4263 1.1 dyoung
4264 1.5.2.2 jdolecek if (adapter->link_up) {
4265 1.5.2.2 jdolecek if (adapter->link_active == FALSE) {
4266 1.5.2.2 jdolecek if (adapter->link_speed == IXGBE_LINK_SPEED_10GB_FULL){
4267 1.5.2.2 jdolecek /*
4268 1.5.2.2 jdolecek * Discard count for both MAC Local Fault and
4269 1.5.2.2 jdolecek * Remote Fault because those registers are
4270 1.5.2.2 jdolecek * valid only when the link speed is up and
4271 1.5.2.2 jdolecek * 10Gbps.
4272 1.5.2.2 jdolecek */
4273 1.5.2.2 jdolecek IXGBE_READ_REG(hw, IXGBE_MLFC);
4274 1.5.2.2 jdolecek IXGBE_READ_REG(hw, IXGBE_MRFC);
4275 1.5.2.2 jdolecek }
4276 1.1 dyoung
4277 1.5.2.2 jdolecek if (bootverbose) {
4278 1.5.2.2 jdolecek const char *bpsmsg;
4279 1.1 dyoung
4280 1.5.2.2 jdolecek switch (adapter->link_speed) {
4281 1.5.2.2 jdolecek case IXGBE_LINK_SPEED_10GB_FULL:
4282 1.5.2.2 jdolecek bpsmsg = "10 Gbps";
4283 1.5.2.2 jdolecek break;
4284 1.5.2.2 jdolecek case IXGBE_LINK_SPEED_5GB_FULL:
4285 1.5.2.2 jdolecek bpsmsg = "5 Gbps";
4286 1.5.2.2 jdolecek break;
4287 1.5.2.2 jdolecek case IXGBE_LINK_SPEED_2_5GB_FULL:
4288 1.5.2.2 jdolecek bpsmsg = "2.5 Gbps";
4289 1.5.2.2 jdolecek break;
4290 1.5.2.2 jdolecek case IXGBE_LINK_SPEED_1GB_FULL:
4291 1.5.2.2 jdolecek bpsmsg = "1 Gbps";
4292 1.5.2.2 jdolecek break;
4293 1.5.2.2 jdolecek case IXGBE_LINK_SPEED_100_FULL:
4294 1.5.2.2 jdolecek bpsmsg = "100 Mbps";
4295 1.5.2.2 jdolecek break;
4296 1.5.2.2 jdolecek case IXGBE_LINK_SPEED_10_FULL:
4297 1.5.2.2 jdolecek bpsmsg = "10 Mbps";
4298 1.5.2.2 jdolecek break;
4299 1.5.2.2 jdolecek default:
4300 1.5.2.2 jdolecek bpsmsg = "unknown speed";
4301 1.5.2.2 jdolecek break;
4302 1.5.2.2 jdolecek }
4303 1.5.2.2 jdolecek device_printf(dev, "Link is up %s %s \n",
4304 1.5.2.2 jdolecek bpsmsg, "Full Duplex");
4305 1.5.2.2 jdolecek }
4306 1.5.2.2 jdolecek adapter->link_active = TRUE;
4307 1.5.2.2 jdolecek /* Update any Flow Control changes */
4308 1.5.2.2 jdolecek ixgbe_fc_enable(&adapter->hw);
4309 1.5.2.2 jdolecek /* Update DMA coalescing config */
4310 1.5.2.2 jdolecek ixgbe_config_dmac(adapter);
4311 1.5.2.2 jdolecek if_link_state_change(ifp, LINK_STATE_UP);
4312 1.5.2.2 jdolecek if (adapter->feat_en & IXGBE_FEATURE_SRIOV)
4313 1.5.2.2 jdolecek ixgbe_ping_all_vfs(adapter);
4314 1.5.2.2 jdolecek }
4315 1.5.2.2 jdolecek } else { /* Link down */
4316 1.5.2.2 jdolecek if (adapter->link_active == TRUE) {
4317 1.5.2.2 jdolecek if (bootverbose)
4318 1.5.2.2 jdolecek device_printf(dev, "Link is Down\n");
4319 1.5.2.2 jdolecek if_link_state_change(ifp, LINK_STATE_DOWN);
4320 1.5.2.2 jdolecek adapter->link_active = FALSE;
4321 1.5.2.2 jdolecek if (adapter->feat_en & IXGBE_FEATURE_SRIOV)
4322 1.5.2.2 jdolecek ixgbe_ping_all_vfs(adapter);
4323 1.1 dyoung }
4324 1.1 dyoung }
4325 1.1 dyoung
4326 1.5.2.2 jdolecek return;
4327 1.5.2.2 jdolecek } /* ixgbe_update_link_status */
4328 1.1 dyoung
4329 1.5.2.2 jdolecek /************************************************************************
4330 1.5.2.2 jdolecek * ixgbe_config_dmac - Configure DMA Coalescing
4331 1.5.2.2 jdolecek ************************************************************************/
4332 1.5.2.2 jdolecek static void
4333 1.5.2.2 jdolecek ixgbe_config_dmac(struct adapter *adapter)
4334 1.5.2.2 jdolecek {
4335 1.5.2.2 jdolecek struct ixgbe_hw *hw = &adapter->hw;
4336 1.5.2.2 jdolecek struct ixgbe_dmac_config *dcfg = &hw->mac.dmac_config;
4337 1.1 dyoung
4338 1.5.2.2 jdolecek if (hw->mac.type < ixgbe_mac_X550 || !hw->mac.ops.dmac_config)
4339 1.5.2.2 jdolecek return;
4340 1.1 dyoung
4341 1.5.2.2 jdolecek if (dcfg->watchdog_timer ^ adapter->dmac ||
4342 1.5.2.2 jdolecek dcfg->link_speed ^ adapter->link_speed) {
4343 1.5.2.2 jdolecek dcfg->watchdog_timer = adapter->dmac;
4344 1.5.2.2 jdolecek dcfg->fcoe_en = false;
4345 1.5.2.2 jdolecek dcfg->link_speed = adapter->link_speed;
4346 1.5.2.2 jdolecek dcfg->num_tcs = 1;
4347 1.5.2.2 jdolecek
4348 1.5.2.2 jdolecek INIT_DEBUGOUT2("dmac settings: watchdog %d, link speed %d\n",
4349 1.5.2.2 jdolecek dcfg->watchdog_timer, dcfg->link_speed);
4350 1.5.2.2 jdolecek
4351 1.5.2.2 jdolecek hw->mac.ops.dmac_config(hw);
4352 1.5.2.2 jdolecek }
4353 1.5.2.2 jdolecek } /* ixgbe_config_dmac */
4354 1.5.2.2 jdolecek
4355 1.5.2.2 jdolecek /************************************************************************
4356 1.5.2.2 jdolecek * ixgbe_enable_intr
4357 1.5.2.2 jdolecek ************************************************************************/
4358 1.5.2.2 jdolecek static void
4359 1.5.2.2 jdolecek ixgbe_enable_intr(struct adapter *adapter)
4360 1.5.2.2 jdolecek {
4361 1.5.2.2 jdolecek struct ixgbe_hw *hw = &adapter->hw;
4362 1.5.2.2 jdolecek struct ix_queue *que = adapter->queues;
4363 1.5.2.2 jdolecek u32 mask, fwsm;
4364 1.1 dyoung
4365 1.5.2.2 jdolecek mask = (IXGBE_EIMS_ENABLE_MASK & ~IXGBE_EIMS_RTX_QUEUE);
4366 1.1 dyoung
4367 1.5.2.2 jdolecek switch (adapter->hw.mac.type) {
4368 1.5.2.2 jdolecek case ixgbe_mac_82599EB:
4369 1.5.2.2 jdolecek mask |= IXGBE_EIMS_ECC;
4370 1.5.2.2 jdolecek /* Temperature sensor on some adapters */
4371 1.5.2.2 jdolecek mask |= IXGBE_EIMS_GPI_SDP0;
4372 1.5.2.2 jdolecek /* SFP+ (RX_LOS_N & MOD_ABS_N) */
4373 1.5.2.2 jdolecek mask |= IXGBE_EIMS_GPI_SDP1;
4374 1.5.2.2 jdolecek mask |= IXGBE_EIMS_GPI_SDP2;
4375 1.5.2.2 jdolecek break;
4376 1.5.2.2 jdolecek case ixgbe_mac_X540:
4377 1.5.2.2 jdolecek /* Detect if Thermal Sensor is enabled */
4378 1.5.2.2 jdolecek fwsm = IXGBE_READ_REG(hw, IXGBE_FWSM);
4379 1.5.2.2 jdolecek if (fwsm & IXGBE_FWSM_TS_ENABLED)
4380 1.5.2.2 jdolecek mask |= IXGBE_EIMS_TS;
4381 1.5.2.2 jdolecek mask |= IXGBE_EIMS_ECC;
4382 1.5.2.2 jdolecek break;
4383 1.5.2.2 jdolecek case ixgbe_mac_X550:
4384 1.5.2.2 jdolecek /* MAC thermal sensor is automatically enabled */
4385 1.5.2.2 jdolecek mask |= IXGBE_EIMS_TS;
4386 1.5.2.2 jdolecek mask |= IXGBE_EIMS_ECC;
4387 1.5.2.2 jdolecek break;
4388 1.5.2.2 jdolecek case ixgbe_mac_X550EM_x:
4389 1.5.2.2 jdolecek case ixgbe_mac_X550EM_a:
4390 1.5.2.2 jdolecek /* Some devices use SDP0 for important information */
4391 1.5.2.2 jdolecek if (hw->device_id == IXGBE_DEV_ID_X550EM_X_SFP ||
4392 1.5.2.2 jdolecek hw->device_id == IXGBE_DEV_ID_X550EM_A_SFP ||
4393 1.5.2.2 jdolecek hw->device_id == IXGBE_DEV_ID_X550EM_A_SFP_N ||
4394 1.5.2.2 jdolecek hw->device_id == IXGBE_DEV_ID_X550EM_X_10G_T)
4395 1.5.2.2 jdolecek mask |= IXGBE_EIMS_GPI_SDP0_BY_MAC(hw);
4396 1.5.2.2 jdolecek if (hw->phy.type == ixgbe_phy_x550em_ext_t)
4397 1.5.2.2 jdolecek mask |= IXGBE_EICR_GPI_SDP0_X540;
4398 1.5.2.2 jdolecek mask |= IXGBE_EIMS_ECC;
4399 1.5.2.2 jdolecek break;
4400 1.5.2.2 jdolecek default:
4401 1.5.2.2 jdolecek break;
4402 1.5.2.2 jdolecek }
4403 1.1 dyoung
4404 1.5.2.2 jdolecek /* Enable Fan Failure detection */
4405 1.5.2.2 jdolecek if (adapter->feat_en & IXGBE_FEATURE_FAN_FAIL)
4406 1.5.2.2 jdolecek mask |= IXGBE_EIMS_GPI_SDP1;
4407 1.5.2.2 jdolecek /* Enable SR-IOV */
4408 1.5.2.2 jdolecek if (adapter->feat_en & IXGBE_FEATURE_SRIOV)
4409 1.5.2.2 jdolecek mask |= IXGBE_EIMS_MAILBOX;
4410 1.5.2.2 jdolecek /* Enable Flow Director */
4411 1.5.2.2 jdolecek if (adapter->feat_en & IXGBE_FEATURE_FDIR)
4412 1.5.2.2 jdolecek mask |= IXGBE_EIMS_FLOW_DIR;
4413 1.1 dyoung
4414 1.5.2.2 jdolecek IXGBE_WRITE_REG(hw, IXGBE_EIMS, mask);
4415 1.1 dyoung
4416 1.5.2.2 jdolecek /* With MSI-X we use auto clear */
4417 1.5.2.2 jdolecek if (adapter->msix_mem) {
4418 1.5.2.2 jdolecek mask = IXGBE_EIMS_ENABLE_MASK;
4419 1.5.2.2 jdolecek /* Don't autoclear Link */
4420 1.5.2.2 jdolecek mask &= ~IXGBE_EIMS_OTHER;
4421 1.5.2.2 jdolecek mask &= ~IXGBE_EIMS_LSC;
4422 1.5.2.2 jdolecek if (adapter->feat_cap & IXGBE_FEATURE_SRIOV)
4423 1.5.2.2 jdolecek mask &= ~IXGBE_EIMS_MAILBOX;
4424 1.5.2.2 jdolecek IXGBE_WRITE_REG(hw, IXGBE_EIAC, mask);
4425 1.5.2.2 jdolecek }
4426 1.1 dyoung
4427 1.1 dyoung /*
4428 1.5.2.2 jdolecek * Now enable all queues, this is done separately to
4429 1.5.2.2 jdolecek * allow for handling the extended (beyond 32) MSI-X
4430 1.5.2.2 jdolecek * vectors that can be used by 82599
4431 1.1 dyoung */
4432 1.5.2.2 jdolecek for (int i = 0; i < adapter->num_queues; i++, que++)
4433 1.5.2.2 jdolecek ixgbe_enable_queue(adapter, que->msix);
4434 1.1 dyoung
4435 1.5.2.2 jdolecek IXGBE_WRITE_FLUSH(hw);
4436 1.1 dyoung
4437 1.5.2.2 jdolecek return;
4438 1.5.2.2 jdolecek } /* ixgbe_enable_intr */
4439 1.1 dyoung
4440 1.5.2.2 jdolecek /************************************************************************
4441 1.5.2.2 jdolecek * ixgbe_disable_intr
4442 1.5.2.2 jdolecek ************************************************************************/
4443 1.1 dyoung static void
4444 1.5.2.2 jdolecek ixgbe_disable_intr(struct adapter *adapter)
4445 1.1 dyoung {
4446 1.5.2.2 jdolecek if (adapter->msix_mem)
4447 1.5.2.2 jdolecek IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIAC, 0);
4448 1.5.2.2 jdolecek if (adapter->hw.mac.type == ixgbe_mac_82598EB) {
4449 1.5.2.2 jdolecek IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMC, ~0);
4450 1.5.2.2 jdolecek } else {
4451 1.5.2.2 jdolecek IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMC, 0xFFFF0000);
4452 1.5.2.2 jdolecek IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMC_EX(0), ~0);
4453 1.5.2.2 jdolecek IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMC_EX(1), ~0);
4454 1.5.2.2 jdolecek }
4455 1.5.2.2 jdolecek IXGBE_WRITE_FLUSH(&adapter->hw);
4456 1.1 dyoung
4457 1.5.2.2 jdolecek return;
4458 1.5.2.2 jdolecek } /* ixgbe_disable_intr */
4459 1.1 dyoung
4460 1.5.2.2 jdolecek /************************************************************************
4461 1.5.2.2 jdolecek * ixgbe_legacy_irq - Legacy Interrupt Service routine
4462 1.5.2.2 jdolecek ************************************************************************/
4463 1.5.2.2 jdolecek static int
4464 1.5.2.2 jdolecek ixgbe_legacy_irq(void *arg)
4465 1.5.2.2 jdolecek {
4466 1.5.2.2 jdolecek struct ix_queue *que = arg;
4467 1.5.2.2 jdolecek struct adapter *adapter = que->adapter;
4468 1.5.2.2 jdolecek struct ixgbe_hw *hw = &adapter->hw;
4469 1.5.2.2 jdolecek struct ifnet *ifp = adapter->ifp;
4470 1.5.2.2 jdolecek struct tx_ring *txr = adapter->tx_rings;
4471 1.5.2.2 jdolecek bool more = false;
4472 1.5.2.2 jdolecek u32 eicr, eicr_mask;
4473 1.1 dyoung
4474 1.5.2.2 jdolecek /* Silicon errata #26 on 82598 */
4475 1.5.2.2 jdolecek IXGBE_WRITE_REG(hw, IXGBE_EIMC, IXGBE_IRQ_CLEAR_MASK);
4476 1.1 dyoung
4477 1.5.2.2 jdolecek eicr = IXGBE_READ_REG(hw, IXGBE_EICR);
4478 1.1 dyoung
4479 1.5.2.2 jdolecek adapter->stats.pf.legint.ev_count++;
4480 1.5.2.2 jdolecek ++que->irqs.ev_count;
4481 1.5.2.2 jdolecek if (eicr == 0) {
4482 1.5.2.2 jdolecek adapter->stats.pf.intzero.ev_count++;
4483 1.5.2.2 jdolecek if ((ifp->if_flags & IFF_UP) != 0)
4484 1.5.2.2 jdolecek ixgbe_enable_intr(adapter);
4485 1.5.2.2 jdolecek return 0;
4486 1.5.2.2 jdolecek }
4487 1.1 dyoung
4488 1.5.2.2 jdolecek if ((ifp->if_flags & IFF_RUNNING) != 0) {
4489 1.5.2.2 jdolecek #ifdef __NetBSD__
4490 1.5.2.2 jdolecek /* Don't run ixgbe_rxeof in interrupt context */
4491 1.5.2.2 jdolecek more = true;
4492 1.5.2.2 jdolecek #else
4493 1.5.2.2 jdolecek more = ixgbe_rxeof(que);
4494 1.5.2.2 jdolecek #endif
4495 1.1 dyoung
4496 1.5.2.2 jdolecek IXGBE_TX_LOCK(txr);
4497 1.5.2.2 jdolecek ixgbe_txeof(txr);
4498 1.5.2.2 jdolecek #ifdef notyet
4499 1.5.2.2 jdolecek if (!ixgbe_ring_empty(ifp, txr->br))
4500 1.5.2.2 jdolecek ixgbe_start_locked(ifp, txr);
4501 1.5.2.2 jdolecek #endif
4502 1.5.2.2 jdolecek IXGBE_TX_UNLOCK(txr);
4503 1.1 dyoung }
4504 1.1 dyoung
4505 1.5.2.2 jdolecek /* Check for fan failure */
4506 1.5.2.2 jdolecek if (adapter->feat_en & IXGBE_FEATURE_FAN_FAIL) {
4507 1.5.2.2 jdolecek ixgbe_check_fan_failure(adapter, eicr, true);
4508 1.5.2.2 jdolecek IXGBE_WRITE_REG(hw, IXGBE_EIMS, IXGBE_EICR_GPI_SDP1_BY_MAC(hw));
4509 1.1 dyoung }
4510 1.1 dyoung
4511 1.5.2.2 jdolecek /* Link status change */
4512 1.5.2.2 jdolecek if (eicr & IXGBE_EICR_LSC)
4513 1.5.2.2 jdolecek softint_schedule(adapter->link_si);
4514 1.1 dyoung
4515 1.5.2.2 jdolecek if (ixgbe_is_sfp(hw)) {
4516 1.5.2.2 jdolecek /* Pluggable optics-related interrupt */
4517 1.5.2.2 jdolecek if (hw->mac.type >= ixgbe_mac_X540)
4518 1.5.2.2 jdolecek eicr_mask = IXGBE_EICR_GPI_SDP0_X540;
4519 1.5.2.2 jdolecek else
4520 1.5.2.2 jdolecek eicr_mask = IXGBE_EICR_GPI_SDP2_BY_MAC(hw);
4521 1.1 dyoung
4522 1.5.2.2 jdolecek if (eicr & eicr_mask) {
4523 1.5.2.2 jdolecek IXGBE_WRITE_REG(hw, IXGBE_EICR, eicr_mask);
4524 1.5.2.2 jdolecek softint_schedule(adapter->mod_si);
4525 1.1 dyoung }
4526 1.1 dyoung
4527 1.5.2.2 jdolecek if ((hw->mac.type == ixgbe_mac_82599EB) &&
4528 1.5.2.2 jdolecek (eicr & IXGBE_EICR_GPI_SDP1_BY_MAC(hw))) {
4529 1.5.2.2 jdolecek IXGBE_WRITE_REG(hw, IXGBE_EICR,
4530 1.5.2.2 jdolecek IXGBE_EICR_GPI_SDP1_BY_MAC(hw));
4531 1.5.2.2 jdolecek softint_schedule(adapter->msf_si);
4532 1.5.2.2 jdolecek }
4533 1.1 dyoung }
4534 1.1 dyoung
4535 1.5.2.2 jdolecek /* External PHY interrupt */
4536 1.5.2.2 jdolecek if ((hw->phy.type == ixgbe_phy_x550em_ext_t) &&
4537 1.5.2.2 jdolecek (eicr & IXGBE_EICR_GPI_SDP0_X540))
4538 1.5.2.2 jdolecek softint_schedule(adapter->phy_si);
4539 1.1 dyoung
4540 1.5.2.2 jdolecek if (more)
4541 1.5.2.2 jdolecek softint_schedule(que->que_si);
4542 1.5.2.2 jdolecek else
4543 1.5.2.2 jdolecek ixgbe_enable_intr(adapter);
4544 1.1 dyoung
4545 1.5.2.2 jdolecek return 1;
4546 1.5.2.2 jdolecek } /* ixgbe_legacy_irq */
4547 1.1 dyoung
4548 1.5.2.2 jdolecek /************************************************************************
4549 1.5.2.2 jdolecek * ixgbe_free_pci_resources
4550 1.5.2.2 jdolecek ************************************************************************/
4551 1.1 dyoung static void
4552 1.5.2.2 jdolecek ixgbe_free_pci_resources(struct adapter *adapter)
4553 1.1 dyoung {
4554 1.5.2.2 jdolecek struct ix_queue *que = adapter->queues;
4555 1.5.2.2 jdolecek int rid;
4556 1.1 dyoung
4557 1.5.2.2 jdolecek /*
4558 1.5.2.2 jdolecek * Release all msix queue resources:
4559 1.5.2.2 jdolecek */
4560 1.5.2.2 jdolecek for (int i = 0; i < adapter->num_queues; i++, que++) {
4561 1.5.2.2 jdolecek if (que->res != NULL)
4562 1.5.2.2 jdolecek pci_intr_disestablish(adapter->osdep.pc,
4563 1.5.2.2 jdolecek adapter->osdep.ihs[i]);
4564 1.1 dyoung }
4565 1.1 dyoung
4566 1.5.2.2 jdolecek /* Clean the Legacy or Link interrupt last */
4567 1.5.2.2 jdolecek if (adapter->vector) /* we are doing MSIX */
4568 1.5.2.2 jdolecek rid = adapter->vector;
4569 1.5.2.2 jdolecek else
4570 1.5.2.2 jdolecek rid = 0;
4571 1.1 dyoung
4572 1.5.2.2 jdolecek if (adapter->osdep.ihs[rid] != NULL) {
4573 1.5.2.2 jdolecek pci_intr_disestablish(adapter->osdep.pc,
4574 1.5.2.2 jdolecek adapter->osdep.ihs[rid]);
4575 1.5.2.2 jdolecek adapter->osdep.ihs[rid] = NULL;
4576 1.1 dyoung }
4577 1.1 dyoung
4578 1.5.2.2 jdolecek pci_intr_release(adapter->osdep.pc, adapter->osdep.intrs,
4579 1.5.2.2 jdolecek adapter->osdep.nintrs);
4580 1.5.2.2 jdolecek
4581 1.5.2.2 jdolecek if (adapter->osdep.mem_size != 0) {
4582 1.5.2.2 jdolecek bus_space_unmap(adapter->osdep.mem_bus_space_tag,
4583 1.5.2.2 jdolecek adapter->osdep.mem_bus_space_handle,
4584 1.5.2.2 jdolecek adapter->osdep.mem_size);
4585 1.1 dyoung }
4586 1.1 dyoung
4587 1.1 dyoung return;
4588 1.5.2.2 jdolecek } /* ixgbe_free_pci_resources */
4589 1.1 dyoung
4590 1.5.2.2 jdolecek /************************************************************************
4591 1.5.2.2 jdolecek * ixgbe_set_sysctl_value
4592 1.5.2.2 jdolecek ************************************************************************/
4593 1.5.2.2 jdolecek static void
4594 1.5.2.2 jdolecek ixgbe_set_sysctl_value(struct adapter *adapter, const char *name,
4595 1.5.2.2 jdolecek const char *description, int *limit, int value)
4596 1.1 dyoung {
4597 1.5.2.2 jdolecek device_t dev = adapter->dev;
4598 1.5.2.2 jdolecek struct sysctllog **log;
4599 1.5.2.2 jdolecek const struct sysctlnode *rnode, *cnode;
4600 1.1 dyoung
4601 1.5.2.2 jdolecek log = &adapter->sysctllog;
4602 1.5.2.2 jdolecek if ((rnode = ixgbe_sysctl_instance(adapter)) == NULL) {
4603 1.5.2.2 jdolecek aprint_error_dev(dev, "could not create sysctl root\n");
4604 1.5.2.2 jdolecek return;
4605 1.5.2.2 jdolecek }
4606 1.5.2.2 jdolecek if (sysctl_createv(log, 0, &rnode, &cnode,
4607 1.5.2.2 jdolecek CTLFLAG_READWRITE, CTLTYPE_INT,
4608 1.5.2.2 jdolecek name, SYSCTL_DESCR(description),
4609 1.5.2.2 jdolecek NULL, 0, limit, 0, CTL_CREATE, CTL_EOL) != 0)
4610 1.5.2.2 jdolecek aprint_error_dev(dev, "could not create sysctl\n");
4611 1.5.2.2 jdolecek *limit = value;
4612 1.5.2.2 jdolecek } /* ixgbe_set_sysctl_value */
4613 1.1 dyoung
4614 1.5.2.2 jdolecek /************************************************************************
4615 1.5.2.2 jdolecek * ixgbe_sysctl_flowcntl
4616 1.5.2.2 jdolecek *
4617 1.5.2.2 jdolecek * SYSCTL wrapper around setting Flow Control
4618 1.5.2.2 jdolecek ************************************************************************/
4619 1.5.2.2 jdolecek static int
4620 1.5.2.2 jdolecek ixgbe_sysctl_flowcntl(SYSCTLFN_ARGS)
4621 1.1 dyoung {
4622 1.5.2.2 jdolecek struct sysctlnode node = *rnode;
4623 1.5.2.2 jdolecek struct adapter *adapter = (struct adapter *)node.sysctl_data;
4624 1.5.2.2 jdolecek int error, fc;
4625 1.1 dyoung
4626 1.5.2.2 jdolecek fc = adapter->hw.fc.current_mode;
4627 1.5.2.2 jdolecek node.sysctl_data = &fc;
4628 1.5.2.2 jdolecek error = sysctl_lookup(SYSCTLFN_CALL(&node));
4629 1.5.2.2 jdolecek if (error != 0 || newp == NULL)
4630 1.5.2.2 jdolecek return error;
4631 1.1 dyoung
4632 1.5.2.2 jdolecek /* Don't bother if it's not changed */
4633 1.5.2.2 jdolecek if (fc == adapter->hw.fc.current_mode)
4634 1.5.2.2 jdolecek return (0);
4635 1.1 dyoung
4636 1.5.2.2 jdolecek return ixgbe_set_flowcntl(adapter, fc);
4637 1.5.2.2 jdolecek } /* ixgbe_sysctl_flowcntl */
4638 1.1 dyoung
4639 1.5.2.2 jdolecek /************************************************************************
4640 1.5.2.2 jdolecek * ixgbe_set_flowcntl - Set flow control
4641 1.1 dyoung *
4642 1.5.2.2 jdolecek * Flow control values:
4643 1.5.2.2 jdolecek * 0 - off
4644 1.5.2.2 jdolecek * 1 - rx pause
4645 1.5.2.2 jdolecek * 2 - tx pause
4646 1.5.2.2 jdolecek * 3 - full
4647 1.5.2.2 jdolecek ************************************************************************/
4648 1.5.2.2 jdolecek static int
4649 1.5.2.2 jdolecek ixgbe_set_flowcntl(struct adapter *adapter, int fc)
4650 1.1 dyoung {
4651 1.5.2.2 jdolecek switch (fc) {
4652 1.5.2.2 jdolecek case ixgbe_fc_rx_pause:
4653 1.5.2.2 jdolecek case ixgbe_fc_tx_pause:
4654 1.5.2.2 jdolecek case ixgbe_fc_full:
4655 1.5.2.2 jdolecek adapter->hw.fc.requested_mode = fc;
4656 1.5.2.2 jdolecek if (adapter->num_queues > 1)
4657 1.5.2.2 jdolecek ixgbe_disable_rx_drop(adapter);
4658 1.1 dyoung break;
4659 1.5.2.2 jdolecek case ixgbe_fc_none:
4660 1.5.2.2 jdolecek adapter->hw.fc.requested_mode = ixgbe_fc_none;
4661 1.5.2.2 jdolecek if (adapter->num_queues > 1)
4662 1.5.2.2 jdolecek ixgbe_enable_rx_drop(adapter);
4663 1.1 dyoung break;
4664 1.5.2.2 jdolecek default:
4665 1.5.2.2 jdolecek return (EINVAL);
4666 1.5.2.2 jdolecek }
4667 1.1 dyoung
4668 1.5.2.2 jdolecek #if 0 /* XXX NetBSD */
4669 1.5.2.2 jdolecek /* Don't autoneg if forcing a value */
4670 1.5.2.2 jdolecek adapter->hw.fc.disable_fc_autoneg = TRUE;
4671 1.1 dyoung #endif
4672 1.5.2.2 jdolecek ixgbe_fc_enable(&adapter->hw);
4673 1.1 dyoung
4674 1.5.2.2 jdolecek return (0);
4675 1.5.2.2 jdolecek } /* ixgbe_set_flowcntl */
4676 1.1 dyoung
4677 1.5.2.2 jdolecek /************************************************************************
4678 1.5.2.2 jdolecek * ixgbe_enable_rx_drop
4679 1.5.2.2 jdolecek *
4680 1.5.2.2 jdolecek * Enable the hardware to drop packets when the buffer is
4681 1.5.2.2 jdolecek * full. This is useful with multiqueue, so that no single
4682 1.5.2.2 jdolecek * queue being full stalls the entire RX engine. We only
4683 1.5.2.2 jdolecek * enable this when Multiqueue is enabled AND Flow Control
4684 1.5.2.2 jdolecek * is disabled.
4685 1.5.2.2 jdolecek ************************************************************************/
4686 1.5.2.2 jdolecek static void
4687 1.5.2.2 jdolecek ixgbe_enable_rx_drop(struct adapter *adapter)
4688 1.5.2.2 jdolecek {
4689 1.5.2.2 jdolecek struct ixgbe_hw *hw = &adapter->hw;
4690 1.5.2.2 jdolecek struct rx_ring *rxr;
4691 1.5.2.2 jdolecek u32 srrctl;
4692 1.1 dyoung
4693 1.5.2.2 jdolecek for (int i = 0; i < adapter->num_queues; i++) {
4694 1.5.2.2 jdolecek rxr = &adapter->rx_rings[i];
4695 1.5.2.2 jdolecek srrctl = IXGBE_READ_REG(hw, IXGBE_SRRCTL(rxr->me));
4696 1.5.2.2 jdolecek srrctl |= IXGBE_SRRCTL_DROP_EN;
4697 1.5.2.2 jdolecek IXGBE_WRITE_REG(hw, IXGBE_SRRCTL(rxr->me), srrctl);
4698 1.1 dyoung }
4699 1.1 dyoung
4700 1.5.2.2 jdolecek /* enable drop for each vf */
4701 1.5.2.2 jdolecek for (int i = 0; i < adapter->num_vfs; i++) {
4702 1.5.2.2 jdolecek IXGBE_WRITE_REG(hw, IXGBE_QDE,
4703 1.5.2.2 jdolecek (IXGBE_QDE_WRITE | (i << IXGBE_QDE_IDX_SHIFT) |
4704 1.5.2.2 jdolecek IXGBE_QDE_ENABLE));
4705 1.5.2.2 jdolecek }
4706 1.5.2.2 jdolecek } /* ixgbe_enable_rx_drop */
4707 1.1 dyoung
4708 1.5.2.2 jdolecek /************************************************************************
4709 1.5.2.2 jdolecek * ixgbe_disable_rx_drop
4710 1.5.2.2 jdolecek ************************************************************************/
4711 1.5.2.2 jdolecek static void
4712 1.5.2.2 jdolecek ixgbe_disable_rx_drop(struct adapter *adapter)
4713 1.5.2.2 jdolecek {
4714 1.5.2.2 jdolecek struct ixgbe_hw *hw = &adapter->hw;
4715 1.5.2.2 jdolecek struct rx_ring *rxr;
4716 1.5.2.2 jdolecek u32 srrctl;
4717 1.1 dyoung
4718 1.5.2.2 jdolecek for (int i = 0; i < adapter->num_queues; i++) {
4719 1.5.2.2 jdolecek rxr = &adapter->rx_rings[i];
4720 1.5.2.2 jdolecek srrctl = IXGBE_READ_REG(hw, IXGBE_SRRCTL(rxr->me));
4721 1.5.2.2 jdolecek srrctl &= ~IXGBE_SRRCTL_DROP_EN;
4722 1.5.2.2 jdolecek IXGBE_WRITE_REG(hw, IXGBE_SRRCTL(rxr->me), srrctl);
4723 1.1 dyoung }
4724 1.1 dyoung
4725 1.5.2.2 jdolecek /* disable drop for each vf */
4726 1.5.2.2 jdolecek for (int i = 0; i < adapter->num_vfs; i++) {
4727 1.5.2.2 jdolecek IXGBE_WRITE_REG(hw, IXGBE_QDE,
4728 1.5.2.2 jdolecek (IXGBE_QDE_WRITE | (i << IXGBE_QDE_IDX_SHIFT)));
4729 1.1 dyoung }
4730 1.5.2.2 jdolecek } /* ixgbe_disable_rx_drop */
4731 1.1 dyoung
4732 1.5.2.2 jdolecek /************************************************************************
4733 1.5.2.2 jdolecek * ixgbe_sysctl_advertise
4734 1.5.2.2 jdolecek *
4735 1.5.2.2 jdolecek * SYSCTL wrapper around setting advertised speed
4736 1.5.2.2 jdolecek ************************************************************************/
4737 1.5.2.2 jdolecek static int
4738 1.5.2.2 jdolecek ixgbe_sysctl_advertise(SYSCTLFN_ARGS)
4739 1.5.2.2 jdolecek {
4740 1.5.2.2 jdolecek struct sysctlnode node = *rnode;
4741 1.5.2.2 jdolecek struct adapter *adapter = (struct adapter *)node.sysctl_data;
4742 1.5.2.2 jdolecek int error = 0, advertise;
4743 1.1 dyoung
4744 1.5.2.2 jdolecek advertise = adapter->advertise;
4745 1.5.2.2 jdolecek node.sysctl_data = &advertise;
4746 1.5.2.2 jdolecek error = sysctl_lookup(SYSCTLFN_CALL(&node));
4747 1.5.2.2 jdolecek if (error != 0 || newp == NULL)
4748 1.5.2.2 jdolecek return error;
4749 1.1 dyoung
4750 1.5.2.2 jdolecek return ixgbe_set_advertise(adapter, advertise);
4751 1.5.2.2 jdolecek } /* ixgbe_sysctl_advertise */
4752 1.5.2.2 jdolecek
4753 1.5.2.2 jdolecek /************************************************************************
4754 1.5.2.2 jdolecek * ixgbe_set_advertise - Control advertised link speed
4755 1.1 dyoung *
4756 1.5.2.2 jdolecek * Flags:
4757 1.5.2.2 jdolecek * 0x00 - Default (all capable link speed)
4758 1.5.2.2 jdolecek * 0x01 - advertise 100 Mb
4759 1.5.2.2 jdolecek * 0x02 - advertise 1G
4760 1.5.2.2 jdolecek * 0x04 - advertise 10G
4761 1.5.2.2 jdolecek * 0x08 - advertise 10 Mb
4762 1.5.2.2 jdolecek * 0x10 - advertise 2.5G
4763 1.5.2.2 jdolecek * 0x20 - advertise 5G
4764 1.5.2.2 jdolecek ************************************************************************/
4765 1.5.2.2 jdolecek static int
4766 1.5.2.2 jdolecek ixgbe_set_advertise(struct adapter *adapter, int advertise)
4767 1.1 dyoung {
4768 1.5.2.2 jdolecek device_t dev;
4769 1.5.2.2 jdolecek struct ixgbe_hw *hw;
4770 1.5.2.2 jdolecek ixgbe_link_speed speed = 0;
4771 1.5.2.2 jdolecek ixgbe_link_speed link_caps = 0;
4772 1.5.2.2 jdolecek s32 err = IXGBE_NOT_IMPLEMENTED;
4773 1.5.2.2 jdolecek bool negotiate = FALSE;
4774 1.1 dyoung
4775 1.5.2.2 jdolecek /* Checks to validate new value */
4776 1.5.2.2 jdolecek if (adapter->advertise == advertise) /* no change */
4777 1.5.2.2 jdolecek return (0);
4778 1.5.2.2 jdolecek
4779 1.5.2.2 jdolecek dev = adapter->dev;
4780 1.5.2.2 jdolecek hw = &adapter->hw;
4781 1.1 dyoung
4782 1.5.2.2 jdolecek /* No speed changes for backplane media */
4783 1.5.2.2 jdolecek if (hw->phy.media_type == ixgbe_media_type_backplane)
4784 1.5.2.2 jdolecek return (ENODEV);
4785 1.1 dyoung
4786 1.5.2.2 jdolecek if (!((hw->phy.media_type == ixgbe_media_type_copper) ||
4787 1.5.2.2 jdolecek (hw->phy.multispeed_fiber))) {
4788 1.5.2.2 jdolecek device_printf(dev,
4789 1.5.2.2 jdolecek "Advertised speed can only be set on copper or "
4790 1.5.2.2 jdolecek "multispeed fiber media types.\n");
4791 1.5.2.2 jdolecek return (EINVAL);
4792 1.5.2.2 jdolecek }
4793 1.5.2.2 jdolecek
4794 1.5.2.2 jdolecek if (advertise < 0x0 || advertise > 0x2f) {
4795 1.5.2.2 jdolecek device_printf(dev,
4796 1.5.2.2 jdolecek "Invalid advertised speed; valid modes are 0x0 through 0x7\n");
4797 1.5.2.2 jdolecek return (EINVAL);
4798 1.5.2.2 jdolecek }
4799 1.5.2.2 jdolecek
4800 1.5.2.2 jdolecek if (hw->mac.ops.get_link_capabilities) {
4801 1.5.2.2 jdolecek err = hw->mac.ops.get_link_capabilities(hw, &link_caps,
4802 1.5.2.2 jdolecek &negotiate);
4803 1.5.2.2 jdolecek if (err != IXGBE_SUCCESS) {
4804 1.5.2.2 jdolecek device_printf(dev, "Unable to determine supported advertise speeds\n");
4805 1.5.2.2 jdolecek return (ENODEV);
4806 1.1 dyoung }
4807 1.1 dyoung }
4808 1.5.2.2 jdolecek
4809 1.5.2.2 jdolecek /* Set new value and report new advertised mode */
4810 1.5.2.2 jdolecek if (advertise & 0x1) {
4811 1.5.2.2 jdolecek if (!(link_caps & IXGBE_LINK_SPEED_100_FULL)) {
4812 1.5.2.2 jdolecek device_printf(dev, "Interface does not support 100Mb advertised speed\n");
4813 1.5.2.2 jdolecek return (EINVAL);
4814 1.1 dyoung }
4815 1.5.2.2 jdolecek speed |= IXGBE_LINK_SPEED_100_FULL;
4816 1.1 dyoung }
4817 1.5.2.2 jdolecek if (advertise & 0x2) {
4818 1.5.2.2 jdolecek if (!(link_caps & IXGBE_LINK_SPEED_1GB_FULL)) {
4819 1.5.2.2 jdolecek device_printf(dev, "Interface does not support 1Gb advertised speed\n");
4820 1.5.2.2 jdolecek return (EINVAL);
4821 1.5.2.2 jdolecek }
4822 1.5.2.2 jdolecek speed |= IXGBE_LINK_SPEED_1GB_FULL;
4823 1.5.2.2 jdolecek }
4824 1.5.2.2 jdolecek if (advertise & 0x4) {
4825 1.5.2.2 jdolecek if (!(link_caps & IXGBE_LINK_SPEED_10GB_FULL)) {
4826 1.5.2.2 jdolecek device_printf(dev, "Interface does not support 10Gb advertised speed\n");
4827 1.5.2.2 jdolecek return (EINVAL);
4828 1.5.2.2 jdolecek }
4829 1.5.2.2 jdolecek speed |= IXGBE_LINK_SPEED_10GB_FULL;
4830 1.5.2.2 jdolecek }
4831 1.5.2.2 jdolecek if (advertise & 0x8) {
4832 1.5.2.2 jdolecek if (!(link_caps & IXGBE_LINK_SPEED_10_FULL)) {
4833 1.5.2.2 jdolecek device_printf(dev, "Interface does not support 10Mb advertised speed\n");
4834 1.5.2.2 jdolecek return (EINVAL);
4835 1.5.2.2 jdolecek }
4836 1.5.2.2 jdolecek speed |= IXGBE_LINK_SPEED_10_FULL;
4837 1.5.2.2 jdolecek }
4838 1.5.2.2 jdolecek if (advertise & 0x10) {
4839 1.5.2.2 jdolecek if (!(link_caps & IXGBE_LINK_SPEED_2_5GB_FULL)) {
4840 1.5.2.2 jdolecek device_printf(dev, "Interface does not support 2.5Gb advertised speed\n");
4841 1.5.2.2 jdolecek return (EINVAL);
4842 1.5.2.2 jdolecek }
4843 1.5.2.2 jdolecek speed |= IXGBE_LINK_SPEED_2_5GB_FULL;
4844 1.5.2.2 jdolecek }
4845 1.5.2.2 jdolecek if (advertise & 0x20) {
4846 1.5.2.2 jdolecek if (!(link_caps & IXGBE_LINK_SPEED_5GB_FULL)) {
4847 1.5.2.2 jdolecek device_printf(dev, "Interface does not support 5Gb advertised speed\n");
4848 1.5.2.2 jdolecek return (EINVAL);
4849 1.5.2.2 jdolecek }
4850 1.5.2.2 jdolecek speed |= IXGBE_LINK_SPEED_5GB_FULL;
4851 1.5.2.2 jdolecek }
4852 1.5.2.2 jdolecek if (advertise == 0)
4853 1.5.2.2 jdolecek speed = link_caps; /* All capable link speed */
4854 1.1 dyoung
4855 1.5.2.2 jdolecek hw->mac.autotry_restart = TRUE;
4856 1.5.2.2 jdolecek hw->mac.ops.setup_link(hw, speed, TRUE);
4857 1.5.2.2 jdolecek adapter->advertise = advertise;
4858 1.1 dyoung
4859 1.5.2.2 jdolecek return (0);
4860 1.5.2.2 jdolecek } /* ixgbe_set_advertise */
4861 1.1 dyoung
4862 1.5.2.2 jdolecek /************************************************************************
4863 1.5.2.2 jdolecek * ixgbe_get_advertise - Get current advertised speed settings
4864 1.5.2.2 jdolecek *
4865 1.5.2.2 jdolecek * Formatted for sysctl usage.
4866 1.5.2.2 jdolecek * Flags:
4867 1.5.2.2 jdolecek * 0x01 - advertise 100 Mb
4868 1.5.2.2 jdolecek * 0x02 - advertise 1G
4869 1.5.2.2 jdolecek * 0x04 - advertise 10G
4870 1.5.2.2 jdolecek * 0x08 - advertise 10 Mb (yes, Mb)
4871 1.5.2.2 jdolecek * 0x10 - advertise 2.5G
4872 1.5.2.2 jdolecek * 0x20 - advertise 5G
4873 1.5.2.2 jdolecek ************************************************************************/
4874 1.5.2.2 jdolecek static int
4875 1.5.2.2 jdolecek ixgbe_get_advertise(struct adapter *adapter)
4876 1.5.2.2 jdolecek {
4877 1.5.2.2 jdolecek struct ixgbe_hw *hw = &adapter->hw;
4878 1.5.2.2 jdolecek int speed;
4879 1.5.2.2 jdolecek ixgbe_link_speed link_caps = 0;
4880 1.5.2.2 jdolecek s32 err;
4881 1.5.2.2 jdolecek bool negotiate = FALSE;
4882 1.1 dyoung
4883 1.5.2.2 jdolecek /*
4884 1.5.2.2 jdolecek * Advertised speed means nothing unless it's copper or
4885 1.5.2.2 jdolecek * multi-speed fiber
4886 1.5.2.2 jdolecek */
4887 1.5.2.2 jdolecek if (!(hw->phy.media_type == ixgbe_media_type_copper) &&
4888 1.5.2.2 jdolecek !(hw->phy.multispeed_fiber))
4889 1.5.2.2 jdolecek return (0);
4890 1.1 dyoung
4891 1.5.2.2 jdolecek err = hw->mac.ops.get_link_capabilities(hw, &link_caps, &negotiate);
4892 1.5.2.2 jdolecek if (err != IXGBE_SUCCESS)
4893 1.5.2.2 jdolecek return (0);
4894 1.1 dyoung
4895 1.5.2.2 jdolecek speed =
4896 1.5.2.2 jdolecek ((link_caps & IXGBE_LINK_SPEED_10GB_FULL) ? 0x04 : 0) |
4897 1.5.2.2 jdolecek ((link_caps & IXGBE_LINK_SPEED_1GB_FULL) ? 0x02 : 0) |
4898 1.5.2.2 jdolecek ((link_caps & IXGBE_LINK_SPEED_100_FULL) ? 0x01 : 0) |
4899 1.5.2.2 jdolecek ((link_caps & IXGBE_LINK_SPEED_10_FULL) ? 0x08 : 0) |
4900 1.5.2.2 jdolecek ((link_caps & IXGBE_LINK_SPEED_2_5GB_FULL) ? 0x10 : 0) |
4901 1.5.2.2 jdolecek ((link_caps & IXGBE_LINK_SPEED_5GB_FULL) ? 0x20 : 0);
4902 1.5.2.2 jdolecek
4903 1.5.2.2 jdolecek return speed;
4904 1.5.2.2 jdolecek } /* ixgbe_get_advertise */
4905 1.5.2.2 jdolecek
4906 1.5.2.2 jdolecek /************************************************************************
4907 1.5.2.2 jdolecek * ixgbe_sysctl_dmac - Manage DMA Coalescing
4908 1.5.2.2 jdolecek *
4909 1.5.2.2 jdolecek * Control values:
4910 1.5.2.2 jdolecek * 0/1 - off / on (use default value of 1000)
4911 1.5.2.2 jdolecek *
4912 1.5.2.2 jdolecek * Legal timer values are:
4913 1.5.2.2 jdolecek * 50,100,250,500,1000,2000,5000,10000
4914 1.5.2.2 jdolecek *
4915 1.5.2.2 jdolecek * Turning off interrupt moderation will also turn this off.
4916 1.5.2.2 jdolecek ************************************************************************/
4917 1.5.2.2 jdolecek static int
4918 1.5.2.2 jdolecek ixgbe_sysctl_dmac(SYSCTLFN_ARGS)
4919 1.1 dyoung {
4920 1.5.2.2 jdolecek struct sysctlnode node = *rnode;
4921 1.5.2.2 jdolecek struct adapter *adapter = (struct adapter *)node.sysctl_data;
4922 1.5.2.2 jdolecek struct ifnet *ifp = adapter->ifp;
4923 1.5.2.2 jdolecek int error;
4924 1.5.2.2 jdolecek int newval;
4925 1.1 dyoung
4926 1.5.2.2 jdolecek newval = adapter->dmac;
4927 1.5.2.2 jdolecek node.sysctl_data = &newval;
4928 1.5.2.2 jdolecek error = sysctl_lookup(SYSCTLFN_CALL(&node));
4929 1.5.2.2 jdolecek if ((error) || (newp == NULL))
4930 1.5.2.2 jdolecek return (error);
4931 1.1 dyoung
4932 1.5.2.2 jdolecek switch (newval) {
4933 1.5.2.2 jdolecek case 0:
4934 1.5.2.2 jdolecek /* Disabled */
4935 1.5.2.2 jdolecek adapter->dmac = 0;
4936 1.5.2.2 jdolecek break;
4937 1.5.2.2 jdolecek case 1:
4938 1.5.2.2 jdolecek /* Enable and use default */
4939 1.5.2.2 jdolecek adapter->dmac = 1000;
4940 1.5.2.2 jdolecek break;
4941 1.5.2.2 jdolecek case 50:
4942 1.5.2.2 jdolecek case 100:
4943 1.5.2.2 jdolecek case 250:
4944 1.5.2.2 jdolecek case 500:
4945 1.5.2.2 jdolecek case 1000:
4946 1.5.2.2 jdolecek case 2000:
4947 1.5.2.2 jdolecek case 5000:
4948 1.5.2.2 jdolecek case 10000:
4949 1.5.2.2 jdolecek /* Legal values - allow */
4950 1.5.2.2 jdolecek adapter->dmac = newval;
4951 1.5.2.2 jdolecek break;
4952 1.5.2.2 jdolecek default:
4953 1.5.2.2 jdolecek /* Do nothing, illegal value */
4954 1.5.2.2 jdolecek return (EINVAL);
4955 1.5.2.2 jdolecek }
4956 1.1 dyoung
4957 1.5.2.2 jdolecek /* Re-initialize hardware if it's already running */
4958 1.5.2.2 jdolecek if (ifp->if_flags & IFF_RUNNING)
4959 1.5.2.2 jdolecek ixgbe_init(ifp);
4960 1.5.2.2 jdolecek
4961 1.5.2.2 jdolecek return (0);
4962 1.1 dyoung }
4963 1.1 dyoung
4964 1.5.2.2 jdolecek #ifdef IXGBE_DEBUG
4965 1.5.2.2 jdolecek /************************************************************************
4966 1.5.2.2 jdolecek * ixgbe_sysctl_power_state
4967 1.5.2.2 jdolecek *
4968 1.5.2.2 jdolecek * Sysctl to test power states
4969 1.5.2.2 jdolecek * Values:
4970 1.5.2.2 jdolecek * 0 - set device to D0
4971 1.5.2.2 jdolecek * 3 - set device to D3
4972 1.5.2.2 jdolecek * (none) - get current device power state
4973 1.5.2.2 jdolecek ************************************************************************/
4974 1.5.2.2 jdolecek static int
4975 1.5.2.2 jdolecek ixgbe_sysctl_power_state(SYSCTLFN_ARGS)
4976 1.1 dyoung {
4977 1.5.2.2 jdolecek #ifdef notyet
4978 1.5.2.2 jdolecek struct sysctlnode node = *rnode;
4979 1.5.2.2 jdolecek struct adapter *adapter = (struct adapter *)node.sysctl_data;
4980 1.5.2.2 jdolecek device_t dev = adapter->dev;
4981 1.5.2.2 jdolecek int curr_ps, new_ps, error = 0;
4982 1.1 dyoung
4983 1.5.2.2 jdolecek curr_ps = new_ps = pci_get_powerstate(dev);
4984 1.1 dyoung
4985 1.5.2.2 jdolecek error = sysctl_lookup(SYSCTLFN_CALL(&node));
4986 1.5.2.2 jdolecek if ((error) || (req->newp == NULL))
4987 1.5.2.2 jdolecek return (error);
4988 1.1 dyoung
4989 1.5.2.2 jdolecek if (new_ps == curr_ps)
4990 1.5.2.2 jdolecek return (0);
4991 1.1 dyoung
4992 1.5.2.2 jdolecek if (new_ps == 3 && curr_ps == 0)
4993 1.5.2.2 jdolecek error = DEVICE_SUSPEND(dev);
4994 1.5.2.2 jdolecek else if (new_ps == 0 && curr_ps == 3)
4995 1.5.2.2 jdolecek error = DEVICE_RESUME(dev);
4996 1.5.2.2 jdolecek else
4997 1.5.2.2 jdolecek return (EINVAL);
4998 1.1 dyoung
4999 1.5.2.2 jdolecek device_printf(dev, "New state: %d\n", pci_get_powerstate(dev));
5000 1.1 dyoung
5001 1.5.2.2 jdolecek return (error);
5002 1.5.2.2 jdolecek #else
5003 1.5.2.2 jdolecek return 0;
5004 1.5.2.2 jdolecek #endif
5005 1.5.2.2 jdolecek } /* ixgbe_sysctl_power_state */
5006 1.1 dyoung #endif
5007 1.1 dyoung
5008 1.5.2.2 jdolecek /************************************************************************
5009 1.5.2.2 jdolecek * ixgbe_sysctl_wol_enable
5010 1.5.2.2 jdolecek *
5011 1.5.2.2 jdolecek * Sysctl to enable/disable the WoL capability,
5012 1.5.2.2 jdolecek * if supported by the adapter.
5013 1.5.2.2 jdolecek *
5014 1.5.2.2 jdolecek * Values:
5015 1.5.2.2 jdolecek * 0 - disabled
5016 1.5.2.2 jdolecek * 1 - enabled
5017 1.5.2.2 jdolecek ************************************************************************/
5018 1.5.2.2 jdolecek static int
5019 1.5.2.2 jdolecek ixgbe_sysctl_wol_enable(SYSCTLFN_ARGS)
5020 1.5.2.2 jdolecek {
5021 1.5.2.2 jdolecek struct sysctlnode node = *rnode;
5022 1.5.2.2 jdolecek struct adapter *adapter = (struct adapter *)node.sysctl_data;
5023 1.5.2.2 jdolecek struct ixgbe_hw *hw = &adapter->hw;
5024 1.5.2.2 jdolecek bool new_wol_enabled;
5025 1.5.2.2 jdolecek int error = 0;
5026 1.1 dyoung
5027 1.5.2.2 jdolecek new_wol_enabled = hw->wol_enabled;
5028 1.5.2.2 jdolecek node.sysctl_data = &new_wol_enabled;
5029 1.5.2.2 jdolecek error = sysctl_lookup(SYSCTLFN_CALL(&node));
5030 1.5.2.2 jdolecek if ((error) || (newp == NULL))
5031 1.5.2.2 jdolecek return (error);
5032 1.5.2.2 jdolecek if (new_wol_enabled == hw->wol_enabled)
5033 1.5.2.2 jdolecek return (0);
5034 1.1 dyoung
5035 1.5.2.2 jdolecek if (new_wol_enabled && !adapter->wol_support)
5036 1.5.2.2 jdolecek return (ENODEV);
5037 1.5.2.2 jdolecek else
5038 1.5.2.2 jdolecek hw->wol_enabled = new_wol_enabled;
5039 1.1 dyoung
5040 1.5.2.2 jdolecek return (0);
5041 1.5.2.2 jdolecek } /* ixgbe_sysctl_wol_enable */
5042 1.1 dyoung
5043 1.5.2.2 jdolecek /************************************************************************
5044 1.5.2.2 jdolecek * ixgbe_sysctl_wufc - Wake Up Filter Control
5045 1.5.2.2 jdolecek *
5046 1.5.2.2 jdolecek * Sysctl to enable/disable the types of packets that the
5047 1.5.2.2 jdolecek * adapter will wake up on upon receipt.
5048 1.5.2.2 jdolecek * Flags:
5049 1.5.2.2 jdolecek * 0x1 - Link Status Change
5050 1.5.2.2 jdolecek * 0x2 - Magic Packet
5051 1.5.2.2 jdolecek * 0x4 - Direct Exact
5052 1.5.2.2 jdolecek * 0x8 - Directed Multicast
5053 1.5.2.2 jdolecek * 0x10 - Broadcast
5054 1.5.2.2 jdolecek * 0x20 - ARP/IPv4 Request Packet
5055 1.5.2.2 jdolecek * 0x40 - Direct IPv4 Packet
5056 1.5.2.2 jdolecek * 0x80 - Direct IPv6 Packet
5057 1.5.2.2 jdolecek *
5058 1.5.2.2 jdolecek * Settings not listed above will cause the sysctl to return an error.
5059 1.5.2.2 jdolecek ************************************************************************/
5060 1.5.2.2 jdolecek static int
5061 1.5.2.2 jdolecek ixgbe_sysctl_wufc(SYSCTLFN_ARGS)
5062 1.1 dyoung {
5063 1.5.2.2 jdolecek struct sysctlnode node = *rnode;
5064 1.5.2.2 jdolecek struct adapter *adapter = (struct adapter *)node.sysctl_data;
5065 1.5.2.2 jdolecek int error = 0;
5066 1.5.2.2 jdolecek u32 new_wufc;
5067 1.1 dyoung
5068 1.5.2.2 jdolecek new_wufc = adapter->wufc;
5069 1.5.2.2 jdolecek node.sysctl_data = &new_wufc;
5070 1.5.2.2 jdolecek error = sysctl_lookup(SYSCTLFN_CALL(&node));
5071 1.5.2.2 jdolecek if ((error) || (newp == NULL))
5072 1.5.2.2 jdolecek return (error);
5073 1.5.2.2 jdolecek if (new_wufc == adapter->wufc)
5074 1.5.2.2 jdolecek return (0);
5075 1.1 dyoung
5076 1.5.2.2 jdolecek if (new_wufc & 0xffffff00)
5077 1.5.2.2 jdolecek return (EINVAL);
5078 1.1 dyoung
5079 1.5.2.2 jdolecek new_wufc &= 0xff;
5080 1.5.2.2 jdolecek new_wufc |= (0xffffff & adapter->wufc);
5081 1.5.2.2 jdolecek adapter->wufc = new_wufc;
5082 1.1 dyoung
5083 1.5.2.2 jdolecek return (0);
5084 1.5.2.2 jdolecek } /* ixgbe_sysctl_wufc */
5085 1.1 dyoung
5086 1.5.2.2 jdolecek #ifdef IXGBE_DEBUG
5087 1.5.2.2 jdolecek /************************************************************************
5088 1.5.2.2 jdolecek * ixgbe_sysctl_print_rss_config
5089 1.5.2.2 jdolecek ************************************************************************/
5090 1.5.2.2 jdolecek static int
5091 1.5.2.2 jdolecek ixgbe_sysctl_print_rss_config(SYSCTLFN_ARGS)
5092 1.1 dyoung {
5093 1.5.2.2 jdolecek #ifdef notyet
5094 1.5.2.2 jdolecek struct sysctlnode node = *rnode;
5095 1.5.2.2 jdolecek struct adapter *adapter = (struct adapter *)node.sysctl_data;
5096 1.1 dyoung struct ixgbe_hw *hw = &adapter->hw;
5097 1.5.2.2 jdolecek device_t dev = adapter->dev;
5098 1.5.2.2 jdolecek struct sbuf *buf;
5099 1.5.2.2 jdolecek int error = 0, reta_size;
5100 1.5.2.2 jdolecek u32 reg;
5101 1.5.2.2 jdolecek
5102 1.5.2.2 jdolecek buf = sbuf_new_for_sysctl(NULL, NULL, 128, req);
5103 1.5.2.2 jdolecek if (!buf) {
5104 1.5.2.2 jdolecek device_printf(dev, "Could not allocate sbuf for output.\n");
5105 1.5.2.2 jdolecek return (ENOMEM);
5106 1.5.2.2 jdolecek }
5107 1.5.2.2 jdolecek
5108 1.5.2.2 jdolecek // TODO: use sbufs to make a string to print out
5109 1.5.2.2 jdolecek /* Set multiplier for RETA setup and table size based on MAC */
5110 1.5.2.2 jdolecek switch (adapter->hw.mac.type) {
5111 1.5.2.2 jdolecek case ixgbe_mac_X550:
5112 1.5.2.2 jdolecek case ixgbe_mac_X550EM_x:
5113 1.5.2.2 jdolecek case ixgbe_mac_X550EM_a:
5114 1.5.2.2 jdolecek reta_size = 128;
5115 1.1 dyoung break;
5116 1.1 dyoung default:
5117 1.5.2.2 jdolecek reta_size = 32;
5118 1.1 dyoung break;
5119 1.1 dyoung }
5120 1.1 dyoung
5121 1.5.2.2 jdolecek /* Print out the redirection table */
5122 1.5.2.2 jdolecek sbuf_cat(buf, "\n");
5123 1.5.2.2 jdolecek for (int i = 0; i < reta_size; i++) {
5124 1.5.2.2 jdolecek if (i < 32) {
5125 1.5.2.2 jdolecek reg = IXGBE_READ_REG(hw, IXGBE_RETA(i));
5126 1.5.2.2 jdolecek sbuf_printf(buf, "RETA(%2d): 0x%08x\n", i, reg);
5127 1.5.2.2 jdolecek } else {
5128 1.5.2.2 jdolecek reg = IXGBE_READ_REG(hw, IXGBE_ERETA(i - 32));
5129 1.5.2.2 jdolecek sbuf_printf(buf, "ERETA(%2d): 0x%08x\n", i - 32, reg);
5130 1.5.2.2 jdolecek }
5131 1.5.2.2 jdolecek }
5132 1.1 dyoung
5133 1.5.2.2 jdolecek // TODO: print more config
5134 1.1 dyoung
5135 1.5.2.2 jdolecek error = sbuf_finish(buf);
5136 1.5.2.2 jdolecek if (error)
5137 1.5.2.2 jdolecek device_printf(dev, "Error finishing sbuf: %d\n", error);
5138 1.1 dyoung
5139 1.5.2.2 jdolecek sbuf_delete(buf);
5140 1.5.2.2 jdolecek #endif
5141 1.5.2.2 jdolecek return (0);
5142 1.5.2.2 jdolecek } /* ixgbe_sysctl_print_rss_config */
5143 1.5.2.2 jdolecek #endif /* IXGBE_DEBUG */
5144 1.1 dyoung
5145 1.5.2.2 jdolecek /************************************************************************
5146 1.5.2.2 jdolecek * ixgbe_sysctl_phy_temp - Retrieve temperature of PHY
5147 1.5.2.2 jdolecek *
5148 1.5.2.2 jdolecek * For X552/X557-AT devices using an external PHY
5149 1.5.2.2 jdolecek ************************************************************************/
5150 1.5.2.2 jdolecek static int
5151 1.5.2.2 jdolecek ixgbe_sysctl_phy_temp(SYSCTLFN_ARGS)
5152 1.1 dyoung {
5153 1.5.2.2 jdolecek struct sysctlnode node = *rnode;
5154 1.5.2.2 jdolecek struct adapter *adapter = (struct adapter *)node.sysctl_data;
5155 1.5.2.2 jdolecek struct ixgbe_hw *hw = &adapter->hw;
5156 1.5.2.2 jdolecek int val;
5157 1.5.2.2 jdolecek u16 reg;
5158 1.5.2.2 jdolecek int error;
5159 1.1 dyoung
5160 1.5.2.2 jdolecek if (hw->device_id != IXGBE_DEV_ID_X550EM_X_10G_T) {
5161 1.5.2.2 jdolecek device_printf(adapter->dev,
5162 1.5.2.2 jdolecek "Device has no supported external thermal sensor.\n");
5163 1.5.2.2 jdolecek return (ENODEV);
5164 1.1 dyoung }
5165 1.1 dyoung
5166 1.5.2.2 jdolecek if (hw->phy.ops.read_reg(hw, IXGBE_PHY_CURRENT_TEMP,
5167 1.5.2.2 jdolecek IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE, ®)) {
5168 1.5.2.2 jdolecek device_printf(adapter->dev,
5169 1.5.2.2 jdolecek "Error reading from PHY's current temperature register\n");
5170 1.5.2.2 jdolecek return (EAGAIN);
5171 1.5.2.2 jdolecek }
5172 1.1 dyoung
5173 1.5.2.2 jdolecek node.sysctl_data = &val;
5174 1.1 dyoung
5175 1.5.2.2 jdolecek /* Shift temp for output */
5176 1.5.2.2 jdolecek val = reg >> 8;
5177 1.5.2.2 jdolecek
5178 1.5.2.2 jdolecek error = sysctl_lookup(SYSCTLFN_CALL(&node));
5179 1.5.2.2 jdolecek if ((error) || (newp == NULL))
5180 1.5.2.2 jdolecek return (error);
5181 1.5.2.2 jdolecek
5182 1.5.2.2 jdolecek return (0);
5183 1.5.2.2 jdolecek } /* ixgbe_sysctl_phy_temp */
5184 1.5.2.2 jdolecek
5185 1.5.2.2 jdolecek /************************************************************************
5186 1.5.2.2 jdolecek * ixgbe_sysctl_phy_overtemp_occurred
5187 1.5.2.2 jdolecek *
5188 1.5.2.2 jdolecek * Reports (directly from the PHY) whether the current PHY
5189 1.5.2.2 jdolecek * temperature is over the overtemp threshold.
5190 1.5.2.2 jdolecek ************************************************************************/
5191 1.5.2.2 jdolecek static int
5192 1.5.2.2 jdolecek ixgbe_sysctl_phy_overtemp_occurred(SYSCTLFN_ARGS)
5193 1.1 dyoung {
5194 1.5.2.2 jdolecek struct sysctlnode node = *rnode;
5195 1.5.2.2 jdolecek struct adapter *adapter = (struct adapter *)node.sysctl_data;
5196 1.1 dyoung struct ixgbe_hw *hw = &adapter->hw;
5197 1.5.2.2 jdolecek int val, error;
5198 1.5.2.2 jdolecek u16 reg;
5199 1.1 dyoung
5200 1.5.2.2 jdolecek if (hw->device_id != IXGBE_DEV_ID_X550EM_X_10G_T) {
5201 1.5.2.2 jdolecek device_printf(adapter->dev,
5202 1.5.2.2 jdolecek "Device has no supported external thermal sensor.\n");
5203 1.5.2.2 jdolecek return (ENODEV);
5204 1.1 dyoung }
5205 1.1 dyoung
5206 1.5.2.2 jdolecek if (hw->phy.ops.read_reg(hw, IXGBE_PHY_OVERTEMP_STATUS,
5207 1.5.2.2 jdolecek IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE, ®)) {
5208 1.5.2.2 jdolecek device_printf(adapter->dev,
5209 1.5.2.2 jdolecek "Error reading from PHY's temperature status register\n");
5210 1.5.2.2 jdolecek return (EAGAIN);
5211 1.5.2.2 jdolecek }
5212 1.1 dyoung
5213 1.5.2.2 jdolecek node.sysctl_data = &val;
5214 1.1 dyoung
5215 1.5.2.2 jdolecek /* Get occurrence bit */
5216 1.5.2.2 jdolecek val = !!(reg & 0x4000);
5217 1.1 dyoung
5218 1.5.2.2 jdolecek error = sysctl_lookup(SYSCTLFN_CALL(&node));
5219 1.5.2.2 jdolecek if ((error) || (newp == NULL))
5220 1.5.2.2 jdolecek return (error);
5221 1.1 dyoung
5222 1.5.2.2 jdolecek return (0);
5223 1.5.2.2 jdolecek } /* ixgbe_sysctl_phy_overtemp_occurred */
5224 1.1 dyoung
5225 1.5.2.2 jdolecek /************************************************************************
5226 1.5.2.2 jdolecek * ixgbe_sysctl_eee_state
5227 1.1 dyoung *
5228 1.5.2.2 jdolecek * Sysctl to set EEE power saving feature
5229 1.5.2.2 jdolecek * Values:
5230 1.5.2.2 jdolecek * 0 - disable EEE
5231 1.5.2.2 jdolecek * 1 - enable EEE
5232 1.5.2.2 jdolecek * (none) - get current device EEE state
5233 1.5.2.2 jdolecek ************************************************************************/
5234 1.5.2.2 jdolecek static int
5235 1.5.2.2 jdolecek ixgbe_sysctl_eee_state(SYSCTLFN_ARGS)
5236 1.1 dyoung {
5237 1.5.2.2 jdolecek struct sysctlnode node = *rnode;
5238 1.5.2.2 jdolecek struct adapter *adapter = (struct adapter *)node.sysctl_data;
5239 1.1 dyoung struct ifnet *ifp = adapter->ifp;
5240 1.5.2.2 jdolecek device_t dev = adapter->dev;
5241 1.5.2.2 jdolecek int curr_eee, new_eee, error = 0;
5242 1.5.2.2 jdolecek s32 retval;
5243 1.1 dyoung
5244 1.5.2.2 jdolecek curr_eee = new_eee = !!(adapter->feat_en & IXGBE_FEATURE_EEE);
5245 1.5.2.2 jdolecek node.sysctl_data = &new_eee;
5246 1.5.2.2 jdolecek error = sysctl_lookup(SYSCTLFN_CALL(&node));
5247 1.5.2.2 jdolecek if ((error) || (newp == NULL))
5248 1.5.2.2 jdolecek return (error);
5249 1.1 dyoung
5250 1.5.2.2 jdolecek /* Nothing to do */
5251 1.5.2.2 jdolecek if (new_eee == curr_eee)
5252 1.5.2.2 jdolecek return (0);
5253 1.1 dyoung
5254 1.5.2.2 jdolecek /* Not supported */
5255 1.5.2.2 jdolecek if (!(adapter->feat_cap & IXGBE_FEATURE_EEE))
5256 1.5.2.2 jdolecek return (EINVAL);
5257 1.1 dyoung
5258 1.5.2.2 jdolecek /* Bounds checking */
5259 1.5.2.2 jdolecek if ((new_eee < 0) || (new_eee > 1))
5260 1.5.2.2 jdolecek return (EINVAL);
5261 1.1 dyoung
5262 1.5.2.2 jdolecek retval = adapter->hw.mac.ops.setup_eee(&adapter->hw, new_eee);
5263 1.5.2.2 jdolecek if (retval) {
5264 1.5.2.2 jdolecek device_printf(dev, "Error in EEE setup: 0x%08X\n", retval);
5265 1.5.2.2 jdolecek return (EINVAL);
5266 1.1 dyoung }
5267 1.1 dyoung
5268 1.5.2.2 jdolecek /* Restart auto-neg */
5269 1.5.2.2 jdolecek ixgbe_init(ifp);
5270 1.1 dyoung
5271 1.5.2.2 jdolecek device_printf(dev, "New EEE state: %d\n", new_eee);
5272 1.1 dyoung
5273 1.5.2.2 jdolecek /* Cache new value */
5274 1.5.2.2 jdolecek if (new_eee)
5275 1.5.2.2 jdolecek adapter->feat_en |= IXGBE_FEATURE_EEE;
5276 1.5.2.2 jdolecek else
5277 1.5.2.2 jdolecek adapter->feat_en &= ~IXGBE_FEATURE_EEE;
5278 1.5.2.2 jdolecek
5279 1.5.2.2 jdolecek return (error);
5280 1.5.2.2 jdolecek } /* ixgbe_sysctl_eee_state */
5281 1.5.2.2 jdolecek
5282 1.5.2.2 jdolecek /************************************************************************
5283 1.5.2.2 jdolecek * ixgbe_init_device_features
5284 1.5.2.2 jdolecek ************************************************************************/
5285 1.5.2.2 jdolecek static void
5286 1.5.2.2 jdolecek ixgbe_init_device_features(struct adapter *adapter)
5287 1.5.2.2 jdolecek {
5288 1.5.2.2 jdolecek adapter->feat_cap = IXGBE_FEATURE_NETMAP
5289 1.5.2.2 jdolecek | IXGBE_FEATURE_RSS
5290 1.5.2.2 jdolecek | IXGBE_FEATURE_MSI
5291 1.5.2.2 jdolecek | IXGBE_FEATURE_MSIX
5292 1.5.2.2 jdolecek | IXGBE_FEATURE_LEGACY_IRQ
5293 1.5.2.2 jdolecek | IXGBE_FEATURE_LEGACY_TX;
5294 1.5.2.2 jdolecek
5295 1.5.2.2 jdolecek /* Set capabilities first... */
5296 1.5.2.2 jdolecek switch (adapter->hw.mac.type) {
5297 1.5.2.2 jdolecek case ixgbe_mac_82598EB:
5298 1.5.2.2 jdolecek if (adapter->hw.device_id == IXGBE_DEV_ID_82598AT)
5299 1.5.2.2 jdolecek adapter->feat_cap |= IXGBE_FEATURE_FAN_FAIL;
5300 1.5.2.2 jdolecek break;
5301 1.5.2.2 jdolecek case ixgbe_mac_X540:
5302 1.5.2.2 jdolecek adapter->feat_cap |= IXGBE_FEATURE_SRIOV;
5303 1.5.2.2 jdolecek adapter->feat_cap |= IXGBE_FEATURE_FDIR;
5304 1.5.2.2 jdolecek if ((adapter->hw.device_id == IXGBE_DEV_ID_X540_BYPASS) &&
5305 1.5.2.2 jdolecek (adapter->hw.bus.func == 0))
5306 1.5.2.2 jdolecek adapter->feat_cap |= IXGBE_FEATURE_BYPASS;
5307 1.5.2.2 jdolecek break;
5308 1.5.2.2 jdolecek case ixgbe_mac_X550:
5309 1.5.2.2 jdolecek adapter->feat_cap |= IXGBE_FEATURE_TEMP_SENSOR;
5310 1.5.2.2 jdolecek adapter->feat_cap |= IXGBE_FEATURE_SRIOV;
5311 1.5.2.2 jdolecek adapter->feat_cap |= IXGBE_FEATURE_FDIR;
5312 1.5.2.2 jdolecek break;
5313 1.5.2.2 jdolecek case ixgbe_mac_X550EM_x:
5314 1.5.2.2 jdolecek adapter->feat_cap |= IXGBE_FEATURE_SRIOV;
5315 1.5.2.2 jdolecek adapter->feat_cap |= IXGBE_FEATURE_FDIR;
5316 1.5.2.2 jdolecek if (adapter->hw.device_id == IXGBE_DEV_ID_X550EM_X_KR)
5317 1.5.2.2 jdolecek adapter->feat_cap |= IXGBE_FEATURE_EEE;
5318 1.5.2.2 jdolecek break;
5319 1.5.2.2 jdolecek case ixgbe_mac_X550EM_a:
5320 1.5.2.2 jdolecek adapter->feat_cap |= IXGBE_FEATURE_SRIOV;
5321 1.5.2.2 jdolecek adapter->feat_cap |= IXGBE_FEATURE_FDIR;
5322 1.5.2.2 jdolecek adapter->feat_cap &= ~IXGBE_FEATURE_LEGACY_IRQ;
5323 1.5.2.2 jdolecek if ((adapter->hw.device_id == IXGBE_DEV_ID_X550EM_A_1G_T) ||
5324 1.5.2.2 jdolecek (adapter->hw.device_id == IXGBE_DEV_ID_X550EM_A_1G_T_L)) {
5325 1.5.2.2 jdolecek adapter->feat_cap |= IXGBE_FEATURE_TEMP_SENSOR;
5326 1.5.2.2 jdolecek adapter->feat_cap |= IXGBE_FEATURE_EEE;
5327 1.5.2.2 jdolecek }
5328 1.5.2.2 jdolecek break;
5329 1.5.2.2 jdolecek case ixgbe_mac_82599EB:
5330 1.5.2.2 jdolecek adapter->feat_cap |= IXGBE_FEATURE_SRIOV;
5331 1.5.2.2 jdolecek adapter->feat_cap |= IXGBE_FEATURE_FDIR;
5332 1.5.2.2 jdolecek if ((adapter->hw.device_id == IXGBE_DEV_ID_82599_BYPASS) &&
5333 1.5.2.2 jdolecek (adapter->hw.bus.func == 0))
5334 1.5.2.2 jdolecek adapter->feat_cap |= IXGBE_FEATURE_BYPASS;
5335 1.5.2.2 jdolecek if (adapter->hw.device_id == IXGBE_DEV_ID_82599_QSFP_SF_QP)
5336 1.5.2.2 jdolecek adapter->feat_cap &= ~IXGBE_FEATURE_LEGACY_IRQ;
5337 1.5.2.2 jdolecek break;
5338 1.5.2.2 jdolecek default:
5339 1.5.2.2 jdolecek break;
5340 1.1 dyoung }
5341 1.1 dyoung
5342 1.5.2.2 jdolecek /* Enabled by default... */
5343 1.5.2.2 jdolecek /* Fan failure detection */
5344 1.5.2.2 jdolecek if (adapter->feat_cap & IXGBE_FEATURE_FAN_FAIL)
5345 1.5.2.2 jdolecek adapter->feat_en |= IXGBE_FEATURE_FAN_FAIL;
5346 1.5.2.2 jdolecek /* Netmap */
5347 1.5.2.2 jdolecek if (adapter->feat_cap & IXGBE_FEATURE_NETMAP)
5348 1.5.2.2 jdolecek adapter->feat_en |= IXGBE_FEATURE_NETMAP;
5349 1.5.2.2 jdolecek /* EEE */
5350 1.5.2.2 jdolecek if (adapter->feat_cap & IXGBE_FEATURE_EEE)
5351 1.5.2.2 jdolecek adapter->feat_en |= IXGBE_FEATURE_EEE;
5352 1.5.2.2 jdolecek /* Thermal Sensor */
5353 1.5.2.2 jdolecek if (adapter->feat_cap & IXGBE_FEATURE_TEMP_SENSOR)
5354 1.5.2.2 jdolecek adapter->feat_en |= IXGBE_FEATURE_TEMP_SENSOR;
5355 1.5.2.2 jdolecek
5356 1.5.2.2 jdolecek /* Enabled via global sysctl... */
5357 1.5.2.2 jdolecek /* Flow Director */
5358 1.5.2.2 jdolecek if (ixgbe_enable_fdir) {
5359 1.5.2.2 jdolecek if (adapter->feat_cap & IXGBE_FEATURE_FDIR)
5360 1.5.2.2 jdolecek adapter->feat_en |= IXGBE_FEATURE_FDIR;
5361 1.5.2.2 jdolecek else
5362 1.5.2.2 jdolecek device_printf(adapter->dev, "Device does not support Flow Director. Leaving disabled.");
5363 1.5.2.2 jdolecek }
5364 1.5.2.2 jdolecek /* Legacy (single queue) transmit */
5365 1.5.2.2 jdolecek if ((adapter->feat_cap & IXGBE_FEATURE_LEGACY_TX) &&
5366 1.5.2.2 jdolecek ixgbe_enable_legacy_tx)
5367 1.5.2.2 jdolecek adapter->feat_en |= IXGBE_FEATURE_LEGACY_TX;
5368 1.5.2.2 jdolecek /*
5369 1.5.2.2 jdolecek * Message Signal Interrupts - Extended (MSI-X)
5370 1.5.2.2 jdolecek * Normal MSI is only enabled if MSI-X calls fail.
5371 1.5.2.2 jdolecek */
5372 1.5.2.2 jdolecek if (!ixgbe_enable_msix)
5373 1.5.2.2 jdolecek adapter->feat_cap &= ~IXGBE_FEATURE_MSIX;
5374 1.5.2.2 jdolecek /* Receive-Side Scaling (RSS) */
5375 1.5.2.2 jdolecek if ((adapter->feat_cap & IXGBE_FEATURE_RSS) && ixgbe_enable_rss)
5376 1.5.2.2 jdolecek adapter->feat_en |= IXGBE_FEATURE_RSS;
5377 1.5.2.2 jdolecek
5378 1.5.2.2 jdolecek /* Disable features with unmet dependencies... */
5379 1.5.2.2 jdolecek /* No MSI-X */
5380 1.5.2.2 jdolecek if (!(adapter->feat_cap & IXGBE_FEATURE_MSIX)) {
5381 1.5.2.2 jdolecek adapter->feat_cap &= ~IXGBE_FEATURE_RSS;
5382 1.5.2.2 jdolecek adapter->feat_cap &= ~IXGBE_FEATURE_SRIOV;
5383 1.5.2.2 jdolecek adapter->feat_en &= ~IXGBE_FEATURE_RSS;
5384 1.5.2.2 jdolecek adapter->feat_en &= ~IXGBE_FEATURE_SRIOV;
5385 1.5.2.2 jdolecek }
5386 1.5.2.2 jdolecek } /* ixgbe_init_device_features */
5387 1.1 dyoung
5388 1.5.2.2 jdolecek /************************************************************************
5389 1.5.2.2 jdolecek * ixgbe_probe - Device identification routine
5390 1.5.2.2 jdolecek *
5391 1.5.2.2 jdolecek * Determines if the driver should be loaded on
5392 1.5.2.2 jdolecek * adapter based on its PCI vendor/device ID.
5393 1.5.2.2 jdolecek *
5394 1.5.2.2 jdolecek * return BUS_PROBE_DEFAULT on success, positive on failure
5395 1.5.2.2 jdolecek ************************************************************************/
5396 1.5.2.2 jdolecek static int
5397 1.5.2.2 jdolecek ixgbe_probe(device_t dev, cfdata_t cf, void *aux)
5398 1.5.2.2 jdolecek {
5399 1.5.2.2 jdolecek const struct pci_attach_args *pa = aux;
5400 1.5.2.2 jdolecek
5401 1.5.2.2 jdolecek return (ixgbe_lookup(pa) != NULL) ? 1 : 0;
5402 1.1 dyoung }
5403 1.1 dyoung
5404 1.5.2.2 jdolecek static ixgbe_vendor_info_t *
5405 1.5.2.2 jdolecek ixgbe_lookup(const struct pci_attach_args *pa)
5406 1.1 dyoung {
5407 1.5.2.2 jdolecek ixgbe_vendor_info_t *ent;
5408 1.5.2.2 jdolecek pcireg_t subid;
5409 1.1 dyoung
5410 1.5.2.2 jdolecek INIT_DEBUGOUT("ixgbe_lookup: begin");
5411 1.5.2.2 jdolecek
5412 1.5.2.2 jdolecek if (PCI_VENDOR(pa->pa_id) != IXGBE_INTEL_VENDOR_ID)
5413 1.5.2.2 jdolecek return NULL;
5414 1.5.2.2 jdolecek
5415 1.5.2.2 jdolecek subid = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_SUBSYS_ID_REG);
5416 1.5.2.2 jdolecek
5417 1.5.2.2 jdolecek for (ent = ixgbe_vendor_info_array; ent->vendor_id != 0; ent++) {
5418 1.5.2.2 jdolecek if ((PCI_VENDOR(pa->pa_id) == ent->vendor_id) &&
5419 1.5.2.2 jdolecek (PCI_PRODUCT(pa->pa_id) == ent->device_id) &&
5420 1.5.2.2 jdolecek ((PCI_SUBSYS_VENDOR(subid) == ent->subvendor_id) ||
5421 1.5.2.2 jdolecek (ent->subvendor_id == 0)) &&
5422 1.5.2.2 jdolecek ((PCI_SUBSYS_ID(subid) == ent->subdevice_id) ||
5423 1.5.2.2 jdolecek (ent->subdevice_id == 0))) {
5424 1.5.2.2 jdolecek ++ixgbe_total_ports;
5425 1.5.2.2 jdolecek return ent;
5426 1.5.2.2 jdolecek }
5427 1.5.2.2 jdolecek }
5428 1.5.2.2 jdolecek return NULL;
5429 1.1 dyoung }
5430 1.1 dyoung
5431 1.5.2.2 jdolecek static int
5432 1.5.2.2 jdolecek ixgbe_ifflags_cb(struct ethercom *ec)
5433 1.1 dyoung {
5434 1.5.2.2 jdolecek struct ifnet *ifp = &ec->ec_if;
5435 1.5.2.2 jdolecek struct adapter *adapter = ifp->if_softc;
5436 1.5.2.2 jdolecek int change = ifp->if_flags ^ adapter->if_flags, rc = 0;
5437 1.1 dyoung
5438 1.5.2.2 jdolecek IXGBE_CORE_LOCK(adapter);
5439 1.5.2.2 jdolecek
5440 1.5.2.2 jdolecek if (change != 0)
5441 1.5.2.2 jdolecek adapter->if_flags = ifp->if_flags;
5442 1.5.2.2 jdolecek
5443 1.5.2.2 jdolecek if ((change & ~(IFF_CANTCHANGE | IFF_DEBUG)) != 0)
5444 1.5.2.2 jdolecek rc = ENETRESET;
5445 1.5.2.2 jdolecek else if ((change & (IFF_PROMISC | IFF_ALLMULTI)) != 0)
5446 1.5.2.2 jdolecek ixgbe_set_promisc(adapter);
5447 1.5.2.2 jdolecek
5448 1.5.2.2 jdolecek /* Set up VLAN support and filter */
5449 1.5.2.2 jdolecek ixgbe_setup_vlan_hw_support(adapter);
5450 1.5.2.2 jdolecek
5451 1.5.2.2 jdolecek IXGBE_CORE_UNLOCK(adapter);
5452 1.5.2.2 jdolecek
5453 1.5.2.2 jdolecek return rc;
5454 1.1 dyoung }
5455 1.1 dyoung
5456 1.5.2.2 jdolecek /************************************************************************
5457 1.5.2.2 jdolecek * ixgbe_ioctl - Ioctl entry point
5458 1.5.2.2 jdolecek *
5459 1.5.2.2 jdolecek * Called when the user wants to configure the interface.
5460 1.5.2.2 jdolecek *
5461 1.5.2.2 jdolecek * return 0 on success, positive on failure
5462 1.5.2.2 jdolecek ************************************************************************/
5463 1.5.2.2 jdolecek static int
5464 1.5.2.2 jdolecek ixgbe_ioctl(struct ifnet * ifp, u_long command, void *data)
5465 1.1 dyoung {
5466 1.5.2.2 jdolecek struct adapter *adapter = ifp->if_softc;
5467 1.5.2.2 jdolecek struct ixgbe_hw *hw = &adapter->hw;
5468 1.5.2.2 jdolecek struct ifcapreq *ifcr = data;
5469 1.5.2.2 jdolecek struct ifreq *ifr = data;
5470 1.5.2.2 jdolecek int error = 0;
5471 1.5.2.2 jdolecek int l4csum_en;
5472 1.5.2.2 jdolecek const int l4csum = IFCAP_CSUM_TCPv4_Rx|IFCAP_CSUM_UDPv4_Rx|
5473 1.5.2.2 jdolecek IFCAP_CSUM_TCPv6_Rx|IFCAP_CSUM_UDPv6_Rx;
5474 1.5.2.2 jdolecek
5475 1.5.2.2 jdolecek switch (command) {
5476 1.5.2.2 jdolecek case SIOCSIFFLAGS:
5477 1.5.2.2 jdolecek IOCTL_DEBUGOUT("ioctl: SIOCSIFFLAGS (Set Interface Flags)");
5478 1.5.2.2 jdolecek break;
5479 1.5.2.2 jdolecek case SIOCADDMULTI:
5480 1.5.2.2 jdolecek case SIOCDELMULTI:
5481 1.5.2.2 jdolecek IOCTL_DEBUGOUT("ioctl: SIOC(ADD|DEL)MULTI");
5482 1.5.2.2 jdolecek break;
5483 1.5.2.2 jdolecek case SIOCSIFMEDIA:
5484 1.5.2.2 jdolecek case SIOCGIFMEDIA:
5485 1.5.2.2 jdolecek IOCTL_DEBUGOUT("ioctl: SIOCxIFMEDIA (Get/Set Interface Media)");
5486 1.5.2.2 jdolecek break;
5487 1.5.2.2 jdolecek case SIOCSIFCAP:
5488 1.5.2.2 jdolecek IOCTL_DEBUGOUT("ioctl: SIOCSIFCAP (Set Capabilities)");
5489 1.5.2.2 jdolecek break;
5490 1.5.2.2 jdolecek case SIOCSIFMTU:
5491 1.5.2.2 jdolecek IOCTL_DEBUGOUT("ioctl: SIOCSIFMTU (Set Interface MTU)");
5492 1.5.2.2 jdolecek break;
5493 1.5.2.2 jdolecek #ifdef __NetBSD__
5494 1.5.2.2 jdolecek case SIOCINITIFADDR:
5495 1.5.2.2 jdolecek IOCTL_DEBUGOUT("ioctl: SIOCINITIFADDR");
5496 1.5.2.2 jdolecek break;
5497 1.5.2.2 jdolecek case SIOCGIFFLAGS:
5498 1.5.2.2 jdolecek IOCTL_DEBUGOUT("ioctl: SIOCGIFFLAGS");
5499 1.5.2.2 jdolecek break;
5500 1.5.2.2 jdolecek case SIOCGIFAFLAG_IN:
5501 1.5.2.2 jdolecek IOCTL_DEBUGOUT("ioctl: SIOCGIFAFLAG_IN");
5502 1.5.2.2 jdolecek break;
5503 1.5.2.2 jdolecek case SIOCGIFADDR:
5504 1.5.2.2 jdolecek IOCTL_DEBUGOUT("ioctl: SIOCGIFADDR");
5505 1.5.2.2 jdolecek break;
5506 1.5.2.2 jdolecek case SIOCGIFMTU:
5507 1.5.2.2 jdolecek IOCTL_DEBUGOUT("ioctl: SIOCGIFMTU (Get Interface MTU)");
5508 1.5.2.2 jdolecek break;
5509 1.5.2.2 jdolecek case SIOCGIFCAP:
5510 1.5.2.2 jdolecek IOCTL_DEBUGOUT("ioctl: SIOCGIFCAP (Get IF cap)");
5511 1.5.2.2 jdolecek break;
5512 1.5.2.2 jdolecek case SIOCGETHERCAP:
5513 1.5.2.2 jdolecek IOCTL_DEBUGOUT("ioctl: SIOCGETHERCAP (Get ethercap)");
5514 1.5.2.2 jdolecek break;
5515 1.5.2.2 jdolecek case SIOCGLIFADDR:
5516 1.5.2.2 jdolecek IOCTL_DEBUGOUT("ioctl: SIOCGLIFADDR (Get Interface addr)");
5517 1.5.2.2 jdolecek break;
5518 1.5.2.2 jdolecek case SIOCZIFDATA:
5519 1.5.2.2 jdolecek IOCTL_DEBUGOUT("ioctl: SIOCZIFDATA (Zero counter)");
5520 1.5.2.2 jdolecek hw->mac.ops.clear_hw_cntrs(hw);
5521 1.5.2.2 jdolecek ixgbe_clear_evcnt(adapter);
5522 1.5.2.2 jdolecek break;
5523 1.5.2.2 jdolecek case SIOCAIFADDR:
5524 1.5.2.2 jdolecek IOCTL_DEBUGOUT("ioctl: SIOCAIFADDR (add/chg IF alias)");
5525 1.5.2.2 jdolecek break;
5526 1.5.2.2 jdolecek #endif
5527 1.5.2.2 jdolecek default:
5528 1.5.2.2 jdolecek IOCTL_DEBUGOUT1("ioctl: UNKNOWN (0x%X)", (int)command);
5529 1.5.2.2 jdolecek break;
5530 1.5.2.2 jdolecek }
5531 1.1 dyoung
5532 1.5.2.2 jdolecek switch (command) {
5533 1.5.2.2 jdolecek case SIOCSIFMEDIA:
5534 1.5.2.2 jdolecek case SIOCGIFMEDIA:
5535 1.5.2.2 jdolecek return ifmedia_ioctl(ifp, ifr, &adapter->media, command);
5536 1.5.2.2 jdolecek case SIOCGI2C:
5537 1.5.2.2 jdolecek {
5538 1.5.2.2 jdolecek struct ixgbe_i2c_req i2c;
5539 1.1 dyoung
5540 1.5.2.2 jdolecek IOCTL_DEBUGOUT("ioctl: SIOCGI2C (Get I2C Data)");
5541 1.5.2.2 jdolecek error = copyin(ifr->ifr_data, &i2c, sizeof(i2c));
5542 1.5.2.2 jdolecek if (error != 0)
5543 1.5.2.2 jdolecek break;
5544 1.5.2.2 jdolecek if (i2c.dev_addr != 0xA0 && i2c.dev_addr != 0xA2) {
5545 1.5.2.2 jdolecek error = EINVAL;
5546 1.5.2.2 jdolecek break;
5547 1.5.2.2 jdolecek }
5548 1.5.2.2 jdolecek if (i2c.len > sizeof(i2c.data)) {
5549 1.5.2.2 jdolecek error = EINVAL;
5550 1.5.2.2 jdolecek break;
5551 1.5.2.2 jdolecek }
5552 1.1 dyoung
5553 1.5.2.2 jdolecek hw->phy.ops.read_i2c_byte(hw, i2c.offset,
5554 1.5.2.2 jdolecek i2c.dev_addr, i2c.data);
5555 1.5.2.2 jdolecek error = copyout(&i2c, ifr->ifr_data, sizeof(i2c));
5556 1.5.2.2 jdolecek break;
5557 1.5.2.2 jdolecek }
5558 1.5.2.2 jdolecek case SIOCSIFCAP:
5559 1.5.2.2 jdolecek /* Layer-4 Rx checksum offload has to be turned on and
5560 1.5.2.2 jdolecek * off as a unit.
5561 1.5.2.2 jdolecek */
5562 1.5.2.2 jdolecek l4csum_en = ifcr->ifcr_capenable & l4csum;
5563 1.5.2.2 jdolecek if (l4csum_en != l4csum && l4csum_en != 0)
5564 1.5.2.2 jdolecek return EINVAL;
5565 1.5.2.2 jdolecek /*FALLTHROUGH*/
5566 1.5.2.2 jdolecek case SIOCADDMULTI:
5567 1.5.2.2 jdolecek case SIOCDELMULTI:
5568 1.5.2.2 jdolecek case SIOCSIFFLAGS:
5569 1.5.2.2 jdolecek case SIOCSIFMTU:
5570 1.5.2.2 jdolecek default:
5571 1.5.2.2 jdolecek if ((error = ether_ioctl(ifp, command, data)) != ENETRESET)
5572 1.5.2.2 jdolecek return error;
5573 1.5.2.2 jdolecek if ((ifp->if_flags & IFF_RUNNING) == 0)
5574 1.5.2.2 jdolecek ;
5575 1.5.2.2 jdolecek else if (command == SIOCSIFCAP || command == SIOCSIFMTU) {
5576 1.5.2.2 jdolecek IXGBE_CORE_LOCK(adapter);
5577 1.5.2.2 jdolecek ixgbe_init_locked(adapter);
5578 1.5.2.2 jdolecek ixgbe_recalculate_max_frame(adapter);
5579 1.5.2.2 jdolecek IXGBE_CORE_UNLOCK(adapter);
5580 1.5.2.2 jdolecek } else if (command == SIOCADDMULTI || command == SIOCDELMULTI) {
5581 1.5.2.2 jdolecek /*
5582 1.5.2.2 jdolecek * Multicast list has changed; set the hardware filter
5583 1.5.2.2 jdolecek * accordingly.
5584 1.5.2.2 jdolecek */
5585 1.5.2.2 jdolecek IXGBE_CORE_LOCK(adapter);
5586 1.5.2.2 jdolecek ixgbe_disable_intr(adapter);
5587 1.5.2.2 jdolecek ixgbe_set_multi(adapter);
5588 1.5.2.2 jdolecek ixgbe_enable_intr(adapter);
5589 1.5.2.2 jdolecek IXGBE_CORE_UNLOCK(adapter);
5590 1.5.2.2 jdolecek }
5591 1.1 dyoung return 0;
5592 1.5.2.2 jdolecek }
5593 1.1 dyoung
5594 1.5.2.2 jdolecek return error;
5595 1.5.2.2 jdolecek } /* ixgbe_ioctl */
5596 1.1 dyoung
5597 1.5.2.2 jdolecek /************************************************************************
5598 1.5.2.2 jdolecek * ixgbe_check_fan_failure
5599 1.5.2.2 jdolecek ************************************************************************/
5600 1.5.2.2 jdolecek static void
5601 1.5.2.2 jdolecek ixgbe_check_fan_failure(struct adapter *adapter, u32 reg, bool in_interrupt)
5602 1.1 dyoung {
5603 1.5.2.2 jdolecek u32 mask;
5604 1.1 dyoung
5605 1.5.2.2 jdolecek mask = (in_interrupt) ? IXGBE_EICR_GPI_SDP1_BY_MAC(&adapter->hw) :
5606 1.5.2.2 jdolecek IXGBE_ESDP_SDP1;
5607 1.1 dyoung
5608 1.5.2.2 jdolecek if (reg & mask)
5609 1.5.2.2 jdolecek device_printf(adapter->dev, "\nCRITICAL: FAN FAILURE!! REPLACE IMMEDIATELY!!\n");
5610 1.5.2.2 jdolecek } /* ixgbe_check_fan_failure */
5611 1.5.2.2 jdolecek
5612 1.5.2.2 jdolecek /************************************************************************
5613 1.5.2.2 jdolecek * ixgbe_handle_que
5614 1.5.2.2 jdolecek ************************************************************************/
5615 1.1 dyoung static void
5616 1.5.2.2 jdolecek ixgbe_handle_que(void *context)
5617 1.1 dyoung {
5618 1.5.2.2 jdolecek struct ix_queue *que = context;
5619 1.5.2.2 jdolecek struct adapter *adapter = que->adapter;
5620 1.5.2.2 jdolecek struct tx_ring *txr = que->txr;
5621 1.5.2.2 jdolecek struct ifnet *ifp = adapter->ifp;
5622 1.1 dyoung
5623 1.5.2.2 jdolecek adapter->handleq.ev_count++;
5624 1.1 dyoung
5625 1.5.2.2 jdolecek if (ifp->if_flags & IFF_RUNNING) {
5626 1.5.2.2 jdolecek ixgbe_rxeof(que);
5627 1.5.2.2 jdolecek IXGBE_TX_LOCK(txr);
5628 1.5.2.2 jdolecek ixgbe_txeof(txr);
5629 1.5.2.2 jdolecek if (!(adapter->feat_en & IXGBE_FEATURE_LEGACY_TX))
5630 1.5.2.2 jdolecek if (!ixgbe_mq_ring_empty(ifp, txr->txr_interq))
5631 1.5.2.2 jdolecek ixgbe_mq_start_locked(ifp, txr);
5632 1.5.2.2 jdolecek /* Only for queue 0 */
5633 1.5.2.2 jdolecek /* NetBSD still needs this for CBQ */
5634 1.5.2.2 jdolecek if ((&adapter->queues[0] == que)
5635 1.5.2.2 jdolecek && (!ixgbe_legacy_ring_empty(ifp, NULL)))
5636 1.5.2.2 jdolecek ixgbe_legacy_start_locked(ifp, txr);
5637 1.5.2.2 jdolecek IXGBE_TX_UNLOCK(txr);
5638 1.5.2.2 jdolecek }
5639 1.1 dyoung
5640 1.5.2.2 jdolecek /* Re-enable this interrupt */
5641 1.5.2.2 jdolecek if (que->res != NULL)
5642 1.5.2.2 jdolecek ixgbe_enable_queue(adapter, que->msix);
5643 1.5.2.2 jdolecek else
5644 1.5.2.2 jdolecek ixgbe_enable_intr(adapter);
5645 1.1 dyoung
5646 1.5.2.2 jdolecek return;
5647 1.5.2.2 jdolecek } /* ixgbe_handle_que */
5648 1.1 dyoung
5649 1.5.2.2 jdolecek /************************************************************************
5650 1.5.2.2 jdolecek * ixgbe_allocate_legacy - Setup the Legacy or MSI Interrupt handler
5651 1.5.2.2 jdolecek ************************************************************************/
5652 1.5.2.2 jdolecek static int
5653 1.5.2.2 jdolecek ixgbe_allocate_legacy(struct adapter *adapter,
5654 1.5.2.2 jdolecek const struct pci_attach_args *pa)
5655 1.5.2.2 jdolecek {
5656 1.5.2.2 jdolecek device_t dev = adapter->dev;
5657 1.5.2.2 jdolecek struct ix_queue *que = adapter->queues;
5658 1.5.2.2 jdolecek struct tx_ring *txr = adapter->tx_rings;
5659 1.5.2.2 jdolecek int counts[PCI_INTR_TYPE_SIZE];
5660 1.5.2.2 jdolecek pci_intr_type_t intr_type, max_type;
5661 1.5.2.2 jdolecek char intrbuf[PCI_INTRSTR_LEN];
5662 1.5.2.2 jdolecek const char *intrstr = NULL;
5663 1.5.2.2 jdolecek
5664 1.5.2.2 jdolecek /* We allocate a single interrupt resource */
5665 1.5.2.2 jdolecek max_type = PCI_INTR_TYPE_MSI;
5666 1.5.2.2 jdolecek counts[PCI_INTR_TYPE_MSIX] = 0;
5667 1.5.2.2 jdolecek counts[PCI_INTR_TYPE_MSI] =
5668 1.5.2.2 jdolecek (adapter->feat_en & IXGBE_FEATURE_MSI) ? 1 : 0;
5669 1.5.2.2 jdolecek counts[PCI_INTR_TYPE_INTX] =
5670 1.5.2.2 jdolecek (adapter->feat_en & IXGBE_FEATURE_LEGACY_IRQ) ? 1 : 0;
5671 1.5.2.2 jdolecek
5672 1.5.2.2 jdolecek alloc_retry:
5673 1.5.2.2 jdolecek if (pci_intr_alloc(pa, &adapter->osdep.intrs, counts, max_type) != 0) {
5674 1.5.2.2 jdolecek aprint_error_dev(dev, "couldn't alloc interrupt\n");
5675 1.5.2.2 jdolecek return ENXIO;
5676 1.5.2.2 jdolecek }
5677 1.5.2.2 jdolecek adapter->osdep.nintrs = 1;
5678 1.5.2.2 jdolecek intrstr = pci_intr_string(adapter->osdep.pc, adapter->osdep.intrs[0],
5679 1.5.2.2 jdolecek intrbuf, sizeof(intrbuf));
5680 1.5.2.2 jdolecek adapter->osdep.ihs[0] = pci_intr_establish_xname(adapter->osdep.pc,
5681 1.5.2.2 jdolecek adapter->osdep.intrs[0], IPL_NET, ixgbe_legacy_irq, que,
5682 1.5.2.2 jdolecek device_xname(dev));
5683 1.5.2.2 jdolecek if (adapter->osdep.ihs[0] == NULL) {
5684 1.5.2.2 jdolecek intr_type = pci_intr_type(adapter->osdep.pc,
5685 1.5.2.2 jdolecek adapter->osdep.intrs[0]);
5686 1.5.2.2 jdolecek aprint_error_dev(dev,"unable to establish %s\n",
5687 1.5.2.2 jdolecek (intr_type == PCI_INTR_TYPE_MSI) ? "MSI" : "INTx");
5688 1.5.2.2 jdolecek pci_intr_release(adapter->osdep.pc, adapter->osdep.intrs, 1);
5689 1.5.2.2 jdolecek switch (intr_type) {
5690 1.5.2.2 jdolecek case PCI_INTR_TYPE_MSI:
5691 1.5.2.2 jdolecek /* The next try is for INTx: Disable MSI */
5692 1.5.2.2 jdolecek max_type = PCI_INTR_TYPE_INTX;
5693 1.5.2.2 jdolecek counts[PCI_INTR_TYPE_INTX] = 1;
5694 1.5.2.2 jdolecek goto alloc_retry;
5695 1.5.2.2 jdolecek case PCI_INTR_TYPE_INTX:
5696 1.5.2.2 jdolecek default:
5697 1.5.2.2 jdolecek /* See below */
5698 1.1 dyoung break;
5699 1.5.2.2 jdolecek }
5700 1.5.2.2 jdolecek }
5701 1.5.2.2 jdolecek if (adapter->osdep.ihs[0] == NULL) {
5702 1.5.2.2 jdolecek aprint_error_dev(dev,
5703 1.5.2.2 jdolecek "couldn't establish interrupt%s%s\n",
5704 1.5.2.2 jdolecek intrstr ? " at " : "", intrstr ? intrstr : "");
5705 1.5.2.2 jdolecek pci_intr_release(adapter->osdep.pc, adapter->osdep.intrs, 1);
5706 1.5.2.2 jdolecek return ENXIO;
5707 1.5.2.2 jdolecek }
5708 1.5.2.2 jdolecek aprint_normal_dev(dev, "interrupting at %s\n", intrstr);
5709 1.5.2.2 jdolecek /*
5710 1.5.2.2 jdolecek * Try allocating a fast interrupt and the associated deferred
5711 1.5.2.2 jdolecek * processing contexts.
5712 1.5.2.2 jdolecek */
5713 1.5.2.2 jdolecek if (!(adapter->feat_en & IXGBE_FEATURE_LEGACY_TX))
5714 1.5.2.2 jdolecek txr->txr_si =
5715 1.5.2.2 jdolecek softint_establish(SOFTINT_NET | IXGBE_SOFTINFT_FLAGS,
5716 1.5.2.2 jdolecek ixgbe_deferred_mq_start, txr);
5717 1.5.2.2 jdolecek que->que_si = softint_establish(SOFTINT_NET | IXGBE_SOFTINFT_FLAGS,
5718 1.5.2.2 jdolecek ixgbe_handle_que, que);
5719 1.1 dyoung
5720 1.5.2.2 jdolecek /* Tasklets for Link, SFP and Multispeed Fiber */
5721 1.5.2.2 jdolecek adapter->link_si = softint_establish(SOFTINT_NET |IXGBE_SOFTINFT_FLAGS,
5722 1.5.2.2 jdolecek ixgbe_handle_link, adapter);
5723 1.5.2.2 jdolecek adapter->mod_si = softint_establish(SOFTINT_NET | IXGBE_SOFTINFT_FLAGS,
5724 1.5.2.2 jdolecek ixgbe_handle_mod, adapter);
5725 1.5.2.2 jdolecek adapter->msf_si = softint_establish(SOFTINT_NET | IXGBE_SOFTINFT_FLAGS,
5726 1.5.2.2 jdolecek ixgbe_handle_msf, adapter);
5727 1.5.2.2 jdolecek adapter->phy_si = softint_establish(SOFTINT_NET | IXGBE_SOFTINFT_FLAGS,
5728 1.5.2.2 jdolecek ixgbe_handle_phy, adapter);
5729 1.5.2.2 jdolecek
5730 1.5.2.2 jdolecek if (adapter->feat_en & IXGBE_FEATURE_FDIR)
5731 1.5.2.2 jdolecek adapter->fdir_si =
5732 1.5.2.2 jdolecek softint_establish(SOFTINT_NET | IXGBE_SOFTINFT_FLAGS,
5733 1.5.2.2 jdolecek ixgbe_reinit_fdir, adapter);
5734 1.5.2.2 jdolecek
5735 1.5.2.2 jdolecek if ((!(adapter->feat_en & IXGBE_FEATURE_LEGACY_TX) &
5736 1.5.2.2 jdolecek (txr->txr_si == NULL)) ||
5737 1.5.2.2 jdolecek que->que_si == NULL ||
5738 1.5.2.2 jdolecek adapter->link_si == NULL ||
5739 1.5.2.2 jdolecek adapter->mod_si == NULL ||
5740 1.5.2.2 jdolecek ((adapter->feat_en & IXGBE_FEATURE_FDIR) &
5741 1.5.2.2 jdolecek (adapter->fdir_si == NULL)) ||
5742 1.5.2.2 jdolecek adapter->msf_si == NULL) {
5743 1.5.2.2 jdolecek aprint_error_dev(dev,
5744 1.5.2.2 jdolecek "could not establish software interrupts\n");
5745 1.1 dyoung
5746 1.5.2.2 jdolecek return ENXIO;
5747 1.5.2.2 jdolecek }
5748 1.5.2.2 jdolecek /* For simplicity in the handlers */
5749 1.5.2.2 jdolecek adapter->active_queues = IXGBE_EIMS_ENABLE_MASK;
5750 1.1 dyoung
5751 1.5.2.2 jdolecek return (0);
5752 1.5.2.2 jdolecek } /* ixgbe_allocate_legacy */
5753 1.1 dyoung
5754 1.1 dyoung
5755 1.5.2.2 jdolecek /************************************************************************
5756 1.5.2.2 jdolecek * ixgbe_allocate_msix - Setup MSI-X Interrupt resources and handlers
5757 1.5.2.2 jdolecek ************************************************************************/
5758 1.5.2.2 jdolecek static int
5759 1.5.2.2 jdolecek ixgbe_allocate_msix(struct adapter *adapter, const struct pci_attach_args *pa)
5760 1.5.2.2 jdolecek {
5761 1.5.2.2 jdolecek device_t dev = adapter->dev;
5762 1.5.2.2 jdolecek struct ix_queue *que = adapter->queues;
5763 1.5.2.2 jdolecek struct tx_ring *txr = adapter->tx_rings;
5764 1.5.2.2 jdolecek pci_chipset_tag_t pc;
5765 1.5.2.2 jdolecek char intrbuf[PCI_INTRSTR_LEN];
5766 1.5.2.2 jdolecek char intr_xname[32];
5767 1.5.2.2 jdolecek const char *intrstr = NULL;
5768 1.5.2.2 jdolecek int error, vector = 0;
5769 1.5.2.2 jdolecek int cpu_id = 0;
5770 1.5.2.2 jdolecek kcpuset_t *affinity;
5771 1.5.2.2 jdolecek #ifdef RSS
5772 1.5.2.2 jdolecek unsigned int rss_buckets = 0;
5773 1.5.2.2 jdolecek kcpuset_t cpu_mask;
5774 1.5.2.2 jdolecek #endif
5775 1.1 dyoung
5776 1.5.2.2 jdolecek pc = adapter->osdep.pc;
5777 1.5.2.2 jdolecek #ifdef RSS
5778 1.5.2.2 jdolecek /*
5779 1.5.2.2 jdolecek * If we're doing RSS, the number of queues needs to
5780 1.5.2.2 jdolecek * match the number of RSS buckets that are configured.
5781 1.5.2.2 jdolecek *
5782 1.5.2.2 jdolecek * + If there's more queues than RSS buckets, we'll end
5783 1.5.2.2 jdolecek * up with queues that get no traffic.
5784 1.5.2.2 jdolecek *
5785 1.5.2.2 jdolecek * + If there's more RSS buckets than queues, we'll end
5786 1.5.2.2 jdolecek * up having multiple RSS buckets map to the same queue,
5787 1.5.2.2 jdolecek * so there'll be some contention.
5788 1.5.2.2 jdolecek */
5789 1.5.2.2 jdolecek rss_buckets = rss_getnumbuckets();
5790 1.5.2.2 jdolecek if ((adapter->feat_en & IXGBE_FEATURE_RSS) &&
5791 1.5.2.2 jdolecek (adapter->num_queues != rss_buckets)) {
5792 1.5.2.2 jdolecek device_printf(dev,
5793 1.5.2.2 jdolecek "%s: number of queues (%d) != number of RSS buckets (%d)"
5794 1.5.2.2 jdolecek "; performance will be impacted.\n",
5795 1.5.2.2 jdolecek __func__, adapter->num_queues, rss_buckets);
5796 1.5.2.2 jdolecek }
5797 1.5.2.2 jdolecek #endif
5798 1.1 dyoung
5799 1.5.2.2 jdolecek adapter->osdep.nintrs = adapter->num_queues + 1;
5800 1.5.2.2 jdolecek if (pci_msix_alloc_exact(pa, &adapter->osdep.intrs,
5801 1.5.2.2 jdolecek adapter->osdep.nintrs) != 0) {
5802 1.5.2.2 jdolecek aprint_error_dev(dev,
5803 1.5.2.2 jdolecek "failed to allocate MSI-X interrupt\n");
5804 1.5.2.2 jdolecek return (ENXIO);
5805 1.5.2.2 jdolecek }
5806 1.1 dyoung
5807 1.5.2.2 jdolecek kcpuset_create(&affinity, false);
5808 1.5.2.2 jdolecek for (int i = 0; i < adapter->num_queues; i++, vector++, que++, txr++) {
5809 1.5.2.2 jdolecek snprintf(intr_xname, sizeof(intr_xname), "%s TXRX%d",
5810 1.5.2.2 jdolecek device_xname(dev), i);
5811 1.5.2.2 jdolecek intrstr = pci_intr_string(pc, adapter->osdep.intrs[i], intrbuf,
5812 1.5.2.2 jdolecek sizeof(intrbuf));
5813 1.5.2.2 jdolecek #ifdef IXGBE_MPSAFE
5814 1.5.2.2 jdolecek pci_intr_setattr(pc, &adapter->osdep.intrs[i], PCI_INTR_MPSAFE,
5815 1.5.2.2 jdolecek true);
5816 1.5.2.2 jdolecek #endif
5817 1.5.2.2 jdolecek /* Set the handler function */
5818 1.5.2.2 jdolecek que->res = adapter->osdep.ihs[i] = pci_intr_establish_xname(pc,
5819 1.5.2.2 jdolecek adapter->osdep.intrs[i], IPL_NET, ixgbe_msix_que, que,
5820 1.5.2.2 jdolecek intr_xname);
5821 1.5.2.2 jdolecek if (que->res == NULL) {
5822 1.5.2.2 jdolecek pci_intr_release(pc, adapter->osdep.intrs,
5823 1.5.2.2 jdolecek adapter->osdep.nintrs);
5824 1.5.2.2 jdolecek aprint_error_dev(dev,
5825 1.5.2.2 jdolecek "Failed to register QUE handler\n");
5826 1.5.2.2 jdolecek kcpuset_destroy(affinity);
5827 1.5.2.2 jdolecek return ENXIO;
5828 1.1 dyoung }
5829 1.5.2.2 jdolecek que->msix = vector;
5830 1.5.2.2 jdolecek adapter->active_queues |= (u64)(1 << que->msix);
5831 1.5.2.2 jdolecek
5832 1.5.2.2 jdolecek if (adapter->feat_en & IXGBE_FEATURE_RSS) {
5833 1.5.2.2 jdolecek #ifdef RSS
5834 1.5.2.2 jdolecek /*
5835 1.5.2.2 jdolecek * The queue ID is used as the RSS layer bucket ID.
5836 1.5.2.2 jdolecek * We look up the queue ID -> RSS CPU ID and select
5837 1.5.2.2 jdolecek * that.
5838 1.5.2.2 jdolecek */
5839 1.5.2.2 jdolecek cpu_id = rss_getcpu(i % rss_getnumbuckets());
5840 1.5.2.2 jdolecek CPU_SETOF(cpu_id, &cpu_mask);
5841 1.5.2.2 jdolecek #endif
5842 1.5.2.2 jdolecek } else {
5843 1.5.2.2 jdolecek /*
5844 1.5.2.2 jdolecek * Bind the MSI-X vector, and thus the
5845 1.5.2.2 jdolecek * rings to the corresponding CPU.
5846 1.5.2.2 jdolecek *
5847 1.5.2.2 jdolecek * This just happens to match the default RSS
5848 1.5.2.2 jdolecek * round-robin bucket -> queue -> CPU allocation.
5849 1.5.2.2 jdolecek */
5850 1.5.2.2 jdolecek if (adapter->num_queues > 1)
5851 1.5.2.2 jdolecek cpu_id = i;
5852 1.1 dyoung }
5853 1.5.2.2 jdolecek /* Round-robin affinity */
5854 1.5.2.2 jdolecek kcpuset_zero(affinity);
5855 1.5.2.2 jdolecek kcpuset_set(affinity, cpu_id % ncpu);
5856 1.5.2.2 jdolecek error = interrupt_distribute(adapter->osdep.ihs[i], affinity,
5857 1.5.2.2 jdolecek NULL);
5858 1.5.2.2 jdolecek aprint_normal_dev(dev, "for TX/RX, interrupting at %s",
5859 1.5.2.2 jdolecek intrstr);
5860 1.5.2.2 jdolecek if (error == 0) {
5861 1.5.2.2 jdolecek #if 1 /* def IXGBE_DEBUG */
5862 1.5.2.2 jdolecek #ifdef RSS
5863 1.5.2.2 jdolecek aprintf_normal(", bound RSS bucket %d to CPU %d", i,
5864 1.5.2.2 jdolecek cpu_id % ncpu);
5865 1.5.2.2 jdolecek #else
5866 1.5.2.2 jdolecek aprint_normal(", bound queue %d to cpu %d", i,
5867 1.5.2.2 jdolecek cpu_id % ncpu);
5868 1.5.2.2 jdolecek #endif
5869 1.5.2.2 jdolecek #endif /* IXGBE_DEBUG */
5870 1.1 dyoung }
5871 1.5.2.2 jdolecek aprint_normal("\n");
5872 1.1 dyoung
5873 1.5.2.2 jdolecek if (!(adapter->feat_en & IXGBE_FEATURE_LEGACY_TX))
5874 1.5.2.2 jdolecek txr->txr_si = softint_establish(
5875 1.5.2.2 jdolecek SOFTINT_NET | IXGBE_SOFTINFT_FLAGS,
5876 1.5.2.2 jdolecek ixgbe_deferred_mq_start, txr);
5877 1.5.2.2 jdolecek que->que_si
5878 1.5.2.2 jdolecek = softint_establish(SOFTINT_NET | IXGBE_SOFTINFT_FLAGS,
5879 1.5.2.2 jdolecek ixgbe_handle_que, que);
5880 1.5.2.2 jdolecek if (que->que_si == NULL) {
5881 1.5.2.2 jdolecek aprint_error_dev(dev,
5882 1.5.2.2 jdolecek "could not establish software interrupt\n");
5883 1.5.2.2 jdolecek }
5884 1.1 dyoung }
5885 1.1 dyoung
5886 1.5.2.2 jdolecek /* and Link */
5887 1.5.2.2 jdolecek cpu_id++;
5888 1.5.2.2 jdolecek snprintf(intr_xname, sizeof(intr_xname), "%s link", device_xname(dev));
5889 1.5.2.2 jdolecek intrstr = pci_intr_string(pc, adapter->osdep.intrs[vector], intrbuf,
5890 1.5.2.2 jdolecek sizeof(intrbuf));
5891 1.5.2.2 jdolecek #ifdef IXGBE_MPSAFE
5892 1.5.2.2 jdolecek pci_intr_setattr(pc, &adapter->osdep.intrs[vector], PCI_INTR_MPSAFE,
5893 1.5.2.2 jdolecek true);
5894 1.5.2.2 jdolecek #endif
5895 1.5.2.2 jdolecek /* Set the link handler function */
5896 1.5.2.2 jdolecek adapter->osdep.ihs[vector] = pci_intr_establish_xname(pc,
5897 1.5.2.2 jdolecek adapter->osdep.intrs[vector], IPL_NET, ixgbe_msix_link, adapter,
5898 1.5.2.2 jdolecek intr_xname);
5899 1.5.2.2 jdolecek if (adapter->osdep.ihs[vector] == NULL) {
5900 1.5.2.2 jdolecek adapter->res = NULL;
5901 1.5.2.2 jdolecek aprint_error_dev(dev, "Failed to register LINK handler\n");
5902 1.5.2.2 jdolecek kcpuset_destroy(affinity);
5903 1.5.2.2 jdolecek return (ENXIO);
5904 1.5.2.2 jdolecek }
5905 1.5.2.2 jdolecek /* Round-robin affinity */
5906 1.5.2.2 jdolecek kcpuset_zero(affinity);
5907 1.5.2.2 jdolecek kcpuset_set(affinity, cpu_id % ncpu);
5908 1.5.2.2 jdolecek error = interrupt_distribute(adapter->osdep.ihs[vector], affinity,NULL);
5909 1.5.2.2 jdolecek
5910 1.5.2.2 jdolecek aprint_normal_dev(dev,
5911 1.5.2.2 jdolecek "for link, interrupting at %s", intrstr);
5912 1.5.2.2 jdolecek if (error == 0)
5913 1.5.2.2 jdolecek aprint_normal(", affinity to cpu %d\n", cpu_id % ncpu);
5914 1.5.2.2 jdolecek else
5915 1.5.2.2 jdolecek aprint_normal("\n");
5916 1.1 dyoung
5917 1.5.2.2 jdolecek adapter->vector = vector;
5918 1.5.2.2 jdolecek /* Tasklets for Link, SFP and Multispeed Fiber */
5919 1.5.2.2 jdolecek adapter->link_si = softint_establish(SOFTINT_NET |IXGBE_SOFTINFT_FLAGS,
5920 1.5.2.2 jdolecek ixgbe_handle_link, adapter);
5921 1.5.2.2 jdolecek adapter->mod_si = softint_establish(SOFTINT_NET | IXGBE_SOFTINFT_FLAGS,
5922 1.5.2.2 jdolecek ixgbe_handle_mod, adapter);
5923 1.5.2.2 jdolecek adapter->msf_si = softint_establish(SOFTINT_NET | IXGBE_SOFTINFT_FLAGS,
5924 1.5.2.2 jdolecek ixgbe_handle_msf, adapter);
5925 1.5.2.2 jdolecek if (adapter->feat_cap & IXGBE_FEATURE_SRIOV)
5926 1.5.2.2 jdolecek adapter->mbx_si =
5927 1.5.2.2 jdolecek softint_establish(SOFTINT_NET | IXGBE_SOFTINFT_FLAGS,
5928 1.5.2.2 jdolecek ixgbe_handle_mbx, adapter);
5929 1.5.2.2 jdolecek adapter->phy_si = softint_establish(SOFTINT_NET | IXGBE_SOFTINFT_FLAGS,
5930 1.5.2.2 jdolecek ixgbe_handle_phy, adapter);
5931 1.5.2.2 jdolecek if (adapter->feat_en & IXGBE_FEATURE_FDIR)
5932 1.5.2.2 jdolecek adapter->fdir_si =
5933 1.5.2.2 jdolecek softint_establish(SOFTINT_NET | IXGBE_SOFTINFT_FLAGS,
5934 1.5.2.2 jdolecek ixgbe_reinit_fdir, adapter);
5935 1.1 dyoung
5936 1.5.2.2 jdolecek kcpuset_destroy(affinity);
5937 1.1 dyoung
5938 1.5.2.2 jdolecek return (0);
5939 1.5.2.2 jdolecek } /* ixgbe_allocate_msix */
5940 1.1 dyoung
5941 1.5.2.2 jdolecek /************************************************************************
5942 1.5.2.2 jdolecek * ixgbe_configure_interrupts
5943 1.5.2.2 jdolecek *
5944 1.5.2.2 jdolecek * Setup MSI-X, MSI, or legacy interrupts (in that order).
5945 1.5.2.2 jdolecek * This will also depend on user settings.
5946 1.5.2.2 jdolecek ************************************************************************/
5947 1.5.2.2 jdolecek static int
5948 1.5.2.2 jdolecek ixgbe_configure_interrupts(struct adapter *adapter)
5949 1.5.2.2 jdolecek {
5950 1.5.2.2 jdolecek device_t dev = adapter->dev;
5951 1.5.2.2 jdolecek struct ixgbe_mac_info *mac = &adapter->hw.mac;
5952 1.5.2.2 jdolecek int want, queues, msgs;
5953 1.1 dyoung
5954 1.5.2.2 jdolecek /* Default to 1 queue if MSI-X setup fails */
5955 1.5.2.2 jdolecek adapter->num_queues = 1;
5956 1.1 dyoung
5957 1.5.2.2 jdolecek /* Override by tuneable */
5958 1.5.2.2 jdolecek if (!(adapter->feat_cap & IXGBE_FEATURE_MSIX))
5959 1.5.2.2 jdolecek goto msi;
5960 1.1 dyoung
5961 1.5.2.2 jdolecek /* First try MSI-X */
5962 1.5.2.2 jdolecek msgs = pci_msix_count(adapter->osdep.pc, adapter->osdep.tag);
5963 1.5.2.2 jdolecek msgs = MIN(msgs, IXG_MAX_NINTR);
5964 1.5.2.2 jdolecek if (msgs < 2)
5965 1.5.2.2 jdolecek goto msi;
5966 1.1 dyoung
5967 1.5.2.2 jdolecek adapter->msix_mem = (void *)1; /* XXX */
5968 1.1 dyoung
5969 1.5.2.2 jdolecek /* Figure out a reasonable auto config value */
5970 1.5.2.2 jdolecek queues = (ncpu > (msgs - 1)) ? (msgs - 1) : ncpu;
5971 1.1 dyoung
5972 1.5.2.2 jdolecek #ifdef RSS
5973 1.5.2.2 jdolecek /* If we're doing RSS, clamp at the number of RSS buckets */
5974 1.5.2.2 jdolecek if (adapter->feat_en & IXGBE_FEATURE_RSS)
5975 1.5.2.2 jdolecek queues = min(queues, rss_getnumbuckets());
5976 1.5.2.2 jdolecek #endif
5977 1.5.2.2 jdolecek if (ixgbe_num_queues > queues) {
5978 1.5.2.2 jdolecek aprint_error_dev(adapter->dev, "ixgbe_num_queues (%d) is too large, using reduced amount (%d).\n", ixgbe_num_queues, queues);
5979 1.5.2.2 jdolecek ixgbe_num_queues = queues;
5980 1.1 dyoung }
5981 1.1 dyoung
5982 1.5.2.2 jdolecek if (ixgbe_num_queues != 0)
5983 1.5.2.2 jdolecek queues = ixgbe_num_queues;
5984 1.5.2.2 jdolecek else
5985 1.5.2.2 jdolecek queues = min(queues,
5986 1.5.2.2 jdolecek min(mac->max_tx_queues, mac->max_rx_queues));
5987 1.1 dyoung
5988 1.5.2.2 jdolecek /* reflect correct sysctl value */
5989 1.5.2.2 jdolecek ixgbe_num_queues = queues;
5990 1.1 dyoung
5991 1.5.2.2 jdolecek /*
5992 1.5.2.2 jdolecek * Want one vector (RX/TX pair) per queue
5993 1.5.2.2 jdolecek * plus an additional for Link.
5994 1.5.2.2 jdolecek */
5995 1.5.2.2 jdolecek want = queues + 1;
5996 1.5.2.2 jdolecek if (msgs >= want)
5997 1.5.2.2 jdolecek msgs = want;
5998 1.5.2.2 jdolecek else {
5999 1.5.2.2 jdolecek aprint_error_dev(dev, "MSI-X Configuration Problem, "
6000 1.5.2.2 jdolecek "%d vectors but %d queues wanted!\n",
6001 1.5.2.2 jdolecek msgs, want);
6002 1.5.2.2 jdolecek goto msi;
6003 1.1 dyoung }
6004 1.5.2.2 jdolecek device_printf(dev,
6005 1.5.2.2 jdolecek "Using MSI-X interrupts with %d vectors\n", msgs);
6006 1.5.2.2 jdolecek adapter->num_queues = queues;
6007 1.5.2.2 jdolecek adapter->feat_en |= IXGBE_FEATURE_MSIX;
6008 1.5.2.2 jdolecek return (0);
6009 1.1 dyoung
6010 1.5.2.2 jdolecek /*
6011 1.5.2.2 jdolecek * MSI-X allocation failed or provided us with
6012 1.5.2.2 jdolecek * less vectors than needed. Free MSI-X resources
6013 1.5.2.2 jdolecek * and we'll try enabling MSI.
6014 1.5.2.2 jdolecek */
6015 1.5.2.2 jdolecek msi:
6016 1.5.2.2 jdolecek /* Without MSI-X, some features are no longer supported */
6017 1.5.2.2 jdolecek adapter->feat_cap &= ~IXGBE_FEATURE_RSS;
6018 1.5.2.2 jdolecek adapter->feat_en &= ~IXGBE_FEATURE_RSS;
6019 1.5.2.2 jdolecek adapter->feat_cap &= ~IXGBE_FEATURE_SRIOV;
6020 1.5.2.2 jdolecek adapter->feat_en &= ~IXGBE_FEATURE_SRIOV;
6021 1.5.2.2 jdolecek
6022 1.5.2.2 jdolecek msgs = pci_msi_count(adapter->osdep.pc, adapter->osdep.tag);
6023 1.5.2.2 jdolecek adapter->msix_mem = NULL; /* XXX */
6024 1.5.2.2 jdolecek if (msgs > 1)
6025 1.5.2.2 jdolecek msgs = 1;
6026 1.5.2.2 jdolecek if (msgs != 0) {
6027 1.5.2.2 jdolecek msgs = 1;
6028 1.5.2.2 jdolecek adapter->feat_en |= IXGBE_FEATURE_MSI;
6029 1.5.2.2 jdolecek aprint_normal_dev(dev, "Using an MSI interrupt\n");
6030 1.5.2.2 jdolecek return (0);
6031 1.5.2.2 jdolecek }
6032 1.1 dyoung
6033 1.5.2.2 jdolecek if (!(adapter->feat_cap & IXGBE_FEATURE_LEGACY_IRQ)) {
6034 1.5.2.2 jdolecek aprint_error_dev(dev,
6035 1.5.2.2 jdolecek "Device does not support legacy interrupts.\n");
6036 1.5.2.2 jdolecek return 1;
6037 1.5.2.2 jdolecek }
6038 1.1 dyoung
6039 1.5.2.2 jdolecek adapter->feat_en |= IXGBE_FEATURE_LEGACY_IRQ;
6040 1.5.2.2 jdolecek aprint_normal_dev(dev, "Using a Legacy interrupt\n");
6041 1.1 dyoung
6042 1.5.2.2 jdolecek return (0);
6043 1.5.2.2 jdolecek } /* ixgbe_configure_interrupts */
6044 1.1 dyoung
6045 1.1 dyoung
6046 1.5.2.2 jdolecek /************************************************************************
6047 1.5.2.2 jdolecek * ixgbe_handle_link - Tasklet for MSI-X Link interrupts
6048 1.5.2.2 jdolecek *
6049 1.5.2.2 jdolecek * Done outside of interrupt context since the driver might sleep
6050 1.5.2.2 jdolecek ************************************************************************/
6051 1.5.2.2 jdolecek static void
6052 1.5.2.2 jdolecek ixgbe_handle_link(void *context)
6053 1.5.2.2 jdolecek {
6054 1.5.2.2 jdolecek struct adapter *adapter = context;
6055 1.5.2.2 jdolecek struct ixgbe_hw *hw = &adapter->hw;
6056 1.1 dyoung
6057 1.5.2.2 jdolecek ixgbe_check_link(hw, &adapter->link_speed, &adapter->link_up, 0);
6058 1.5.2.2 jdolecek ixgbe_update_link_status(adapter);
6059 1.1 dyoung
6060 1.5.2.2 jdolecek /* Re-enable link interrupts */
6061 1.5.2.2 jdolecek IXGBE_WRITE_REG(hw, IXGBE_EIMS, IXGBE_EIMS_LSC);
6062 1.5.2.2 jdolecek } /* ixgbe_handle_link */
6063 1.5.2.2 jdolecek
6064 1.5.2.2 jdolecek /************************************************************************
6065 1.5.2.2 jdolecek * ixgbe_rearm_queues
6066 1.5.2.2 jdolecek ************************************************************************/
6067 1.5.2.2 jdolecek static void
6068 1.5.2.2 jdolecek ixgbe_rearm_queues(struct adapter *adapter, u64 queues)
6069 1.5.2.2 jdolecek {
6070 1.5.2.2 jdolecek u32 mask;
6071 1.1 dyoung
6072 1.5.2.2 jdolecek switch (adapter->hw.mac.type) {
6073 1.5.2.2 jdolecek case ixgbe_mac_82598EB:
6074 1.5.2.2 jdolecek mask = (IXGBE_EIMS_RTX_QUEUE & queues);
6075 1.5.2.2 jdolecek IXGBE_WRITE_REG(&adapter->hw, IXGBE_EICS, mask);
6076 1.5.2.2 jdolecek break;
6077 1.5.2.2 jdolecek case ixgbe_mac_82599EB:
6078 1.5.2.2 jdolecek case ixgbe_mac_X540:
6079 1.5.2.2 jdolecek case ixgbe_mac_X550:
6080 1.5.2.2 jdolecek case ixgbe_mac_X550EM_x:
6081 1.5.2.2 jdolecek case ixgbe_mac_X550EM_a:
6082 1.5.2.2 jdolecek mask = (queues & 0xFFFFFFFF);
6083 1.5.2.2 jdolecek IXGBE_WRITE_REG(&adapter->hw, IXGBE_EICS_EX(0), mask);
6084 1.5.2.2 jdolecek mask = (queues >> 32);
6085 1.5.2.2 jdolecek IXGBE_WRITE_REG(&adapter->hw, IXGBE_EICS_EX(1), mask);
6086 1.5.2.2 jdolecek break;
6087 1.5.2.2 jdolecek default:
6088 1.5.2.2 jdolecek break;
6089 1.5.2.2 jdolecek }
6090 1.5.2.2 jdolecek } /* ixgbe_rearm_queues */
6091