18eb6488eSEric Joyner /****************************************************************************** 28eb6488eSEric Joyner 38eb6488eSEric Joyner Copyright (c) 2001-2017, Intel Corporation 48eb6488eSEric Joyner All rights reserved. 58eb6488eSEric Joyner 68eb6488eSEric Joyner Redistribution and use in source and binary forms, with or without 78eb6488eSEric Joyner modification, are permitted provided that the following conditions are met: 88eb6488eSEric Joyner 98eb6488eSEric Joyner 1. Redistributions of source code must retain the above copyright notice, 108eb6488eSEric Joyner this list of conditions and the following disclaimer. 118eb6488eSEric Joyner 128eb6488eSEric Joyner 2. Redistributions in binary form must reproduce the above copyright 138eb6488eSEric Joyner notice, this list of conditions and the following disclaimer in the 148eb6488eSEric Joyner documentation and/or other materials provided with the distribution. 158eb6488eSEric Joyner 168eb6488eSEric Joyner 3. Neither the name of the Intel Corporation nor the names of its 178eb6488eSEric Joyner contributors may be used to endorse or promote products derived from 188eb6488eSEric Joyner this software without specific prior written permission. 198eb6488eSEric Joyner 208eb6488eSEric Joyner THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 218eb6488eSEric Joyner AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 228eb6488eSEric Joyner IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 238eb6488eSEric Joyner ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 248eb6488eSEric Joyner LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 258eb6488eSEric Joyner CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 268eb6488eSEric Joyner SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 278eb6488eSEric Joyner INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 288eb6488eSEric Joyner CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 298eb6488eSEric Joyner ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 308eb6488eSEric Joyner POSSIBILITY OF SUCH DAMAGE. 318eb6488eSEric Joyner 328eb6488eSEric Joyner ******************************************************************************/ 338eb6488eSEric Joyner /*$FreeBSD$*/ 348eb6488eSEric Joyner 358eb6488eSEric Joyner 368eb6488eSEric Joyner #include "ixgbe.h" 378eb6488eSEric Joyner 388eb6488eSEric Joyner /************************************************************************ 398eb6488eSEric Joyner * ixgbe_bypass_mutex_enter 408eb6488eSEric Joyner * 418eb6488eSEric Joyner * Mutex support for the bypass feature. Using a dual lock 428eb6488eSEric Joyner * to facilitate a privileged access to the watchdog update 438eb6488eSEric Joyner * over other threads. 448eb6488eSEric Joyner ************************************************************************/ 458eb6488eSEric Joyner static void 468eb6488eSEric Joyner ixgbe_bypass_mutex_enter(struct adapter *adapter) 478eb6488eSEric Joyner { 488eb6488eSEric Joyner while (atomic_cmpset_int(&adapter->bypass.low, 0, 1) == 0) 498eb6488eSEric Joyner usec_delay(3000); 508eb6488eSEric Joyner while (atomic_cmpset_int(&adapter->bypass.high, 0, 1) == 0) 518eb6488eSEric Joyner usec_delay(3000); 528eb6488eSEric Joyner return; 538eb6488eSEric Joyner } /* ixgbe_bypass_mutex_enter */ 548eb6488eSEric Joyner 558eb6488eSEric Joyner /************************************************************************ 568eb6488eSEric Joyner * ixgbe_bypass_mutex_clear 578eb6488eSEric Joyner ************************************************************************/ 588eb6488eSEric Joyner static void 598eb6488eSEric Joyner ixgbe_bypass_mutex_clear(struct adapter *adapter) 608eb6488eSEric Joyner { 618eb6488eSEric Joyner while (atomic_cmpset_int(&adapter->bypass.high, 1, 0) == 0) 628eb6488eSEric Joyner usec_delay(6000); 638eb6488eSEric Joyner while (atomic_cmpset_int(&adapter->bypass.low, 1, 0) == 0) 648eb6488eSEric Joyner usec_delay(6000); 658eb6488eSEric Joyner return; 668eb6488eSEric Joyner } /* ixgbe_bypass_mutex_clear */ 678eb6488eSEric Joyner 688eb6488eSEric Joyner /************************************************************************ 698eb6488eSEric Joyner * ixgbe_bypass_wd_mutex_enter 708eb6488eSEric Joyner * 718eb6488eSEric Joyner * Watchdog entry is allowed to simply grab the high priority 728eb6488eSEric Joyner ************************************************************************/ 738eb6488eSEric Joyner static void 748eb6488eSEric Joyner ixgbe_bypass_wd_mutex_enter(struct adapter *adapter) 758eb6488eSEric Joyner { 768eb6488eSEric Joyner while (atomic_cmpset_int(&adapter->bypass.high, 0, 1) == 0) 778eb6488eSEric Joyner usec_delay(3000); 788eb6488eSEric Joyner return; 798eb6488eSEric Joyner } /* ixgbe_bypass_wd_mutex_enter */ 808eb6488eSEric Joyner 818eb6488eSEric Joyner /************************************************************************ 828eb6488eSEric Joyner * ixgbe_bypass_wd_mutex_clear 838eb6488eSEric Joyner ************************************************************************/ 848eb6488eSEric Joyner static void 858eb6488eSEric Joyner ixgbe_bypass_wd_mutex_clear(struct adapter *adapter) 868eb6488eSEric Joyner { 878eb6488eSEric Joyner while (atomic_cmpset_int(&adapter->bypass.high, 1, 0) == 0) 888eb6488eSEric Joyner usec_delay(6000); 898eb6488eSEric Joyner return; 908eb6488eSEric Joyner } /* ixgbe_bypass_wd_mutex_clear */ 918eb6488eSEric Joyner 928eb6488eSEric Joyner /************************************************************************ 938eb6488eSEric Joyner * ixgbe_get_bypass_time 948eb6488eSEric Joyner ************************************************************************/ 958eb6488eSEric Joyner static void 968eb6488eSEric Joyner ixgbe_get_bypass_time(u32 *year, u32 *sec) 978eb6488eSEric Joyner { 988eb6488eSEric Joyner struct timespec current; 998eb6488eSEric Joyner 1008eb6488eSEric Joyner *year = 1970; /* time starts at 01/01/1970 */ 1018eb6488eSEric Joyner nanotime(¤t); 1028eb6488eSEric Joyner *sec = current.tv_sec; 1038eb6488eSEric Joyner 1048eb6488eSEric Joyner while(*sec > SEC_THIS_YEAR(*year)) { 1058eb6488eSEric Joyner *sec -= SEC_THIS_YEAR(*year); 1068eb6488eSEric Joyner (*year)++; 1078eb6488eSEric Joyner } 1088eb6488eSEric Joyner } /* ixgbe_get_bypass_time */ 1098eb6488eSEric Joyner 1108eb6488eSEric Joyner /************************************************************************ 1118eb6488eSEric Joyner * ixgbe_bp_version 1128eb6488eSEric Joyner * 1138eb6488eSEric Joyner * Display the feature version 1148eb6488eSEric Joyner ************************************************************************/ 1158eb6488eSEric Joyner static int 1168eb6488eSEric Joyner ixgbe_bp_version(SYSCTL_HANDLER_ARGS) 1178eb6488eSEric Joyner { 1188eb6488eSEric Joyner struct adapter *adapter = (struct adapter *) arg1; 1198eb6488eSEric Joyner struct ixgbe_hw *hw = &adapter->hw; 1208eb6488eSEric Joyner int error = 0; 1218eb6488eSEric Joyner static int version = 0; 1228eb6488eSEric Joyner u32 cmd; 1238eb6488eSEric Joyner 1248eb6488eSEric Joyner ixgbe_bypass_mutex_enter(adapter); 1258eb6488eSEric Joyner cmd = BYPASS_PAGE_CTL2 | BYPASS_WE; 1268eb6488eSEric Joyner cmd |= (BYPASS_EEPROM_VER_ADD << BYPASS_CTL2_OFFSET_SHIFT) & 1278eb6488eSEric Joyner BYPASS_CTL2_OFFSET_M; 1288eb6488eSEric Joyner if ((error = hw->mac.ops.bypass_rw(hw, cmd, &version) != 0)) 1298eb6488eSEric Joyner goto err; 1308eb6488eSEric Joyner msec_delay(100); 1318eb6488eSEric Joyner cmd &= ~BYPASS_WE; 1328eb6488eSEric Joyner if ((error = hw->mac.ops.bypass_rw(hw, cmd, &version) != 0)) 1338eb6488eSEric Joyner goto err; 1348eb6488eSEric Joyner ixgbe_bypass_mutex_clear(adapter); 1358eb6488eSEric Joyner version &= BYPASS_CTL2_DATA_M; 1368eb6488eSEric Joyner error = sysctl_handle_int(oidp, &version, 0, req); 1378eb6488eSEric Joyner return (error); 1388eb6488eSEric Joyner err: 1398eb6488eSEric Joyner ixgbe_bypass_mutex_clear(adapter); 1408eb6488eSEric Joyner return (error); 1418eb6488eSEric Joyner 1428eb6488eSEric Joyner } /* ixgbe_bp_version */ 1438eb6488eSEric Joyner 1448eb6488eSEric Joyner /************************************************************************ 1458eb6488eSEric Joyner * ixgbe_bp_set_state 1468eb6488eSEric Joyner * 1478eb6488eSEric Joyner * Show/Set the Bypass State: 1488eb6488eSEric Joyner * 1 = NORMAL 1498eb6488eSEric Joyner * 2 = BYPASS 1508eb6488eSEric Joyner * 3 = ISOLATE 1518eb6488eSEric Joyner * 1528eb6488eSEric Joyner * With no argument the state is displayed, 1538eb6488eSEric Joyner * passing a value will set it. 1548eb6488eSEric Joyner ************************************************************************/ 1558eb6488eSEric Joyner static int 1568eb6488eSEric Joyner ixgbe_bp_set_state(SYSCTL_HANDLER_ARGS) 1578eb6488eSEric Joyner { 1588eb6488eSEric Joyner struct adapter *adapter = (struct adapter *) arg1; 1598eb6488eSEric Joyner struct ixgbe_hw *hw = &adapter->hw; 1608eb6488eSEric Joyner int error = 0; 1618eb6488eSEric Joyner static int state = 0; 1628eb6488eSEric Joyner 1638eb6488eSEric Joyner /* Get the current state */ 1648eb6488eSEric Joyner ixgbe_bypass_mutex_enter(adapter); 1658eb6488eSEric Joyner error = hw->mac.ops.bypass_rw(hw, 1668eb6488eSEric Joyner BYPASS_PAGE_CTL0, &state); 1678eb6488eSEric Joyner ixgbe_bypass_mutex_clear(adapter); 168c19c7afeSEric Joyner if (error != 0) 1698eb6488eSEric Joyner return (error); 1708eb6488eSEric Joyner state = (state >> BYPASS_STATUS_OFF_SHIFT) & 0x3; 1718eb6488eSEric Joyner 1728eb6488eSEric Joyner error = sysctl_handle_int(oidp, &state, 0, req); 173c19c7afeSEric Joyner if ((error != 0) || (req->newptr == NULL)) 1748eb6488eSEric Joyner return (error); 1758eb6488eSEric Joyner 1768eb6488eSEric Joyner /* Sanity check new state */ 1778eb6488eSEric Joyner switch (state) { 1788eb6488eSEric Joyner case BYPASS_NORM: 1798eb6488eSEric Joyner case BYPASS_BYPASS: 1808eb6488eSEric Joyner case BYPASS_ISOLATE: 1818eb6488eSEric Joyner break; 1828eb6488eSEric Joyner default: 1838eb6488eSEric Joyner return (EINVAL); 1848eb6488eSEric Joyner } 1858eb6488eSEric Joyner ixgbe_bypass_mutex_enter(adapter); 1868eb6488eSEric Joyner if ((error = hw->mac.ops.bypass_set(hw, BYPASS_PAGE_CTL0, 1878eb6488eSEric Joyner BYPASS_MODE_OFF_M, state) != 0)) 1888eb6488eSEric Joyner goto out; 1898eb6488eSEric Joyner /* Set AUTO back on so FW can receive events */ 1908eb6488eSEric Joyner error = hw->mac.ops.bypass_set(hw, BYPASS_PAGE_CTL0, 1918eb6488eSEric Joyner BYPASS_MODE_OFF_M, BYPASS_AUTO); 1928eb6488eSEric Joyner out: 1938eb6488eSEric Joyner ixgbe_bypass_mutex_clear(adapter); 1948eb6488eSEric Joyner usec_delay(6000); 1958eb6488eSEric Joyner return (error); 1968eb6488eSEric Joyner } /* ixgbe_bp_set_state */ 1978eb6488eSEric Joyner 1988eb6488eSEric Joyner /************************************************************************ 1998eb6488eSEric Joyner * The following routines control the operational 2008eb6488eSEric Joyner * "rules" of the feature, what behavior will occur 2018eb6488eSEric Joyner * when particular events occur. 2028eb6488eSEric Joyner * Values are: 2038eb6488eSEric Joyner * 0 - no change for the event (NOP) 2048eb6488eSEric Joyner * 1 - go to Normal operation 2058eb6488eSEric Joyner * 2 - go to Bypass operation 2068eb6488eSEric Joyner * 3 - go to Isolate operation 2078eb6488eSEric Joyner * Calling the entry with no argument just displays 2088eb6488eSEric Joyner * the current rule setting. 2098eb6488eSEric Joyner ************************************************************************/ 2108eb6488eSEric Joyner 2118eb6488eSEric Joyner /************************************************************************ 2128eb6488eSEric Joyner * ixgbe_bp_timeout 2138eb6488eSEric Joyner * 2148eb6488eSEric Joyner * This is to set the Rule for the watchdog, 2158eb6488eSEric Joyner * not the actual watchdog timeout value. 2168eb6488eSEric Joyner ************************************************************************/ 2178eb6488eSEric Joyner static int 2188eb6488eSEric Joyner ixgbe_bp_timeout(SYSCTL_HANDLER_ARGS) 2198eb6488eSEric Joyner { 2208eb6488eSEric Joyner struct adapter *adapter = (struct adapter *) arg1; 2218eb6488eSEric Joyner struct ixgbe_hw *hw = &adapter->hw; 2228eb6488eSEric Joyner int error = 0; 2238eb6488eSEric Joyner static int timeout = 0; 2248eb6488eSEric Joyner 2258eb6488eSEric Joyner /* Get the current value */ 2268eb6488eSEric Joyner ixgbe_bypass_mutex_enter(adapter); 2278eb6488eSEric Joyner error = hw->mac.ops.bypass_rw(hw, BYPASS_PAGE_CTL0, &timeout); 2288eb6488eSEric Joyner ixgbe_bypass_mutex_clear(adapter); 2298eb6488eSEric Joyner if (error) 2308eb6488eSEric Joyner return (error); 2318eb6488eSEric Joyner timeout = (timeout >> BYPASS_WDTIMEOUT_SHIFT) & 0x3; 2328eb6488eSEric Joyner 2338eb6488eSEric Joyner error = sysctl_handle_int(oidp, &timeout, 0, req); 2348eb6488eSEric Joyner if ((error) || (req->newptr == NULL)) 2358eb6488eSEric Joyner return (error); 2368eb6488eSEric Joyner 2378eb6488eSEric Joyner /* Sanity check on the setting */ 2388eb6488eSEric Joyner switch (timeout) { 2398eb6488eSEric Joyner case BYPASS_NOP: 2408eb6488eSEric Joyner case BYPASS_NORM: 2418eb6488eSEric Joyner case BYPASS_BYPASS: 2428eb6488eSEric Joyner case BYPASS_ISOLATE: 2438eb6488eSEric Joyner break; 2448eb6488eSEric Joyner default: 2458eb6488eSEric Joyner return (EINVAL); 2468eb6488eSEric Joyner } 2478eb6488eSEric Joyner 2488eb6488eSEric Joyner /* Set the new state */ 2498eb6488eSEric Joyner ixgbe_bypass_mutex_enter(adapter); 2508eb6488eSEric Joyner error = hw->mac.ops.bypass_set(hw, BYPASS_PAGE_CTL0, 2518eb6488eSEric Joyner BYPASS_WDTIMEOUT_M, timeout << BYPASS_WDTIMEOUT_SHIFT); 2528eb6488eSEric Joyner ixgbe_bypass_mutex_clear(adapter); 2538eb6488eSEric Joyner usec_delay(6000); 2548eb6488eSEric Joyner return (error); 2558eb6488eSEric Joyner } /* ixgbe_bp_timeout */ 2568eb6488eSEric Joyner 2578eb6488eSEric Joyner /************************************************************************ 2588eb6488eSEric Joyner * ixgbe_bp_main_on 2598eb6488eSEric Joyner ************************************************************************/ 2608eb6488eSEric Joyner static int 2618eb6488eSEric Joyner ixgbe_bp_main_on(SYSCTL_HANDLER_ARGS) 2628eb6488eSEric Joyner { 2638eb6488eSEric Joyner struct adapter *adapter = (struct adapter *) arg1; 2648eb6488eSEric Joyner struct ixgbe_hw *hw = &adapter->hw; 2658eb6488eSEric Joyner int error = 0; 2668eb6488eSEric Joyner static int main_on = 0; 2678eb6488eSEric Joyner 2688eb6488eSEric Joyner ixgbe_bypass_mutex_enter(adapter); 2698eb6488eSEric Joyner error = hw->mac.ops.bypass_rw(hw, BYPASS_PAGE_CTL0, &main_on); 2708eb6488eSEric Joyner main_on = (main_on >> BYPASS_MAIN_ON_SHIFT) & 0x3; 2718eb6488eSEric Joyner ixgbe_bypass_mutex_clear(adapter); 2728eb6488eSEric Joyner if (error) 2738eb6488eSEric Joyner return (error); 2748eb6488eSEric Joyner 2758eb6488eSEric Joyner error = sysctl_handle_int(oidp, &main_on, 0, req); 2768eb6488eSEric Joyner if ((error) || (req->newptr == NULL)) 2778eb6488eSEric Joyner return (error); 2788eb6488eSEric Joyner 2798eb6488eSEric Joyner /* Sanity check on the setting */ 2808eb6488eSEric Joyner switch (main_on) { 2818eb6488eSEric Joyner case BYPASS_NOP: 2828eb6488eSEric Joyner case BYPASS_NORM: 2838eb6488eSEric Joyner case BYPASS_BYPASS: 2848eb6488eSEric Joyner case BYPASS_ISOLATE: 2858eb6488eSEric Joyner break; 2868eb6488eSEric Joyner default: 2878eb6488eSEric Joyner return (EINVAL); 2888eb6488eSEric Joyner } 2898eb6488eSEric Joyner 2908eb6488eSEric Joyner /* Set the new state */ 2918eb6488eSEric Joyner ixgbe_bypass_mutex_enter(adapter); 2928eb6488eSEric Joyner error = hw->mac.ops.bypass_set(hw, BYPASS_PAGE_CTL0, 2938eb6488eSEric Joyner BYPASS_MAIN_ON_M, main_on << BYPASS_MAIN_ON_SHIFT); 2948eb6488eSEric Joyner ixgbe_bypass_mutex_clear(adapter); 2958eb6488eSEric Joyner usec_delay(6000); 2968eb6488eSEric Joyner return (error); 2978eb6488eSEric Joyner } /* ixgbe_bp_main_on */ 2988eb6488eSEric Joyner 2998eb6488eSEric Joyner /************************************************************************ 3008eb6488eSEric Joyner * ixgbe_bp_main_off 3018eb6488eSEric Joyner ************************************************************************/ 3028eb6488eSEric Joyner static int 3038eb6488eSEric Joyner ixgbe_bp_main_off(SYSCTL_HANDLER_ARGS) 3048eb6488eSEric Joyner { 3058eb6488eSEric Joyner struct adapter *adapter = (struct adapter *) arg1; 3068eb6488eSEric Joyner struct ixgbe_hw *hw = &adapter->hw; 3078eb6488eSEric Joyner int error = 0; 3088eb6488eSEric Joyner static int main_off = 0; 3098eb6488eSEric Joyner 3108eb6488eSEric Joyner ixgbe_bypass_mutex_enter(adapter); 3118eb6488eSEric Joyner error = hw->mac.ops.bypass_rw(hw, BYPASS_PAGE_CTL0, &main_off); 3128eb6488eSEric Joyner ixgbe_bypass_mutex_clear(adapter); 3138eb6488eSEric Joyner if (error) 3148eb6488eSEric Joyner return (error); 3158eb6488eSEric Joyner main_off = (main_off >> BYPASS_MAIN_OFF_SHIFT) & 0x3; 3168eb6488eSEric Joyner 3178eb6488eSEric Joyner error = sysctl_handle_int(oidp, &main_off, 0, req); 3188eb6488eSEric Joyner if ((error) || (req->newptr == NULL)) 3198eb6488eSEric Joyner return (error); 3208eb6488eSEric Joyner 3218eb6488eSEric Joyner /* Sanity check on the setting */ 3228eb6488eSEric Joyner switch (main_off) { 3238eb6488eSEric Joyner case BYPASS_NOP: 3248eb6488eSEric Joyner case BYPASS_NORM: 3258eb6488eSEric Joyner case BYPASS_BYPASS: 3268eb6488eSEric Joyner case BYPASS_ISOLATE: 3278eb6488eSEric Joyner break; 3288eb6488eSEric Joyner default: 3298eb6488eSEric Joyner return (EINVAL); 3308eb6488eSEric Joyner } 3318eb6488eSEric Joyner 3328eb6488eSEric Joyner /* Set the new state */ 3338eb6488eSEric Joyner ixgbe_bypass_mutex_enter(adapter); 3348eb6488eSEric Joyner error = hw->mac.ops.bypass_set(hw, BYPASS_PAGE_CTL0, 3358eb6488eSEric Joyner BYPASS_MAIN_OFF_M, main_off << BYPASS_MAIN_OFF_SHIFT); 3368eb6488eSEric Joyner ixgbe_bypass_mutex_clear(adapter); 3378eb6488eSEric Joyner usec_delay(6000); 3388eb6488eSEric Joyner return (error); 3398eb6488eSEric Joyner } /* ixgbe_bp_main_off */ 3408eb6488eSEric Joyner 3418eb6488eSEric Joyner /************************************************************************ 3428eb6488eSEric Joyner * ixgbe_bp_aux_on 3438eb6488eSEric Joyner ************************************************************************/ 3448eb6488eSEric Joyner static int 3458eb6488eSEric Joyner ixgbe_bp_aux_on(SYSCTL_HANDLER_ARGS) 3468eb6488eSEric Joyner { 3478eb6488eSEric Joyner struct adapter *adapter = (struct adapter *) arg1; 3488eb6488eSEric Joyner struct ixgbe_hw *hw = &adapter->hw; 3498eb6488eSEric Joyner int error = 0; 3508eb6488eSEric Joyner static int aux_on = 0; 3518eb6488eSEric Joyner 3528eb6488eSEric Joyner ixgbe_bypass_mutex_enter(adapter); 3538eb6488eSEric Joyner error = hw->mac.ops.bypass_rw(hw, BYPASS_PAGE_CTL0, &aux_on); 3548eb6488eSEric Joyner ixgbe_bypass_mutex_clear(adapter); 3558eb6488eSEric Joyner if (error) 3568eb6488eSEric Joyner return (error); 3578eb6488eSEric Joyner aux_on = (aux_on >> BYPASS_AUX_ON_SHIFT) & 0x3; 3588eb6488eSEric Joyner 3598eb6488eSEric Joyner error = sysctl_handle_int(oidp, &aux_on, 0, req); 3608eb6488eSEric Joyner if ((error) || (req->newptr == NULL)) 3618eb6488eSEric Joyner return (error); 3628eb6488eSEric Joyner 3638eb6488eSEric Joyner /* Sanity check on the setting */ 3648eb6488eSEric Joyner switch (aux_on) { 3658eb6488eSEric Joyner case BYPASS_NOP: 3668eb6488eSEric Joyner case BYPASS_NORM: 3678eb6488eSEric Joyner case BYPASS_BYPASS: 3688eb6488eSEric Joyner case BYPASS_ISOLATE: 3698eb6488eSEric Joyner break; 3708eb6488eSEric Joyner default: 3718eb6488eSEric Joyner return (EINVAL); 3728eb6488eSEric Joyner } 3738eb6488eSEric Joyner 3748eb6488eSEric Joyner /* Set the new state */ 3758eb6488eSEric Joyner ixgbe_bypass_mutex_enter(adapter); 3768eb6488eSEric Joyner error = hw->mac.ops.bypass_set(hw, BYPASS_PAGE_CTL0, 3778eb6488eSEric Joyner BYPASS_AUX_ON_M, aux_on << BYPASS_AUX_ON_SHIFT); 3788eb6488eSEric Joyner ixgbe_bypass_mutex_clear(adapter); 3798eb6488eSEric Joyner usec_delay(6000); 3808eb6488eSEric Joyner return (error); 3818eb6488eSEric Joyner } /* ixgbe_bp_aux_on */ 3828eb6488eSEric Joyner 3838eb6488eSEric Joyner /************************************************************************ 3848eb6488eSEric Joyner * ixgbe_bp_aux_off 3858eb6488eSEric Joyner ************************************************************************/ 3868eb6488eSEric Joyner static int 3878eb6488eSEric Joyner ixgbe_bp_aux_off(SYSCTL_HANDLER_ARGS) 3888eb6488eSEric Joyner { 3898eb6488eSEric Joyner struct adapter *adapter = (struct adapter *) arg1; 3908eb6488eSEric Joyner struct ixgbe_hw *hw = &adapter->hw; 3918eb6488eSEric Joyner int error = 0; 3928eb6488eSEric Joyner static int aux_off = 0; 3938eb6488eSEric Joyner 3948eb6488eSEric Joyner ixgbe_bypass_mutex_enter(adapter); 3958eb6488eSEric Joyner error = hw->mac.ops.bypass_rw(hw, BYPASS_PAGE_CTL0, &aux_off); 3968eb6488eSEric Joyner ixgbe_bypass_mutex_clear(adapter); 3978eb6488eSEric Joyner if (error) 3988eb6488eSEric Joyner return (error); 3998eb6488eSEric Joyner aux_off = (aux_off >> BYPASS_AUX_OFF_SHIFT) & 0x3; 4008eb6488eSEric Joyner 4018eb6488eSEric Joyner error = sysctl_handle_int(oidp, &aux_off, 0, req); 4028eb6488eSEric Joyner if ((error) || (req->newptr == NULL)) 4038eb6488eSEric Joyner return (error); 4048eb6488eSEric Joyner 4058eb6488eSEric Joyner /* Sanity check on the setting */ 4068eb6488eSEric Joyner switch (aux_off) { 4078eb6488eSEric Joyner case BYPASS_NOP: 4088eb6488eSEric Joyner case BYPASS_NORM: 4098eb6488eSEric Joyner case BYPASS_BYPASS: 4108eb6488eSEric Joyner case BYPASS_ISOLATE: 4118eb6488eSEric Joyner break; 4128eb6488eSEric Joyner default: 4138eb6488eSEric Joyner return (EINVAL); 4148eb6488eSEric Joyner } 4158eb6488eSEric Joyner 4168eb6488eSEric Joyner /* Set the new state */ 4178eb6488eSEric Joyner ixgbe_bypass_mutex_enter(adapter); 4188eb6488eSEric Joyner error = hw->mac.ops.bypass_set(hw, BYPASS_PAGE_CTL0, 4198eb6488eSEric Joyner BYPASS_AUX_OFF_M, aux_off << BYPASS_AUX_OFF_SHIFT); 4208eb6488eSEric Joyner ixgbe_bypass_mutex_clear(adapter); 4218eb6488eSEric Joyner usec_delay(6000); 4228eb6488eSEric Joyner return (error); 4238eb6488eSEric Joyner } /* ixgbe_bp_aux_off */ 4248eb6488eSEric Joyner 4258eb6488eSEric Joyner /************************************************************************ 4268eb6488eSEric Joyner * ixgbe_bp_wd_set - Set the Watchdog timer value 4278eb6488eSEric Joyner * 4288eb6488eSEric Joyner * Valid settings are: 4298eb6488eSEric Joyner * - 0 will disable the watchdog 4308eb6488eSEric Joyner * - 1, 2, 3, 4, 8, 16, 32 4318eb6488eSEric Joyner * - anything else is invalid and will be ignored 4328eb6488eSEric Joyner ************************************************************************/ 4338eb6488eSEric Joyner static int 4348eb6488eSEric Joyner ixgbe_bp_wd_set(SYSCTL_HANDLER_ARGS) 4358eb6488eSEric Joyner { 4368eb6488eSEric Joyner struct adapter *adapter = (struct adapter *) arg1; 4378eb6488eSEric Joyner struct ixgbe_hw *hw = &adapter->hw; 4388eb6488eSEric Joyner int error, tmp; 4398eb6488eSEric Joyner static int timeout = 0; 440c19c7afeSEric Joyner u32 mask, arg; 4418eb6488eSEric Joyner 4428eb6488eSEric Joyner /* Get the current hardware value */ 4438eb6488eSEric Joyner ixgbe_bypass_mutex_enter(adapter); 4448eb6488eSEric Joyner error = hw->mac.ops.bypass_rw(hw, BYPASS_PAGE_CTL0, &tmp); 4458eb6488eSEric Joyner ixgbe_bypass_mutex_clear(adapter); 4468eb6488eSEric Joyner if (error) 4478eb6488eSEric Joyner return (error); 4488eb6488eSEric Joyner /* 4498eb6488eSEric Joyner * If armed keep the displayed value, 4508eb6488eSEric Joyner * else change the display to zero. 4518eb6488eSEric Joyner */ 4528eb6488eSEric Joyner if ((tmp & (0x1 << BYPASS_WDT_ENABLE_SHIFT)) == 0) 4538eb6488eSEric Joyner timeout = 0; 4548eb6488eSEric Joyner 4558eb6488eSEric Joyner error = sysctl_handle_int(oidp, &timeout, 0, req); 4568eb6488eSEric Joyner if ((error) || (req->newptr == NULL)) 4578eb6488eSEric Joyner return (error); 4588eb6488eSEric Joyner 459c19c7afeSEric Joyner arg = 0x1 << BYPASS_WDT_ENABLE_SHIFT; 460c19c7afeSEric Joyner mask = BYPASS_WDT_ENABLE_M | BYPASS_WDT_VALUE_M; 4618eb6488eSEric Joyner switch (timeout) { 4628eb6488eSEric Joyner case 0: /* disables the timer */ 463c19c7afeSEric Joyner arg = BYPASS_PAGE_CTL0; 464c19c7afeSEric Joyner mask = BYPASS_WDT_ENABLE_M; 4658eb6488eSEric Joyner break; 4668eb6488eSEric Joyner case 1: 467c19c7afeSEric Joyner arg |= BYPASS_WDT_1_5 << BYPASS_WDT_TIME_SHIFT; 4688eb6488eSEric Joyner break; 4698eb6488eSEric Joyner case 2: 470c19c7afeSEric Joyner arg |= BYPASS_WDT_2 << BYPASS_WDT_TIME_SHIFT; 4718eb6488eSEric Joyner break; 4728eb6488eSEric Joyner case 3: 473c19c7afeSEric Joyner arg |= BYPASS_WDT_3 << BYPASS_WDT_TIME_SHIFT; 4748eb6488eSEric Joyner break; 4758eb6488eSEric Joyner case 4: 476c19c7afeSEric Joyner arg |= BYPASS_WDT_4 << BYPASS_WDT_TIME_SHIFT; 4778eb6488eSEric Joyner break; 4788eb6488eSEric Joyner case 8: 479c19c7afeSEric Joyner arg |= BYPASS_WDT_8 << BYPASS_WDT_TIME_SHIFT; 4808eb6488eSEric Joyner break; 4818eb6488eSEric Joyner case 16: 482c19c7afeSEric Joyner arg |= BYPASS_WDT_16 << BYPASS_WDT_TIME_SHIFT; 4838eb6488eSEric Joyner break; 4848eb6488eSEric Joyner case 32: 485c19c7afeSEric Joyner arg |= BYPASS_WDT_32 << BYPASS_WDT_TIME_SHIFT; 4868eb6488eSEric Joyner break; 4878eb6488eSEric Joyner default: 4888eb6488eSEric Joyner return (EINVAL); 4898eb6488eSEric Joyner } 490c19c7afeSEric Joyner 4918eb6488eSEric Joyner /* Set the new watchdog */ 4928eb6488eSEric Joyner ixgbe_bypass_mutex_enter(adapter); 4938eb6488eSEric Joyner error = hw->mac.ops.bypass_set(hw, BYPASS_PAGE_CTL0, mask, arg); 4948eb6488eSEric Joyner ixgbe_bypass_mutex_clear(adapter); 4958eb6488eSEric Joyner 4968eb6488eSEric Joyner return (error); 4978eb6488eSEric Joyner } /* ixgbe_bp_wd_set */ 4988eb6488eSEric Joyner 4998eb6488eSEric Joyner /************************************************************************ 5008eb6488eSEric Joyner * ixgbe_bp_wd_reset - Reset the Watchdog timer 5018eb6488eSEric Joyner * 5028eb6488eSEric Joyner * To activate this it must be called with any argument. 5038eb6488eSEric Joyner ************************************************************************/ 5048eb6488eSEric Joyner static int 5058eb6488eSEric Joyner ixgbe_bp_wd_reset(SYSCTL_HANDLER_ARGS) 5068eb6488eSEric Joyner { 5078eb6488eSEric Joyner struct adapter *adapter = (struct adapter *) arg1; 5088eb6488eSEric Joyner struct ixgbe_hw *hw = &adapter->hw; 5098eb6488eSEric Joyner u32 sec, year; 5108eb6488eSEric Joyner int cmd, count = 0, error = 0; 5118eb6488eSEric Joyner int reset_wd = 0; 5128eb6488eSEric Joyner 5138eb6488eSEric Joyner error = sysctl_handle_int(oidp, &reset_wd, 0, req); 5148eb6488eSEric Joyner if ((error) || (req->newptr == NULL)) 5158eb6488eSEric Joyner return (error); 5168eb6488eSEric Joyner 5178eb6488eSEric Joyner cmd = BYPASS_PAGE_CTL1 | BYPASS_WE | BYPASS_CTL1_WDT_PET; 5188eb6488eSEric Joyner 5198eb6488eSEric Joyner /* Resync the FW time while writing to CTL1 anyway */ 5208eb6488eSEric Joyner ixgbe_get_bypass_time(&year, &sec); 5218eb6488eSEric Joyner 5228eb6488eSEric Joyner cmd |= (sec & BYPASS_CTL1_TIME_M) | BYPASS_CTL1_VALID; 5238eb6488eSEric Joyner cmd |= BYPASS_CTL1_OFFTRST; 5248eb6488eSEric Joyner 5258eb6488eSEric Joyner ixgbe_bypass_wd_mutex_enter(adapter); 5268eb6488eSEric Joyner error = hw->mac.ops.bypass_rw(hw, cmd, &reset_wd); 5278eb6488eSEric Joyner 5288eb6488eSEric Joyner /* Read until it matches what we wrote, or we time out */ 5298eb6488eSEric Joyner do { 5308eb6488eSEric Joyner if (count++ > 10) { 5318eb6488eSEric Joyner error = IXGBE_BYPASS_FW_WRITE_FAILURE; 5328eb6488eSEric Joyner break; 5338eb6488eSEric Joyner } 534c19c7afeSEric Joyner error = hw->mac.ops.bypass_rw(hw, BYPASS_PAGE_CTL1, &reset_wd); 535c19c7afeSEric Joyner if (error != 0) { 5368eb6488eSEric Joyner error = IXGBE_ERR_INVALID_ARGUMENT; 5378eb6488eSEric Joyner break; 5388eb6488eSEric Joyner } 5398eb6488eSEric Joyner } while (!hw->mac.ops.bypass_valid_rd(cmd, reset_wd)); 5408eb6488eSEric Joyner 5418eb6488eSEric Joyner reset_wd = 0; 5428eb6488eSEric Joyner ixgbe_bypass_wd_mutex_clear(adapter); 5438eb6488eSEric Joyner return (error); 5448eb6488eSEric Joyner } /* ixgbe_bp_wd_reset */ 5458eb6488eSEric Joyner 5468eb6488eSEric Joyner /************************************************************************ 5478eb6488eSEric Joyner * ixgbe_bp_log - Display the bypass log 5488eb6488eSEric Joyner * 5498eb6488eSEric Joyner * You must pass a non-zero arg to sysctl 5508eb6488eSEric Joyner ************************************************************************/ 5518eb6488eSEric Joyner static int 5528eb6488eSEric Joyner ixgbe_bp_log(SYSCTL_HANDLER_ARGS) 5538eb6488eSEric Joyner { 5548eb6488eSEric Joyner struct adapter *adapter = (struct adapter *) arg1; 5558eb6488eSEric Joyner struct ixgbe_hw *hw = &adapter->hw; 5568eb6488eSEric Joyner u32 cmd, base, head; 5578eb6488eSEric Joyner u32 log_off, count = 0; 5588eb6488eSEric Joyner static int status = 0; 5598eb6488eSEric Joyner u8 data; 5608eb6488eSEric Joyner struct ixgbe_bypass_eeprom eeprom[BYPASS_MAX_LOGS]; 5618eb6488eSEric Joyner int i, error = 0; 5628eb6488eSEric Joyner 5638eb6488eSEric Joyner error = sysctl_handle_int(oidp, &status, 0, req); 5648eb6488eSEric Joyner if ((error) || (req->newptr == NULL)) 5658eb6488eSEric Joyner return (error); 5668eb6488eSEric Joyner 5678eb6488eSEric Joyner /* Keep the log display single-threaded */ 5688eb6488eSEric Joyner while (atomic_cmpset_int(&adapter->bypass.log, 0, 1) == 0) 5698eb6488eSEric Joyner usec_delay(3000); 5708eb6488eSEric Joyner 5718eb6488eSEric Joyner ixgbe_bypass_mutex_enter(adapter); 5728eb6488eSEric Joyner 5738eb6488eSEric Joyner /* Find Current head of the log eeprom offset */ 5748eb6488eSEric Joyner cmd = BYPASS_PAGE_CTL2 | BYPASS_WE; 5758eb6488eSEric Joyner cmd |= (0x1 << BYPASS_CTL2_OFFSET_SHIFT) & BYPASS_CTL2_OFFSET_M; 5768eb6488eSEric Joyner error = hw->mac.ops.bypass_rw(hw, cmd, &status); 5778eb6488eSEric Joyner if (error) 5788eb6488eSEric Joyner goto unlock_err; 5798eb6488eSEric Joyner 5808eb6488eSEric Joyner /* wait for the write to stick */ 5818eb6488eSEric Joyner msec_delay(100); 5828eb6488eSEric Joyner 5838eb6488eSEric Joyner /* Now read the results */ 5848eb6488eSEric Joyner cmd &= ~BYPASS_WE; 5858eb6488eSEric Joyner error = hw->mac.ops.bypass_rw(hw, cmd, &status); 5868eb6488eSEric Joyner if (error) 5878eb6488eSEric Joyner goto unlock_err; 5888eb6488eSEric Joyner 5898eb6488eSEric Joyner ixgbe_bypass_mutex_clear(adapter); 5908eb6488eSEric Joyner 5918eb6488eSEric Joyner base = status & BYPASS_CTL2_DATA_M; 5928eb6488eSEric Joyner head = (status & BYPASS_CTL2_HEAD_M) >> BYPASS_CTL2_HEAD_SHIFT; 5938eb6488eSEric Joyner 5948eb6488eSEric Joyner /* address of the first log */ 5958eb6488eSEric Joyner log_off = base + (head * 5); 5968eb6488eSEric Joyner 5978eb6488eSEric Joyner /* extract all the log entries */ 5988eb6488eSEric Joyner while (count < BYPASS_MAX_LOGS) { 5998eb6488eSEric Joyner eeprom[count].logs = 0; 6008eb6488eSEric Joyner eeprom[count].actions = 0; 6018eb6488eSEric Joyner 6028eb6488eSEric Joyner /* Log 5 bytes store in on u32 and a u8 */ 6038eb6488eSEric Joyner for (i = 0; i < 4; i++) { 6048eb6488eSEric Joyner ixgbe_bypass_mutex_enter(adapter); 6058eb6488eSEric Joyner error = hw->mac.ops.bypass_rd_eep(hw, log_off + i, 6068eb6488eSEric Joyner &data); 6078eb6488eSEric Joyner ixgbe_bypass_mutex_clear(adapter); 6088eb6488eSEric Joyner if (error) 609c19c7afeSEric Joyner return (EINVAL); 6108eb6488eSEric Joyner eeprom[count].logs += data << (8 * i); 6118eb6488eSEric Joyner } 6128eb6488eSEric Joyner 6138eb6488eSEric Joyner ixgbe_bypass_mutex_enter(adapter); 6148eb6488eSEric Joyner error = hw->mac.ops.bypass_rd_eep(hw, 6158eb6488eSEric Joyner log_off + i, &eeprom[count].actions); 6168eb6488eSEric Joyner ixgbe_bypass_mutex_clear(adapter); 6178eb6488eSEric Joyner if (error) 618c19c7afeSEric Joyner return (EINVAL); 6198eb6488eSEric Joyner 6208eb6488eSEric Joyner /* Quit if not a unread log */ 6218eb6488eSEric Joyner if (!(eeprom[count].logs & BYPASS_LOG_CLEAR_M)) 6228eb6488eSEric Joyner break; 6238eb6488eSEric Joyner /* 6248eb6488eSEric Joyner * Log looks good so store the address where it's 6258eb6488eSEric Joyner * Unread Log bit is so we can clear it after safely 6268eb6488eSEric Joyner * pulling out all of the log data. 6278eb6488eSEric Joyner */ 6288eb6488eSEric Joyner eeprom[count].clear_off = log_off; 6298eb6488eSEric Joyner 6308eb6488eSEric Joyner count++; 6318eb6488eSEric Joyner head = head ? head - 1 : BYPASS_MAX_LOGS; 6328eb6488eSEric Joyner log_off = base + (head * 5); 6338eb6488eSEric Joyner } 6348eb6488eSEric Joyner 6358eb6488eSEric Joyner /* reverse order (oldest first) for output */ 6368eb6488eSEric Joyner while (count--) { 6378eb6488eSEric Joyner int year; 6388eb6488eSEric Joyner u32 mon, days, hours, min, sec; 6398eb6488eSEric Joyner u32 time = eeprom[count].logs & BYPASS_LOG_TIME_M; 6408eb6488eSEric Joyner u32 event = (eeprom[count].logs & BYPASS_LOG_EVENT_M) >> 6418eb6488eSEric Joyner BYPASS_LOG_EVENT_SHIFT; 6428eb6488eSEric Joyner u8 action = eeprom[count].actions & BYPASS_LOG_ACTION_M; 6438eb6488eSEric Joyner u16 day_mon[2][13] = { 6448eb6488eSEric Joyner {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365}, 6458eb6488eSEric Joyner {0, 31, 59, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366} 6468eb6488eSEric Joyner }; 6478eb6488eSEric Joyner char *event_str[] = {"unknown", "main on", "aux on", 6488eb6488eSEric Joyner "main off", "aux off", "WDT", "user" }; 6498eb6488eSEric Joyner char *action_str[] = {"ignore", "normal", "bypass", "isolate",}; 6508eb6488eSEric Joyner 6518eb6488eSEric Joyner /* verify vaild data 1 - 6 */ 6528eb6488eSEric Joyner if (event < BYPASS_EVENT_MAIN_ON || event > BYPASS_EVENT_USR) 6538eb6488eSEric Joyner event = 0; 6548eb6488eSEric Joyner 6558eb6488eSEric Joyner /* 6568eb6488eSEric Joyner * time is in sec's this year, so convert to something 6578eb6488eSEric Joyner * printable. 6588eb6488eSEric Joyner */ 6598eb6488eSEric Joyner ixgbe_get_bypass_time(&year, &sec); 6608eb6488eSEric Joyner days = time / SEC_PER_DAY; 6618eb6488eSEric Joyner for (i = 11; days < day_mon[LEAP_YR(year)][i]; i--) 6628eb6488eSEric Joyner continue; 6638eb6488eSEric Joyner mon = i + 1; /* display month as 1-12 */ 6648eb6488eSEric Joyner time -= (day_mon[LEAP_YR(year)][i] * SEC_PER_DAY); 6658eb6488eSEric Joyner days = (time / SEC_PER_DAY) + 1; /* first day is 1 */ 6668eb6488eSEric Joyner time %= SEC_PER_DAY; 6678eb6488eSEric Joyner hours = time / (60 * 60); 6688eb6488eSEric Joyner time %= (60 * 60); 6698eb6488eSEric Joyner min = time / 60; 6708eb6488eSEric Joyner sec = time % 60; 6718eb6488eSEric Joyner device_printf(adapter->dev, 6728eb6488eSEric Joyner "UT %02d/%02d %02d:%02d:%02d %8.8s -> %7.7s\n", 6738eb6488eSEric Joyner mon, days, hours, min, sec, event_str[event], 6748eb6488eSEric Joyner action_str[action]); 6758eb6488eSEric Joyner cmd = BYPASS_PAGE_CTL2 | BYPASS_WE | BYPASS_CTL2_RW; 6768eb6488eSEric Joyner cmd |= ((eeprom[count].clear_off + 3) 6778eb6488eSEric Joyner << BYPASS_CTL2_OFFSET_SHIFT) & BYPASS_CTL2_OFFSET_M; 6788eb6488eSEric Joyner cmd |= ((eeprom[count].logs & ~BYPASS_LOG_CLEAR_M) >> 24); 6798eb6488eSEric Joyner 6808eb6488eSEric Joyner ixgbe_bypass_mutex_enter(adapter); 6818eb6488eSEric Joyner 6828eb6488eSEric Joyner error = hw->mac.ops.bypass_rw(hw, cmd, &status); 6838eb6488eSEric Joyner 6848eb6488eSEric Joyner /* wait for the write to stick */ 6858eb6488eSEric Joyner msec_delay(100); 6868eb6488eSEric Joyner 6878eb6488eSEric Joyner ixgbe_bypass_mutex_clear(adapter); 6888eb6488eSEric Joyner 6898eb6488eSEric Joyner if (error) 690c19c7afeSEric Joyner return (EINVAL); 6918eb6488eSEric Joyner } 6928eb6488eSEric Joyner 6938eb6488eSEric Joyner status = 0; /* reset */ 6948eb6488eSEric Joyner /* Another log command can now run */ 6958eb6488eSEric Joyner while (atomic_cmpset_int(&adapter->bypass.log, 1, 0) == 0) 6968eb6488eSEric Joyner usec_delay(3000); 6978eb6488eSEric Joyner return (error); 6988eb6488eSEric Joyner 6998eb6488eSEric Joyner unlock_err: 7008eb6488eSEric Joyner ixgbe_bypass_mutex_clear(adapter); 7018eb6488eSEric Joyner status = 0; /* reset */ 7028eb6488eSEric Joyner while (atomic_cmpset_int(&adapter->bypass.log, 1, 0) == 0) 7038eb6488eSEric Joyner usec_delay(3000); 704c19c7afeSEric Joyner return (EINVAL); 7058eb6488eSEric Joyner } /* ixgbe_bp_log */ 7068eb6488eSEric Joyner 7078eb6488eSEric Joyner /************************************************************************ 7088eb6488eSEric Joyner * ixgbe_bypass_init - Set up infrastructure for the bypass feature 7098eb6488eSEric Joyner * 7108eb6488eSEric Joyner * Do time and sysctl initialization here. This feature is 7118eb6488eSEric Joyner * only enabled for the first port of a bypass adapter. 7128eb6488eSEric Joyner ************************************************************************/ 7138eb6488eSEric Joyner void 7148eb6488eSEric Joyner ixgbe_bypass_init(struct adapter *adapter) 7158eb6488eSEric Joyner { 7168eb6488eSEric Joyner struct ixgbe_hw *hw = &adapter->hw; 7178eb6488eSEric Joyner device_t dev = adapter->dev; 7188eb6488eSEric Joyner struct sysctl_oid *bp_node; 7198eb6488eSEric Joyner struct sysctl_oid_list *bp_list; 7208eb6488eSEric Joyner u32 mask, value, sec, year; 7218eb6488eSEric Joyner 7228eb6488eSEric Joyner if (!(adapter->feat_cap & IXGBE_FEATURE_BYPASS)) 7238eb6488eSEric Joyner return; 7248eb6488eSEric Joyner 7258eb6488eSEric Joyner /* First set up time for the hardware */ 7268eb6488eSEric Joyner ixgbe_get_bypass_time(&year, &sec); 7278eb6488eSEric Joyner 7288eb6488eSEric Joyner mask = BYPASS_CTL1_TIME_M 7298eb6488eSEric Joyner | BYPASS_CTL1_VALID_M 7308eb6488eSEric Joyner | BYPASS_CTL1_OFFTRST_M; 7318eb6488eSEric Joyner 7328eb6488eSEric Joyner value = (sec & BYPASS_CTL1_TIME_M) 7338eb6488eSEric Joyner | BYPASS_CTL1_VALID 7348eb6488eSEric Joyner | BYPASS_CTL1_OFFTRST; 7358eb6488eSEric Joyner 7368eb6488eSEric Joyner ixgbe_bypass_mutex_enter(adapter); 7378eb6488eSEric Joyner hw->mac.ops.bypass_set(hw, BYPASS_PAGE_CTL1, mask, value); 7388eb6488eSEric Joyner ixgbe_bypass_mutex_clear(adapter); 7398eb6488eSEric Joyner 7408eb6488eSEric Joyner /* Now set up the SYSCTL infrastructure */ 7418eb6488eSEric Joyner 7428eb6488eSEric Joyner /* 7438eb6488eSEric Joyner * The log routine is kept separate from the other 7448eb6488eSEric Joyner * children so a general display command like: 7458eb6488eSEric Joyner * `sysctl dev.ix.0.bypass` will not show the log. 7468eb6488eSEric Joyner */ 7478eb6488eSEric Joyner SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev), 7488eb6488eSEric Joyner SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), 749*20b91f0aSPawel Biernacki OID_AUTO, "bypass_log", 750*20b91f0aSPawel Biernacki CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_NEEDGIANT, 7518eb6488eSEric Joyner adapter, 0, ixgbe_bp_log, "I", "Bypass Log"); 7528eb6488eSEric Joyner 7538eb6488eSEric Joyner /* All other setting are hung from the 'bypass' node */ 7548eb6488eSEric Joyner bp_node = SYSCTL_ADD_NODE(device_get_sysctl_ctx(dev), 7558eb6488eSEric Joyner SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), 756*20b91f0aSPawel Biernacki OID_AUTO, "bypass", CTLFLAG_RD | CTLFLAG_MPSAFE, NULL, "Bypass"); 7578eb6488eSEric Joyner 7588eb6488eSEric Joyner bp_list = SYSCTL_CHILDREN(bp_node); 7598eb6488eSEric Joyner 7608eb6488eSEric Joyner SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev), bp_list, 761*20b91f0aSPawel Biernacki OID_AUTO, "version", CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_NEEDGIANT, 7628eb6488eSEric Joyner adapter, 0, ixgbe_bp_version, "I", "Bypass Version"); 7638eb6488eSEric Joyner 7648eb6488eSEric Joyner SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev), bp_list, 765*20b91f0aSPawel Biernacki OID_AUTO, "state", CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_NEEDGIANT, 7668eb6488eSEric Joyner adapter, 0, ixgbe_bp_set_state, "I", "Bypass State"); 7678eb6488eSEric Joyner 7688eb6488eSEric Joyner SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev), bp_list, 769*20b91f0aSPawel Biernacki OID_AUTO, "timeout", CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_NEEDGIANT, 7708eb6488eSEric Joyner adapter, 0, ixgbe_bp_timeout, "I", "Bypass Timeout"); 7718eb6488eSEric Joyner 7728eb6488eSEric Joyner SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev), bp_list, 773*20b91f0aSPawel Biernacki OID_AUTO, "main_on", CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_NEEDGIANT, 7748eb6488eSEric Joyner adapter, 0, ixgbe_bp_main_on, "I", "Bypass Main On"); 7758eb6488eSEric Joyner 7768eb6488eSEric Joyner SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev), bp_list, 777*20b91f0aSPawel Biernacki OID_AUTO, "main_off", CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_NEEDGIANT, 7788eb6488eSEric Joyner adapter, 0, ixgbe_bp_main_off, "I", "Bypass Main Off"); 7798eb6488eSEric Joyner 7808eb6488eSEric Joyner SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev), bp_list, 781*20b91f0aSPawel Biernacki OID_AUTO, "aux_on", CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_NEEDGIANT, 7828eb6488eSEric Joyner adapter, 0, ixgbe_bp_aux_on, "I", "Bypass Aux On"); 7838eb6488eSEric Joyner 7848eb6488eSEric Joyner SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev), bp_list, 785*20b91f0aSPawel Biernacki OID_AUTO, "aux_off", CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_NEEDGIANT, 7868eb6488eSEric Joyner adapter, 0, ixgbe_bp_aux_off, "I", "Bypass Aux Off"); 7878eb6488eSEric Joyner 7888eb6488eSEric Joyner SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev), bp_list, 789*20b91f0aSPawel Biernacki OID_AUTO, "wd_set", CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_NEEDGIANT, 7908eb6488eSEric Joyner adapter, 0, ixgbe_bp_wd_set, "I", "Set BP Watchdog"); 7918eb6488eSEric Joyner 7928eb6488eSEric Joyner SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev), bp_list, 793*20b91f0aSPawel Biernacki OID_AUTO, "wd_reset", CTLTYPE_INT | CTLFLAG_WR | CTLFLAG_NEEDGIANT, 7948eb6488eSEric Joyner adapter, 0, ixgbe_bp_wd_reset, "S", "Bypass WD Reset"); 7958eb6488eSEric Joyner 7968eb6488eSEric Joyner adapter->feat_en |= IXGBE_FEATURE_BYPASS; 7978eb6488eSEric Joyner } /* ixgbe_bypass_init */ 7988eb6488eSEric Joyner 799