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