summaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/ath/ath6kl/sdio.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/ath/ath6kl/sdio.c')
-rw-r--r--drivers/net/wireless/ath/ath6kl/sdio.c86
1 files changed, 54 insertions, 32 deletions
diff --git a/drivers/net/wireless/ath/ath6kl/sdio.c b/drivers/net/wireless/ath/ath6kl/sdio.c
index d9f55914b893..07dcf00ca1a7 100644
--- a/drivers/net/wireless/ath/ath6kl/sdio.c
+++ b/drivers/net/wireless/ath/ath6kl/sdio.c
@@ -779,7 +779,7 @@ out:
return ret;
}
-static int ath6kl_sdio_suspend(struct ath6kl *ar, struct cfg80211_wowlan *wow)
+static int ath6kl_set_sdio_pm_caps(struct ath6kl *ar)
{
struct ath6kl_sdio *ar_sdio = ath6kl_sdio_priv(ar);
struct sdio_func *func = ar_sdio->func;
@@ -790,60 +790,82 @@ static int ath6kl_sdio_suspend(struct ath6kl *ar, struct cfg80211_wowlan *wow)
ath6kl_dbg(ATH6KL_DBG_SUSPEND, "sdio suspend pm_caps 0x%x\n", flags);
- if (!(flags & MMC_PM_KEEP_POWER) ||
- (ar->conf_flags & ATH6KL_CONF_SUSPEND_CUTPOWER)) {
- /* as host doesn't support keep power we need to cut power */
- return ath6kl_cfg80211_suspend(ar, ATH6KL_CFG_SUSPEND_CUTPOWER,
- NULL);
- }
+ if (!(flags & MMC_PM_WAKE_SDIO_IRQ) ||
+ !(flags & MMC_PM_KEEP_POWER))
+ return -EINVAL;
ret = sdio_set_host_pm_flags(func, MMC_PM_KEEP_POWER);
if (ret) {
- printk(KERN_ERR "ath6kl: set sdio pm flags failed: %d\n",
- ret);
+ ath6kl_err("set sdio keep pwr flag failed: %d\n", ret);
return ret;
}
- if (!(flags & MMC_PM_WAKE_SDIO_IRQ))
- goto deepsleep;
-
/* sdio irq wakes up host */
+ ret = sdio_set_host_pm_flags(func, MMC_PM_WAKE_SDIO_IRQ);
+ if (ret)
+ ath6kl_err("set sdio wake irq flag failed: %d\n", ret);
+
+ return ret;
+}
+
+static int ath6kl_sdio_suspend(struct ath6kl *ar, struct cfg80211_wowlan *wow)
+{
+ struct ath6kl_sdio *ar_sdio = ath6kl_sdio_priv(ar);
+ struct sdio_func *func = ar_sdio->func;
+ mmc_pm_flag_t flags;
+ int ret;
if (ar->state == ATH6KL_STATE_SCHED_SCAN) {
+ ath6kl_dbg(ATH6KL_DBG_SUSPEND, "sched scan is in progress\n");
+
+ ret = ath6kl_set_sdio_pm_caps(ar);
+ if (ret)
+ goto cut_pwr;
+
ret = ath6kl_cfg80211_suspend(ar,
ATH6KL_CFG_SUSPEND_SCHED_SCAN,
NULL);
- if (ret) {
- ath6kl_warn("Schedule scan suspend failed: %d", ret);
- return ret;
- }
-
- ret = sdio_set_host_pm_flags(func, MMC_PM_WAKE_SDIO_IRQ);
if (ret)
- ath6kl_warn("set sdio wake irq flag failed: %d\n", ret);
+ goto cut_pwr;
- return ret;
+ return 0;
}
- if (wow) {
- /*
- * The host sdio controller is capable of keep power and
- * sdio irq wake up at this point. It's fine to continue
- * wow suspend operation.
- */
+ if (ar->suspend_mode == WLAN_POWER_STATE_WOW ||
+ (!ar->suspend_mode && wow)) {
+
+ ret = ath6kl_set_sdio_pm_caps(ar);
+ if (ret)
+ goto cut_pwr;
+
ret = ath6kl_cfg80211_suspend(ar, ATH6KL_CFG_SUSPEND_WOW, wow);
if (ret)
- return ret;
+ goto cut_pwr;
+
+ return 0;
+ }
+
+ if (ar->suspend_mode == WLAN_POWER_STATE_DEEP_SLEEP ||
+ !ar->suspend_mode) {
- ret = sdio_set_host_pm_flags(func, MMC_PM_WAKE_SDIO_IRQ);
+ flags = sdio_get_host_pm_caps(func);
+ if (!(flags & MMC_PM_KEEP_POWER))
+ goto cut_pwr;
+
+ ret = sdio_set_host_pm_flags(func, MMC_PM_KEEP_POWER);
if (ret)
- ath6kl_err("set sdio wake irq flag failed: %d\n", ret);
+ goto cut_pwr;
- return ret;
+ ret = ath6kl_cfg80211_suspend(ar, ATH6KL_CFG_SUSPEND_DEEPSLEEP,
+ NULL);
+ if (ret)
+ goto cut_pwr;
+
+ return 0;
}
-deepsleep:
- return ath6kl_cfg80211_suspend(ar, ATH6KL_CFG_SUSPEND_DEEPSLEEP, NULL);
+cut_pwr:
+ return ath6kl_cfg80211_suspend(ar, ATH6KL_CFG_SUSPEND_CUTPOWER, NULL);
}
static int ath6kl_sdio_resume(struct ath6kl *ar)