diff options
author | Raja Mani <rmani@qca.qualcomm.com> | 2012-03-21 05:33:38 -0400 |
---|---|---|
committer | Kalle Valo <kvalo@qca.qualcomm.com> | 2012-03-26 09:07:40 -0400 |
commit | 40abc2defbca6a6d7fde49082586430350d0a535 (patch) | |
tree | 64e436a139d706cd8f6088481321eb0ab231c98f | |
parent | 055bde493fc9a41b6b3e45381b454c18e2045d5b (diff) |
ath6kl: Optimize target power in deep sleep suspend
Adding below steps helps to get good power numbers
in deep sleep suspend path,
* Disable WOW mode.
* Flush data packets and wait for all control packets.
to be cleared in TX path before deep sleep suspend.
* Set host sleep mode to SLEEP.
Below steps are added to perform the recovery action
while the system resume from deep sleep,
* Set host sleep mode to AWAKE.
* Reset scan parameters to default value.
In addition, Debug prints are added to track deep sleep
suspend/resume state.
Signed-off-by: Raja Mani <rmani@qca.qualcomm.com>
Signed-off-by: Kalle Valo <kvalo@qca.qualcomm.com>
-rw-r--r-- | drivers/net/wireless/ath/ath6kl/cfg80211.c | 98 |
1 files changed, 81 insertions, 17 deletions
diff --git a/drivers/net/wireless/ath/ath6kl/cfg80211.c b/drivers/net/wireless/ath/ath6kl/cfg80211.c index e3c4c404ba11..80910286d1b8 100644 --- a/drivers/net/wireless/ath/ath6kl/cfg80211.c +++ b/drivers/net/wireless/ath/ath6kl/cfg80211.c | |||
@@ -2130,6 +2130,77 @@ static int ath6kl_wow_resume(struct ath6kl *ar) | |||
2130 | return 0; | 2130 | return 0; |
2131 | } | 2131 | } |
2132 | 2132 | ||
2133 | static int ath6kl_cfg80211_deepsleep_suspend(struct ath6kl *ar) | ||
2134 | { | ||
2135 | struct ath6kl_vif *vif; | ||
2136 | int ret; | ||
2137 | |||
2138 | vif = ath6kl_vif_first(ar); | ||
2139 | if (!vif) | ||
2140 | return -EIO; | ||
2141 | |||
2142 | if (!ath6kl_cfg80211_ready(vif)) | ||
2143 | return -EIO; | ||
2144 | |||
2145 | ath6kl_cfg80211_stop_all(ar); | ||
2146 | |||
2147 | /* Save the current power mode before enabling power save */ | ||
2148 | ar->wmi->saved_pwr_mode = ar->wmi->pwr_mode; | ||
2149 | |||
2150 | ret = ath6kl_wmi_powermode_cmd(ar->wmi, 0, REC_POWER); | ||
2151 | if (ret) | ||
2152 | return ret; | ||
2153 | |||
2154 | /* Disable WOW mode */ | ||
2155 | ret = ath6kl_wmi_set_wow_mode_cmd(ar->wmi, vif->fw_vif_idx, | ||
2156 | ATH6KL_WOW_MODE_DISABLE, | ||
2157 | 0, 0); | ||
2158 | if (ret) | ||
2159 | return ret; | ||
2160 | |||
2161 | /* Flush all non control pkts in TX path */ | ||
2162 | ath6kl_tx_data_cleanup(ar); | ||
2163 | |||
2164 | ret = ath6kl_cfg80211_host_sleep(ar, vif); | ||
2165 | if (ret) | ||
2166 | return ret; | ||
2167 | |||
2168 | return 0; | ||
2169 | } | ||
2170 | |||
2171 | static int ath6kl_cfg80211_deepsleep_resume(struct ath6kl *ar) | ||
2172 | { | ||
2173 | struct ath6kl_vif *vif; | ||
2174 | int ret; | ||
2175 | |||
2176 | vif = ath6kl_vif_first(ar); | ||
2177 | |||
2178 | if (!vif) | ||
2179 | return -EIO; | ||
2180 | |||
2181 | if (ar->wmi->pwr_mode != ar->wmi->saved_pwr_mode) { | ||
2182 | ret = ath6kl_wmi_powermode_cmd(ar->wmi, 0, | ||
2183 | ar->wmi->saved_pwr_mode); | ||
2184 | if (ret) | ||
2185 | return ret; | ||
2186 | } | ||
2187 | |||
2188 | ret = ath6kl_wmi_set_host_sleep_mode_cmd(ar->wmi, vif->fw_vif_idx, | ||
2189 | ATH6KL_HOST_MODE_AWAKE); | ||
2190 | if (ret) | ||
2191 | return ret; | ||
2192 | |||
2193 | ar->state = ATH6KL_STATE_ON; | ||
2194 | |||
2195 | /* Reset scan parameter to default values */ | ||
2196 | ret = ath6kl_wmi_scanparams_cmd(ar->wmi, vif->fw_vif_idx, | ||
2197 | 0, 0, 0, 0, 0, 0, 3, 0, 0, 0); | ||
2198 | if (ret) | ||
2199 | return ret; | ||
2200 | |||
2201 | return 0; | ||
2202 | } | ||
2203 | |||
2133 | int ath6kl_cfg80211_suspend(struct ath6kl *ar, | 2204 | int ath6kl_cfg80211_suspend(struct ath6kl *ar, |
2134 | enum ath6kl_cfg_suspend_mode mode, | 2205 | enum ath6kl_cfg_suspend_mode mode, |
2135 | struct cfg80211_wowlan *wow) | 2206 | struct cfg80211_wowlan *wow) |
@@ -2158,15 +2229,12 @@ int ath6kl_cfg80211_suspend(struct ath6kl *ar, | |||
2158 | 2229 | ||
2159 | case ATH6KL_CFG_SUSPEND_DEEPSLEEP: | 2230 | case ATH6KL_CFG_SUSPEND_DEEPSLEEP: |
2160 | 2231 | ||
2161 | ath6kl_cfg80211_stop_all(ar); | 2232 | ath6kl_dbg(ATH6KL_DBG_SUSPEND, "deep sleep suspend\n"); |
2162 | |||
2163 | /* save the current power mode before enabling power save */ | ||
2164 | ar->wmi->saved_pwr_mode = ar->wmi->pwr_mode; | ||
2165 | 2233 | ||
2166 | ret = ath6kl_wmi_powermode_cmd(ar->wmi, 0, REC_POWER); | 2234 | ret = ath6kl_cfg80211_deepsleep_suspend(ar); |
2167 | if (ret) { | 2235 | if (ret) { |
2168 | ath6kl_warn("wmi powermode command failed during suspend: %d\n", | 2236 | ath6kl_err("deepsleep suspend failed: %d\n", ret); |
2169 | ret); | 2237 | return ret; |
2170 | } | 2238 | } |
2171 | 2239 | ||
2172 | ar->state = ATH6KL_STATE_DEEPSLEEP; | 2240 | ar->state = ATH6KL_STATE_DEEPSLEEP; |
@@ -2227,17 +2295,13 @@ int ath6kl_cfg80211_resume(struct ath6kl *ar) | |||
2227 | break; | 2295 | break; |
2228 | 2296 | ||
2229 | case ATH6KL_STATE_DEEPSLEEP: | 2297 | case ATH6KL_STATE_DEEPSLEEP: |
2230 | if (ar->wmi->pwr_mode != ar->wmi->saved_pwr_mode) { | 2298 | ath6kl_dbg(ATH6KL_DBG_SUSPEND, "deep sleep resume\n"); |
2231 | ret = ath6kl_wmi_powermode_cmd(ar->wmi, 0, | ||
2232 | ar->wmi->saved_pwr_mode); | ||
2233 | if (ret) { | ||
2234 | ath6kl_warn("wmi powermode command failed during resume: %d\n", | ||
2235 | ret); | ||
2236 | } | ||
2237 | } | ||
2238 | |||
2239 | ar->state = ATH6KL_STATE_ON; | ||
2240 | 2299 | ||
2300 | ret = ath6kl_cfg80211_deepsleep_resume(ar); | ||
2301 | if (ret) { | ||
2302 | ath6kl_warn("deep sleep resume failed: %d\n", ret); | ||
2303 | return ret; | ||
2304 | } | ||
2241 | break; | 2305 | break; |
2242 | 2306 | ||
2243 | case ATH6KL_STATE_CUTPOWER: | 2307 | case ATH6KL_STATE_CUTPOWER: |