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