ath6kl: Add provision to define suspend policy in disconnected state.
authorRaja Mani <rmani@qca.qualcomm.com>
Tue, 6 Mar 2012 09:33:59 +0000 (15:03 +0530)
committerKalle Valo <kvalo@qca.qualcomm.com>
Wed, 7 Mar 2012 07:17:10 +0000 (09:17 +0200)
It gives flexibility to the user to define suspend policy
when the suspend mode is set to WOW and the device is in
disconnected state at the time of suspend.

New module parameter wow_mode is added to get the choice
from the user. This parameter is valid only if the module
parameter suspend_mode is set to WOW.

To force WOW in connected state and cut power
in disconnected state:
  suspend_mode=0x3 wow_mode=0x1

To force WOW in connected state and deep sleep
in disconnected state (this is also the default wow_mode):
   suspend_mode=0x3 wow_mode=0x2

If there is no value specified to wow_mode during insmod,
deep sleep mode will be tried in the disconnected state.

kvalo: clarified commit log

Signed-off-by: Raja Mani <rmani@qca.qualcomm.com>
Signed-off-by: Kalle Valo <kvalo@qca.qualcomm.com>
drivers/net/wireless/ath/ath6kl/cfg80211.c
drivers/net/wireless/ath/ath6kl/core.c
drivers/net/wireless/ath/ath6kl/core.h
drivers/net/wireless/ath/ath6kl/sdio.c

index 9abc7a6a69b13396bee96152bdeb5b5680769b69..528529406e490deee900e1e3a2844f1709c69ff8 100644 (file)
@@ -2046,10 +2046,9 @@ int ath6kl_cfg80211_suspend(struct ath6kl *ar,
                ath6kl_tx_data_cleanup(ar);
 
                ret = ath6kl_wow_suspend(ar, wow);
-               if (ret) {
-                       ath6kl_err("wow suspend failed: %d\n", ret);
+               if (ret)
                        return ret;
-               }
+
                ar->state = ATH6KL_STATE_WOW;
                break;
 
index 84dd9786622f3f46fbe677c5f5d6faa9857dcda1..bc3a41447b8e62aedafdfaa9d821b0c5879a0af8 100644 (file)
 
 unsigned int debug_mask;
 static unsigned int suspend_mode;
+static unsigned int wow_mode;
 static unsigned int uart_debug;
 static unsigned int ath6kl_p2p;
 static unsigned int testmode;
 
 module_param(debug_mask, uint, 0644);
 module_param(suspend_mode, uint, 0644);
+module_param(wow_mode, uint, 0644);
 module_param(uart_debug, uint, 0644);
 module_param(ath6kl_p2p, uint, 0644);
 module_param(testmode, uint, 0644);
@@ -119,6 +121,13 @@ int ath6kl_core_init(struct ath6kl *ar)
        else
                ar->suspend_mode = 0;
 
+       if (suspend_mode == WLAN_POWER_STATE_WOW &&
+           (wow_mode == WLAN_POWER_STATE_CUT_PWR ||
+            wow_mode == WLAN_POWER_STATE_DEEP_SLEEP))
+               ar->wow_suspend_mode = wow_mode;
+       else
+               ar->wow_suspend_mode = 0;
+
        if (uart_debug)
                ar->conf_flags |= ATH6KL_CONF_UART_DEBUG;
 
index b6bdece63361165b192a938147483befffac54ac..b9d810f32006ba839375033984d8011767e8bc8c 100644 (file)
@@ -636,6 +636,7 @@ struct ath6kl {
 
        u16 conf_flags;
        u16 suspend_mode;
+       u16 wow_suspend_mode;
        wait_queue_head_t event_wq;
        struct ath6kl_mbox_info mbox_info;
 
index e2f42a13395249d96a8406a6599ff5921804cf74..9b6282a1422562be8e4c1eb68e87c8f6609dfcfb 100644 (file)
@@ -836,6 +836,7 @@ 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;
+       bool try_deepsleep = false;
        int ret;
 
        if (ar->state == ATH6KL_STATE_SCHED_SCAN) {
@@ -862,14 +863,21 @@ static int ath6kl_sdio_suspend(struct ath6kl *ar, struct cfg80211_wowlan *wow)
                        goto cut_pwr;
 
                ret = ath6kl_cfg80211_suspend(ar, ATH6KL_CFG_SUSPEND_WOW, wow);
-               if (ret)
-                       goto cut_pwr;
-
-               return 0;
+               if (ret && ret != -ENOTCONN)
+                       ath6kl_err("wow suspend failed: %d\n", ret);
+
+               if (ret && (!ar->wow_suspend_mode ||
+                   ar->wow_suspend_mode == WLAN_POWER_STATE_DEEP_SLEEP))
+                               try_deepsleep = true;
+               else if (ret &&
+                        ar->wow_suspend_mode == WLAN_POWER_STATE_CUT_PWR)
+                               goto cut_pwr;
+               if (!ret)
+                       return 0;
        }
 
        if (ar->suspend_mode == WLAN_POWER_STATE_DEEP_SLEEP ||
-           !ar->suspend_mode) {
+           !ar->suspend_mode || try_deepsleep) {
 
                flags = sdio_get_host_pm_caps(func);
                if (!(flags & MMC_PM_KEEP_POWER))