diff options
author | Sujith Manoharan | 2012-06-25 10:24:49 +0200 |
---|---|---|
committer | John W. Linville | 2012-06-26 20:28:52 +0200 |
commit | 6bcfe67f9865fb51ec78fc9b09887375db7e08b5 (patch) | |
tree | a2483b522edc9672842527985eb423bafba0473c /drivers/net/wireless/ath/ath9k/htc_drv_main.c | |
parent | ath9k_htc: Use atomic operations for op_flags (diff) | |
download | kernel-qcow2-linux-6bcfe67f9865fb51ec78fc9b09887375db7e08b5.tar.gz kernel-qcow2-linux-6bcfe67f9865fb51ec78fc9b09887375db7e08b5.tar.xz kernel-qcow2-linux-6bcfe67f9865fb51ec78fc9b09887375db7e08b5.zip |
ath9k_htc: Fix IDLE power save
Remove the radio enable/disable stuff and fix the
transition to FULL_SLEEP mode when the device is idle.
Signed-off-by: Sujith Manoharan <c_manoha@qca.qualcomm.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/ath/ath9k/htc_drv_main.c')
-rw-r--r-- | drivers/net/wireless/ath/ath9k/htc_drv_main.c | 50 |
1 files changed, 20 insertions, 30 deletions
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_main.c b/drivers/net/wireless/ath/ath9k/htc_drv_main.c index 0fc0d35414c0..fc8cd8284108 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_main.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_main.c @@ -75,14 +75,19 @@ unlock: void ath9k_htc_ps_restore(struct ath9k_htc_priv *priv) { + bool reset; + mutex_lock(&priv->htc_pm_lock); if (--priv->ps_usecount != 0) goto unlock; - if (priv->ps_idle) + if (priv->ps_idle) { + ath9k_hw_setrxabort(priv->ah, true); + ath9k_hw_stopdmarecv(priv->ah, &reset); ath9k_hw_setpower(priv->ah, ATH9K_PM_FULL_SLEEP); - else if (priv->ps_enabled) + } else if (priv->ps_enabled) { ath9k_hw_setpower(priv->ah, ATH9K_PM_NETWORK_SLEEP); + } unlock: mutex_unlock(&priv->htc_pm_lock); @@ -1178,24 +1183,20 @@ static int ath9k_htc_config(struct ieee80211_hw *hw, u32 changed) struct ath9k_htc_priv *priv = hw->priv; struct ath_common *common = ath9k_hw_common(priv->ah); struct ieee80211_conf *conf = &hw->conf; + bool chip_reset = false; + int ret = 0; mutex_lock(&priv->mutex); + ath9k_htc_ps_wakeup(priv); if (changed & IEEE80211_CONF_CHANGE_IDLE) { - bool enable_radio = false; - bool idle = !!(conf->flags & IEEE80211_CONF_IDLE); - mutex_lock(&priv->htc_pm_lock); - if (!idle && priv->ps_idle) - enable_radio = true; - priv->ps_idle = idle; - mutex_unlock(&priv->htc_pm_lock); - if (enable_radio) { - ath_dbg(common, CONFIG, "not-idle: enabling radio\n"); - ath9k_htc_setpower(priv, ATH9K_PM_AWAKE); - ath9k_htc_radio_enable(hw); - } + priv->ps_idle = !!(conf->flags & IEEE80211_CONF_IDLE); + if (priv->ps_idle) + chip_reset = true; + + mutex_unlock(&priv->htc_pm_lock); } /* @@ -1210,7 +1211,7 @@ static int ath9k_htc_config(struct ieee80211_hw *hw, u32 changed) ath9k_htc_remove_monitor_interface(priv); } - if (changed & IEEE80211_CONF_CHANGE_CHANNEL) { + if ((changed & IEEE80211_CONF_CHANGE_CHANNEL) || chip_reset) { struct ieee80211_channel *curchan = hw->conf.channel; int pos = curchan->hw_value; @@ -1223,8 +1224,8 @@ static int ath9k_htc_config(struct ieee80211_hw *hw, u32 changed) if (ath9k_htc_set_channel(priv, hw, &priv->ah->channels[pos]) < 0) { ath_err(common, "Unable to set channel\n"); - mutex_unlock(&priv->mutex); - return -EINVAL; + ret = -EINVAL; + goto out; } } @@ -1246,21 +1247,10 @@ static int ath9k_htc_config(struct ieee80211_hw *hw, u32 changed) priv->txpowlimit, &priv->curtxpow); } - if (changed & IEEE80211_CONF_CHANGE_IDLE) { - mutex_lock(&priv->htc_pm_lock); - if (!priv->ps_idle) { - mutex_unlock(&priv->htc_pm_lock); - goto out; - } - mutex_unlock(&priv->htc_pm_lock); - - ath_dbg(common, CONFIG, "idle: disabling radio\n"); - ath9k_htc_radio_disable(hw); - } - out: + ath9k_htc_ps_restore(priv); mutex_unlock(&priv->mutex); - return 0; + return ret; } #define SUPPORTED_FILTERS \ |