aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/ath9k/main.c
diff options
context:
space:
mode:
authorVivek Natarajan <vivek.natraj@gmail.com>2009-01-20 00:47:08 -0500
committerJohn W. Linville <linville@tuxdriver.com>2009-01-29 16:01:03 -0500
commit3cbb5dd73697b3f1c677daffe29f00ace22b71e9 (patch)
tree39fcb371ef37b9a2a53a4cdf72a8e98c64d9e98e /drivers/net/wireless/ath9k/main.c
parentc5d0569882b9c264be31dcb0758961bfc479deea (diff)
ath9k: Enable dynamic power save in ath9k.
This patch implements dynamic power save feature for ath9k. Signed-off-by: Vivek Natarajan <vnatarajan@atheros.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/ath9k/main.c')
-rw-r--r--drivers/net/wireless/ath9k/main.c39
1 files changed, 38 insertions, 1 deletions
diff --git a/drivers/net/wireless/ath9k/main.c b/drivers/net/wireless/ath9k/main.c
index 8ad927a8870c..b494a0d7e8b5 100644
--- a/drivers/net/wireless/ath9k/main.c
+++ b/drivers/net/wireless/ath9k/main.c
@@ -237,6 +237,8 @@ static int ath_set_channel(struct ath_softc *sc, struct ath9k_channel *hchan)
237 if (sc->sc_flags & SC_OP_INVALID) 237 if (sc->sc_flags & SC_OP_INVALID)
238 return -EIO; 238 return -EIO;
239 239
240 ath9k_ps_wakeup(sc);
241
240 /* 242 /*
241 * This is only performed if the channel settings have 243 * This is only performed if the channel settings have
242 * actually changed. 244 * actually changed.
@@ -287,6 +289,7 @@ static int ath_set_channel(struct ath_softc *sc, struct ath9k_channel *hchan)
287 ath_cache_conf_rate(sc, &hw->conf); 289 ath_cache_conf_rate(sc, &hw->conf);
288 ath_update_txpow(sc); 290 ath_update_txpow(sc);
289 ath9k_hw_set_interrupts(ah, sc->sc_imask); 291 ath9k_hw_set_interrupts(ah, sc->sc_imask);
292 ath9k_ps_restore(sc);
290 return 0; 293 return 0;
291} 294}
292 295
@@ -559,8 +562,10 @@ irqreturn_t ath_isr(int irq, void *dev)
559 ATH9K_HW_CAP_AUTOSLEEP)) { 562 ATH9K_HW_CAP_AUTOSLEEP)) {
560 /* Clear RxAbort bit so that we can 563 /* Clear RxAbort bit so that we can
561 * receive frames */ 564 * receive frames */
565 ath9k_hw_setpower(ah, ATH9K_PM_AWAKE);
562 ath9k_hw_setrxabort(ah, 0); 566 ath9k_hw_setrxabort(ah, 0);
563 sched = true; 567 sched = true;
568 sc->sc_flags |= SC_OP_WAIT_FOR_BEACON;
564 } 569 }
565 } 570 }
566 } 571 }
@@ -1044,6 +1049,7 @@ static void ath_radio_enable(struct ath_softc *sc)
1044 struct ieee80211_channel *channel = sc->hw->conf.channel; 1049 struct ieee80211_channel *channel = sc->hw->conf.channel;
1045 int r; 1050 int r;
1046 1051
1052 ath9k_ps_wakeup(sc);
1047 spin_lock_bh(&sc->sc_resetlock); 1053 spin_lock_bh(&sc->sc_resetlock);
1048 1054
1049 r = ath9k_hw_reset(ah, ah->ah_curchan, false); 1055 r = ath9k_hw_reset(ah, ah->ah_curchan, false);
@@ -1075,6 +1081,7 @@ static void ath_radio_enable(struct ath_softc *sc)
1075 ath9k_hw_set_gpio(ah, ATH_LED_PIN, 0); 1081 ath9k_hw_set_gpio(ah, ATH_LED_PIN, 0);
1076 1082
1077 ieee80211_wake_queues(sc->hw); 1083 ieee80211_wake_queues(sc->hw);
1084 ath9k_ps_restore(sc);
1078} 1085}
1079 1086
1080static void ath_radio_disable(struct ath_softc *sc) 1087static void ath_radio_disable(struct ath_softc *sc)
@@ -1083,6 +1090,7 @@ static void ath_radio_disable(struct ath_softc *sc)
1083 struct ieee80211_channel *channel = sc->hw->conf.channel; 1090 struct ieee80211_channel *channel = sc->hw->conf.channel;
1084 int r; 1091 int r;
1085 1092
1093 ath9k_ps_wakeup(sc);
1086 ieee80211_stop_queues(sc->hw); 1094 ieee80211_stop_queues(sc->hw);
1087 1095
1088 /* Disable LED */ 1096 /* Disable LED */
@@ -1108,6 +1116,7 @@ static void ath_radio_disable(struct ath_softc *sc)
1108 1116
1109 ath9k_hw_phy_disable(ah); 1117 ath9k_hw_phy_disable(ah);
1110 ath9k_hw_setpower(ah, ATH9K_PM_FULL_SLEEP); 1118 ath9k_hw_setpower(ah, ATH9K_PM_FULL_SLEEP);
1119 ath9k_ps_restore(sc);
1111} 1120}
1112 1121
1113static bool ath_is_rfkill_set(struct ath_softc *sc) 1122static bool ath_is_rfkill_set(struct ath_softc *sc)
@@ -1259,6 +1268,8 @@ void ath_detach(struct ath_softc *sc)
1259 struct ieee80211_hw *hw = sc->hw; 1268 struct ieee80211_hw *hw = sc->hw;
1260 int i = 0; 1269 int i = 0;
1261 1270
1271 ath9k_ps_wakeup(sc);
1272
1262 DPRINTF(sc, ATH_DBG_CONFIG, "Detach ATH hw\n"); 1273 DPRINTF(sc, ATH_DBG_CONFIG, "Detach ATH hw\n");
1263 1274
1264#if defined(CONFIG_RFKILL) || defined(CONFIG_RFKILL_MODULE) 1275#if defined(CONFIG_RFKILL) || defined(CONFIG_RFKILL_MODULE)
@@ -1283,6 +1294,7 @@ void ath_detach(struct ath_softc *sc)
1283 1294
1284 ath9k_hw_detach(sc->sc_ah); 1295 ath9k_hw_detach(sc->sc_ah);
1285 ath9k_exit_debug(sc); 1296 ath9k_exit_debug(sc);
1297 ath9k_ps_restore(sc);
1286} 1298}
1287 1299
1288static int ath_init(u16 devid, struct ath_softc *sc) 1300static int ath_init(u16 devid, struct ath_softc *sc)
@@ -1526,7 +1538,9 @@ int ath_attach(u16 devid, struct ath_softc *sc)
1526 hw->flags = IEEE80211_HW_RX_INCLUDES_FCS | 1538 hw->flags = IEEE80211_HW_RX_INCLUDES_FCS |
1527 IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING | 1539 IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING |
1528 IEEE80211_HW_SIGNAL_DBM | 1540 IEEE80211_HW_SIGNAL_DBM |
1529 IEEE80211_HW_AMPDU_AGGREGATION; 1541 IEEE80211_HW_AMPDU_AGGREGATION |
1542 IEEE80211_HW_SUPPORTS_PS |
1543 IEEE80211_HW_PS_NULLFUNC_STACK;
1530 1544
1531 if (AR_SREV_9160_10_OR_LATER(sc->sc_ah)) 1545 if (AR_SREV_9160_10_OR_LATER(sc->sc_ah))
1532 hw->flags |= IEEE80211_HW_MFP_CAPABLE; 1546 hw->flags |= IEEE80211_HW_MFP_CAPABLE;
@@ -2090,6 +2104,27 @@ static int ath9k_config(struct ieee80211_hw *hw, u32 changed)
2090 struct ieee80211_conf *conf = &hw->conf; 2104 struct ieee80211_conf *conf = &hw->conf;
2091 2105
2092 mutex_lock(&sc->mutex); 2106 mutex_lock(&sc->mutex);
2107 if (changed & IEEE80211_CONF_CHANGE_PS) {
2108 if (conf->flags & IEEE80211_CONF_PS) {
2109 if ((sc->sc_imask & ATH9K_INT_TIM_TIMER) == 0) {
2110 sc->sc_imask |= ATH9K_INT_TIM_TIMER;
2111 ath9k_hw_set_interrupts(sc->sc_ah,
2112 sc->sc_imask);
2113 }
2114 ath9k_hw_setrxabort(sc->sc_ah, 1);
2115 ath9k_hw_setpower(sc->sc_ah, ATH9K_PM_NETWORK_SLEEP);
2116 } else {
2117 ath9k_hw_setpower(sc->sc_ah, ATH9K_PM_AWAKE);
2118 ath9k_hw_setrxabort(sc->sc_ah, 0);
2119 sc->sc_flags &= ~SC_OP_WAIT_FOR_BEACON;
2120 if (sc->sc_imask & ATH9K_INT_TIM_TIMER) {
2121 sc->sc_imask &= ~ATH9K_INT_TIM_TIMER;
2122 ath9k_hw_set_interrupts(sc->sc_ah,
2123 sc->sc_imask);
2124 }
2125 }
2126 }
2127
2093 if (changed & IEEE80211_CONF_CHANGE_CHANNEL) { 2128 if (changed & IEEE80211_CONF_CHANGE_CHANNEL) {
2094 struct ieee80211_channel *curchan = hw->conf.channel; 2129 struct ieee80211_channel *curchan = hw->conf.channel;
2095 int pos; 2130 int pos;
@@ -2310,6 +2345,7 @@ static int ath9k_set_key(struct ieee80211_hw *hw,
2310 struct ath_softc *sc = hw->priv; 2345 struct ath_softc *sc = hw->priv;
2311 int ret = 0; 2346 int ret = 0;
2312 2347
2348 ath9k_ps_wakeup(sc);
2313 DPRINTF(sc, ATH_DBG_KEYCACHE, "Set HW Key\n"); 2349 DPRINTF(sc, ATH_DBG_KEYCACHE, "Set HW Key\n");
2314 2350
2315 switch (cmd) { 2351 switch (cmd) {
@@ -2333,6 +2369,7 @@ static int ath9k_set_key(struct ieee80211_hw *hw,
2333 ret = -EINVAL; 2369 ret = -EINVAL;
2334 } 2370 }
2335 2371
2372 ath9k_ps_restore(sc);
2336 return ret; 2373 return ret;
2337} 2374}
2338 2375