From owner-svn-src-all@freebsd.org Sat Jul 4 02:59:31 2015 Return-Path: Delivered-To: svn-src-all@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id 407B8995698; Sat, 4 Jul 2015 02:59:31 +0000 (UTC) (envelope-from adrian@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2001:1900:2254:2068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id 2523915D1; Sat, 4 Jul 2015 02:59:31 +0000 (UTC) (envelope-from adrian@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.70]) by repo.freebsd.org (8.14.9/8.14.9) with ESMTP id t642xV52022417; Sat, 4 Jul 2015 02:59:31 GMT (envelope-from adrian@FreeBSD.org) Received: (from adrian@localhost) by repo.freebsd.org (8.14.9/8.14.9/Submit) id t642xUC6022416; Sat, 4 Jul 2015 02:59:30 GMT (envelope-from adrian@FreeBSD.org) Message-Id: <201507040259.t642xUC6022416@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: adrian set sender to adrian@FreeBSD.org using -f From: Adrian Chadd Date: Sat, 4 Jul 2015 02:59:30 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r285120 - head/sys/dev/ath X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.20 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 04 Jul 2015 02:59:31 -0000 Author: adrian Date: Sat Jul 4 02:59:30 2015 New Revision: 285120 URL: https://svnweb.freebsd.org/changeset/base/285120 Log: Wake up the hardware before doing anything in sysctl. This stops the panics that occur on MIPS platforms when doing say, 'sysctl dev.ath.0' whilst the MAC is asleep. The MIPS platform is rather unforgiving in getting power-save register access wrong and you will get all kinds of odd failures if you don't have things woken up at the right times. Tested: * QCA9558 (TP-Link Archer C7 v2) * AR9331 (Carambola 2) .. with no VAPs configured and ath0 down (thus the MAC is definitely asleep.) PR: kern/201117 Modified: head/sys/dev/ath/if_ath_sysctl.c Modified: head/sys/dev/ath/if_ath_sysctl.c ============================================================================== --- head/sys/dev/ath/if_ath_sysctl.c Sat Jul 4 02:37:36 2015 (r285119) +++ head/sys/dev/ath/if_ath_sysctl.c Sat Jul 4 02:59:30 2015 (r285120) @@ -134,26 +134,52 @@ static int ath_sysctl_acktimeout(SYSCTL_HANDLER_ARGS) { struct ath_softc *sc = arg1; - u_int acktimeout = ath_hal_getacktimeout(sc->sc_ah); + u_int acktimeout; int error; + ATH_LOCK(sc); + ath_power_set_power_state(sc, HAL_PM_AWAKE); + acktimeout = ath_hal_getacktimeout(sc->sc_ah); + ATH_UNLOCK(sc); + error = sysctl_handle_int(oidp, &acktimeout, 0, req); if (error || !req->newptr) - return error; - return !ath_hal_setacktimeout(sc->sc_ah, acktimeout) ? EINVAL : 0; + goto finish; + + error = !ath_hal_setacktimeout(sc->sc_ah, acktimeout) ? EINVAL : 0; + +finish: + ATH_LOCK(sc); + ath_power_restore_power_state(sc); + ATH_UNLOCK(sc); + + return (error); } static int ath_sysctl_ctstimeout(SYSCTL_HANDLER_ARGS) { struct ath_softc *sc = arg1; - u_int ctstimeout = ath_hal_getctstimeout(sc->sc_ah); + u_int ctstimeout; int error; + ATH_LOCK(sc); + ath_power_set_power_state(sc, HAL_PM_AWAKE); + ctstimeout = ath_hal_getctstimeout(sc->sc_ah); + ATH_UNLOCK(sc); + error = sysctl_handle_int(oidp, &ctstimeout, 0, req); if (error || !req->newptr) - return error; - return !ath_hal_setctstimeout(sc->sc_ah, ctstimeout) ? EINVAL : 0; + goto finish; + + error = !ath_hal_setctstimeout(sc->sc_ah, ctstimeout) ? EINVAL : 0; + +finish: + ATH_LOCK(sc); + ath_power_restore_power_state(sc); + ATH_UNLOCK(sc); + + return (error); } static int @@ -221,14 +247,22 @@ static int ath_sysctl_txantenna(SYSCTL_HANDLER_ARGS) { struct ath_softc *sc = arg1; - u_int txantenna = ath_hal_getantennaswitch(sc->sc_ah); + u_int txantenna; int error; + ATH_LOCK(sc); + ath_power_set_power_state(sc, HAL_PM_AWAKE); + ATH_UNLOCK(sc); + + txantenna = ath_hal_getantennaswitch(sc->sc_ah); + error = sysctl_handle_int(oidp, &txantenna, 0, req); if (!error && req->newptr) { /* XXX assumes 2 antenna ports */ - if (txantenna < HAL_ANT_VARIABLE || txantenna > HAL_ANT_FIXED_B) - return EINVAL; + if (txantenna < HAL_ANT_VARIABLE || txantenna > HAL_ANT_FIXED_B) { + error = EINVAL; + goto finish; + } ath_hal_setantennaswitch(sc->sc_ah, txantenna); /* * NB: with the switch locked this isn't meaningful, @@ -237,36 +271,67 @@ ath_sysctl_txantenna(SYSCTL_HANDLER_ARGS */ sc->sc_txantenna = txantenna; } - return error; + +finish: + ATH_LOCK(sc); + ath_power_restore_power_state(sc); + ATH_UNLOCK(sc); + + return (error); } static int ath_sysctl_rxantenna(SYSCTL_HANDLER_ARGS) { struct ath_softc *sc = arg1; - u_int defantenna = ath_hal_getdefantenna(sc->sc_ah); + u_int defantenna; int error; + ATH_LOCK(sc); + ath_power_set_power_state(sc, HAL_PM_AWAKE); + defantenna = ath_hal_getdefantenna(sc->sc_ah); + ATH_UNLOCK(sc); + error = sysctl_handle_int(oidp, &defantenna, 0, req); if (!error && req->newptr) ath_hal_setdefantenna(sc->sc_ah, defantenna); - return error; + + ATH_LOCK(sc); + ath_power_restore_power_state(sc); + ATH_UNLOCK(sc); + + return (error); } static int ath_sysctl_diversity(SYSCTL_HANDLER_ARGS) { struct ath_softc *sc = arg1; - u_int diversity = ath_hal_getdiversity(sc->sc_ah); + u_int diversity; int error; + ATH_LOCK(sc); + ath_power_set_power_state(sc, HAL_PM_AWAKE); + ATH_UNLOCK(sc); + + diversity = ath_hal_getdiversity(sc->sc_ah); + error = sysctl_handle_int(oidp, &diversity, 0, req); if (error || !req->newptr) - return error; - if (!ath_hal_setdiversity(sc->sc_ah, diversity)) - return EINVAL; + goto finish; + if (!ath_hal_setdiversity(sc->sc_ah, diversity)) { + error = EINVAL; + goto finish; + } sc->sc_diversity = diversity; - return 0; + error = 0; + +finish: + ATH_LOCK(sc); + ath_power_restore_power_state(sc); + ATH_UNLOCK(sc); + + return (error); } static int @@ -276,12 +341,26 @@ ath_sysctl_diag(SYSCTL_HANDLER_ARGS) u_int32_t diag; int error; - if (!ath_hal_getdiag(sc->sc_ah, &diag)) - return EINVAL; + ATH_LOCK(sc); + ath_power_set_power_state(sc, HAL_PM_AWAKE); + ATH_UNLOCK(sc); + + if (!ath_hal_getdiag(sc->sc_ah, &diag)) { + error = EINVAL; + goto finish; + } + error = sysctl_handle_int(oidp, &diag, 0, req); if (error || !req->newptr) - return error; - return !ath_hal_setdiag(sc->sc_ah, diag) ? EINVAL : 0; + goto finish; + error = !ath_hal_setdiag(sc->sc_ah, diag) ? EINVAL : 0; + +finish: + ATH_LOCK(sc); + ath_power_restore_power_state(sc); + ATH_UNLOCK(sc); + + return (error); } static int @@ -292,26 +371,51 @@ ath_sysctl_tpscale(SYSCTL_HANDLER_ARGS) u_int32_t scale; int error; + ATH_LOCK(sc); + ath_power_set_power_state(sc, HAL_PM_AWAKE); + ATH_UNLOCK(sc); + (void) ath_hal_gettpscale(sc->sc_ah, &scale); error = sysctl_handle_int(oidp, &scale, 0, req); if (error || !req->newptr) - return error; - return !ath_hal_settpscale(sc->sc_ah, scale) ? EINVAL : + goto finish; + + error = !ath_hal_settpscale(sc->sc_ah, scale) ? EINVAL : (ifp->if_drv_flags & IFF_DRV_RUNNING) ? ath_reset(ifp, ATH_RESET_NOLOSS) : 0; + +finish: + ATH_LOCK(sc); + ath_power_restore_power_state(sc); + ATH_UNLOCK(sc); + + return (error); } static int ath_sysctl_tpc(SYSCTL_HANDLER_ARGS) { struct ath_softc *sc = arg1; - u_int tpc = ath_hal_gettpc(sc->sc_ah); + u_int tpc; int error; + ATH_LOCK(sc); + ath_power_set_power_state(sc, HAL_PM_AWAKE); + ATH_UNLOCK(sc); + + tpc = ath_hal_gettpc(sc->sc_ah); + error = sysctl_handle_int(oidp, &tpc, 0, req); if (error || !req->newptr) - return error; - return !ath_hal_settpc(sc->sc_ah, tpc) ? EINVAL : 0; + goto finish; + error = !ath_hal_settpc(sc->sc_ah, tpc) ? EINVAL : 0; + +finish: + ATH_LOCK(sc); + ath_power_restore_power_state(sc); + ATH_UNLOCK(sc); + + return (error); } static int @@ -320,18 +424,35 @@ ath_sysctl_rfkill(SYSCTL_HANDLER_ARGS) struct ath_softc *sc = arg1; struct ifnet *ifp = sc->sc_ifp; struct ath_hal *ah = sc->sc_ah; - u_int rfkill = ath_hal_getrfkill(ah); + u_int rfkill; int error; + ATH_LOCK(sc); + ath_power_set_power_state(sc, HAL_PM_AWAKE); + ATH_UNLOCK(sc); + + rfkill = ath_hal_getrfkill(ah); + error = sysctl_handle_int(oidp, &rfkill, 0, req); if (error || !req->newptr) - return error; - if (rfkill == ath_hal_getrfkill(ah)) /* unchanged */ - return 0; - if (!ath_hal_setrfkill(ah, rfkill)) - return EINVAL; - return (ifp->if_drv_flags & IFF_DRV_RUNNING) ? + goto finish; + if (rfkill == ath_hal_getrfkill(ah)) { /* unchanged */ + error = 0; + goto finish; + } + if (!ath_hal_setrfkill(ah, rfkill)) { + error = EINVAL; + goto finish; + } + error = (ifp->if_drv_flags & IFF_DRV_RUNNING) ? ath_reset(ifp, ATH_RESET_FULL) : 0; + +finish: + ATH_LOCK(sc); + ath_power_restore_power_state(sc); + ATH_UNLOCK(sc); + + return (error); } static int @@ -440,12 +561,18 @@ ath_sysctl_rfsilent(SYSCTL_HANDLER_ARGS) u_int rfsilent; int error; + ATH_LOCK(sc); + ath_power_set_power_state(sc, HAL_PM_AWAKE); + ATH_UNLOCK(sc); + (void) ath_hal_getrfsilent(sc->sc_ah, &rfsilent); error = sysctl_handle_int(oidp, &rfsilent, 0, req); if (error || !req->newptr) - return error; - if (!ath_hal_setrfsilent(sc->sc_ah, rfsilent)) - return EINVAL; + goto finish; + if (!ath_hal_setrfsilent(sc->sc_ah, rfsilent)) { + error = EINVAL; + goto finish; + } /* * Earlier chips (< AR5212) have up to 8 GPIO * pins exposed. @@ -456,7 +583,14 @@ ath_sysctl_rfsilent(SYSCTL_HANDLER_ARGS) */ sc->sc_rfsilentpin = rfsilent & 0x3c; sc->sc_rfsilentpol = (rfsilent & 0x2) != 0; - return 0; + error = 0; + +finish: + ATH_LOCK(sc); + ath_power_restore_power_state(sc); + ATH_UNLOCK(sc); + + return (error); } static int @@ -466,11 +600,22 @@ ath_sysctl_tpack(SYSCTL_HANDLER_ARGS) u_int32_t tpack; int error; + ATH_LOCK(sc); + ath_power_set_power_state(sc, HAL_PM_AWAKE); + ATH_UNLOCK(sc); + (void) ath_hal_gettpack(sc->sc_ah, &tpack); error = sysctl_handle_int(oidp, &tpack, 0, req); if (error || !req->newptr) - return error; - return !ath_hal_settpack(sc->sc_ah, tpack) ? EINVAL : 0; + goto finish; + error = !ath_hal_settpack(sc->sc_ah, tpack) ? EINVAL : 0; + +finish: + ATH_LOCK(sc); + ath_power_restore_power_state(sc); + ATH_UNLOCK(sc); + + return (error); } static int @@ -480,11 +625,23 @@ ath_sysctl_tpcts(SYSCTL_HANDLER_ARGS) u_int32_t tpcts; int error; + ATH_LOCK(sc); + ath_power_set_power_state(sc, HAL_PM_AWAKE); + ATH_UNLOCK(sc); + (void) ath_hal_gettpcts(sc->sc_ah, &tpcts); error = sysctl_handle_int(oidp, &tpcts, 0, req); if (error || !req->newptr) - return error; - return !ath_hal_settpcts(sc->sc_ah, tpcts) ? EINVAL : 0; + goto finish; + + error = !ath_hal_settpcts(sc->sc_ah, tpcts) ? EINVAL : 0; + +finish: + ATH_LOCK(sc); + ath_power_restore_power_state(sc); + ATH_UNLOCK(sc); + + return (error); } static int @@ -493,15 +650,21 @@ ath_sysctl_intmit(SYSCTL_HANDLER_ARGS) struct ath_softc *sc = arg1; int intmit, error; + ATH_LOCK(sc); + ath_power_set_power_state(sc, HAL_PM_AWAKE); + ATH_UNLOCK(sc); + intmit = ath_hal_getintmit(sc->sc_ah); error = sysctl_handle_int(oidp, &intmit, 0, req); if (error || !req->newptr) - return error; + goto finish; /* reusing error; 1 here means "good"; 0 means "fail" */ error = ath_hal_setintmit(sc->sc_ah, intmit); - if (! error) - return EINVAL; + if (! error) { + error = EINVAL; + goto finish; + } /* * Reset the hardware here - disabling ANI in the HAL @@ -511,7 +674,14 @@ ath_sysctl_intmit(SYSCTL_HANDLER_ARGS) if (sc->sc_ifp->if_drv_flags & IFF_DRV_RUNNING) ath_reset(sc->sc_ifp, ATH_RESET_NOLOSS); - return 0; + error = 0; + +finish: + ATH_LOCK(sc); + ath_power_restore_power_state(sc); + ATH_UNLOCK(sc); + + return (error); } #ifdef IEEE80211_SUPPORT_TDMA @@ -565,15 +735,28 @@ ath_sysctl_hangcheck(SYSCTL_HANDLER_ARGS if (val == 0) return 0; + ATH_LOCK(sc); + ath_power_set_power_state(sc, HAL_PM_AWAKE); + ATH_UNLOCK(sc); + /* Do a hang check */ if (!ath_hal_getdiagstate(ah, HAL_DIAG_CHECK_HANGS, &mask, sizeof(mask), - (void *) &sp, &rsize)) - return (0); + (void *) &sp, &rsize)) { + error = 0; + goto finish; + } + device_printf(sc->sc_dev, "%s: sp=0x%08x\n", __func__, *sp); val = 0; - return 0; + error = 0; +finish: + ATH_LOCK(sc); + ath_power_restore_power_state(sc); + ATH_UNLOCK(sc); + + return (error); } #ifdef ATH_DEBUG_ALQ