From ccd11de0ba26fb0f2f95e5936820a382c30ab43a Mon Sep 17 00:00:00 2001 From: nbd Date: Tue, 15 Nov 2011 14:53:21 +0000 Subject: [PATCH] ath9k: reorganize patches, reset hardware after full sleep (fixes #10349) git-svn-id: svn://svn.openwrt.org/openwrt/trunk@29155 3c298f89-4303-0410-b956-a3cf2f4a3e73 --- .../560-ath9k_reset_after_full_sleep.patch | 68 +++++++++++++++++++ ...h => 561-ath9k_fix_ps_idle_handling.patch} | 40 +++++++---- ..._flush.patch => 562-ath9k_fix_flush.patch} | 4 +- .../mac80211/patches/562-ath9k_fix_led.patch | 30 -------- .../patches/563-ath9k_fix_full_sleep_tx.patch | 22 ------ 5 files changed, 98 insertions(+), 66 deletions(-) create mode 100644 package/mac80211/patches/560-ath9k_reset_after_full_sleep.patch rename package/mac80211/patches/{560-ath9k_fix_radio_stop.patch => 561-ath9k_fix_ps_idle_handling.patch} (86%) rename package/mac80211/patches/{561-ath9k_fix_flush.patch => 562-ath9k_fix_flush.patch} (87%) delete mode 100644 package/mac80211/patches/562-ath9k_fix_led.patch delete mode 100644 package/mac80211/patches/563-ath9k_fix_full_sleep_tx.patch diff --git a/package/mac80211/patches/560-ath9k_reset_after_full_sleep.patch b/package/mac80211/patches/560-ath9k_reset_after_full_sleep.patch new file mode 100644 index 000000000..9a5b58001 --- /dev/null +++ b/package/mac80211/patches/560-ath9k_reset_after_full_sleep.patch @@ -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", diff --git a/package/mac80211/patches/560-ath9k_fix_radio_stop.patch b/package/mac80211/patches/561-ath9k_fix_ps_idle_handling.patch similarity index 86% rename from package/mac80211/patches/560-ath9k_fix_radio_stop.patch rename to package/mac80211/patches/561-ath9k_fix_ps_idle_handling.patch index 2367ffa6a..40f24e1ec 100644 --- a/package/mac80211/patches/560-ath9k_fix_radio_stop.patch +++ b/package/mac80211/patches/561-ath9k_fix_ps_idle_handling.patch @@ -1,6 +1,6 @@ --- a/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 } @@ -83,7 +83,7 @@ static int ath_reset(struct ath_softc *sc, bool retry_tx) { 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. */ spin_lock_bh(&sc->sc_pcu_lock); @@ -93,13 +93,15 @@ r = ath9k_hw_reset(ah, init_channel, ah->caldata, false); if (r) { 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; } -+ 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 @@ -110,7 +112,15 @@ spin_unlock_bh(&sc->sc_pcu_lock); 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. */ ath9k_hw_disable_interrupts(ah); @@ -128,12 +138,15 @@ + tasklet_kill(&sc->intr_tq); + tasklet_kill(&sc->bcon_tasklet); + ++ prev_idle = sc->ps_idle; + sc->ps_idle = true; + + 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); @@ -166,8 +179,11 @@ + ath9k_ps_restore(sc); 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_common *common = ath9k_hw_common(ah); struct ieee80211_conf *conf = &hw->conf; @@ -177,7 +193,7 @@ 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 * the end. */ @@ -195,7 +211,7 @@ /* * 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, "Set power: %d\n", conf->power_level); sc->config.txpowlimit = 2 * conf->power_level; diff --git a/package/mac80211/patches/561-ath9k_fix_flush.patch b/package/mac80211/patches/562-ath9k_fix_flush.patch similarity index 87% rename from package/mac80211/patches/561-ath9k_fix_flush.patch rename to package/mac80211/patches/562-ath9k_fix_flush.patch index df2089060..a5329adc9 100644 --- a/package/mac80211/patches/561-ath9k_fix_flush.patch +++ b/package/mac80211/patches/562-ath9k_fix_flush.patch @@ -1,6 +1,6 @@ --- a/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; } @@ -10,7 +10,7 @@ for (j = 0; j < timeout; j++) { 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) diff --git a/package/mac80211/patches/562-ath9k_fix_led.patch b/package/mac80211/patches/562-ath9k_fix_led.patch deleted file mode 100644 index 0ef16684b..000000000 --- a/package/mac80211/patches/562-ath9k_fix_led.patch +++ /dev/null @@ -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); - diff --git a/package/mac80211/patches/563-ath9k_fix_full_sleep_tx.patch b/package/mac80211/patches/563-ath9k_fix_full_sleep_tx.patch deleted file mode 100644 index 17575b9e4..000000000 --- a/package/mac80211/patches/563-ath9k_fix_full_sleep_tx.patch +++ /dev/null @@ -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",