diff options
author | Vivek Natarajan <vnatarajan@atheros.com> | 2010-04-27 03:35:37 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2010-04-27 16:09:21 -0400 |
commit | 8a8572a821e5763525f5e4ac104bc28fd798fd5e (patch) | |
tree | a44cbed64f207cd8edc982e7ae0873e6aedd2252 | |
parent | 7b7b5e56d7bdfdd0eb5ea13e6c9613b16b8eac46 (diff) |
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>
-rw-r--r-- | drivers/net/wireless/ath/ath9k/htc.h | 1 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/htc_drv_main.c | 71 |
2 files changed, 53 insertions, 19 deletions
diff --git a/drivers/net/wireless/ath/ath9k/htc.h b/drivers/net/wireless/ath/ath9k/htc.h index b771e20075a5..1ae18bbc4d9e 100644 --- a/drivers/net/wireless/ath/ath9k/htc.h +++ b/drivers/net/wireless/ath/ath9k/htc.h | |||
@@ -379,6 +379,7 @@ struct ath9k_htc_priv { | |||
379 | struct mutex htc_pm_lock; | 379 | struct mutex htc_pm_lock; |
380 | unsigned long ps_usecount; | 380 | unsigned long ps_usecount; |
381 | bool ps_enabled; | 381 | bool ps_enabled; |
382 | bool ps_idle; | ||
382 | 383 | ||
383 | struct ath_led radio_led; | 384 | struct ath_led radio_led; |
384 | struct ath_led assoc_led; | 385 | struct ath_led assoc_led; |
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_main.c b/drivers/net/wireless/ath/ath9k/htc_drv_main.c index 644776a51ac0..ca7f3a78eb11 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_main.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_main.c | |||
@@ -94,8 +94,11 @@ void ath9k_htc_ps_restore(struct ath9k_htc_priv *priv) | |||
94 | if (--priv->ps_usecount != 0) | 94 | if (--priv->ps_usecount != 0) |
95 | goto unlock; | 95 | goto unlock; |
96 | 96 | ||
97 | if (priv->ps_enabled) | 97 | if (priv->ps_idle) |
98 | ath9k_hw_setpower(priv->ah, ATH9K_PM_FULL_SLEEP); | ||
99 | else if (priv->ps_enabled) | ||
98 | ath9k_hw_setpower(priv->ah, ATH9K_PM_NETWORK_SLEEP); | 100 | ath9k_hw_setpower(priv->ah, ATH9K_PM_NETWORK_SLEEP); |
101 | |||
99 | unlock: | 102 | unlock: |
100 | mutex_unlock(&priv->htc_pm_lock); | 103 | mutex_unlock(&priv->htc_pm_lock); |
101 | } | 104 | } |
@@ -1096,7 +1099,7 @@ fail_tx: | |||
1096 | return 0; | 1099 | return 0; |
1097 | } | 1100 | } |
1098 | 1101 | ||
1099 | static int ath9k_htc_start(struct ieee80211_hw *hw) | 1102 | static int ath9k_htc_radio_enable(struct ieee80211_hw *hw) |
1100 | { | 1103 | { |
1101 | struct ath9k_htc_priv *priv = hw->priv; | 1104 | struct ath9k_htc_priv *priv = hw->priv; |
1102 | struct ath_hw *ah = priv->ah; | 1105 | struct ath_hw *ah = priv->ah; |
@@ -1112,8 +1115,6 @@ static int ath9k_htc_start(struct ieee80211_hw *hw) | |||
1112 | "Starting driver with initial channel: %d MHz\n", | 1115 | "Starting driver with initial channel: %d MHz\n", |
1113 | curchan->center_freq); | 1116 | curchan->center_freq); |
1114 | 1117 | ||
1115 | mutex_lock(&priv->mutex); | ||
1116 | |||
1117 | /* setup initial channel */ | 1118 | /* setup initial channel */ |
1118 | init_channel = ath9k_cmn_get_curchannel(hw, ah); | 1119 | init_channel = ath9k_cmn_get_curchannel(hw, ah); |
1119 | 1120 | ||
@@ -1126,7 +1127,7 @@ static int ath9k_htc_start(struct ieee80211_hw *hw) | |||
1126 | ath_print(common, ATH_DBG_FATAL, | 1127 | ath_print(common, ATH_DBG_FATAL, |
1127 | "Unable to reset hardware; reset status %d " | 1128 | "Unable to reset hardware; reset status %d " |
1128 | "(freq %u MHz)\n", ret, curchan->center_freq); | 1129 | "(freq %u MHz)\n", ret, curchan->center_freq); |
1129 | goto mutex_unlock; | 1130 | return ret; |
1130 | } | 1131 | } |
1131 | 1132 | ||
1132 | ath_update_txpow(priv); | 1133 | ath_update_txpow(priv); |
@@ -1134,16 +1135,8 @@ static int ath9k_htc_start(struct ieee80211_hw *hw) | |||
1134 | mode = ath9k_htc_get_curmode(priv, init_channel); | 1135 | mode = ath9k_htc_get_curmode(priv, init_channel); |
1135 | htc_mode = cpu_to_be16(mode); | 1136 | htc_mode = cpu_to_be16(mode); |
1136 | WMI_CMD_BUF(WMI_SET_MODE_CMDID, &htc_mode); | 1137 | WMI_CMD_BUF(WMI_SET_MODE_CMDID, &htc_mode); |
1137 | if (ret) | ||
1138 | goto mutex_unlock; | ||
1139 | |||
1140 | WMI_CMD(WMI_ATH_INIT_CMDID); | 1138 | WMI_CMD(WMI_ATH_INIT_CMDID); |
1141 | if (ret) | ||
1142 | goto mutex_unlock; | ||
1143 | |||
1144 | WMI_CMD(WMI_START_RECV_CMDID); | 1139 | WMI_CMD(WMI_START_RECV_CMDID); |
1145 | if (ret) | ||
1146 | goto mutex_unlock; | ||
1147 | 1140 | ||
1148 | ath9k_host_rx_init(priv); | 1141 | ath9k_host_rx_init(priv); |
1149 | 1142 | ||
@@ -1156,12 +1149,22 @@ static int ath9k_htc_start(struct ieee80211_hw *hw) | |||
1156 | 1149 | ||
1157 | ieee80211_wake_queues(hw); | 1150 | ieee80211_wake_queues(hw); |
1158 | 1151 | ||
1159 | mutex_unlock: | 1152 | return ret; |
1153 | } | ||
1154 | |||
1155 | static int ath9k_htc_start(struct ieee80211_hw *hw) | ||
1156 | { | ||
1157 | struct ath9k_htc_priv *priv = hw->priv; | ||
1158 | int ret = 0; | ||
1159 | |||
1160 | mutex_lock(&priv->mutex); | ||
1161 | ret = ath9k_htc_radio_enable(hw); | ||
1160 | mutex_unlock(&priv->mutex); | 1162 | mutex_unlock(&priv->mutex); |
1163 | |||
1161 | return ret; | 1164 | return ret; |
1162 | } | 1165 | } |
1163 | 1166 | ||
1164 | static void ath9k_htc_stop(struct ieee80211_hw *hw) | 1167 | static void ath9k_htc_radio_disable(struct ieee80211_hw *hw) |
1165 | { | 1168 | { |
1166 | struct ath9k_htc_priv *priv = hw->priv; | 1169 | struct ath9k_htc_priv *priv = hw->priv; |
1167 | struct ath_hw *ah = priv->ah; | 1170 | struct ath_hw *ah = priv->ah; |
@@ -1169,11 +1172,8 @@ static void ath9k_htc_stop(struct ieee80211_hw *hw) | |||
1169 | int ret = 0; | 1172 | int ret = 0; |
1170 | u8 cmd_rsp; | 1173 | u8 cmd_rsp; |
1171 | 1174 | ||
1172 | mutex_lock(&priv->mutex); | ||
1173 | |||
1174 | if (priv->op_flags & OP_INVALID) { | 1175 | if (priv->op_flags & OP_INVALID) { |
1175 | ath_print(common, ATH_DBG_ANY, "Device not present\n"); | 1176 | ath_print(common, ATH_DBG_ANY, "Device not present\n"); |
1176 | mutex_unlock(&priv->mutex); | ||
1177 | return; | 1177 | return; |
1178 | } | 1178 | } |
1179 | 1179 | ||
@@ -1208,11 +1208,20 @@ static void ath9k_htc_stop(struct ieee80211_hw *hw) | |||
1208 | } | 1208 | } |
1209 | 1209 | ||
1210 | priv->op_flags |= OP_INVALID; | 1210 | priv->op_flags |= OP_INVALID; |
1211 | mutex_unlock(&priv->mutex); | ||
1212 | 1211 | ||
1213 | ath_print(common, ATH_DBG_CONFIG, "Driver halt\n"); | 1212 | ath_print(common, ATH_DBG_CONFIG, "Driver halt\n"); |
1214 | } | 1213 | } |
1215 | 1214 | ||
1215 | static void ath9k_htc_stop(struct ieee80211_hw *hw) | ||
1216 | { | ||
1217 | struct ath9k_htc_priv *priv = hw->priv; | ||
1218 | |||
1219 | mutex_lock(&priv->mutex); | ||
1220 | ath9k_htc_radio_disable(hw); | ||
1221 | mutex_unlock(&priv->mutex); | ||
1222 | } | ||
1223 | |||
1224 | |||
1216 | static int ath9k_htc_add_interface(struct ieee80211_hw *hw, | 1225 | static int ath9k_htc_add_interface(struct ieee80211_hw *hw, |
1217 | struct ieee80211_vif *vif) | 1226 | struct ieee80211_vif *vif) |
1218 | { | 1227 | { |
@@ -1326,6 +1335,23 @@ static int ath9k_htc_config(struct ieee80211_hw *hw, u32 changed) | |||
1326 | 1335 | ||
1327 | mutex_lock(&priv->mutex); | 1336 | mutex_lock(&priv->mutex); |
1328 | 1337 | ||
1338 | if (changed & IEEE80211_CONF_CHANGE_IDLE) { | ||
1339 | bool enable_radio = false; | ||
1340 | bool idle = !!(conf->flags & IEEE80211_CONF_IDLE); | ||
1341 | |||
1342 | if (!idle && priv->ps_idle) | ||
1343 | enable_radio = true; | ||
1344 | |||
1345 | priv->ps_idle = idle; | ||
1346 | |||
1347 | if (enable_radio) { | ||
1348 | ath9k_htc_setpower(priv, ATH9K_PM_AWAKE); | ||
1349 | ath9k_htc_radio_enable(hw); | ||
1350 | ath_print(common, ATH_DBG_CONFIG, | ||
1351 | "not-idle: enabling radio\n"); | ||
1352 | } | ||
1353 | } | ||
1354 | |||
1329 | if (changed & IEEE80211_CONF_CHANGE_CHANNEL) { | 1355 | if (changed & IEEE80211_CONF_CHANGE_CHANNEL) { |
1330 | struct ieee80211_channel *curchan = hw->conf.channel; | 1356 | struct ieee80211_channel *curchan = hw->conf.channel; |
1331 | int pos = curchan->hw_value; | 1357 | int pos = curchan->hw_value; |
@@ -1369,6 +1395,13 @@ static int ath9k_htc_config(struct ieee80211_hw *hw, u32 changed) | |||
1369 | } | 1395 | } |
1370 | } | 1396 | } |
1371 | 1397 | ||
1398 | if (priv->ps_idle) { | ||
1399 | ath_print(common, ATH_DBG_CONFIG, | ||
1400 | "idle: disabling radio\n"); | ||
1401 | ath9k_htc_radio_disable(hw); | ||
1402 | } | ||
1403 | |||
1404 | |||
1372 | mutex_unlock(&priv->mutex); | 1405 | mutex_unlock(&priv->mutex); |
1373 | 1406 | ||
1374 | return 0; | 1407 | return 0; |