Home | History | Annotate | Line # | Download | only in ixgbe
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(&current);
    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