diff options
Diffstat (limited to 'drivers/net/wireless/ath/ath9k/htc_drv_main.c')
-rw-r--r-- | drivers/net/wireless/ath/ath9k/htc_drv_main.c | 84 |
1 files changed, 59 insertions, 25 deletions
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_main.c b/drivers/net/wireless/ath/ath9k/htc_drv_main.c index ec7bcc8696ec..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 | } |
@@ -153,7 +156,6 @@ static int ath9k_htc_set_channel(struct ath9k_htc_priv *priv, | |||
153 | ath_print(common, ATH_DBG_FATAL, | 156 | ath_print(common, ATH_DBG_FATAL, |
154 | "Unable to reset channel (%u Mhz) " | 157 | "Unable to reset channel (%u Mhz) " |
155 | "reset status %d\n", channel->center_freq, ret); | 158 | "reset status %d\n", channel->center_freq, ret); |
156 | ath9k_htc_ps_restore(priv); | ||
157 | goto err; | 159 | goto err; |
158 | } | 160 | } |
159 | 161 | ||
@@ -1097,7 +1099,7 @@ fail_tx: | |||
1097 | return 0; | 1099 | return 0; |
1098 | } | 1100 | } |
1099 | 1101 | ||
1100 | static int ath9k_htc_start(struct ieee80211_hw *hw) | 1102 | static int ath9k_htc_radio_enable(struct ieee80211_hw *hw) |
1101 | { | 1103 | { |
1102 | struct ath9k_htc_priv *priv = hw->priv; | 1104 | struct ath9k_htc_priv *priv = hw->priv; |
1103 | struct ath_hw *ah = priv->ah; | 1105 | struct ath_hw *ah = priv->ah; |
@@ -1113,8 +1115,6 @@ static int ath9k_htc_start(struct ieee80211_hw *hw) | |||
1113 | "Starting driver with initial channel: %d MHz\n", | 1115 | "Starting driver with initial channel: %d MHz\n", |
1114 | curchan->center_freq); | 1116 | curchan->center_freq); |
1115 | 1117 | ||
1116 | mutex_lock(&priv->mutex); | ||
1117 | |||
1118 | /* setup initial channel */ | 1118 | /* setup initial channel */ |
1119 | init_channel = ath9k_cmn_get_curchannel(hw, ah); | 1119 | init_channel = ath9k_cmn_get_curchannel(hw, ah); |
1120 | 1120 | ||
@@ -1127,7 +1127,7 @@ static int ath9k_htc_start(struct ieee80211_hw *hw) | |||
1127 | ath_print(common, ATH_DBG_FATAL, | 1127 | ath_print(common, ATH_DBG_FATAL, |
1128 | "Unable to reset hardware; reset status %d " | 1128 | "Unable to reset hardware; reset status %d " |
1129 | "(freq %u MHz)\n", ret, curchan->center_freq); | 1129 | "(freq %u MHz)\n", ret, curchan->center_freq); |
1130 | goto mutex_unlock; | 1130 | return ret; |
1131 | } | 1131 | } |
1132 | 1132 | ||
1133 | ath_update_txpow(priv); | 1133 | ath_update_txpow(priv); |
@@ -1135,16 +1135,8 @@ static int ath9k_htc_start(struct ieee80211_hw *hw) | |||
1135 | mode = ath9k_htc_get_curmode(priv, init_channel); | 1135 | mode = ath9k_htc_get_curmode(priv, init_channel); |
1136 | htc_mode = cpu_to_be16(mode); | 1136 | htc_mode = cpu_to_be16(mode); |
1137 | WMI_CMD_BUF(WMI_SET_MODE_CMDID, &htc_mode); | 1137 | WMI_CMD_BUF(WMI_SET_MODE_CMDID, &htc_mode); |
1138 | if (ret) | ||
1139 | goto mutex_unlock; | ||
1140 | |||
1141 | WMI_CMD(WMI_ATH_INIT_CMDID); | 1138 | WMI_CMD(WMI_ATH_INIT_CMDID); |
1142 | if (ret) | ||
1143 | goto mutex_unlock; | ||
1144 | |||
1145 | WMI_CMD(WMI_START_RECV_CMDID); | 1139 | WMI_CMD(WMI_START_RECV_CMDID); |
1146 | if (ret) | ||
1147 | goto mutex_unlock; | ||
1148 | 1140 | ||
1149 | ath9k_host_rx_init(priv); | 1141 | ath9k_host_rx_init(priv); |
1150 | 1142 | ||
@@ -1157,12 +1149,22 @@ static int ath9k_htc_start(struct ieee80211_hw *hw) | |||
1157 | 1149 | ||
1158 | ieee80211_wake_queues(hw); | 1150 | ieee80211_wake_queues(hw); |
1159 | 1151 | ||
1160 | 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); | ||
1161 | mutex_unlock(&priv->mutex); | 1162 | mutex_unlock(&priv->mutex); |
1163 | |||
1162 | return ret; | 1164 | return ret; |
1163 | } | 1165 | } |
1164 | 1166 | ||
1165 | static void ath9k_htc_stop(struct ieee80211_hw *hw) | 1167 | static void ath9k_htc_radio_disable(struct ieee80211_hw *hw) |
1166 | { | 1168 | { |
1167 | struct ath9k_htc_priv *priv = hw->priv; | 1169 | struct ath9k_htc_priv *priv = hw->priv; |
1168 | struct ath_hw *ah = priv->ah; | 1170 | struct ath_hw *ah = priv->ah; |
@@ -1170,14 +1172,18 @@ static void ath9k_htc_stop(struct ieee80211_hw *hw) | |||
1170 | int ret = 0; | 1172 | int ret = 0; |
1171 | u8 cmd_rsp; | 1173 | u8 cmd_rsp; |
1172 | 1174 | ||
1173 | mutex_lock(&priv->mutex); | ||
1174 | |||
1175 | if (priv->op_flags & OP_INVALID) { | 1175 | if (priv->op_flags & OP_INVALID) { |
1176 | ath_print(common, ATH_DBG_ANY, "Device not present\n"); | 1176 | ath_print(common, ATH_DBG_ANY, "Device not present\n"); |
1177 | mutex_unlock(&priv->mutex); | ||
1178 | return; | 1177 | return; |
1179 | } | 1178 | } |
1180 | 1179 | ||
1180 | /* Cancel all the running timers/work .. */ | ||
1181 | cancel_work_sync(&priv->ps_work); | ||
1182 | cancel_delayed_work_sync(&priv->ath9k_ani_work); | ||
1183 | cancel_delayed_work_sync(&priv->ath9k_aggr_work); | ||
1184 | cancel_delayed_work_sync(&priv->ath9k_led_blink_work); | ||
1185 | ath9k_led_stop_brightness(priv); | ||
1186 | |||
1181 | ath9k_htc_ps_wakeup(priv); | 1187 | ath9k_htc_ps_wakeup(priv); |
1182 | htc_stop(priv->htc); | 1188 | htc_stop(priv->htc); |
1183 | WMI_CMD(WMI_DISABLE_INTR_CMDID); | 1189 | WMI_CMD(WMI_DISABLE_INTR_CMDID); |
@@ -1189,11 +1195,6 @@ static void ath9k_htc_stop(struct ieee80211_hw *hw) | |||
1189 | ath9k_htc_ps_restore(priv); | 1195 | ath9k_htc_ps_restore(priv); |
1190 | ath9k_htc_setpower(priv, ATH9K_PM_FULL_SLEEP); | 1196 | ath9k_htc_setpower(priv, ATH9K_PM_FULL_SLEEP); |
1191 | 1197 | ||
1192 | cancel_work_sync(&priv->ps_work); | ||
1193 | cancel_delayed_work_sync(&priv->ath9k_ani_work); | ||
1194 | cancel_delayed_work_sync(&priv->ath9k_aggr_work); | ||
1195 | cancel_delayed_work_sync(&priv->ath9k_led_blink_work); | ||
1196 | ath9k_led_stop_brightness(priv); | ||
1197 | skb_queue_purge(&priv->tx_queue); | 1198 | skb_queue_purge(&priv->tx_queue); |
1198 | 1199 | ||
1199 | /* Remove monitor interface here */ | 1200 | /* Remove monitor interface here */ |
@@ -1207,11 +1208,20 @@ static void ath9k_htc_stop(struct ieee80211_hw *hw) | |||
1207 | } | 1208 | } |
1208 | 1209 | ||
1209 | priv->op_flags |= OP_INVALID; | 1210 | priv->op_flags |= OP_INVALID; |
1210 | mutex_unlock(&priv->mutex); | ||
1211 | 1211 | ||
1212 | ath_print(common, ATH_DBG_CONFIG, "Driver halt\n"); | 1212 | ath_print(common, ATH_DBG_CONFIG, "Driver halt\n"); |
1213 | } | 1213 | } |
1214 | 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 | |||
1215 | static int ath9k_htc_add_interface(struct ieee80211_hw *hw, | 1225 | static int ath9k_htc_add_interface(struct ieee80211_hw *hw, |
1216 | struct ieee80211_vif *vif) | 1226 | struct ieee80211_vif *vif) |
1217 | { | 1227 | { |
@@ -1325,6 +1335,23 @@ static int ath9k_htc_config(struct ieee80211_hw *hw, u32 changed) | |||
1325 | 1335 | ||
1326 | mutex_lock(&priv->mutex); | 1336 | mutex_lock(&priv->mutex); |
1327 | 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 | |||
1328 | if (changed & IEEE80211_CONF_CHANGE_CHANNEL) { | 1355 | if (changed & IEEE80211_CONF_CHANGE_CHANNEL) { |
1329 | struct ieee80211_channel *curchan = hw->conf.channel; | 1356 | struct ieee80211_channel *curchan = hw->conf.channel; |
1330 | int pos = curchan->hw_value; | 1357 | int pos = curchan->hw_value; |
@@ -1368,6 +1395,13 @@ static int ath9k_htc_config(struct ieee80211_hw *hw, u32 changed) | |||
1368 | } | 1395 | } |
1369 | } | 1396 | } |
1370 | 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 | |||
1371 | mutex_unlock(&priv->mutex); | 1405 | mutex_unlock(&priv->mutex); |
1372 | 1406 | ||
1373 | return 0; | 1407 | return 0; |