if_bypass.c revision 1.2.2.2 1 1.2.2.2 jdolecek /******************************************************************************
2 1.2.2.2 jdolecek
3 1.2.2.2 jdolecek Copyright (c) 2001-2017, Intel Corporation
4 1.2.2.2 jdolecek All rights reserved.
5 1.2.2.2 jdolecek
6 1.2.2.2 jdolecek Redistribution and use in source and binary forms, with or without
7 1.2.2.2 jdolecek modification, are permitted provided that the following conditions are met:
8 1.2.2.2 jdolecek
9 1.2.2.2 jdolecek 1. Redistributions of source code must retain the above copyright notice,
10 1.2.2.2 jdolecek this list of conditions and the following disclaimer.
11 1.2.2.2 jdolecek
12 1.2.2.2 jdolecek 2. Redistributions in binary form must reproduce the above copyright
13 1.2.2.2 jdolecek notice, this list of conditions and the following disclaimer in the
14 1.2.2.2 jdolecek documentation and/or other materials provided with the distribution.
15 1.2.2.2 jdolecek
16 1.2.2.2 jdolecek 3. Neither the name of the Intel Corporation nor the names of its
17 1.2.2.2 jdolecek contributors may be used to endorse or promote products derived from
18 1.2.2.2 jdolecek this software without specific prior written permission.
19 1.2.2.2 jdolecek
20 1.2.2.2 jdolecek THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21 1.2.2.2 jdolecek AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 1.2.2.2 jdolecek IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 1.2.2.2 jdolecek ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
24 1.2.2.2 jdolecek LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25 1.2.2.2 jdolecek CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26 1.2.2.2 jdolecek SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27 1.2.2.2 jdolecek INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28 1.2.2.2 jdolecek CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29 1.2.2.2 jdolecek ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30 1.2.2.2 jdolecek POSSIBILITY OF SUCH DAMAGE.
31 1.2.2.2 jdolecek
32 1.2.2.2 jdolecek ******************************************************************************/
33 1.2.2.2 jdolecek /*$FreeBSD: head/sys/dev/ixgbe/if_bypass.c 320688 2017-07-05 17:27:03Z erj $*/
34 1.2.2.2 jdolecek
35 1.2.2.2 jdolecek
36 1.2.2.2 jdolecek #include "ixgbe.h"
37 1.2.2.2 jdolecek
38 1.2.2.2 jdolecek /************************************************************************
39 1.2.2.2 jdolecek * ixgbe_bypass_mutex_enter
40 1.2.2.2 jdolecek *
41 1.2.2.2 jdolecek * Mutex support for the bypass feature. Using a dual lock
42 1.2.2.2 jdolecek * to facilitate a privileged access to the watchdog update
43 1.2.2.2 jdolecek * over other threads.
44 1.2.2.2 jdolecek ************************************************************************/
45 1.2.2.2 jdolecek static void
46 1.2.2.2 jdolecek ixgbe_bypass_mutex_enter(struct adapter *adapter)
47 1.2.2.2 jdolecek {
48 1.2.2.2 jdolecek while (atomic_cas_uint(&adapter->bypass.low, 0, 1) == 0)
49 1.2.2.2 jdolecek usec_delay(3000);
50 1.2.2.2 jdolecek while (atomic_cas_uint(&adapter->bypass.high, 0, 1) == 0)
51 1.2.2.2 jdolecek usec_delay(3000);
52 1.2.2.2 jdolecek return;
53 1.2.2.2 jdolecek } /* ixgbe_bypass_mutex_enter */
54 1.2.2.2 jdolecek
55 1.2.2.2 jdolecek /************************************************************************
56 1.2.2.2 jdolecek * ixgbe_bypass_mutex_clear
57 1.2.2.2 jdolecek ************************************************************************/
58 1.2.2.2 jdolecek static void
59 1.2.2.2 jdolecek ixgbe_bypass_mutex_clear(struct adapter *adapter)
60 1.2.2.2 jdolecek {
61 1.2.2.2 jdolecek while (atomic_cas_uint(&adapter->bypass.high, 1, 0) == 0)
62 1.2.2.2 jdolecek usec_delay(6000);
63 1.2.2.2 jdolecek while (atomic_cas_uint(&adapter->bypass.low, 1, 0) == 0)
64 1.2.2.2 jdolecek usec_delay(6000);
65 1.2.2.2 jdolecek return;
66 1.2.2.2 jdolecek } /* ixgbe_bypass_mutex_clear */
67 1.2.2.2 jdolecek
68 1.2.2.2 jdolecek /************************************************************************
69 1.2.2.2 jdolecek * ixgbe_bypass_wd_mutex_enter
70 1.2.2.2 jdolecek *
71 1.2.2.2 jdolecek * Watchdog entry is allowed to simply grab the high priority
72 1.2.2.2 jdolecek ************************************************************************/
73 1.2.2.2 jdolecek static void
74 1.2.2.2 jdolecek ixgbe_bypass_wd_mutex_enter(struct adapter *adapter)
75 1.2.2.2 jdolecek {
76 1.2.2.2 jdolecek while (atomic_cas_uint(&adapter->bypass.high, 0, 1) == 0)
77 1.2.2.2 jdolecek usec_delay(3000);
78 1.2.2.2 jdolecek return;
79 1.2.2.2 jdolecek } /* ixgbe_bypass_wd_mutex_enter */
80 1.2.2.2 jdolecek
81 1.2.2.2 jdolecek /************************************************************************
82 1.2.2.2 jdolecek * ixgbe_bypass_wd_mutex_clear
83 1.2.2.2 jdolecek ************************************************************************/
84 1.2.2.2 jdolecek static void
85 1.2.2.2 jdolecek ixgbe_bypass_wd_mutex_clear(struct adapter *adapter)
86 1.2.2.2 jdolecek {
87 1.2.2.2 jdolecek while (atomic_cas_uint(&adapter->bypass.high, 1, 0) == 0)
88 1.2.2.2 jdolecek usec_delay(6000);
89 1.2.2.2 jdolecek return;
90 1.2.2.2 jdolecek } /* ixgbe_bypass_wd_mutex_clear */
91 1.2.2.2 jdolecek
92 1.2.2.2 jdolecek /************************************************************************
93 1.2.2.2 jdolecek * ixgbe_get_bypass_time
94 1.2.2.2 jdolecek ************************************************************************/
95 1.2.2.2 jdolecek static void
96 1.2.2.2 jdolecek ixgbe_get_bypass_time(u32 *year, u32 *sec)
97 1.2.2.2 jdolecek {
98 1.2.2.2 jdolecek struct timespec current;
99 1.2.2.2 jdolecek
100 1.2.2.2 jdolecek *year = 1970; /* time starts at 01/01/1970 */
101 1.2.2.2 jdolecek nanotime(¤t);
102 1.2.2.2 jdolecek *sec = current.tv_sec;
103 1.2.2.2 jdolecek
104 1.2.2.2 jdolecek while(*sec > SEC_THIS_YEAR(*year)) {
105 1.2.2.2 jdolecek *sec -= SEC_THIS_YEAR(*year);
106 1.2.2.2 jdolecek (*year)++;
107 1.2.2.2 jdolecek }
108 1.2.2.2 jdolecek } /* ixgbe_get_bypass_time */
109 1.2.2.2 jdolecek
110 1.2.2.2 jdolecek /************************************************************************
111 1.2.2.2 jdolecek * ixgbe_bp_version
112 1.2.2.2 jdolecek *
113 1.2.2.2 jdolecek * Display the feature version
114 1.2.2.2 jdolecek ************************************************************************/
115 1.2.2.2 jdolecek static int
116 1.2.2.2 jdolecek ixgbe_bp_version(SYSCTLFN_ARGS)
117 1.2.2.2 jdolecek {
118 1.2.2.2 jdolecek struct sysctlnode node = *rnode;
119 1.2.2.2 jdolecek struct adapter *adapter = (struct adapter *)node.sysctl_data;
120 1.2.2.2 jdolecek struct ixgbe_hw *hw = &adapter->hw;
121 1.2.2.2 jdolecek int error = 0;
122 1.2.2.2 jdolecek static int featversion = 0;
123 1.2.2.2 jdolecek u32 cmd;
124 1.2.2.2 jdolecek
125 1.2.2.2 jdolecek ixgbe_bypass_mutex_enter(adapter);
126 1.2.2.2 jdolecek cmd = BYPASS_PAGE_CTL2 | BYPASS_WE;
127 1.2.2.2 jdolecek cmd |= (BYPASS_EEPROM_VER_ADD << BYPASS_CTL2_OFFSET_SHIFT) &
128 1.2.2.2 jdolecek BYPASS_CTL2_OFFSET_M;
129 1.2.2.2 jdolecek if ((error = hw->mac.ops.bypass_rw(hw, cmd, &featversion) != 0))
130 1.2.2.2 jdolecek goto err;
131 1.2.2.2 jdolecek msec_delay(100);
132 1.2.2.2 jdolecek cmd &= ~BYPASS_WE;
133 1.2.2.2 jdolecek if ((error = hw->mac.ops.bypass_rw(hw, cmd, &featversion) != 0))
134 1.2.2.2 jdolecek goto err;
135 1.2.2.2 jdolecek ixgbe_bypass_mutex_clear(adapter);
136 1.2.2.2 jdolecek featversion &= BYPASS_CTL2_DATA_M;
137 1.2.2.2 jdolecek node.sysctl_data = &featversion;
138 1.2.2.2 jdolecek error = sysctl_lookup(SYSCTLFN_CALL(&node));
139 1.2.2.2 jdolecek return (error);
140 1.2.2.2 jdolecek err:
141 1.2.2.2 jdolecek ixgbe_bypass_mutex_clear(adapter);
142 1.2.2.2 jdolecek return (error);
143 1.2.2.2 jdolecek
144 1.2.2.2 jdolecek } /* ixgbe_bp_version */
145 1.2.2.2 jdolecek
146 1.2.2.2 jdolecek /************************************************************************
147 1.2.2.2 jdolecek * ixgbe_bp_set_state
148 1.2.2.2 jdolecek *
149 1.2.2.2 jdolecek * Show/Set the Bypass State:
150 1.2.2.2 jdolecek * 1 = NORMAL
151 1.2.2.2 jdolecek * 2 = BYPASS
152 1.2.2.2 jdolecek * 3 = ISOLATE
153 1.2.2.2 jdolecek *
154 1.2.2.2 jdolecek * With no argument the state is displayed,
155 1.2.2.2 jdolecek * passing a value will set it.
156 1.2.2.2 jdolecek ************************************************************************/
157 1.2.2.2 jdolecek static int
158 1.2.2.2 jdolecek ixgbe_bp_set_state(SYSCTLFN_ARGS)
159 1.2.2.2 jdolecek {
160 1.2.2.2 jdolecek struct sysctlnode node = *rnode;
161 1.2.2.2 jdolecek struct adapter *adapter = (struct adapter *)node.sysctl_data;
162 1.2.2.2 jdolecek struct ixgbe_hw *hw = &adapter->hw;
163 1.2.2.2 jdolecek int error = 0;
164 1.2.2.2 jdolecek static int state = 0;
165 1.2.2.2 jdolecek
166 1.2.2.2 jdolecek /* Get the current state */
167 1.2.2.2 jdolecek ixgbe_bypass_mutex_enter(adapter);
168 1.2.2.2 jdolecek error = hw->mac.ops.bypass_rw(hw,
169 1.2.2.2 jdolecek BYPASS_PAGE_CTL0, &state);
170 1.2.2.2 jdolecek ixgbe_bypass_mutex_clear(adapter);
171 1.2.2.2 jdolecek if (error)
172 1.2.2.2 jdolecek return (error);
173 1.2.2.2 jdolecek state = (state >> BYPASS_STATUS_OFF_SHIFT) & 0x3;
174 1.2.2.2 jdolecek
175 1.2.2.2 jdolecek node.sysctl_data = &state;
176 1.2.2.2 jdolecek error = sysctl_lookup(SYSCTLFN_CALL(&node));
177 1.2.2.2 jdolecek if ((error) || (newp == NULL))
178 1.2.2.2 jdolecek return (error);
179 1.2.2.2 jdolecek
180 1.2.2.2 jdolecek /* Sanity check new state */
181 1.2.2.2 jdolecek switch (state) {
182 1.2.2.2 jdolecek case BYPASS_NORM:
183 1.2.2.2 jdolecek case BYPASS_BYPASS:
184 1.2.2.2 jdolecek case BYPASS_ISOLATE:
185 1.2.2.2 jdolecek break;
186 1.2.2.2 jdolecek default:
187 1.2.2.2 jdolecek return (EINVAL);
188 1.2.2.2 jdolecek }
189 1.2.2.2 jdolecek ixgbe_bypass_mutex_enter(adapter);
190 1.2.2.2 jdolecek if ((error = hw->mac.ops.bypass_set(hw, BYPASS_PAGE_CTL0,
191 1.2.2.2 jdolecek BYPASS_MODE_OFF_M, state) != 0))
192 1.2.2.2 jdolecek goto out;
193 1.2.2.2 jdolecek /* Set AUTO back on so FW can receive events */
194 1.2.2.2 jdolecek error = hw->mac.ops.bypass_set(hw, BYPASS_PAGE_CTL0,
195 1.2.2.2 jdolecek BYPASS_MODE_OFF_M, BYPASS_AUTO);
196 1.2.2.2 jdolecek out:
197 1.2.2.2 jdolecek ixgbe_bypass_mutex_clear(adapter);
198 1.2.2.2 jdolecek usec_delay(6000);
199 1.2.2.2 jdolecek return (error);
200 1.2.2.2 jdolecek } /* ixgbe_bp_set_state */
201 1.2.2.2 jdolecek
202 1.2.2.2 jdolecek /************************************************************************
203 1.2.2.2 jdolecek * The following routines control the operational
204 1.2.2.2 jdolecek * "rules" of the feature, what behavior will occur
205 1.2.2.2 jdolecek * when particular events occur.
206 1.2.2.2 jdolecek * Values are:
207 1.2.2.2 jdolecek * 0 - no change for the event (NOP)
208 1.2.2.2 jdolecek * 1 - go to Normal operation
209 1.2.2.2 jdolecek * 2 - go to Bypass operation
210 1.2.2.2 jdolecek * 3 - go to Isolate operation
211 1.2.2.2 jdolecek * Calling the entry with no argument just displays
212 1.2.2.2 jdolecek * the current rule setting.
213 1.2.2.2 jdolecek ************************************************************************/
214 1.2.2.2 jdolecek
215 1.2.2.2 jdolecek /************************************************************************
216 1.2.2.2 jdolecek * ixgbe_bp_timeout
217 1.2.2.2 jdolecek *
218 1.2.2.2 jdolecek * This is to set the Rule for the watchdog,
219 1.2.2.2 jdolecek * not the actual watchdog timeout value.
220 1.2.2.2 jdolecek ************************************************************************/
221 1.2.2.2 jdolecek static int
222 1.2.2.2 jdolecek ixgbe_bp_timeout(SYSCTLFN_ARGS)
223 1.2.2.2 jdolecek {
224 1.2.2.2 jdolecek struct sysctlnode node = *rnode;
225 1.2.2.2 jdolecek struct adapter *adapter = (struct adapter *)node.sysctl_data;
226 1.2.2.2 jdolecek struct ixgbe_hw *hw = &adapter->hw;
227 1.2.2.2 jdolecek int error = 0;
228 1.2.2.2 jdolecek static int timeout = 0;
229 1.2.2.2 jdolecek
230 1.2.2.2 jdolecek /* Get the current value */
231 1.2.2.2 jdolecek ixgbe_bypass_mutex_enter(adapter);
232 1.2.2.2 jdolecek error = hw->mac.ops.bypass_rw(hw, BYPASS_PAGE_CTL0, &timeout);
233 1.2.2.2 jdolecek ixgbe_bypass_mutex_clear(adapter);
234 1.2.2.2 jdolecek if (error)
235 1.2.2.2 jdolecek return (error);
236 1.2.2.2 jdolecek timeout = (timeout >> BYPASS_WDTIMEOUT_SHIFT) & 0x3;
237 1.2.2.2 jdolecek
238 1.2.2.2 jdolecek node.sysctl_data = &timeout;
239 1.2.2.2 jdolecek error = sysctl_lookup(SYSCTLFN_CALL(&node));
240 1.2.2.2 jdolecek if ((error) || (newp == NULL))
241 1.2.2.2 jdolecek return (error);
242 1.2.2.2 jdolecek
243 1.2.2.2 jdolecek /* Sanity check on the setting */
244 1.2.2.2 jdolecek switch (timeout) {
245 1.2.2.2 jdolecek case BYPASS_NOP:
246 1.2.2.2 jdolecek case BYPASS_NORM:
247 1.2.2.2 jdolecek case BYPASS_BYPASS:
248 1.2.2.2 jdolecek case BYPASS_ISOLATE:
249 1.2.2.2 jdolecek break;
250 1.2.2.2 jdolecek default:
251 1.2.2.2 jdolecek return (EINVAL);
252 1.2.2.2 jdolecek }
253 1.2.2.2 jdolecek
254 1.2.2.2 jdolecek /* Set the new state */
255 1.2.2.2 jdolecek ixgbe_bypass_mutex_enter(adapter);
256 1.2.2.2 jdolecek error = hw->mac.ops.bypass_set(hw, BYPASS_PAGE_CTL0,
257 1.2.2.2 jdolecek BYPASS_WDTIMEOUT_M, timeout << BYPASS_WDTIMEOUT_SHIFT);
258 1.2.2.2 jdolecek ixgbe_bypass_mutex_clear(adapter);
259 1.2.2.2 jdolecek usec_delay(6000);
260 1.2.2.2 jdolecek return (error);
261 1.2.2.2 jdolecek } /* ixgbe_bp_timeout */
262 1.2.2.2 jdolecek
263 1.2.2.2 jdolecek /************************************************************************
264 1.2.2.2 jdolecek * ixgbe_bp_main_on
265 1.2.2.2 jdolecek ************************************************************************/
266 1.2.2.2 jdolecek static int
267 1.2.2.2 jdolecek ixgbe_bp_main_on(SYSCTLFN_ARGS)
268 1.2.2.2 jdolecek {
269 1.2.2.2 jdolecek struct sysctlnode node = *rnode;
270 1.2.2.2 jdolecek struct adapter *adapter = (struct adapter *)node.sysctl_data;
271 1.2.2.2 jdolecek struct ixgbe_hw *hw = &adapter->hw;
272 1.2.2.2 jdolecek int error = 0;
273 1.2.2.2 jdolecek static int main_on = 0;
274 1.2.2.2 jdolecek
275 1.2.2.2 jdolecek ixgbe_bypass_mutex_enter(adapter);
276 1.2.2.2 jdolecek error = hw->mac.ops.bypass_rw(hw, BYPASS_PAGE_CTL0, &main_on);
277 1.2.2.2 jdolecek main_on = (main_on >> BYPASS_MAIN_ON_SHIFT) & 0x3;
278 1.2.2.2 jdolecek ixgbe_bypass_mutex_clear(adapter);
279 1.2.2.2 jdolecek if (error)
280 1.2.2.2 jdolecek return (error);
281 1.2.2.2 jdolecek
282 1.2.2.2 jdolecek node.sysctl_data = &main_on;
283 1.2.2.2 jdolecek error = sysctl_lookup(SYSCTLFN_CALL(&node));
284 1.2.2.2 jdolecek if ((error) || (newp == NULL))
285 1.2.2.2 jdolecek return (error);
286 1.2.2.2 jdolecek
287 1.2.2.2 jdolecek /* Sanity check on the setting */
288 1.2.2.2 jdolecek switch (main_on) {
289 1.2.2.2 jdolecek case BYPASS_NOP:
290 1.2.2.2 jdolecek case BYPASS_NORM:
291 1.2.2.2 jdolecek case BYPASS_BYPASS:
292 1.2.2.2 jdolecek case BYPASS_ISOLATE:
293 1.2.2.2 jdolecek break;
294 1.2.2.2 jdolecek default:
295 1.2.2.2 jdolecek return (EINVAL);
296 1.2.2.2 jdolecek }
297 1.2.2.2 jdolecek
298 1.2.2.2 jdolecek /* Set the new state */
299 1.2.2.2 jdolecek ixgbe_bypass_mutex_enter(adapter);
300 1.2.2.2 jdolecek error = hw->mac.ops.bypass_set(hw, BYPASS_PAGE_CTL0,
301 1.2.2.2 jdolecek BYPASS_MAIN_ON_M, main_on << BYPASS_MAIN_ON_SHIFT);
302 1.2.2.2 jdolecek ixgbe_bypass_mutex_clear(adapter);
303 1.2.2.2 jdolecek usec_delay(6000);
304 1.2.2.2 jdolecek return (error);
305 1.2.2.2 jdolecek } /* ixgbe_bp_main_on */
306 1.2.2.2 jdolecek
307 1.2.2.2 jdolecek /************************************************************************
308 1.2.2.2 jdolecek * ixgbe_bp_main_off
309 1.2.2.2 jdolecek ************************************************************************/
310 1.2.2.2 jdolecek static int
311 1.2.2.2 jdolecek ixgbe_bp_main_off(SYSCTLFN_ARGS)
312 1.2.2.2 jdolecek {
313 1.2.2.2 jdolecek struct sysctlnode node = *rnode;
314 1.2.2.2 jdolecek struct adapter *adapter = (struct adapter *)node.sysctl_data;
315 1.2.2.2 jdolecek struct ixgbe_hw *hw = &adapter->hw;
316 1.2.2.2 jdolecek int error = 0;
317 1.2.2.2 jdolecek static int main_off = 0;
318 1.2.2.2 jdolecek
319 1.2.2.2 jdolecek ixgbe_bypass_mutex_enter(adapter);
320 1.2.2.2 jdolecek error = hw->mac.ops.bypass_rw(hw, BYPASS_PAGE_CTL0, &main_off);
321 1.2.2.2 jdolecek ixgbe_bypass_mutex_clear(adapter);
322 1.2.2.2 jdolecek if (error)
323 1.2.2.2 jdolecek return (error);
324 1.2.2.2 jdolecek main_off = (main_off >> BYPASS_MAIN_OFF_SHIFT) & 0x3;
325 1.2.2.2 jdolecek
326 1.2.2.2 jdolecek node.sysctl_data = &main_off;
327 1.2.2.2 jdolecek error = sysctl_lookup(SYSCTLFN_CALL(&node));
328 1.2.2.2 jdolecek if ((error) || (newp == NULL))
329 1.2.2.2 jdolecek return (error);
330 1.2.2.2 jdolecek
331 1.2.2.2 jdolecek /* Sanity check on the setting */
332 1.2.2.2 jdolecek switch (main_off) {
333 1.2.2.2 jdolecek case BYPASS_NOP:
334 1.2.2.2 jdolecek case BYPASS_NORM:
335 1.2.2.2 jdolecek case BYPASS_BYPASS:
336 1.2.2.2 jdolecek case BYPASS_ISOLATE:
337 1.2.2.2 jdolecek break;
338 1.2.2.2 jdolecek default:
339 1.2.2.2 jdolecek return (EINVAL);
340 1.2.2.2 jdolecek }
341 1.2.2.2 jdolecek
342 1.2.2.2 jdolecek /* Set the new state */
343 1.2.2.2 jdolecek ixgbe_bypass_mutex_enter(adapter);
344 1.2.2.2 jdolecek error = hw->mac.ops.bypass_set(hw, BYPASS_PAGE_CTL0,
345 1.2.2.2 jdolecek BYPASS_MAIN_OFF_M, main_off << BYPASS_MAIN_OFF_SHIFT);
346 1.2.2.2 jdolecek ixgbe_bypass_mutex_clear(adapter);
347 1.2.2.2 jdolecek usec_delay(6000);
348 1.2.2.2 jdolecek return (error);
349 1.2.2.2 jdolecek } /* ixgbe_bp_main_off */
350 1.2.2.2 jdolecek
351 1.2.2.2 jdolecek /************************************************************************
352 1.2.2.2 jdolecek * ixgbe_bp_aux_on
353 1.2.2.2 jdolecek ************************************************************************/
354 1.2.2.2 jdolecek static int
355 1.2.2.2 jdolecek ixgbe_bp_aux_on(SYSCTLFN_ARGS)
356 1.2.2.2 jdolecek {
357 1.2.2.2 jdolecek struct sysctlnode node = *rnode;
358 1.2.2.2 jdolecek struct adapter *adapter = (struct adapter *)node.sysctl_data;
359 1.2.2.2 jdolecek struct ixgbe_hw *hw = &adapter->hw;
360 1.2.2.2 jdolecek int error = 0;
361 1.2.2.2 jdolecek static int aux_on = 0;
362 1.2.2.2 jdolecek
363 1.2.2.2 jdolecek ixgbe_bypass_mutex_enter(adapter);
364 1.2.2.2 jdolecek error = hw->mac.ops.bypass_rw(hw, BYPASS_PAGE_CTL0, &aux_on);
365 1.2.2.2 jdolecek ixgbe_bypass_mutex_clear(adapter);
366 1.2.2.2 jdolecek if (error)
367 1.2.2.2 jdolecek return (error);
368 1.2.2.2 jdolecek aux_on = (aux_on >> BYPASS_AUX_ON_SHIFT) & 0x3;
369 1.2.2.2 jdolecek
370 1.2.2.2 jdolecek node.sysctl_data = &aux_on;
371 1.2.2.2 jdolecek error = sysctl_lookup(SYSCTLFN_CALL(&node));
372 1.2.2.2 jdolecek if ((error) || (newp == NULL))
373 1.2.2.2 jdolecek return (error);
374 1.2.2.2 jdolecek
375 1.2.2.2 jdolecek /* Sanity check on the setting */
376 1.2.2.2 jdolecek switch (aux_on) {
377 1.2.2.2 jdolecek case BYPASS_NOP:
378 1.2.2.2 jdolecek case BYPASS_NORM:
379 1.2.2.2 jdolecek case BYPASS_BYPASS:
380 1.2.2.2 jdolecek case BYPASS_ISOLATE:
381 1.2.2.2 jdolecek break;
382 1.2.2.2 jdolecek default:
383 1.2.2.2 jdolecek return (EINVAL);
384 1.2.2.2 jdolecek }
385 1.2.2.2 jdolecek
386 1.2.2.2 jdolecek /* Set the new state */
387 1.2.2.2 jdolecek ixgbe_bypass_mutex_enter(adapter);
388 1.2.2.2 jdolecek error = hw->mac.ops.bypass_set(hw, BYPASS_PAGE_CTL0,
389 1.2.2.2 jdolecek BYPASS_AUX_ON_M, aux_on << BYPASS_AUX_ON_SHIFT);
390 1.2.2.2 jdolecek ixgbe_bypass_mutex_clear(adapter);
391 1.2.2.2 jdolecek usec_delay(6000);
392 1.2.2.2 jdolecek return (error);
393 1.2.2.2 jdolecek } /* ixgbe_bp_aux_on */
394 1.2.2.2 jdolecek
395 1.2.2.2 jdolecek /************************************************************************
396 1.2.2.2 jdolecek * ixgbe_bp_aux_off
397 1.2.2.2 jdolecek ************************************************************************/
398 1.2.2.2 jdolecek static int
399 1.2.2.2 jdolecek ixgbe_bp_aux_off(SYSCTLFN_ARGS)
400 1.2.2.2 jdolecek {
401 1.2.2.2 jdolecek struct sysctlnode node = *rnode;
402 1.2.2.2 jdolecek struct adapter *adapter = (struct adapter *)node.sysctl_data;
403 1.2.2.2 jdolecek struct ixgbe_hw *hw = &adapter->hw;
404 1.2.2.2 jdolecek int error = 0;
405 1.2.2.2 jdolecek static int aux_off = 0;
406 1.2.2.2 jdolecek
407 1.2.2.2 jdolecek ixgbe_bypass_mutex_enter(adapter);
408 1.2.2.2 jdolecek error = hw->mac.ops.bypass_rw(hw, BYPASS_PAGE_CTL0, &aux_off);
409 1.2.2.2 jdolecek ixgbe_bypass_mutex_clear(adapter);
410 1.2.2.2 jdolecek if (error)
411 1.2.2.2 jdolecek return (error);
412 1.2.2.2 jdolecek aux_off = (aux_off >> BYPASS_AUX_OFF_SHIFT) & 0x3;
413 1.2.2.2 jdolecek
414 1.2.2.2 jdolecek node.sysctl_data = &aux_off;
415 1.2.2.2 jdolecek error = sysctl_lookup(SYSCTLFN_CALL(&node));
416 1.2.2.2 jdolecek if ((error) || (newp == NULL))
417 1.2.2.2 jdolecek return (error);
418 1.2.2.2 jdolecek
419 1.2.2.2 jdolecek /* Sanity check on the setting */
420 1.2.2.2 jdolecek switch (aux_off) {
421 1.2.2.2 jdolecek case BYPASS_NOP:
422 1.2.2.2 jdolecek case BYPASS_NORM:
423 1.2.2.2 jdolecek case BYPASS_BYPASS:
424 1.2.2.2 jdolecek case BYPASS_ISOLATE:
425 1.2.2.2 jdolecek break;
426 1.2.2.2 jdolecek default:
427 1.2.2.2 jdolecek return (EINVAL);
428 1.2.2.2 jdolecek }
429 1.2.2.2 jdolecek
430 1.2.2.2 jdolecek /* Set the new state */
431 1.2.2.2 jdolecek ixgbe_bypass_mutex_enter(adapter);
432 1.2.2.2 jdolecek error = hw->mac.ops.bypass_set(hw, BYPASS_PAGE_CTL0,
433 1.2.2.2 jdolecek BYPASS_AUX_OFF_M, aux_off << BYPASS_AUX_OFF_SHIFT);
434 1.2.2.2 jdolecek ixgbe_bypass_mutex_clear(adapter);
435 1.2.2.2 jdolecek usec_delay(6000);
436 1.2.2.2 jdolecek return (error);
437 1.2.2.2 jdolecek } /* ixgbe_bp_aux_off */
438 1.2.2.2 jdolecek
439 1.2.2.2 jdolecek /************************************************************************
440 1.2.2.2 jdolecek * ixgbe_bp_wd_set - Set the Watchdog timer value
441 1.2.2.2 jdolecek *
442 1.2.2.2 jdolecek * Valid settings are:
443 1.2.2.2 jdolecek * - 0 will disable the watchdog
444 1.2.2.2 jdolecek * - 1, 2, 3, 4, 8, 16, 32
445 1.2.2.2 jdolecek * - anything else is invalid and will be ignored
446 1.2.2.2 jdolecek ************************************************************************/
447 1.2.2.2 jdolecek static int
448 1.2.2.2 jdolecek ixgbe_bp_wd_set(SYSCTLFN_ARGS)
449 1.2.2.2 jdolecek {
450 1.2.2.2 jdolecek struct sysctlnode node = *rnode;
451 1.2.2.2 jdolecek struct adapter *adapter = (struct adapter *)node.sysctl_data;
452 1.2.2.2 jdolecek struct ixgbe_hw *hw = &adapter->hw;
453 1.2.2.2 jdolecek int error, tmp;
454 1.2.2.2 jdolecek static int timeout = 0;
455 1.2.2.2 jdolecek u32 mask, arg = BYPASS_PAGE_CTL0;
456 1.2.2.2 jdolecek
457 1.2.2.2 jdolecek /* Get the current hardware value */
458 1.2.2.2 jdolecek ixgbe_bypass_mutex_enter(adapter);
459 1.2.2.2 jdolecek error = hw->mac.ops.bypass_rw(hw, BYPASS_PAGE_CTL0, &tmp);
460 1.2.2.2 jdolecek ixgbe_bypass_mutex_clear(adapter);
461 1.2.2.2 jdolecek if (error)
462 1.2.2.2 jdolecek return (error);
463 1.2.2.2 jdolecek /*
464 1.2.2.2 jdolecek * If armed keep the displayed value,
465 1.2.2.2 jdolecek * else change the display to zero.
466 1.2.2.2 jdolecek */
467 1.2.2.2 jdolecek if ((tmp & (0x1 << BYPASS_WDT_ENABLE_SHIFT)) == 0)
468 1.2.2.2 jdolecek timeout = 0;
469 1.2.2.2 jdolecek
470 1.2.2.2 jdolecek node.sysctl_data = &timeout;
471 1.2.2.2 jdolecek error = sysctl_lookup(SYSCTLFN_CALL(&node));
472 1.2.2.2 jdolecek if ((error) || (newp == NULL))
473 1.2.2.2 jdolecek return (error);
474 1.2.2.2 jdolecek
475 1.2.2.2 jdolecek mask = BYPASS_WDT_ENABLE_M;
476 1.2.2.2 jdolecek switch (timeout) {
477 1.2.2.2 jdolecek case 0: /* disables the timer */
478 1.2.2.2 jdolecek break;
479 1.2.2.2 jdolecek case 1:
480 1.2.2.2 jdolecek arg = BYPASS_WDT_1_5 << BYPASS_WDT_TIME_SHIFT;
481 1.2.2.2 jdolecek arg |= 0x1 << BYPASS_WDT_ENABLE_SHIFT;
482 1.2.2.2 jdolecek mask |= BYPASS_WDT_VALUE_M;
483 1.2.2.2 jdolecek break;
484 1.2.2.2 jdolecek case 2:
485 1.2.2.2 jdolecek arg = BYPASS_WDT_2 << BYPASS_WDT_TIME_SHIFT;
486 1.2.2.2 jdolecek arg |= 0x1 << BYPASS_WDT_ENABLE_SHIFT;
487 1.2.2.2 jdolecek mask |= BYPASS_WDT_VALUE_M;
488 1.2.2.2 jdolecek break;
489 1.2.2.2 jdolecek case 3:
490 1.2.2.2 jdolecek arg = BYPASS_WDT_3 << BYPASS_WDT_TIME_SHIFT;
491 1.2.2.2 jdolecek arg |= 0x1 << BYPASS_WDT_ENABLE_SHIFT;
492 1.2.2.2 jdolecek mask |= BYPASS_WDT_VALUE_M;
493 1.2.2.2 jdolecek break;
494 1.2.2.2 jdolecek case 4:
495 1.2.2.2 jdolecek arg = BYPASS_WDT_4 << BYPASS_WDT_TIME_SHIFT;
496 1.2.2.2 jdolecek arg |= 0x1 << BYPASS_WDT_ENABLE_SHIFT;
497 1.2.2.2 jdolecek mask |= BYPASS_WDT_VALUE_M;
498 1.2.2.2 jdolecek break;
499 1.2.2.2 jdolecek case 8:
500 1.2.2.2 jdolecek arg = BYPASS_WDT_8 << BYPASS_WDT_TIME_SHIFT;
501 1.2.2.2 jdolecek arg |= 0x1 << BYPASS_WDT_ENABLE_SHIFT;
502 1.2.2.2 jdolecek mask |= BYPASS_WDT_VALUE_M;
503 1.2.2.2 jdolecek break;
504 1.2.2.2 jdolecek case 16:
505 1.2.2.2 jdolecek arg = BYPASS_WDT_16 << BYPASS_WDT_TIME_SHIFT;
506 1.2.2.2 jdolecek arg |= 0x1 << BYPASS_WDT_ENABLE_SHIFT;
507 1.2.2.2 jdolecek mask |= BYPASS_WDT_VALUE_M;
508 1.2.2.2 jdolecek break;
509 1.2.2.2 jdolecek case 32:
510 1.2.2.2 jdolecek arg = BYPASS_WDT_32 << BYPASS_WDT_TIME_SHIFT;
511 1.2.2.2 jdolecek arg |= 0x1 << BYPASS_WDT_ENABLE_SHIFT;
512 1.2.2.2 jdolecek mask |= BYPASS_WDT_VALUE_M;
513 1.2.2.2 jdolecek break;
514 1.2.2.2 jdolecek default:
515 1.2.2.2 jdolecek return (EINVAL);
516 1.2.2.2 jdolecek }
517 1.2.2.2 jdolecek /* Set the new watchdog */
518 1.2.2.2 jdolecek ixgbe_bypass_mutex_enter(adapter);
519 1.2.2.2 jdolecek error = hw->mac.ops.bypass_set(hw, BYPASS_PAGE_CTL0, mask, arg);
520 1.2.2.2 jdolecek ixgbe_bypass_mutex_clear(adapter);
521 1.2.2.2 jdolecek
522 1.2.2.2 jdolecek return (error);
523 1.2.2.2 jdolecek } /* ixgbe_bp_wd_set */
524 1.2.2.2 jdolecek
525 1.2.2.2 jdolecek /************************************************************************
526 1.2.2.2 jdolecek * ixgbe_bp_wd_reset - Reset the Watchdog timer
527 1.2.2.2 jdolecek *
528 1.2.2.2 jdolecek * To activate this it must be called with any argument.
529 1.2.2.2 jdolecek ************************************************************************/
530 1.2.2.2 jdolecek static int
531 1.2.2.2 jdolecek ixgbe_bp_wd_reset(SYSCTLFN_ARGS)
532 1.2.2.2 jdolecek {
533 1.2.2.2 jdolecek struct sysctlnode node = *rnode;
534 1.2.2.2 jdolecek struct adapter *adapter = (struct adapter *)node.sysctl_data;
535 1.2.2.2 jdolecek struct ixgbe_hw *hw = &adapter->hw;
536 1.2.2.2 jdolecek u32 sec, year;
537 1.2.2.2 jdolecek int cmd, count = 0, error = 0;
538 1.2.2.2 jdolecek int reset_wd = 0;
539 1.2.2.2 jdolecek
540 1.2.2.2 jdolecek node.sysctl_data = &reset_wd;
541 1.2.2.2 jdolecek error = sysctl_lookup(SYSCTLFN_CALL(&node));
542 1.2.2.2 jdolecek if ((error) || (newp == NULL))
543 1.2.2.2 jdolecek return (error);
544 1.2.2.2 jdolecek
545 1.2.2.2 jdolecek cmd = BYPASS_PAGE_CTL1 | BYPASS_WE | BYPASS_CTL1_WDT_PET;
546 1.2.2.2 jdolecek
547 1.2.2.2 jdolecek /* Resync the FW time while writing to CTL1 anyway */
548 1.2.2.2 jdolecek ixgbe_get_bypass_time(&year, &sec);
549 1.2.2.2 jdolecek
550 1.2.2.2 jdolecek cmd |= (sec & BYPASS_CTL1_TIME_M) | BYPASS_CTL1_VALID;
551 1.2.2.2 jdolecek cmd |= BYPASS_CTL1_OFFTRST;
552 1.2.2.2 jdolecek
553 1.2.2.2 jdolecek ixgbe_bypass_wd_mutex_enter(adapter);
554 1.2.2.2 jdolecek error = hw->mac.ops.bypass_rw(hw, cmd, &reset_wd);
555 1.2.2.2 jdolecek
556 1.2.2.2 jdolecek /* Read until it matches what we wrote, or we time out */
557 1.2.2.2 jdolecek do {
558 1.2.2.2 jdolecek if (count++ > 10) {
559 1.2.2.2 jdolecek error = IXGBE_BYPASS_FW_WRITE_FAILURE;
560 1.2.2.2 jdolecek break;
561 1.2.2.2 jdolecek }
562 1.2.2.2 jdolecek if (hw->mac.ops.bypass_rw(hw, BYPASS_PAGE_CTL1, &reset_wd)) {
563 1.2.2.2 jdolecek error = IXGBE_ERR_INVALID_ARGUMENT;
564 1.2.2.2 jdolecek break;
565 1.2.2.2 jdolecek }
566 1.2.2.2 jdolecek } while (!hw->mac.ops.bypass_valid_rd(cmd, reset_wd));
567 1.2.2.2 jdolecek
568 1.2.2.2 jdolecek reset_wd = 0;
569 1.2.2.2 jdolecek ixgbe_bypass_wd_mutex_clear(adapter);
570 1.2.2.2 jdolecek return (error);
571 1.2.2.2 jdolecek } /* ixgbe_bp_wd_reset */
572 1.2.2.2 jdolecek
573 1.2.2.2 jdolecek /************************************************************************
574 1.2.2.2 jdolecek * ixgbe_bp_log - Display the bypass log
575 1.2.2.2 jdolecek *
576 1.2.2.2 jdolecek * You must pass a non-zero arg to sysctl
577 1.2.2.2 jdolecek ************************************************************************/
578 1.2.2.2 jdolecek static int
579 1.2.2.2 jdolecek ixgbe_bp_log(SYSCTLFN_ARGS)
580 1.2.2.2 jdolecek {
581 1.2.2.2 jdolecek struct sysctlnode node = *rnode;
582 1.2.2.2 jdolecek struct adapter *adapter = (struct adapter *)node.sysctl_data;
583 1.2.2.2 jdolecek struct ixgbe_hw *hw = &adapter->hw;
584 1.2.2.2 jdolecek u32 cmd, base, head;
585 1.2.2.2 jdolecek u32 log_off, count = 0;
586 1.2.2.2 jdolecek static int status = 0;
587 1.2.2.2 jdolecek u8 data;
588 1.2.2.2 jdolecek struct ixgbe_bypass_eeprom eeprom[BYPASS_MAX_LOGS];
589 1.2.2.2 jdolecek int i, error = 0;
590 1.2.2.2 jdolecek
591 1.2.2.2 jdolecek node.sysctl_data = &status;
592 1.2.2.2 jdolecek error = sysctl_lookup(SYSCTLFN_CALL(&node));
593 1.2.2.2 jdolecek if ((error) || (newp == NULL))
594 1.2.2.2 jdolecek return (error);
595 1.2.2.2 jdolecek
596 1.2.2.2 jdolecek /* Keep the log display single-threaded */
597 1.2.2.2 jdolecek while (atomic_cas_uint(&adapter->bypass.log, 0, 1) == 0)
598 1.2.2.2 jdolecek usec_delay(3000);
599 1.2.2.2 jdolecek
600 1.2.2.2 jdolecek ixgbe_bypass_mutex_enter(adapter);
601 1.2.2.2 jdolecek
602 1.2.2.2 jdolecek /* Find Current head of the log eeprom offset */
603 1.2.2.2 jdolecek cmd = BYPASS_PAGE_CTL2 | BYPASS_WE;
604 1.2.2.2 jdolecek cmd |= (0x1 << BYPASS_CTL2_OFFSET_SHIFT) & BYPASS_CTL2_OFFSET_M;
605 1.2.2.2 jdolecek error = hw->mac.ops.bypass_rw(hw, cmd, &status);
606 1.2.2.2 jdolecek if (error)
607 1.2.2.2 jdolecek goto unlock_err;
608 1.2.2.2 jdolecek
609 1.2.2.2 jdolecek /* wait for the write to stick */
610 1.2.2.2 jdolecek msec_delay(100);
611 1.2.2.2 jdolecek
612 1.2.2.2 jdolecek /* Now read the results */
613 1.2.2.2 jdolecek cmd &= ~BYPASS_WE;
614 1.2.2.2 jdolecek error = hw->mac.ops.bypass_rw(hw, cmd, &status);
615 1.2.2.2 jdolecek if (error)
616 1.2.2.2 jdolecek goto unlock_err;
617 1.2.2.2 jdolecek
618 1.2.2.2 jdolecek ixgbe_bypass_mutex_clear(adapter);
619 1.2.2.2 jdolecek
620 1.2.2.2 jdolecek base = status & BYPASS_CTL2_DATA_M;
621 1.2.2.2 jdolecek head = (status & BYPASS_CTL2_HEAD_M) >> BYPASS_CTL2_HEAD_SHIFT;
622 1.2.2.2 jdolecek
623 1.2.2.2 jdolecek /* address of the first log */
624 1.2.2.2 jdolecek log_off = base + (head * 5);
625 1.2.2.2 jdolecek
626 1.2.2.2 jdolecek /* extract all the log entries */
627 1.2.2.2 jdolecek while (count < BYPASS_MAX_LOGS) {
628 1.2.2.2 jdolecek eeprom[count].logs = 0;
629 1.2.2.2 jdolecek eeprom[count].actions = 0;
630 1.2.2.2 jdolecek
631 1.2.2.2 jdolecek /* Log 5 bytes store in on u32 and a u8 */
632 1.2.2.2 jdolecek for (i = 0; i < 4; i++) {
633 1.2.2.2 jdolecek ixgbe_bypass_mutex_enter(adapter);
634 1.2.2.2 jdolecek error = hw->mac.ops.bypass_rd_eep(hw, log_off + i,
635 1.2.2.2 jdolecek &data);
636 1.2.2.2 jdolecek ixgbe_bypass_mutex_clear(adapter);
637 1.2.2.2 jdolecek if (error)
638 1.2.2.2 jdolecek return (-EINVAL);
639 1.2.2.2 jdolecek eeprom[count].logs += data << (8 * i);
640 1.2.2.2 jdolecek }
641 1.2.2.2 jdolecek
642 1.2.2.2 jdolecek ixgbe_bypass_mutex_enter(adapter);
643 1.2.2.2 jdolecek error = hw->mac.ops.bypass_rd_eep(hw,
644 1.2.2.2 jdolecek log_off + i, &eeprom[count].actions);
645 1.2.2.2 jdolecek ixgbe_bypass_mutex_clear(adapter);
646 1.2.2.2 jdolecek if (error)
647 1.2.2.2 jdolecek return (-EINVAL);
648 1.2.2.2 jdolecek
649 1.2.2.2 jdolecek /* Quit if not a unread log */
650 1.2.2.2 jdolecek if (!(eeprom[count].logs & BYPASS_LOG_CLEAR_M))
651 1.2.2.2 jdolecek break;
652 1.2.2.2 jdolecek /*
653 1.2.2.2 jdolecek * Log looks good so store the address where it's
654 1.2.2.2 jdolecek * Unread Log bit is so we can clear it after safely
655 1.2.2.2 jdolecek * pulling out all of the log data.
656 1.2.2.2 jdolecek */
657 1.2.2.2 jdolecek eeprom[count].clear_off = log_off;
658 1.2.2.2 jdolecek
659 1.2.2.2 jdolecek count++;
660 1.2.2.2 jdolecek head = head ? head - 1 : BYPASS_MAX_LOGS;
661 1.2.2.2 jdolecek log_off = base + (head * 5);
662 1.2.2.2 jdolecek }
663 1.2.2.2 jdolecek
664 1.2.2.2 jdolecek /* reverse order (oldest first) for output */
665 1.2.2.2 jdolecek while (count--) {
666 1.2.2.2 jdolecek int year;
667 1.2.2.2 jdolecek u32 mon, days, hours, min, sec;
668 1.2.2.2 jdolecek u32 time = eeprom[count].logs & BYPASS_LOG_TIME_M;
669 1.2.2.2 jdolecek u32 event = (eeprom[count].logs & BYPASS_LOG_EVENT_M) >>
670 1.2.2.2 jdolecek BYPASS_LOG_EVENT_SHIFT;
671 1.2.2.2 jdolecek u8 action = eeprom[count].actions & BYPASS_LOG_ACTION_M;
672 1.2.2.2 jdolecek u16 day_mon[2][13] = {
673 1.2.2.2 jdolecek {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365},
674 1.2.2.2 jdolecek {0, 31, 59, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366}
675 1.2.2.2 jdolecek };
676 1.2.2.2 jdolecek const char *event_str[] = {"unknown", "main on", "aux on",
677 1.2.2.2 jdolecek "main off", "aux off", "WDT", "user" };
678 1.2.2.2 jdolecek const char *action_str[] = {"ignore", "normal", "bypass",
679 1.2.2.2 jdolecek "isolate",};
680 1.2.2.2 jdolecek
681 1.2.2.2 jdolecek /* verify vaild data 1 - 6 */
682 1.2.2.2 jdolecek if (event < BYPASS_EVENT_MAIN_ON || event > BYPASS_EVENT_USR)
683 1.2.2.2 jdolecek event = 0;
684 1.2.2.2 jdolecek
685 1.2.2.2 jdolecek /*
686 1.2.2.2 jdolecek * time is in sec's this year, so convert to something
687 1.2.2.2 jdolecek * printable.
688 1.2.2.2 jdolecek */
689 1.2.2.2 jdolecek ixgbe_get_bypass_time(&year, &sec);
690 1.2.2.2 jdolecek days = time / SEC_PER_DAY;
691 1.2.2.2 jdolecek for (i = 11; days < day_mon[LEAP_YR(year)][i]; i--)
692 1.2.2.2 jdolecek continue;
693 1.2.2.2 jdolecek mon = i + 1; /* display month as 1-12 */
694 1.2.2.2 jdolecek time -= (day_mon[LEAP_YR(year)][i] * SEC_PER_DAY);
695 1.2.2.2 jdolecek days = (time / SEC_PER_DAY) + 1; /* first day is 1 */
696 1.2.2.2 jdolecek time %= SEC_PER_DAY;
697 1.2.2.2 jdolecek hours = time / (60 * 60);
698 1.2.2.2 jdolecek time %= (60 * 60);
699 1.2.2.2 jdolecek min = time / 60;
700 1.2.2.2 jdolecek sec = time % 60;
701 1.2.2.2 jdolecek device_printf(adapter->dev,
702 1.2.2.2 jdolecek "UT %02d/%02d %02d:%02d:%02d %8.8s -> %7.7s\n",
703 1.2.2.2 jdolecek mon, days, hours, min, sec, event_str[event],
704 1.2.2.2 jdolecek action_str[action]);
705 1.2.2.2 jdolecek cmd = BYPASS_PAGE_CTL2 | BYPASS_WE | BYPASS_CTL2_RW;
706 1.2.2.2 jdolecek cmd |= ((eeprom[count].clear_off + 3)
707 1.2.2.2 jdolecek << BYPASS_CTL2_OFFSET_SHIFT) & BYPASS_CTL2_OFFSET_M;
708 1.2.2.2 jdolecek cmd |= ((eeprom[count].logs & ~BYPASS_LOG_CLEAR_M) >> 24);
709 1.2.2.2 jdolecek
710 1.2.2.2 jdolecek ixgbe_bypass_mutex_enter(adapter);
711 1.2.2.2 jdolecek
712 1.2.2.2 jdolecek error = hw->mac.ops.bypass_rw(hw, cmd, &status);
713 1.2.2.2 jdolecek
714 1.2.2.2 jdolecek /* wait for the write to stick */
715 1.2.2.2 jdolecek msec_delay(100);
716 1.2.2.2 jdolecek
717 1.2.2.2 jdolecek ixgbe_bypass_mutex_clear(adapter);
718 1.2.2.2 jdolecek
719 1.2.2.2 jdolecek if (error)
720 1.2.2.2 jdolecek return (-EINVAL);
721 1.2.2.2 jdolecek }
722 1.2.2.2 jdolecek
723 1.2.2.2 jdolecek status = 0; /* reset */
724 1.2.2.2 jdolecek /* Another log command can now run */
725 1.2.2.2 jdolecek while (atomic_cas_uint(&adapter->bypass.log, 1, 0) == 0)
726 1.2.2.2 jdolecek usec_delay(3000);
727 1.2.2.2 jdolecek return(error);
728 1.2.2.2 jdolecek
729 1.2.2.2 jdolecek unlock_err:
730 1.2.2.2 jdolecek ixgbe_bypass_mutex_clear(adapter);
731 1.2.2.2 jdolecek status = 0; /* reset */
732 1.2.2.2 jdolecek while (atomic_cas_uint(&adapter->bypass.log, 1, 0) == 0)
733 1.2.2.2 jdolecek usec_delay(3000);
734 1.2.2.2 jdolecek return (-EINVAL);
735 1.2.2.2 jdolecek } /* ixgbe_bp_log */
736 1.2.2.2 jdolecek
737 1.2.2.2 jdolecek /************************************************************************
738 1.2.2.2 jdolecek * ixgbe_bypass_init - Set up infrastructure for the bypass feature
739 1.2.2.2 jdolecek *
740 1.2.2.2 jdolecek * Do time and sysctl initialization here. This feature is
741 1.2.2.2 jdolecek * only enabled for the first port of a bypass adapter.
742 1.2.2.2 jdolecek ************************************************************************/
743 1.2.2.2 jdolecek void
744 1.2.2.2 jdolecek ixgbe_bypass_init(struct adapter *adapter)
745 1.2.2.2 jdolecek {
746 1.2.2.2 jdolecek struct ixgbe_hw *hw = &adapter->hw;
747 1.2.2.2 jdolecek device_t dev = adapter->dev;
748 1.2.2.2 jdolecek u32 mask, value, sec, year;
749 1.2.2.2 jdolecek struct sysctllog **log;
750 1.2.2.2 jdolecek const struct sysctlnode *rnode, *cnode;
751 1.2.2.2 jdolecek
752 1.2.2.2 jdolecek if (!(adapter->feat_cap & IXGBE_FEATURE_BYPASS))
753 1.2.2.2 jdolecek return;
754 1.2.2.2 jdolecek
755 1.2.2.2 jdolecek /* First set up time for the hardware */
756 1.2.2.2 jdolecek ixgbe_get_bypass_time(&year, &sec);
757 1.2.2.2 jdolecek
758 1.2.2.2 jdolecek mask = BYPASS_CTL1_TIME_M
759 1.2.2.2 jdolecek | BYPASS_CTL1_VALID_M
760 1.2.2.2 jdolecek | BYPASS_CTL1_OFFTRST_M;
761 1.2.2.2 jdolecek
762 1.2.2.2 jdolecek value = (sec & BYPASS_CTL1_TIME_M)
763 1.2.2.2 jdolecek | BYPASS_CTL1_VALID
764 1.2.2.2 jdolecek | BYPASS_CTL1_OFFTRST;
765 1.2.2.2 jdolecek
766 1.2.2.2 jdolecek ixgbe_bypass_mutex_enter(adapter);
767 1.2.2.2 jdolecek hw->mac.ops.bypass_set(hw, BYPASS_PAGE_CTL1, mask, value);
768 1.2.2.2 jdolecek ixgbe_bypass_mutex_clear(adapter);
769 1.2.2.2 jdolecek
770 1.2.2.2 jdolecek /* Now set up the SYSCTL infrastructure */
771 1.2.2.2 jdolecek log = &adapter->sysctllog;
772 1.2.2.2 jdolecek if ((rnode = ixgbe_sysctl_instance(adapter)) == NULL) {
773 1.2.2.2 jdolecek aprint_error_dev(dev, "could not create sysctl root\n");
774 1.2.2.2 jdolecek return;
775 1.2.2.2 jdolecek }
776 1.2.2.2 jdolecek
777 1.2.2.2 jdolecek /*
778 1.2.2.2 jdolecek * The log routine is kept separate from the other
779 1.2.2.2 jdolecek * children so a general display command like:
780 1.2.2.2 jdolecek * `sysctl dev.ix.0.bypass` will not show the log.
781 1.2.2.2 jdolecek */
782 1.2.2.2 jdolecek sysctl_createv(log, 0, &rnode, &cnode, CTLFLAG_READWRITE,
783 1.2.2.2 jdolecek CTLTYPE_INT, "bypass_log", SYSCTL_DESCR("Bypass Log"),
784 1.2.2.2 jdolecek ixgbe_bp_log, 0, (void *)adapter, 0, CTL_CREATE, CTL_EOL);
785 1.2.2.2 jdolecek
786 1.2.2.2 jdolecek /* All other setting are hung from the 'bypass' node */
787 1.2.2.2 jdolecek sysctl_createv(log, 0, &rnode, &rnode, 0,
788 1.2.2.2 jdolecek CTLTYPE_NODE, "bypass", SYSCTL_DESCR("Bypass"),
789 1.2.2.2 jdolecek NULL, 0, NULL, 0, CTL_CREATE, CTL_EOL);
790 1.2.2.2 jdolecek
791 1.2.2.2 jdolecek sysctl_createv(log, 0, &rnode, &cnode, CTLFLAG_READONLY,
792 1.2.2.2 jdolecek CTLTYPE_INT, "version", SYSCTL_DESCR("Bypass Version"),
793 1.2.2.2 jdolecek ixgbe_bp_version, 0, (void *)adapter, 0, CTL_CREATE, CTL_EOL);
794 1.2.2.2 jdolecek
795 1.2.2.2 jdolecek sysctl_createv(log, 0, &rnode, &cnode, CTLFLAG_READWRITE,
796 1.2.2.2 jdolecek CTLTYPE_INT, "state", SYSCTL_DESCR("Bypass State"),
797 1.2.2.2 jdolecek ixgbe_bp_set_state, 0, (void *)adapter, 0, CTL_CREATE, CTL_EOL);
798 1.2.2.2 jdolecek
799 1.2.2.2 jdolecek sysctl_createv(log, 0, &rnode, &cnode, CTLFLAG_READWRITE,
800 1.2.2.2 jdolecek CTLTYPE_INT, "timeout", SYSCTL_DESCR("Bypass Timeout"),
801 1.2.2.2 jdolecek ixgbe_bp_timeout, 0, (void *)adapter, 0, CTL_CREATE, CTL_EOL);
802 1.2.2.2 jdolecek
803 1.2.2.2 jdolecek sysctl_createv(log, 0, &rnode, &cnode, CTLFLAG_READWRITE,
804 1.2.2.2 jdolecek CTLTYPE_INT, "main_on", SYSCTL_DESCR("Bypass Main On"),
805 1.2.2.2 jdolecek ixgbe_bp_main_on, 0, (void *)adapter, 0, CTL_CREATE, CTL_EOL);
806 1.2.2.2 jdolecek
807 1.2.2.2 jdolecek sysctl_createv(log, 0, &rnode, &cnode, CTLFLAG_READWRITE,
808 1.2.2.2 jdolecek CTLTYPE_INT, "main_off", SYSCTL_DESCR("Bypass Main Off"),
809 1.2.2.2 jdolecek ixgbe_bp_main_off, 0, (void *)adapter, 0, CTL_CREATE, CTL_EOL);
810 1.2.2.2 jdolecek
811 1.2.2.2 jdolecek sysctl_createv(log, 0, &rnode, &cnode, CTLFLAG_READWRITE,
812 1.2.2.2 jdolecek CTLTYPE_INT, "aux_on", SYSCTL_DESCR("Bypass Aux On"),
813 1.2.2.2 jdolecek ixgbe_bp_aux_on, 0, (void *)adapter, 0, CTL_CREATE, CTL_EOL);
814 1.2.2.2 jdolecek
815 1.2.2.2 jdolecek sysctl_createv(log, 0, &rnode, &cnode, CTLFLAG_READWRITE,
816 1.2.2.2 jdolecek CTLTYPE_INT, "aux_off", SYSCTL_DESCR("Bypass Aux Off"),
817 1.2.2.2 jdolecek ixgbe_bp_aux_off, 0, (void *)adapter, 0, CTL_CREATE, CTL_EOL);
818 1.2.2.2 jdolecek
819 1.2.2.2 jdolecek sysctl_createv(log, 0, &rnode, &cnode, CTLFLAG_READWRITE,
820 1.2.2.2 jdolecek CTLTYPE_INT, "wd_set", SYSCTL_DESCR("Set BP Watchdog"),
821 1.2.2.2 jdolecek ixgbe_bp_wd_set, 0, (void *)adapter, 0, CTL_CREATE, CTL_EOL);
822 1.2.2.2 jdolecek
823 1.2.2.2 jdolecek sysctl_createv(log, 0, &rnode, &cnode, CTLFLAG_READWRITE,
824 1.2.2.2 jdolecek CTLTYPE_INT, "wd_reset", SYSCTL_DESCR("Bypass WD Reset"),
825 1.2.2.2 jdolecek ixgbe_bp_wd_reset, 0, (void *)adapter, 0, CTL_CREATE, CTL_EOL);
826 1.2.2.2 jdolecek
827 1.2.2.2 jdolecek adapter->feat_en |= IXGBE_FEATURE_BYPASS;
828 1.2.2.2 jdolecek
829 1.2.2.2 jdolecek return;
830 1.2.2.2 jdolecek } /* ixgbe_bypass_init */
831 1.2.2.2 jdolecek
832