ath9k_htc: Handle CONF_IDLE during unassociated state to save power.

Signed-off-by: Vivek Natarajan <vnatarajan@atheros.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
This commit is contained in:
Vivek Natarajan 2010-04-27 13:05:37 +05:30 committed by John W. Linville
parent 7b7b5e56d7
commit 8a8572a821
2 changed files with 54 additions and 20 deletions

View File

@ -379,6 +379,7 @@ struct ath9k_htc_priv {
struct mutex htc_pm_lock;
unsigned long ps_usecount;
bool ps_enabled;
bool ps_idle;
struct ath_led radio_led;
struct ath_led assoc_led;

View File

@ -94,8 +94,11 @@ void ath9k_htc_ps_restore(struct ath9k_htc_priv *priv)
if (--priv->ps_usecount != 0)
goto unlock;
if (priv->ps_enabled)
if (priv->ps_idle)
ath9k_hw_setpower(priv->ah, ATH9K_PM_FULL_SLEEP);
else if (priv->ps_enabled)
ath9k_hw_setpower(priv->ah, ATH9K_PM_NETWORK_SLEEP);
unlock:
mutex_unlock(&priv->htc_pm_lock);
}
@ -1096,7 +1099,7 @@ static int ath9k_htc_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
return 0;
}
static int ath9k_htc_start(struct ieee80211_hw *hw)
static int ath9k_htc_radio_enable(struct ieee80211_hw *hw)
{
struct ath9k_htc_priv *priv = hw->priv;
struct ath_hw *ah = priv->ah;
@ -1112,8 +1115,6 @@ static int ath9k_htc_start(struct ieee80211_hw *hw)
"Starting driver with initial channel: %d MHz\n",
curchan->center_freq);
mutex_lock(&priv->mutex);
/* setup initial channel */
init_channel = ath9k_cmn_get_curchannel(hw, ah);
@ -1126,7 +1127,7 @@ static int ath9k_htc_start(struct ieee80211_hw *hw)
ath_print(common, ATH_DBG_FATAL,
"Unable to reset hardware; reset status %d "
"(freq %u MHz)\n", ret, curchan->center_freq);
goto mutex_unlock;
return ret;
}
ath_update_txpow(priv);
@ -1134,16 +1135,8 @@ static int ath9k_htc_start(struct ieee80211_hw *hw)
mode = ath9k_htc_get_curmode(priv, init_channel);
htc_mode = cpu_to_be16(mode);
WMI_CMD_BUF(WMI_SET_MODE_CMDID, &htc_mode);
if (ret)
goto mutex_unlock;
WMI_CMD(WMI_ATH_INIT_CMDID);
if (ret)
goto mutex_unlock;
WMI_CMD(WMI_START_RECV_CMDID);
if (ret)
goto mutex_unlock;
ath9k_host_rx_init(priv);
@ -1156,12 +1149,22 @@ static int ath9k_htc_start(struct ieee80211_hw *hw)
ieee80211_wake_queues(hw);
mutex_unlock:
mutex_unlock(&priv->mutex);
return ret;
}
static void ath9k_htc_stop(struct ieee80211_hw *hw)
static int ath9k_htc_start(struct ieee80211_hw *hw)
{
struct ath9k_htc_priv *priv = hw->priv;
int ret = 0;
mutex_lock(&priv->mutex);
ret = ath9k_htc_radio_enable(hw);
mutex_unlock(&priv->mutex);
return ret;
}
static void ath9k_htc_radio_disable(struct ieee80211_hw *hw)
{
struct ath9k_htc_priv *priv = hw->priv;
struct ath_hw *ah = priv->ah;
@ -1169,11 +1172,8 @@ static void ath9k_htc_stop(struct ieee80211_hw *hw)
int ret = 0;
u8 cmd_rsp;
mutex_lock(&priv->mutex);
if (priv->op_flags & OP_INVALID) {
ath_print(common, ATH_DBG_ANY, "Device not present\n");
mutex_unlock(&priv->mutex);
return;
}
@ -1208,11 +1208,20 @@ static void ath9k_htc_stop(struct ieee80211_hw *hw)
}
priv->op_flags |= OP_INVALID;
mutex_unlock(&priv->mutex);
ath_print(common, ATH_DBG_CONFIG, "Driver halt\n");
}
static void ath9k_htc_stop(struct ieee80211_hw *hw)
{
struct ath9k_htc_priv *priv = hw->priv;
mutex_lock(&priv->mutex);
ath9k_htc_radio_disable(hw);
mutex_unlock(&priv->mutex);
}
static int ath9k_htc_add_interface(struct ieee80211_hw *hw,
struct ieee80211_vif *vif)
{
@ -1326,6 +1335,23 @@ static int ath9k_htc_config(struct ieee80211_hw *hw, u32 changed)
mutex_lock(&priv->mutex);
if (changed & IEEE80211_CONF_CHANGE_IDLE) {
bool enable_radio = false;
bool idle = !!(conf->flags & IEEE80211_CONF_IDLE);
if (!idle && priv->ps_idle)
enable_radio = true;
priv->ps_idle = idle;
if (enable_radio) {
ath9k_htc_setpower(priv, ATH9K_PM_AWAKE);
ath9k_htc_radio_enable(hw);
ath_print(common, ATH_DBG_CONFIG,
"not-idle: enabling radio\n");
}
}
if (changed & IEEE80211_CONF_CHANGE_CHANNEL) {
struct ieee80211_channel *curchan = hw->conf.channel;
int pos = curchan->hw_value;
@ -1369,6 +1395,13 @@ static int ath9k_htc_config(struct ieee80211_hw *hw, u32 changed)
}
}
if (priv->ps_idle) {
ath_print(common, ATH_DBG_CONFIG,
"idle: disabling radio\n");
ath9k_htc_radio_disable(hw);
}
mutex_unlock(&priv->mutex);
return 0;