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