mirror of https://github.com/hak5/openwrt.git
ath9k: reorganize patches, reset hardware after full sleep (fixes #10349)
SVN-Revision: 29155lede-17.01
parent
215239a470
commit
817c72ef02
|
@ -0,0 +1,68 @@
|
||||||
|
--- a/drivers/net/wireless/ath/ath9k/ath9k.h
|
||||||
|
+++ b/drivers/net/wireless/ath/ath9k/ath9k.h
|
||||||
|
@@ -619,6 +619,7 @@ struct ath_softc {
|
||||||
|
u16 curtxpow;
|
||||||
|
bool ps_enabled;
|
||||||
|
bool ps_idle;
|
||||||
|
+ bool ps_fullsleep;
|
||||||
|
short nbcnvifs;
|
||||||
|
short nvifs;
|
||||||
|
unsigned long ps_usecount;
|
||||||
|
--- a/drivers/net/wireless/ath/ath9k/main.c
|
||||||
|
+++ b/drivers/net/wireless/ath/ath9k/main.c
|
||||||
|
@@ -118,9 +118,10 @@ void ath9k_ps_restore(struct ath_softc *
|
||||||
|
if (--sc->ps_usecount != 0)
|
||||||
|
goto unlock;
|
||||||
|
|
||||||
|
- if (sc->ps_idle)
|
||||||
|
+ if (sc->ps_idle && (sc->ps_flags & PS_WAIT_FOR_TX_ACK)) {
|
||||||
|
mode = ATH9K_PM_FULL_SLEEP;
|
||||||
|
- else if (sc->ps_enabled &&
|
||||||
|
+ sc->ps_fullsleep = true;
|
||||||
|
+ } else if (sc->ps_enabled &&
|
||||||
|
!(sc->ps_flags & (PS_WAIT_FOR_BEACON |
|
||||||
|
PS_WAIT_FOR_CAB |
|
||||||
|
PS_WAIT_FOR_PSPOLL_DATA |
|
||||||
|
@@ -275,6 +276,7 @@ static bool ath_complete_reset(struct at
|
||||||
|
sc->config.txpowlimit, &sc->curtxpow);
|
||||||
|
ath9k_hw_set_interrupts(ah);
|
||||||
|
ath9k_hw_enable_interrupts(ah);
|
||||||
|
+ sc->ps_fullsleep = false;
|
||||||
|
|
||||||
|
if (!(sc->sc_flags & (SC_OP_OFFCHANNEL)) && start) {
|
||||||
|
if (sc->sc_flags & SC_OP_BEACONS)
|
||||||
|
@@ -332,7 +334,8 @@ static int ath_reset_internal(struct ath
|
||||||
|
hchan = ah->curchan;
|
||||||
|
}
|
||||||
|
|
||||||
|
- if (fastcc && !ath9k_hw_check_alive(ah))
|
||||||
|
+ if (fastcc && (sc->ps_fullsleep ||
|
||||||
|
+ !ath9k_hw_check_alive(ah)))
|
||||||
|
fastcc = false;
|
||||||
|
|
||||||
|
if (!ath_prepare_reset(sc, retry_tx, flush))
|
||||||
|
@@ -1173,6 +1176,13 @@ static void ath9k_tx(struct ieee80211_hw
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
+ /*
|
||||||
|
+ * Cannot tx while the hardware is in full sleep, it first needs a full
|
||||||
|
+ * chip reset to recover from that
|
||||||
|
+ */
|
||||||
|
+ if (unlikely(sc->sc_ah->power_mode == ATH9K_PM_FULL_SLEEP))
|
||||||
|
+ goto exit;
|
||||||
|
+
|
||||||
|
if (unlikely(sc->sc_ah->power_mode != ATH9K_PM_AWAKE)) {
|
||||||
|
/*
|
||||||
|
* We are using PS-Poll and mac80211 can request TX while in
|
||||||
|
--- a/drivers/net/wireless/ath/ath9k/xmit.c
|
||||||
|
+++ b/drivers/net/wireless/ath/ath9k/xmit.c
|
||||||
|
@@ -1983,7 +1983,7 @@ static void ath_tx_complete(struct ath_s
|
||||||
|
skb_pull(skb, padsize);
|
||||||
|
}
|
||||||
|
|
||||||
|
- if (sc->ps_flags & PS_WAIT_FOR_TX_ACK) {
|
||||||
|
+ if ((sc->ps_flags & PS_WAIT_FOR_TX_ACK) && !txq->axq_depth) {
|
||||||
|
sc->ps_flags &= ~PS_WAIT_FOR_TX_ACK;
|
||||||
|
ath_dbg(common, ATH_DBG_PS,
|
||||||
|
"Going back to sleep after having received TX status (0x%lx)\n",
|
|
@ -1,6 +1,6 @@
|
||||||
--- a/drivers/net/wireless/ath/ath9k/main.c
|
--- a/drivers/net/wireless/ath/ath9k/main.c
|
||||||
+++ b/drivers/net/wireless/ath/ath9k/main.c
|
+++ b/drivers/net/wireless/ath/ath9k/main.c
|
||||||
@@ -880,82 +880,6 @@ chip_reset:
|
@@ -883,82 +883,6 @@ chip_reset:
|
||||||
#undef SCHED_INTR
|
#undef SCHED_INTR
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -83,7 +83,7 @@
|
||||||
static int ath_reset(struct ath_softc *sc, bool retry_tx)
|
static int ath_reset(struct ath_softc *sc, bool retry_tx)
|
||||||
{
|
{
|
||||||
int r;
|
int r;
|
||||||
@@ -1091,6 +1015,9 @@ static int ath9k_start(struct ieee80211_
|
@@ -1094,6 +1018,9 @@ static int ath9k_start(struct ieee80211_
|
||||||
* and then setup of the interrupt mask.
|
* and then setup of the interrupt mask.
|
||||||
*/
|
*/
|
||||||
spin_lock_bh(&sc->sc_pcu_lock);
|
spin_lock_bh(&sc->sc_pcu_lock);
|
||||||
|
@ -93,13 +93,15 @@
|
||||||
r = ath9k_hw_reset(ah, init_channel, ah->caldata, false);
|
r = ath9k_hw_reset(ah, init_channel, ah->caldata, false);
|
||||||
if (r) {
|
if (r) {
|
||||||
ath_err(common,
|
ath_err(common,
|
||||||
@@ -1129,6 +1056,16 @@ static int ath9k_start(struct ieee80211_
|
@@ -1132,6 +1059,18 @@ static int ath9k_start(struct ieee80211_
|
||||||
goto mutex_unlock;
|
goto mutex_unlock;
|
||||||
}
|
}
|
||||||
|
|
||||||
+ ath9k_hw_cfg_output(ah, ah->led_pin,
|
+ if (ah->led_pin >= 0) {
|
||||||
+ AR_GPIO_OUTPUT_MUX_AS_OUTPUT);
|
+ ath9k_hw_cfg_output(ah, ah->led_pin,
|
||||||
+ ath9k_hw_set_gpio(ah, ah->led_pin, 0);
|
+ AR_GPIO_OUTPUT_MUX_AS_OUTPUT);
|
||||||
|
+ ath9k_hw_set_gpio(ah, ah->led_pin, 0);
|
||||||
|
+ }
|
||||||
+
|
+
|
||||||
+ /*
|
+ /*
|
||||||
+ * Reset key cache to sane defaults (all entries cleared) instead of
|
+ * Reset key cache to sane defaults (all entries cleared) instead of
|
||||||
|
@ -110,7 +112,15 @@
|
||||||
spin_unlock_bh(&sc->sc_pcu_lock);
|
spin_unlock_bh(&sc->sc_pcu_lock);
|
||||||
|
|
||||||
if ((ah->btcoex_hw.scheme != ATH_BTCOEX_CFG_NONE) &&
|
if ((ah->btcoex_hw.scheme != ATH_BTCOEX_CFG_NONE) &&
|
||||||
@@ -1248,33 +1185,39 @@ static void ath9k_stop(struct ieee80211_
|
@@ -1229,6 +1168,7 @@ static void ath9k_stop(struct ieee80211_
|
||||||
|
struct ath_softc *sc = hw->priv;
|
||||||
|
struct ath_hw *ah = sc->sc_ah;
|
||||||
|
struct ath_common *common = ath9k_hw_common(ah);
|
||||||
|
+ bool prev_idle;
|
||||||
|
|
||||||
|
mutex_lock(&sc->mutex);
|
||||||
|
|
||||||
|
@@ -1258,35 +1198,45 @@ static void ath9k_stop(struct ieee80211_
|
||||||
* before setting the invalid flag. */
|
* before setting the invalid flag. */
|
||||||
ath9k_hw_disable_interrupts(ah);
|
ath9k_hw_disable_interrupts(ah);
|
||||||
|
|
||||||
|
@ -128,12 +138,15 @@
|
||||||
+ tasklet_kill(&sc->intr_tq);
|
+ tasklet_kill(&sc->intr_tq);
|
||||||
+ tasklet_kill(&sc->bcon_tasklet);
|
+ tasklet_kill(&sc->bcon_tasklet);
|
||||||
+
|
+
|
||||||
|
+ prev_idle = sc->ps_idle;
|
||||||
+ sc->ps_idle = true;
|
+ sc->ps_idle = true;
|
||||||
+
|
+
|
||||||
+ spin_lock_bh(&sc->sc_pcu_lock);
|
+ spin_lock_bh(&sc->sc_pcu_lock);
|
||||||
+
|
+
|
||||||
+ ath9k_hw_set_gpio(ah, ah->led_pin, 1);
|
+ if (ah->led_pin >= 0) {
|
||||||
+ ath9k_hw_cfg_gpio_input(ah, ah->led_pin);
|
+ ath9k_hw_set_gpio(ah, ah->led_pin, 1);
|
||||||
|
+ ath9k_hw_cfg_gpio_input(ah, ah->led_pin);
|
||||||
|
+ }
|
||||||
+
|
+
|
||||||
+ ath_prepare_reset(sc, false, true);
|
+ ath_prepare_reset(sc, false, true);
|
||||||
|
|
||||||
|
@ -166,8 +179,11 @@
|
||||||
+ ath9k_ps_restore(sc);
|
+ ath9k_ps_restore(sc);
|
||||||
|
|
||||||
sc->sc_flags |= SC_OP_INVALID;
|
sc->sc_flags |= SC_OP_INVALID;
|
||||||
|
+ sc->ps_idle = prev_idle;
|
||||||
|
|
||||||
@@ -1598,8 +1541,8 @@ static int ath9k_config(struct ieee80211
|
mutex_unlock(&sc->mutex);
|
||||||
|
|
||||||
|
@@ -1608,8 +1558,8 @@ static int ath9k_config(struct ieee80211
|
||||||
struct ath_hw *ah = sc->sc_ah;
|
struct ath_hw *ah = sc->sc_ah;
|
||||||
struct ath_common *common = ath9k_hw_common(ah);
|
struct ath_common *common = ath9k_hw_common(ah);
|
||||||
struct ieee80211_conf *conf = &hw->conf;
|
struct ieee80211_conf *conf = &hw->conf;
|
||||||
|
@ -177,7 +193,7 @@
|
||||||
mutex_lock(&sc->mutex);
|
mutex_lock(&sc->mutex);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -1608,16 +1551,8 @@ static int ath9k_config(struct ieee80211
|
@@ -1618,16 +1568,8 @@ static int ath9k_config(struct ieee80211
|
||||||
* of the changes. Likewise we must only disable the radio towards
|
* of the changes. Likewise we must only disable the radio towards
|
||||||
* the end.
|
* the end.
|
||||||
*/
|
*/
|
||||||
|
@ -195,7 +211,7 @@
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We just prepare to enable PS. We have to wait until our AP has
|
* We just prepare to enable PS. We have to wait until our AP has
|
||||||
@@ -1742,19 +1677,13 @@ static int ath9k_config(struct ieee80211
|
@@ -1752,19 +1694,13 @@ static int ath9k_config(struct ieee80211
|
||||||
ath_dbg(common, ATH_DBG_CONFIG,
|
ath_dbg(common, ATH_DBG_CONFIG,
|
||||||
"Set power: %d\n", conf->power_level);
|
"Set power: %d\n", conf->power_level);
|
||||||
sc->config.txpowlimit = 2 * conf->power_level;
|
sc->config.txpowlimit = 2 * conf->power_level;
|
|
@ -1,6 +1,6 @@
|
||||||
--- a/drivers/net/wireless/ath/ath9k/main.c
|
--- a/drivers/net/wireless/ath/ath9k/main.c
|
||||||
+++ b/drivers/net/wireless/ath/ath9k/main.c
|
+++ b/drivers/net/wireless/ath/ath9k/main.c
|
||||||
@@ -2251,9 +2251,6 @@ static void ath9k_flush(struct ieee80211
|
@@ -2268,9 +2268,6 @@ static void ath9k_flush(struct ieee80211
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -10,7 +10,7 @@
|
||||||
for (j = 0; j < timeout; j++) {
|
for (j = 0; j < timeout; j++) {
|
||||||
bool npend = false;
|
bool npend = false;
|
||||||
|
|
||||||
@@ -2271,21 +2268,22 @@ static void ath9k_flush(struct ieee80211
|
@@ -2288,21 +2285,22 @@ static void ath9k_flush(struct ieee80211
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!npend)
|
if (!npend)
|
|
@ -1,30 +0,0 @@
|
||||||
--- a/drivers/net/wireless/ath/ath9k/main.c
|
|
||||||
+++ b/drivers/net/wireless/ath/ath9k/main.c
|
|
||||||
@@ -1056,9 +1056,11 @@ static int ath9k_start(struct ieee80211_
|
|
||||||
goto mutex_unlock;
|
|
||||||
}
|
|
||||||
|
|
||||||
- ath9k_hw_cfg_output(ah, ah->led_pin,
|
|
||||||
- AR_GPIO_OUTPUT_MUX_AS_OUTPUT);
|
|
||||||
- ath9k_hw_set_gpio(ah, ah->led_pin, 0);
|
|
||||||
+ if (ah->led_pin >= 0) {
|
|
||||||
+ ath9k_hw_cfg_output(ah, ah->led_pin,
|
|
||||||
+ AR_GPIO_OUTPUT_MUX_AS_OUTPUT);
|
|
||||||
+ ath9k_hw_set_gpio(ah, ah->led_pin, 0);
|
|
||||||
+ }
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Reset key cache to sane defaults (all entries cleared) instead of
|
|
||||||
@@ -1197,8 +1199,10 @@ static void ath9k_stop(struct ieee80211_
|
|
||||||
|
|
||||||
spin_lock_bh(&sc->sc_pcu_lock);
|
|
||||||
|
|
||||||
- ath9k_hw_set_gpio(ah, ah->led_pin, 1);
|
|
||||||
- ath9k_hw_cfg_gpio_input(ah, ah->led_pin);
|
|
||||||
+ if (ah->led_pin >= 0) {
|
|
||||||
+ ath9k_hw_set_gpio(ah, ah->led_pin, 1);
|
|
||||||
+ ath9k_hw_cfg_gpio_input(ah, ah->led_pin);
|
|
||||||
+ }
|
|
||||||
|
|
||||||
ath_prepare_reset(sc, false, true);
|
|
||||||
|
|
|
@ -1,22 +0,0 @@
|
||||||
--- a/drivers/net/wireless/ath/ath9k/main.c
|
|
||||||
+++ b/drivers/net/wireless/ath/ath9k/main.c
|
|
||||||
@@ -118,7 +118,7 @@ void ath9k_ps_restore(struct ath_softc *
|
|
||||||
if (--sc->ps_usecount != 0)
|
|
||||||
goto unlock;
|
|
||||||
|
|
||||||
- if (sc->ps_idle)
|
|
||||||
+ if (sc->ps_idle && !(sc->ps_flags & PS_WAIT_FOR_TX_ACK))
|
|
||||||
mode = ATH9K_PM_FULL_SLEEP;
|
|
||||||
else if (sc->ps_enabled &&
|
|
||||||
!(sc->ps_flags & (PS_WAIT_FOR_BEACON |
|
|
||||||
--- a/drivers/net/wireless/ath/ath9k/xmit.c
|
|
||||||
+++ b/drivers/net/wireless/ath/ath9k/xmit.c
|
|
||||||
@@ -1983,7 +1983,7 @@ static void ath_tx_complete(struct ath_s
|
|
||||||
skb_pull(skb, padsize);
|
|
||||||
}
|
|
||||||
|
|
||||||
- if (sc->ps_flags & PS_WAIT_FOR_TX_ACK) {
|
|
||||||
+ if ((sc->ps_flags & PS_WAIT_FOR_TX_ACK) && !txq->axq_depth) {
|
|
||||||
sc->ps_flags &= ~PS_WAIT_FOR_TX_ACK;
|
|
||||||
ath_dbg(common, ATH_DBG_PS,
|
|
||||||
"Going back to sleep after having received TX status (0x%lx)\n",
|
|
Loading…
Reference in New Issue