#include "cfg80211.h"
 
 unsigned int debug_mask;
-static bool suspend_cutpower;
+static unsigned int suspend_mode;
 static unsigned int uart_debug;
 static unsigned int ath6kl_p2p;
 static unsigned int testmode;
 
 module_param(debug_mask, uint, 0644);
-module_param(suspend_cutpower, bool, 0444);
+module_param(suspend_mode, uint, 0644);
 module_param(uart_debug, uint, 0644);
 module_param(ath6kl_p2p, uint, 0644);
 module_param(testmode, uint, 0644);
        ar->conf_flags = ATH6KL_CONF_IGNORE_ERP_BARKER |
                         ATH6KL_CONF_ENABLE_11N | ATH6KL_CONF_ENABLE_TX_BURST;
 
-       if (suspend_cutpower)
-               ar->conf_flags |= ATH6KL_CONF_SUSPEND_CUTPOWER;
+       if (suspend_mode &&
+               suspend_mode >= WLAN_POWER_STATE_CUT_PWR &&
+               suspend_mode <= WLAN_POWER_STATE_WOW)
+               ar->suspend_mode = suspend_mode;
+       else
+               ar->suspend_mode = 0;
 
        if (uart_debug)
                ar->conf_flags |= ATH6KL_CONF_UART_DEBUG;
 
        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;
 
        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)