1*c58d34ddSKevin Bowling /*****************************************************************************
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
32*c58d34ddSKevin Bowling *****************************************************************************/
338eb6488eSEric Joyner
348eb6488eSEric Joyner
358eb6488eSEric Joyner #include "ixgbe.h"
368eb6488eSEric Joyner
378eb6488eSEric Joyner /************************************************************************
388eb6488eSEric Joyner * ixgbe_bypass_mutex_enter
398eb6488eSEric Joyner *
408eb6488eSEric Joyner * Mutex support for the bypass feature. Using a dual lock
418eb6488eSEric Joyner * to facilitate a privileged access to the watchdog update
428eb6488eSEric Joyner * over other threads.
438eb6488eSEric Joyner ************************************************************************/
448eb6488eSEric Joyner static void
ixgbe_bypass_mutex_enter(struct ixgbe_softc * sc)45b1d5caf3SKevin Bowling ixgbe_bypass_mutex_enter(struct ixgbe_softc *sc)
468eb6488eSEric Joyner {
47b1d5caf3SKevin Bowling while (atomic_cmpset_int(&sc->bypass.low, 0, 1) == 0)
488eb6488eSEric Joyner usec_delay(3000);
49b1d5caf3SKevin Bowling while (atomic_cmpset_int(&sc->bypass.high, 0, 1) == 0)
508eb6488eSEric Joyner usec_delay(3000);
518eb6488eSEric Joyner return;
528eb6488eSEric Joyner } /* ixgbe_bypass_mutex_enter */
538eb6488eSEric Joyner
548eb6488eSEric Joyner /************************************************************************
558eb6488eSEric Joyner * ixgbe_bypass_mutex_clear
568eb6488eSEric Joyner ************************************************************************/
578eb6488eSEric Joyner static void
ixgbe_bypass_mutex_clear(struct ixgbe_softc * sc)58b1d5caf3SKevin Bowling ixgbe_bypass_mutex_clear(struct ixgbe_softc *sc)
598eb6488eSEric Joyner {
60b1d5caf3SKevin Bowling while (atomic_cmpset_int(&sc->bypass.high, 1, 0) == 0)
618eb6488eSEric Joyner usec_delay(6000);
62b1d5caf3SKevin Bowling while (atomic_cmpset_int(&sc->bypass.low, 1, 0) == 0)
638eb6488eSEric Joyner usec_delay(6000);
648eb6488eSEric Joyner return;
658eb6488eSEric Joyner } /* ixgbe_bypass_mutex_clear */
668eb6488eSEric Joyner
678eb6488eSEric Joyner /************************************************************************
688eb6488eSEric Joyner * ixgbe_bypass_wd_mutex_enter
698eb6488eSEric Joyner *
708eb6488eSEric Joyner * Watchdog entry is allowed to simply grab the high priority
718eb6488eSEric Joyner ************************************************************************/
728eb6488eSEric Joyner static void
ixgbe_bypass_wd_mutex_enter(struct ixgbe_softc * sc)73b1d5caf3SKevin Bowling ixgbe_bypass_wd_mutex_enter(struct ixgbe_softc *sc)
748eb6488eSEric Joyner {
75b1d5caf3SKevin Bowling while (atomic_cmpset_int(&sc->bypass.high, 0, 1) == 0)
768eb6488eSEric Joyner usec_delay(3000);
778eb6488eSEric Joyner return;
788eb6488eSEric Joyner } /* ixgbe_bypass_wd_mutex_enter */
798eb6488eSEric Joyner
808eb6488eSEric Joyner /************************************************************************
818eb6488eSEric Joyner * ixgbe_bypass_wd_mutex_clear
828eb6488eSEric Joyner ************************************************************************/
838eb6488eSEric Joyner static void
ixgbe_bypass_wd_mutex_clear(struct ixgbe_softc * sc)84b1d5caf3SKevin Bowling ixgbe_bypass_wd_mutex_clear(struct ixgbe_softc *sc)
858eb6488eSEric Joyner {
86b1d5caf3SKevin Bowling while (atomic_cmpset_int(&sc->bypass.high, 1, 0) == 0)
878eb6488eSEric Joyner usec_delay(6000);
888eb6488eSEric Joyner return;
898eb6488eSEric Joyner } /* ixgbe_bypass_wd_mutex_clear */
908eb6488eSEric Joyner
918eb6488eSEric Joyner /************************************************************************
928eb6488eSEric Joyner * ixgbe_get_bypass_time
938eb6488eSEric Joyner ************************************************************************/
948eb6488eSEric Joyner static void
ixgbe_get_bypass_time(u32 * year,u32 * sec)958eb6488eSEric Joyner ixgbe_get_bypass_time(u32 *year, u32 *sec)
968eb6488eSEric Joyner {
978eb6488eSEric Joyner struct timespec current;
988eb6488eSEric Joyner
998eb6488eSEric Joyner *year = 1970; /* time starts at 01/01/1970 */
1008eb6488eSEric Joyner nanotime(¤t);
1018eb6488eSEric Joyner *sec = current.tv_sec;
1028eb6488eSEric Joyner
1038eb6488eSEric Joyner while(*sec > SEC_THIS_YEAR(*year)) {
1048eb6488eSEric Joyner *sec -= SEC_THIS_YEAR(*year);
1058eb6488eSEric Joyner (*year)++;
1068eb6488eSEric Joyner }
1078eb6488eSEric Joyner } /* ixgbe_get_bypass_time */
1088eb6488eSEric Joyner
1098eb6488eSEric Joyner /************************************************************************
1108eb6488eSEric Joyner * ixgbe_bp_version
1118eb6488eSEric Joyner *
1128eb6488eSEric Joyner * Display the feature version
1138eb6488eSEric Joyner ************************************************************************/
1148eb6488eSEric Joyner static int
ixgbe_bp_version(SYSCTL_HANDLER_ARGS)1158eb6488eSEric Joyner ixgbe_bp_version(SYSCTL_HANDLER_ARGS)
1168eb6488eSEric Joyner {
117b1d5caf3SKevin Bowling struct ixgbe_softc *sc = (struct ixgbe_softc *) arg1;
118b1d5caf3SKevin Bowling struct ixgbe_hw *hw = &sc->hw;
1198eb6488eSEric Joyner int error = 0;
1208eb6488eSEric Joyner static int version = 0;
1218eb6488eSEric Joyner u32 cmd;
1228eb6488eSEric Joyner
123b1d5caf3SKevin Bowling ixgbe_bypass_mutex_enter(sc);
1248eb6488eSEric Joyner cmd = BYPASS_PAGE_CTL2 | BYPASS_WE;
1258eb6488eSEric Joyner cmd |= (BYPASS_EEPROM_VER_ADD << BYPASS_CTL2_OFFSET_SHIFT) &
1268eb6488eSEric Joyner BYPASS_CTL2_OFFSET_M;
1278eb6488eSEric Joyner if ((error = hw->mac.ops.bypass_rw(hw, cmd, &version) != 0))
1288eb6488eSEric Joyner goto err;
1298eb6488eSEric Joyner msec_delay(100);
1308eb6488eSEric Joyner cmd &= ~BYPASS_WE;
1318eb6488eSEric Joyner if ((error = hw->mac.ops.bypass_rw(hw, cmd, &version) != 0))
1328eb6488eSEric Joyner goto err;
133b1d5caf3SKevin Bowling ixgbe_bypass_mutex_clear(sc);
1348eb6488eSEric Joyner version &= BYPASS_CTL2_DATA_M;
1358eb6488eSEric Joyner error = sysctl_handle_int(oidp, &version, 0, req);
1368eb6488eSEric Joyner return (error);
1378eb6488eSEric Joyner err:
138b1d5caf3SKevin Bowling ixgbe_bypass_mutex_clear(sc);
1398eb6488eSEric Joyner return (error);
1408eb6488eSEric Joyner
1418eb6488eSEric Joyner } /* ixgbe_bp_version */
1428eb6488eSEric Joyner
1438eb6488eSEric Joyner /************************************************************************
1448eb6488eSEric Joyner * ixgbe_bp_set_state
1458eb6488eSEric Joyner *
1468eb6488eSEric Joyner * Show/Set the Bypass State:
1478eb6488eSEric Joyner * 1 = NORMAL
1488eb6488eSEric Joyner * 2 = BYPASS
1498eb6488eSEric Joyner * 3 = ISOLATE
1508eb6488eSEric Joyner *
1518eb6488eSEric Joyner * With no argument the state is displayed,
1528eb6488eSEric Joyner * passing a value will set it.
1538eb6488eSEric Joyner ************************************************************************/
1548eb6488eSEric Joyner static int
ixgbe_bp_set_state(SYSCTL_HANDLER_ARGS)1558eb6488eSEric Joyner ixgbe_bp_set_state(SYSCTL_HANDLER_ARGS)
1568eb6488eSEric Joyner {
157b1d5caf3SKevin Bowling struct ixgbe_softc *sc = (struct ixgbe_softc *) arg1;
158b1d5caf3SKevin Bowling struct ixgbe_hw *hw = &sc->hw;
1598eb6488eSEric Joyner int error = 0;
1608eb6488eSEric Joyner static int state = 0;
1618eb6488eSEric Joyner
1628eb6488eSEric Joyner /* Get the current state */
163b1d5caf3SKevin Bowling ixgbe_bypass_mutex_enter(sc);
164*c58d34ddSKevin Bowling error = hw->mac.ops.bypass_rw(hw, BYPASS_PAGE_CTL0, &state);
165b1d5caf3SKevin Bowling ixgbe_bypass_mutex_clear(sc);
166c19c7afeSEric Joyner if (error != 0)
1678eb6488eSEric Joyner return (error);
1688eb6488eSEric Joyner state = (state >> BYPASS_STATUS_OFF_SHIFT) & 0x3;
1698eb6488eSEric Joyner
1708eb6488eSEric Joyner error = sysctl_handle_int(oidp, &state, 0, req);
171c19c7afeSEric Joyner if ((error != 0) || (req->newptr == NULL))
1728eb6488eSEric Joyner return (error);
1738eb6488eSEric Joyner
1748eb6488eSEric Joyner /* Sanity check new state */
1758eb6488eSEric Joyner switch (state) {
1768eb6488eSEric Joyner case BYPASS_NORM:
1778eb6488eSEric Joyner case BYPASS_BYPASS:
1788eb6488eSEric Joyner case BYPASS_ISOLATE:
1798eb6488eSEric Joyner break;
1808eb6488eSEric Joyner default:
1818eb6488eSEric Joyner return (EINVAL);
1828eb6488eSEric Joyner }
183b1d5caf3SKevin Bowling ixgbe_bypass_mutex_enter(sc);
1848eb6488eSEric Joyner if ((error = hw->mac.ops.bypass_set(hw, BYPASS_PAGE_CTL0,
1858eb6488eSEric Joyner BYPASS_MODE_OFF_M, state) != 0))
1868eb6488eSEric Joyner goto out;
1878eb6488eSEric Joyner /* Set AUTO back on so FW can receive events */
1888eb6488eSEric Joyner error = hw->mac.ops.bypass_set(hw, BYPASS_PAGE_CTL0,
1898eb6488eSEric Joyner BYPASS_MODE_OFF_M, BYPASS_AUTO);
1908eb6488eSEric Joyner out:
191b1d5caf3SKevin Bowling ixgbe_bypass_mutex_clear(sc);
1928eb6488eSEric Joyner usec_delay(6000);
1938eb6488eSEric Joyner return (error);
1948eb6488eSEric Joyner } /* ixgbe_bp_set_state */
1958eb6488eSEric Joyner
1968eb6488eSEric Joyner /************************************************************************
1978eb6488eSEric Joyner * The following routines control the operational
1988eb6488eSEric Joyner * "rules" of the feature, what behavior will occur
1998eb6488eSEric Joyner * when particular events occur.
2008eb6488eSEric Joyner * Values are:
2018eb6488eSEric Joyner * 0 - no change for the event (NOP)
2028eb6488eSEric Joyner * 1 - go to Normal operation
2038eb6488eSEric Joyner * 2 - go to Bypass operation
2048eb6488eSEric Joyner * 3 - go to Isolate operation
2058eb6488eSEric Joyner * Calling the entry with no argument just displays
2068eb6488eSEric Joyner * the current rule setting.
2078eb6488eSEric Joyner ************************************************************************/
2088eb6488eSEric Joyner
2098eb6488eSEric Joyner /************************************************************************
2108eb6488eSEric Joyner * ixgbe_bp_timeout
2118eb6488eSEric Joyner *
2128eb6488eSEric Joyner * This is to set the Rule for the watchdog,
2138eb6488eSEric Joyner * not the actual watchdog timeout value.
2148eb6488eSEric Joyner ************************************************************************/
2158eb6488eSEric Joyner static int
ixgbe_bp_timeout(SYSCTL_HANDLER_ARGS)2168eb6488eSEric Joyner ixgbe_bp_timeout(SYSCTL_HANDLER_ARGS)
2178eb6488eSEric Joyner {
218b1d5caf3SKevin Bowling struct ixgbe_softc *sc = (struct ixgbe_softc *) arg1;
219b1d5caf3SKevin Bowling struct ixgbe_hw *hw = &sc->hw;
2208eb6488eSEric Joyner int error = 0;
2218eb6488eSEric Joyner static int timeout = 0;
2228eb6488eSEric Joyner
2238eb6488eSEric Joyner /* Get the current value */
224b1d5caf3SKevin Bowling ixgbe_bypass_mutex_enter(sc);
2258eb6488eSEric Joyner error = hw->mac.ops.bypass_rw(hw, BYPASS_PAGE_CTL0, &timeout);
226b1d5caf3SKevin Bowling ixgbe_bypass_mutex_clear(sc);
2278eb6488eSEric Joyner if (error)
2288eb6488eSEric Joyner return (error);
2298eb6488eSEric Joyner timeout = (timeout >> BYPASS_WDTIMEOUT_SHIFT) & 0x3;
2308eb6488eSEric Joyner
2318eb6488eSEric Joyner error = sysctl_handle_int(oidp, &timeout, 0, req);
2328eb6488eSEric Joyner if ((error) || (req->newptr == NULL))
2338eb6488eSEric Joyner return (error);
2348eb6488eSEric Joyner
2358eb6488eSEric Joyner /* Sanity check on the setting */
2368eb6488eSEric Joyner switch (timeout) {
2378eb6488eSEric Joyner case BYPASS_NOP:
2388eb6488eSEric Joyner case BYPASS_NORM:
2398eb6488eSEric Joyner case BYPASS_BYPASS:
2408eb6488eSEric Joyner case BYPASS_ISOLATE:
2418eb6488eSEric Joyner break;
2428eb6488eSEric Joyner default:
2438eb6488eSEric Joyner return (EINVAL);
2448eb6488eSEric Joyner }
2458eb6488eSEric Joyner
2468eb6488eSEric Joyner /* Set the new state */
247b1d5caf3SKevin Bowling ixgbe_bypass_mutex_enter(sc);
2488eb6488eSEric Joyner error = hw->mac.ops.bypass_set(hw, BYPASS_PAGE_CTL0,
2498eb6488eSEric Joyner BYPASS_WDTIMEOUT_M, timeout << BYPASS_WDTIMEOUT_SHIFT);
250b1d5caf3SKevin Bowling ixgbe_bypass_mutex_clear(sc);
2518eb6488eSEric Joyner usec_delay(6000);
2528eb6488eSEric Joyner return (error);
2538eb6488eSEric Joyner } /* ixgbe_bp_timeout */
2548eb6488eSEric Joyner
2558eb6488eSEric Joyner /************************************************************************
2568eb6488eSEric Joyner * ixgbe_bp_main_on
2578eb6488eSEric Joyner ************************************************************************/
2588eb6488eSEric Joyner static int
ixgbe_bp_main_on(SYSCTL_HANDLER_ARGS)2598eb6488eSEric Joyner ixgbe_bp_main_on(SYSCTL_HANDLER_ARGS)
2608eb6488eSEric Joyner {
261b1d5caf3SKevin Bowling struct ixgbe_softc *sc = (struct ixgbe_softc *) arg1;
262b1d5caf3SKevin Bowling struct ixgbe_hw *hw = &sc->hw;
2638eb6488eSEric Joyner int error = 0;
2648eb6488eSEric Joyner static int main_on = 0;
2658eb6488eSEric Joyner
266b1d5caf3SKevin Bowling ixgbe_bypass_mutex_enter(sc);
2678eb6488eSEric Joyner error = hw->mac.ops.bypass_rw(hw, BYPASS_PAGE_CTL0, &main_on);
2688eb6488eSEric Joyner main_on = (main_on >> BYPASS_MAIN_ON_SHIFT) & 0x3;
269b1d5caf3SKevin Bowling ixgbe_bypass_mutex_clear(sc);
2708eb6488eSEric Joyner if (error)
2718eb6488eSEric Joyner return (error);
2728eb6488eSEric Joyner
2738eb6488eSEric Joyner error = sysctl_handle_int(oidp, &main_on, 0, req);
2748eb6488eSEric Joyner if ((error) || (req->newptr == NULL))
2758eb6488eSEric Joyner return (error);
2768eb6488eSEric Joyner
2778eb6488eSEric Joyner /* Sanity check on the setting */
2788eb6488eSEric Joyner switch (main_on) {
2798eb6488eSEric Joyner case BYPASS_NOP:
2808eb6488eSEric Joyner case BYPASS_NORM:
2818eb6488eSEric Joyner case BYPASS_BYPASS:
2828eb6488eSEric Joyner case BYPASS_ISOLATE:
2838eb6488eSEric Joyner break;
2848eb6488eSEric Joyner default:
2858eb6488eSEric Joyner return (EINVAL);
2868eb6488eSEric Joyner }
2878eb6488eSEric Joyner
2888eb6488eSEric Joyner /* Set the new state */
289b1d5caf3SKevin Bowling ixgbe_bypass_mutex_enter(sc);
2908eb6488eSEric Joyner error = hw->mac.ops.bypass_set(hw, BYPASS_PAGE_CTL0,
2918eb6488eSEric Joyner BYPASS_MAIN_ON_M, main_on << BYPASS_MAIN_ON_SHIFT);
292b1d5caf3SKevin Bowling ixgbe_bypass_mutex_clear(sc);
2938eb6488eSEric Joyner usec_delay(6000);
2948eb6488eSEric Joyner return (error);
2958eb6488eSEric Joyner } /* ixgbe_bp_main_on */
2968eb6488eSEric Joyner
2978eb6488eSEric Joyner /************************************************************************
2988eb6488eSEric Joyner * ixgbe_bp_main_off
2998eb6488eSEric Joyner ************************************************************************/
3008eb6488eSEric Joyner static int
ixgbe_bp_main_off(SYSCTL_HANDLER_ARGS)3018eb6488eSEric Joyner ixgbe_bp_main_off(SYSCTL_HANDLER_ARGS)
3028eb6488eSEric Joyner {
303b1d5caf3SKevin Bowling struct ixgbe_softc *sc = (struct ixgbe_softc *) arg1;
304b1d5caf3SKevin Bowling struct ixgbe_hw *hw = &sc->hw;
3058eb6488eSEric Joyner int error = 0;
3068eb6488eSEric Joyner static int main_off = 0;
3078eb6488eSEric Joyner
308b1d5caf3SKevin Bowling ixgbe_bypass_mutex_enter(sc);
3098eb6488eSEric Joyner error = hw->mac.ops.bypass_rw(hw, BYPASS_PAGE_CTL0, &main_off);
310b1d5caf3SKevin Bowling ixgbe_bypass_mutex_clear(sc);
3118eb6488eSEric Joyner if (error)
3128eb6488eSEric Joyner return (error);
3138eb6488eSEric Joyner main_off = (main_off >> BYPASS_MAIN_OFF_SHIFT) & 0x3;
3148eb6488eSEric Joyner
3158eb6488eSEric Joyner error = sysctl_handle_int(oidp, &main_off, 0, req);
3168eb6488eSEric Joyner if ((error) || (req->newptr == NULL))
3178eb6488eSEric Joyner return (error);
3188eb6488eSEric Joyner
3198eb6488eSEric Joyner /* Sanity check on the setting */
3208eb6488eSEric Joyner switch (main_off) {
3218eb6488eSEric Joyner case BYPASS_NOP:
3228eb6488eSEric Joyner case BYPASS_NORM:
3238eb6488eSEric Joyner case BYPASS_BYPASS:
3248eb6488eSEric Joyner case BYPASS_ISOLATE:
3258eb6488eSEric Joyner break;
3268eb6488eSEric Joyner default:
3278eb6488eSEric Joyner return (EINVAL);
3288eb6488eSEric Joyner }
3298eb6488eSEric Joyner
3308eb6488eSEric Joyner /* Set the new state */
331b1d5caf3SKevin Bowling ixgbe_bypass_mutex_enter(sc);
3328eb6488eSEric Joyner error = hw->mac.ops.bypass_set(hw, BYPASS_PAGE_CTL0,
3338eb6488eSEric Joyner BYPASS_MAIN_OFF_M, main_off << BYPASS_MAIN_OFF_SHIFT);
334b1d5caf3SKevin Bowling ixgbe_bypass_mutex_clear(sc);
3358eb6488eSEric Joyner usec_delay(6000);
3368eb6488eSEric Joyner return (error);
3378eb6488eSEric Joyner } /* ixgbe_bp_main_off */
3388eb6488eSEric Joyner
3398eb6488eSEric Joyner /************************************************************************
3408eb6488eSEric Joyner * ixgbe_bp_aux_on
3418eb6488eSEric Joyner ************************************************************************/
3428eb6488eSEric Joyner static int
ixgbe_bp_aux_on(SYSCTL_HANDLER_ARGS)3438eb6488eSEric Joyner ixgbe_bp_aux_on(SYSCTL_HANDLER_ARGS)
3448eb6488eSEric Joyner {
345b1d5caf3SKevin Bowling struct ixgbe_softc *sc = (struct ixgbe_softc *) arg1;
346b1d5caf3SKevin Bowling struct ixgbe_hw *hw = &sc->hw;
3478eb6488eSEric Joyner int error = 0;
3488eb6488eSEric Joyner static int aux_on = 0;
3498eb6488eSEric Joyner
350b1d5caf3SKevin Bowling ixgbe_bypass_mutex_enter(sc);
3518eb6488eSEric Joyner error = hw->mac.ops.bypass_rw(hw, BYPASS_PAGE_CTL0, &aux_on);
352b1d5caf3SKevin Bowling ixgbe_bypass_mutex_clear(sc);
3538eb6488eSEric Joyner if (error)
3548eb6488eSEric Joyner return (error);
3558eb6488eSEric Joyner aux_on = (aux_on >> BYPASS_AUX_ON_SHIFT) & 0x3;
3568eb6488eSEric Joyner
3578eb6488eSEric Joyner error = sysctl_handle_int(oidp, &aux_on, 0, req);
3588eb6488eSEric Joyner if ((error) || (req->newptr == NULL))
3598eb6488eSEric Joyner return (error);
3608eb6488eSEric Joyner
3618eb6488eSEric Joyner /* Sanity check on the setting */
3628eb6488eSEric Joyner switch (aux_on) {
3638eb6488eSEric Joyner case BYPASS_NOP:
3648eb6488eSEric Joyner case BYPASS_NORM:
3658eb6488eSEric Joyner case BYPASS_BYPASS:
3668eb6488eSEric Joyner case BYPASS_ISOLATE:
3678eb6488eSEric Joyner break;
3688eb6488eSEric Joyner default:
3698eb6488eSEric Joyner return (EINVAL);
3708eb6488eSEric Joyner }
3718eb6488eSEric Joyner
3728eb6488eSEric Joyner /* Set the new state */
373b1d5caf3SKevin Bowling ixgbe_bypass_mutex_enter(sc);
3748eb6488eSEric Joyner error = hw->mac.ops.bypass_set(hw, BYPASS_PAGE_CTL0,
3758eb6488eSEric Joyner BYPASS_AUX_ON_M, aux_on << BYPASS_AUX_ON_SHIFT);
376b1d5caf3SKevin Bowling ixgbe_bypass_mutex_clear(sc);
3778eb6488eSEric Joyner usec_delay(6000);
3788eb6488eSEric Joyner return (error);
3798eb6488eSEric Joyner } /* ixgbe_bp_aux_on */
3808eb6488eSEric Joyner
3818eb6488eSEric Joyner /************************************************************************
3828eb6488eSEric Joyner * ixgbe_bp_aux_off
3838eb6488eSEric Joyner ************************************************************************/
3848eb6488eSEric Joyner static int
ixgbe_bp_aux_off(SYSCTL_HANDLER_ARGS)3858eb6488eSEric Joyner ixgbe_bp_aux_off(SYSCTL_HANDLER_ARGS)
3868eb6488eSEric Joyner {
387b1d5caf3SKevin Bowling struct ixgbe_softc *sc = (struct ixgbe_softc *) arg1;
388b1d5caf3SKevin Bowling struct ixgbe_hw *hw = &sc->hw;
3898eb6488eSEric Joyner int error = 0;
3908eb6488eSEric Joyner static int aux_off = 0;
3918eb6488eSEric Joyner
392b1d5caf3SKevin Bowling ixgbe_bypass_mutex_enter(sc);
3938eb6488eSEric Joyner error = hw->mac.ops.bypass_rw(hw, BYPASS_PAGE_CTL0, &aux_off);
394b1d5caf3SKevin Bowling ixgbe_bypass_mutex_clear(sc);
3958eb6488eSEric Joyner if (error)
3968eb6488eSEric Joyner return (error);
3978eb6488eSEric Joyner aux_off = (aux_off >> BYPASS_AUX_OFF_SHIFT) & 0x3;
3988eb6488eSEric Joyner
3998eb6488eSEric Joyner error = sysctl_handle_int(oidp, &aux_off, 0, req);
4008eb6488eSEric Joyner if ((error) || (req->newptr == NULL))
4018eb6488eSEric Joyner return (error);
4028eb6488eSEric Joyner
4038eb6488eSEric Joyner /* Sanity check on the setting */
4048eb6488eSEric Joyner switch (aux_off) {
4058eb6488eSEric Joyner case BYPASS_NOP:
4068eb6488eSEric Joyner case BYPASS_NORM:
4078eb6488eSEric Joyner case BYPASS_BYPASS:
4088eb6488eSEric Joyner case BYPASS_ISOLATE:
4098eb6488eSEric Joyner break;
4108eb6488eSEric Joyner default:
4118eb6488eSEric Joyner return (EINVAL);
4128eb6488eSEric Joyner }
4138eb6488eSEric Joyner
4148eb6488eSEric Joyner /* Set the new state */
415b1d5caf3SKevin Bowling ixgbe_bypass_mutex_enter(sc);
4168eb6488eSEric Joyner error = hw->mac.ops.bypass_set(hw, BYPASS_PAGE_CTL0,
4178eb6488eSEric Joyner BYPASS_AUX_OFF_M, aux_off << BYPASS_AUX_OFF_SHIFT);
418b1d5caf3SKevin Bowling ixgbe_bypass_mutex_clear(sc);
4198eb6488eSEric Joyner usec_delay(6000);
4208eb6488eSEric Joyner return (error);
4218eb6488eSEric Joyner } /* ixgbe_bp_aux_off */
4228eb6488eSEric Joyner
4238eb6488eSEric Joyner /************************************************************************
4248eb6488eSEric Joyner * ixgbe_bp_wd_set - Set the Watchdog timer value
4258eb6488eSEric Joyner *
4268eb6488eSEric Joyner * Valid settings are:
4278eb6488eSEric Joyner * - 0 will disable the watchdog
4288eb6488eSEric Joyner * - 1, 2, 3, 4, 8, 16, 32
4298eb6488eSEric Joyner * - anything else is invalid and will be ignored
4308eb6488eSEric Joyner ************************************************************************/
4318eb6488eSEric Joyner static int
ixgbe_bp_wd_set(SYSCTL_HANDLER_ARGS)4328eb6488eSEric Joyner ixgbe_bp_wd_set(SYSCTL_HANDLER_ARGS)
4338eb6488eSEric Joyner {
434b1d5caf3SKevin Bowling struct ixgbe_softc *sc = (struct ixgbe_softc *) arg1;
435b1d5caf3SKevin Bowling struct ixgbe_hw *hw = &sc->hw;
4368eb6488eSEric Joyner int error, tmp;
4378eb6488eSEric Joyner static int timeout = 0;
438c19c7afeSEric Joyner u32 mask, arg;
4398eb6488eSEric Joyner
4408eb6488eSEric Joyner /* Get the current hardware value */
441b1d5caf3SKevin Bowling ixgbe_bypass_mutex_enter(sc);
4428eb6488eSEric Joyner error = hw->mac.ops.bypass_rw(hw, BYPASS_PAGE_CTL0, &tmp);
443b1d5caf3SKevin Bowling ixgbe_bypass_mutex_clear(sc);
4448eb6488eSEric Joyner if (error)
4458eb6488eSEric Joyner return (error);
4468eb6488eSEric Joyner /*
4478eb6488eSEric Joyner * If armed keep the displayed value,
4488eb6488eSEric Joyner * else change the display to zero.
4498eb6488eSEric Joyner */
4508eb6488eSEric Joyner if ((tmp & (0x1 << BYPASS_WDT_ENABLE_SHIFT)) == 0)
4518eb6488eSEric Joyner timeout = 0;
4528eb6488eSEric Joyner
4538eb6488eSEric Joyner error = sysctl_handle_int(oidp, &timeout, 0, req);
4548eb6488eSEric Joyner if ((error) || (req->newptr == NULL))
4558eb6488eSEric Joyner return (error);
4568eb6488eSEric Joyner
457c19c7afeSEric Joyner arg = 0x1 << BYPASS_WDT_ENABLE_SHIFT;
458c19c7afeSEric Joyner mask = BYPASS_WDT_ENABLE_M | BYPASS_WDT_VALUE_M;
4598eb6488eSEric Joyner switch (timeout) {
4608eb6488eSEric Joyner case 0: /* disables the timer */
461c19c7afeSEric Joyner arg = BYPASS_PAGE_CTL0;
462c19c7afeSEric Joyner mask = BYPASS_WDT_ENABLE_M;
4638eb6488eSEric Joyner break;
4648eb6488eSEric Joyner case 1:
465c19c7afeSEric Joyner arg |= BYPASS_WDT_1_5 << BYPASS_WDT_TIME_SHIFT;
4668eb6488eSEric Joyner break;
4678eb6488eSEric Joyner case 2:
468c19c7afeSEric Joyner arg |= BYPASS_WDT_2 << BYPASS_WDT_TIME_SHIFT;
4698eb6488eSEric Joyner break;
4708eb6488eSEric Joyner case 3:
471c19c7afeSEric Joyner arg |= BYPASS_WDT_3 << BYPASS_WDT_TIME_SHIFT;
4728eb6488eSEric Joyner break;
4738eb6488eSEric Joyner case 4:
474c19c7afeSEric Joyner arg |= BYPASS_WDT_4 << BYPASS_WDT_TIME_SHIFT;
4758eb6488eSEric Joyner break;
4768eb6488eSEric Joyner case 8:
477c19c7afeSEric Joyner arg |= BYPASS_WDT_8 << BYPASS_WDT_TIME_SHIFT;
4788eb6488eSEric Joyner break;
4798eb6488eSEric Joyner case 16:
480c19c7afeSEric Joyner arg |= BYPASS_WDT_16 << BYPASS_WDT_TIME_SHIFT;
4818eb6488eSEric Joyner break;
4828eb6488eSEric Joyner case 32:
483c19c7afeSEric Joyner arg |= BYPASS_WDT_32 << BYPASS_WDT_TIME_SHIFT;
4848eb6488eSEric Joyner break;
4858eb6488eSEric Joyner default:
4868eb6488eSEric Joyner return (EINVAL);
4878eb6488eSEric Joyner }
488c19c7afeSEric Joyner
4898eb6488eSEric Joyner /* Set the new watchdog */
490b1d5caf3SKevin Bowling ixgbe_bypass_mutex_enter(sc);
4918eb6488eSEric Joyner error = hw->mac.ops.bypass_set(hw, BYPASS_PAGE_CTL0, mask, arg);
492b1d5caf3SKevin Bowling ixgbe_bypass_mutex_clear(sc);
4938eb6488eSEric Joyner
4948eb6488eSEric Joyner return (error);
4958eb6488eSEric Joyner } /* ixgbe_bp_wd_set */
4968eb6488eSEric Joyner
4978eb6488eSEric Joyner /************************************************************************
4988eb6488eSEric Joyner * ixgbe_bp_wd_reset - Reset the Watchdog timer
4998eb6488eSEric Joyner *
5008eb6488eSEric Joyner * To activate this it must be called with any argument.
5018eb6488eSEric Joyner ************************************************************************/
5028eb6488eSEric Joyner static int
ixgbe_bp_wd_reset(SYSCTL_HANDLER_ARGS)5038eb6488eSEric Joyner ixgbe_bp_wd_reset(SYSCTL_HANDLER_ARGS)
5048eb6488eSEric Joyner {
505b1d5caf3SKevin Bowling struct ixgbe_softc *sc = (struct ixgbe_softc *) arg1;
506b1d5caf3SKevin Bowling struct ixgbe_hw *hw = &sc->hw;
5078eb6488eSEric Joyner u32 sec, year;
5088eb6488eSEric Joyner int cmd, count = 0, error = 0;
5098eb6488eSEric Joyner int reset_wd = 0;
5108eb6488eSEric Joyner
5118eb6488eSEric Joyner error = sysctl_handle_int(oidp, &reset_wd, 0, req);
5128eb6488eSEric Joyner if ((error) || (req->newptr == NULL))
5138eb6488eSEric Joyner return (error);
5148eb6488eSEric Joyner
5158eb6488eSEric Joyner cmd = BYPASS_PAGE_CTL1 | BYPASS_WE | BYPASS_CTL1_WDT_PET;
5168eb6488eSEric Joyner
5178eb6488eSEric Joyner /* Resync the FW time while writing to CTL1 anyway */
5188eb6488eSEric Joyner ixgbe_get_bypass_time(&year, &sec);
5198eb6488eSEric Joyner
5208eb6488eSEric Joyner cmd |= (sec & BYPASS_CTL1_TIME_M) | BYPASS_CTL1_VALID;
5218eb6488eSEric Joyner cmd |= BYPASS_CTL1_OFFTRST;
5228eb6488eSEric Joyner
523b1d5caf3SKevin Bowling ixgbe_bypass_wd_mutex_enter(sc);
5248eb6488eSEric Joyner error = hw->mac.ops.bypass_rw(hw, cmd, &reset_wd);
5258eb6488eSEric Joyner
5268eb6488eSEric Joyner /* Read until it matches what we wrote, or we time out */
5278eb6488eSEric Joyner do {
5288eb6488eSEric Joyner if (count++ > 10) {
5298eb6488eSEric Joyner error = IXGBE_BYPASS_FW_WRITE_FAILURE;
5308eb6488eSEric Joyner break;
5318eb6488eSEric Joyner }
532c41a0eeeSKevin Bowling if (hw->mac.ops.bypass_rw(hw, BYPASS_PAGE_CTL1, &reset_wd)) {
5338eb6488eSEric Joyner error = IXGBE_ERR_INVALID_ARGUMENT;
5348eb6488eSEric Joyner break;
5358eb6488eSEric Joyner }
5368eb6488eSEric Joyner } while (!hw->mac.ops.bypass_valid_rd(cmd, reset_wd));
5378eb6488eSEric Joyner
5388eb6488eSEric Joyner reset_wd = 0;
539b1d5caf3SKevin Bowling ixgbe_bypass_wd_mutex_clear(sc);
5408eb6488eSEric Joyner return (error);
5418eb6488eSEric Joyner } /* ixgbe_bp_wd_reset */
5428eb6488eSEric Joyner
5438eb6488eSEric Joyner /************************************************************************
5448eb6488eSEric Joyner * ixgbe_bp_log - Display the bypass log
5458eb6488eSEric Joyner *
5468eb6488eSEric Joyner * You must pass a non-zero arg to sysctl
5478eb6488eSEric Joyner ************************************************************************/
5488eb6488eSEric Joyner static int
ixgbe_bp_log(SYSCTL_HANDLER_ARGS)5498eb6488eSEric Joyner ixgbe_bp_log(SYSCTL_HANDLER_ARGS)
5508eb6488eSEric Joyner {
551b1d5caf3SKevin Bowling struct ixgbe_softc *sc = (struct ixgbe_softc *) arg1;
552b1d5caf3SKevin Bowling struct ixgbe_hw *hw = &sc->hw;
5538eb6488eSEric Joyner u32 cmd, base, head;
5548eb6488eSEric Joyner u32 log_off, count = 0;
5558eb6488eSEric Joyner static int status = 0;
5568eb6488eSEric Joyner u8 data;
5578eb6488eSEric Joyner struct ixgbe_bypass_eeprom eeprom[BYPASS_MAX_LOGS];
5588eb6488eSEric Joyner int i, error = 0;
5598eb6488eSEric Joyner
5608eb6488eSEric Joyner error = sysctl_handle_int(oidp, &status, 0, req);
5618eb6488eSEric Joyner if ((error) || (req->newptr == NULL))
5628eb6488eSEric Joyner return (error);
5638eb6488eSEric Joyner
5648eb6488eSEric Joyner /* Keep the log display single-threaded */
565b1d5caf3SKevin Bowling while (atomic_cmpset_int(&sc->bypass.log, 0, 1) == 0)
5668eb6488eSEric Joyner usec_delay(3000);
5678eb6488eSEric Joyner
568b1d5caf3SKevin Bowling ixgbe_bypass_mutex_enter(sc);
5698eb6488eSEric Joyner
5708eb6488eSEric Joyner /* Find Current head of the log eeprom offset */
5718eb6488eSEric Joyner cmd = BYPASS_PAGE_CTL2 | BYPASS_WE;
5728eb6488eSEric Joyner cmd |= (0x1 << BYPASS_CTL2_OFFSET_SHIFT) & BYPASS_CTL2_OFFSET_M;
5738eb6488eSEric Joyner error = hw->mac.ops.bypass_rw(hw, cmd, &status);
5748eb6488eSEric Joyner if (error)
5758eb6488eSEric Joyner goto unlock_err;
5768eb6488eSEric Joyner
5778eb6488eSEric Joyner /* wait for the write to stick */
5788eb6488eSEric Joyner msec_delay(100);
5798eb6488eSEric Joyner
5808eb6488eSEric Joyner /* Now read the results */
5818eb6488eSEric Joyner cmd &= ~BYPASS_WE;
5828eb6488eSEric Joyner error = hw->mac.ops.bypass_rw(hw, cmd, &status);
5838eb6488eSEric Joyner if (error)
5848eb6488eSEric Joyner goto unlock_err;
5858eb6488eSEric Joyner
586b1d5caf3SKevin Bowling ixgbe_bypass_mutex_clear(sc);
5878eb6488eSEric Joyner
5888eb6488eSEric Joyner base = status & BYPASS_CTL2_DATA_M;
5898eb6488eSEric Joyner head = (status & BYPASS_CTL2_HEAD_M) >> BYPASS_CTL2_HEAD_SHIFT;
5908eb6488eSEric Joyner
5918eb6488eSEric Joyner /* address of the first log */
5928eb6488eSEric Joyner log_off = base + (head * 5);
5938eb6488eSEric Joyner
5948eb6488eSEric Joyner /* extract all the log entries */
5958eb6488eSEric Joyner while (count < BYPASS_MAX_LOGS) {
5968eb6488eSEric Joyner eeprom[count].logs = 0;
5978eb6488eSEric Joyner eeprom[count].actions = 0;
5988eb6488eSEric Joyner
5998eb6488eSEric Joyner /* Log 5 bytes store in on u32 and a u8 */
6008eb6488eSEric Joyner for (i = 0; i < 4; i++) {
601b1d5caf3SKevin Bowling ixgbe_bypass_mutex_enter(sc);
6028eb6488eSEric Joyner error = hw->mac.ops.bypass_rd_eep(hw, log_off + i,
6038eb6488eSEric Joyner &data);
604b1d5caf3SKevin Bowling ixgbe_bypass_mutex_clear(sc);
6058eb6488eSEric Joyner if (error)
606c19c7afeSEric Joyner return (EINVAL);
6078eb6488eSEric Joyner eeprom[count].logs += data << (8 * i);
6088eb6488eSEric Joyner }
6098eb6488eSEric Joyner
610b1d5caf3SKevin Bowling ixgbe_bypass_mutex_enter(sc);
6118eb6488eSEric Joyner error = hw->mac.ops.bypass_rd_eep(hw,
6128eb6488eSEric Joyner log_off + i, &eeprom[count].actions);
613b1d5caf3SKevin Bowling ixgbe_bypass_mutex_clear(sc);
6148eb6488eSEric Joyner if (error)
615c19c7afeSEric Joyner return (EINVAL);
6168eb6488eSEric Joyner
6178eb6488eSEric Joyner /* Quit if not a unread log */
6188eb6488eSEric Joyner if (!(eeprom[count].logs & BYPASS_LOG_CLEAR_M))
6198eb6488eSEric Joyner break;
6208eb6488eSEric Joyner /*
6218eb6488eSEric Joyner * Log looks good so store the address where it's
6228eb6488eSEric Joyner * Unread Log bit is so we can clear it after safely
6238eb6488eSEric Joyner * pulling out all of the log data.
6248eb6488eSEric Joyner */
6258eb6488eSEric Joyner eeprom[count].clear_off = log_off;
6268eb6488eSEric Joyner
6278eb6488eSEric Joyner count++;
6288eb6488eSEric Joyner head = head ? head - 1 : BYPASS_MAX_LOGS;
6298eb6488eSEric Joyner log_off = base + (head * 5);
6308eb6488eSEric Joyner }
6318eb6488eSEric Joyner
6328eb6488eSEric Joyner /* reverse order (oldest first) for output */
6338eb6488eSEric Joyner while (count--) {
6348eb6488eSEric Joyner int year;
6358eb6488eSEric Joyner u32 mon, days, hours, min, sec;
6368eb6488eSEric Joyner u32 time = eeprom[count].logs & BYPASS_LOG_TIME_M;
6378eb6488eSEric Joyner u32 event = (eeprom[count].logs & BYPASS_LOG_EVENT_M) >>
6388eb6488eSEric Joyner BYPASS_LOG_EVENT_SHIFT;
6398eb6488eSEric Joyner u8 action = eeprom[count].actions & BYPASS_LOG_ACTION_M;
6408eb6488eSEric Joyner u16 day_mon[2][13] = {
641*c58d34ddSKevin Bowling {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304,
642*c58d34ddSKevin Bowling 334, 365},
643*c58d34ddSKevin Bowling {0, 31, 59, 91, 121, 152, 182, 213, 244, 274, 305,
644*c58d34ddSKevin Bowling 335, 366}
6458eb6488eSEric Joyner };
6468eb6488eSEric Joyner char *event_str[] = {"unknown", "main on", "aux on",
6478eb6488eSEric Joyner "main off", "aux off", "WDT", "user" };
648*c58d34ddSKevin Bowling char *action_str[] =
649*c58d34ddSKevin Bowling {"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;
671b1d5caf3SKevin Bowling device_printf(sc->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
680b1d5caf3SKevin Bowling ixgbe_bypass_mutex_enter(sc);
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
687b1d5caf3SKevin Bowling ixgbe_bypass_mutex_clear(sc);
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 */
695b1d5caf3SKevin Bowling while (atomic_cmpset_int(&sc->bypass.log, 1, 0) == 0)
6968eb6488eSEric Joyner usec_delay(3000);
6978eb6488eSEric Joyner return (error);
6988eb6488eSEric Joyner
6998eb6488eSEric Joyner unlock_err:
700b1d5caf3SKevin Bowling ixgbe_bypass_mutex_clear(sc);
7018eb6488eSEric Joyner status = 0; /* reset */
702b1d5caf3SKevin Bowling while (atomic_cmpset_int(&sc->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
ixgbe_bypass_init(struct ixgbe_softc * sc)714b1d5caf3SKevin Bowling ixgbe_bypass_init(struct ixgbe_softc *sc)
7158eb6488eSEric Joyner {
716b1d5caf3SKevin Bowling struct ixgbe_hw *hw = &sc->hw;
717b1d5caf3SKevin Bowling device_t dev = sc->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
722b1d5caf3SKevin Bowling if (!(sc->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
728*c58d34ddSKevin Bowling mask = BYPASS_CTL1_TIME_M |
729*c58d34ddSKevin Bowling BYPASS_CTL1_VALID_M |
730*c58d34ddSKevin Bowling BYPASS_CTL1_OFFTRST_M;
7318eb6488eSEric Joyner
732*c58d34ddSKevin Bowling value = (sec & BYPASS_CTL1_TIME_M) |
733*c58d34ddSKevin Bowling BYPASS_CTL1_VALID |
734*c58d34ddSKevin Bowling BYPASS_CTL1_OFFTRST;
7358eb6488eSEric Joyner
736b1d5caf3SKevin Bowling ixgbe_bypass_mutex_enter(sc);
7378eb6488eSEric Joyner hw->mac.ops.bypass_set(hw, BYPASS_PAGE_CTL1, mask, value);
738b1d5caf3SKevin Bowling ixgbe_bypass_mutex_clear(sc);
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)),
749c41a0eeeSKevin Bowling OID_AUTO, "bypass_log", CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_MPSAFE,
750b1d5caf3SKevin Bowling sc, 0, ixgbe_bp_log, "I", "Bypass Log");
7518eb6488eSEric Joyner
7528eb6488eSEric Joyner /* All other setting are hung from the 'bypass' node */
7538eb6488eSEric Joyner bp_node = SYSCTL_ADD_NODE(device_get_sysctl_ctx(dev),
7548eb6488eSEric Joyner SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
75520b91f0aSPawel Biernacki OID_AUTO, "bypass", CTLFLAG_RD | CTLFLAG_MPSAFE, NULL, "Bypass");
7568eb6488eSEric Joyner
7578eb6488eSEric Joyner bp_list = SYSCTL_CHILDREN(bp_node);
7588eb6488eSEric Joyner
7598eb6488eSEric Joyner SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev), bp_list,
760c41a0eeeSKevin Bowling OID_AUTO, "version", CTLTYPE_INT | CTLFLAG_RD,
761b1d5caf3SKevin Bowling sc, 0, ixgbe_bp_version, "I", "Bypass Version");
7628eb6488eSEric Joyner
7638eb6488eSEric Joyner SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev), bp_list,
764c41a0eeeSKevin Bowling OID_AUTO, "state", CTLTYPE_INT | CTLFLAG_RW,
765b1d5caf3SKevin Bowling sc, 0, ixgbe_bp_set_state, "I", "Bypass State");
7668eb6488eSEric Joyner
7678eb6488eSEric Joyner SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev), bp_list,
768c41a0eeeSKevin Bowling OID_AUTO, "timeout", CTLTYPE_INT | CTLFLAG_RW,
769b1d5caf3SKevin Bowling sc, 0, ixgbe_bp_timeout, "I", "Bypass Timeout");
7708eb6488eSEric Joyner
7718eb6488eSEric Joyner SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev), bp_list,
772c41a0eeeSKevin Bowling OID_AUTO, "main_on", CTLTYPE_INT | CTLFLAG_RW,
773b1d5caf3SKevin Bowling sc, 0, ixgbe_bp_main_on, "I", "Bypass Main On");
7748eb6488eSEric Joyner
7758eb6488eSEric Joyner SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev), bp_list,
776c41a0eeeSKevin Bowling OID_AUTO, "main_off", CTLTYPE_INT | CTLFLAG_RW,
777b1d5caf3SKevin Bowling sc, 0, ixgbe_bp_main_off, "I", "Bypass Main Off");
7788eb6488eSEric Joyner
7798eb6488eSEric Joyner SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev), bp_list,
780c41a0eeeSKevin Bowling OID_AUTO, "aux_on", CTLTYPE_INT | CTLFLAG_RW,
781b1d5caf3SKevin Bowling sc, 0, ixgbe_bp_aux_on, "I", "Bypass Aux On");
7828eb6488eSEric Joyner
7838eb6488eSEric Joyner SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev), bp_list,
784c41a0eeeSKevin Bowling OID_AUTO, "aux_off", CTLTYPE_INT | CTLFLAG_RW,
785b1d5caf3SKevin Bowling sc, 0, ixgbe_bp_aux_off, "I", "Bypass Aux Off");
7868eb6488eSEric Joyner
7878eb6488eSEric Joyner SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev), bp_list,
788c41a0eeeSKevin Bowling OID_AUTO, "wd_set", CTLTYPE_INT | CTLFLAG_RW,
789b1d5caf3SKevin Bowling sc, 0, ixgbe_bp_wd_set, "I", "Set BP Watchdog");
7908eb6488eSEric Joyner
7918eb6488eSEric Joyner SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev), bp_list,
792c41a0eeeSKevin Bowling OID_AUTO, "wd_reset", CTLTYPE_INT | CTLFLAG_WR,
793b1d5caf3SKevin Bowling sc, 0, ixgbe_bp_wd_reset, "S", "Bypass WD Reset");
7948eb6488eSEric Joyner
795b1d5caf3SKevin Bowling sc->feat_en |= IXGBE_FEATURE_BYPASS;
7968eb6488eSEric Joyner } /* ixgbe_bypass_init */
7978eb6488eSEric Joyner
798