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
This commit is contained in:
parent
30161d035c
commit
52f5515397
@ -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
|
||||
|
Loading…
x
Reference in New Issue
Block a user