aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net
diff options
context:
space:
mode:
authorRaja Mani <rmani@qca.qualcomm.com>2012-01-30 06:43:09 -0500
committerKalle Valo <kvalo@qca.qualcomm.com>2012-01-30 14:22:54 -0500
commite390af779dc671551800514d391928f5a798089a (patch)
tree2602772094fe21b94e6f38c0f2279b24da464644 /drivers/net
parentc86515412f0c364f2d45029b45d5909614087af3 (diff)
ath6kl: Re-architect suspend mode handling in ath6kl_sdio_suspend
Using this patch, the user can bypass existing auto suspend mode selection logic and force ath6kl to enter into the suspend mode what he/she wants. If the user doesn't choose any suspend mode while doing insmod of the driver, auto suspend mode selection logic will kick in and choose suspend mode based on the host SDIO controller capability. Generic module parameter is required to specify suspend mode including Deep Sleep and WOW while doing insmod. Renaming existing mod param variable suspend_cutpower would be sufficient to meet this requirement. New module parameter suspend_mode can take any one of the below suspend state, 1. cut power 2. deep sleep 3. wow Signed-off-by: Raja Mani <rmani@qca.qualcomm.com> Signed-off-by: Kalle Valo <kvalo@qca.qualcomm.com>
Diffstat (limited to 'drivers/net')
-rw-r--r--drivers/net/wireless/ath/ath6kl/core.c12
-rw-r--r--drivers/net/wireless/ath/ath6kl/core.h4
-rw-r--r--drivers/net/wireless/ath/ath6kl/sdio.c86
3 files changed, 64 insertions, 38 deletions
diff --git a/drivers/net/wireless/ath/ath6kl/core.c b/drivers/net/wireless/ath/ath6kl/core.c
index 2a5198185d57..722ca59b88ce 100644
--- a/drivers/net/wireless/ath/ath6kl/core.c
+++ b/drivers/net/wireless/ath/ath6kl/core.c
@@ -25,13 +25,13 @@
25#include "cfg80211.h" 25#include "cfg80211.h"
26 26
27unsigned int debug_mask; 27unsigned int debug_mask;
28static bool suspend_cutpower; 28static unsigned int suspend_mode;
29static unsigned int uart_debug; 29static unsigned int uart_debug;
30static unsigned int ath6kl_p2p; 30static unsigned int ath6kl_p2p;
31static unsigned int testmode; 31static unsigned int testmode;
32 32
33module_param(debug_mask, uint, 0644); 33module_param(debug_mask, uint, 0644);
34module_param(suspend_cutpower, bool, 0444); 34module_param(suspend_mode, uint, 0644);
35module_param(uart_debug, uint, 0644); 35module_param(uart_debug, uint, 0644);
36module_param(ath6kl_p2p, uint, 0644); 36module_param(ath6kl_p2p, uint, 0644);
37module_param(testmode, uint, 0644); 37module_param(testmode, uint, 0644);
@@ -147,8 +147,12 @@ int ath6kl_core_init(struct ath6kl *ar)
147 ar->conf_flags = ATH6KL_CONF_IGNORE_ERP_BARKER | 147 ar->conf_flags = ATH6KL_CONF_IGNORE_ERP_BARKER |
148 ATH6KL_CONF_ENABLE_11N | ATH6KL_CONF_ENABLE_TX_BURST; 148 ATH6KL_CONF_ENABLE_11N | ATH6KL_CONF_ENABLE_TX_BURST;
149 149
150 if (suspend_cutpower) 150 if (suspend_mode &&
151 ar->conf_flags |= ATH6KL_CONF_SUSPEND_CUTPOWER; 151 suspend_mode >= WLAN_POWER_STATE_CUT_PWR &&
152 suspend_mode <= WLAN_POWER_STATE_WOW)
153 ar->suspend_mode = suspend_mode;
154 else
155 ar->suspend_mode = 0;
152 156
153 if (uart_debug) 157 if (uart_debug)
154 ar->conf_flags |= ATH6KL_CONF_UART_DEBUG; 158 ar->conf_flags |= ATH6KL_CONF_UART_DEBUG;
diff --git a/drivers/net/wireless/ath/ath6kl/core.h b/drivers/net/wireless/ath/ath6kl/core.h
index 426f269e8ab0..ce572c04b924 100644
--- a/drivers/net/wireless/ath/ath6kl/core.h
+++ b/drivers/net/wireless/ath/ath6kl/core.h
@@ -196,8 +196,7 @@ struct ath6kl_fw_ie {
196#define ATH6KL_CONF_IGNORE_PS_FAIL_EVT_IN_SCAN BIT(1) 196#define ATH6KL_CONF_IGNORE_PS_FAIL_EVT_IN_SCAN BIT(1)
197#define ATH6KL_CONF_ENABLE_11N BIT(2) 197#define ATH6KL_CONF_ENABLE_11N BIT(2)
198#define ATH6KL_CONF_ENABLE_TX_BURST BIT(3) 198#define ATH6KL_CONF_ENABLE_TX_BURST BIT(3)
199#define ATH6KL_CONF_SUSPEND_CUTPOWER BIT(4) 199#define ATH6KL_CONF_UART_DEBUG BIT(4)
200#define ATH6KL_CONF_UART_DEBUG BIT(5)
201 200
202enum wlan_low_pwr_state { 201enum wlan_low_pwr_state {
203 WLAN_POWER_STATE_ON, 202 WLAN_POWER_STATE_ON,
@@ -619,6 +618,7 @@ struct ath6kl {
619 } hw; 618 } hw;
620 619
621 u16 conf_flags; 620 u16 conf_flags;
621 u16 suspend_mode;
622 wait_queue_head_t event_wq; 622 wait_queue_head_t event_wq;
623 struct ath6kl_mbox_info mbox_info; 623 struct ath6kl_mbox_info mbox_info;
624 624
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:
779 return ret; 779 return ret;
780} 780}
781 781
782static int ath6kl_sdio_suspend(struct ath6kl *ar, struct cfg80211_wowlan *wow) 782static int ath6kl_set_sdio_pm_caps(struct ath6kl *ar)
783{ 783{
784 struct ath6kl_sdio *ar_sdio = ath6kl_sdio_priv(ar); 784 struct ath6kl_sdio *ar_sdio = ath6kl_sdio_priv(ar);
785 struct sdio_func *func = ar_sdio->func; 785 struct sdio_func *func = ar_sdio->func;
@@ -790,60 +790,82 @@ static int ath6kl_sdio_suspend(struct ath6kl *ar, struct cfg80211_wowlan *wow)
790 790
791 ath6kl_dbg(ATH6KL_DBG_SUSPEND, "sdio suspend pm_caps 0x%x\n", flags); 791 ath6kl_dbg(ATH6KL_DBG_SUSPEND, "sdio suspend pm_caps 0x%x\n", flags);
792 792
793 if (!(flags & MMC_PM_KEEP_POWER) || 793 if (!(flags & MMC_PM_WAKE_SDIO_IRQ) ||
794 (ar->conf_flags & ATH6KL_CONF_SUSPEND_CUTPOWER)) { 794 !(flags & MMC_PM_KEEP_POWER))
795 /* as host doesn't support keep power we need to cut power */ 795 return -EINVAL;
796 return ath6kl_cfg80211_suspend(ar, ATH6KL_CFG_SUSPEND_CUTPOWER,
797 NULL);
798 }
799 796
800 ret = sdio_set_host_pm_flags(func, MMC_PM_KEEP_POWER); 797 ret = sdio_set_host_pm_flags(func, MMC_PM_KEEP_POWER);
801 if (ret) { 798 if (ret) {
802 printk(KERN_ERR "ath6kl: set sdio pm flags failed: %d\n", 799 ath6kl_err("set sdio keep pwr flag failed: %d\n", ret);
803 ret);
804 return ret; 800 return ret;
805 } 801 }
806 802
807 if (!(flags & MMC_PM_WAKE_SDIO_IRQ))
808 goto deepsleep;
809
810 /* sdio irq wakes up host */ 803 /* sdio irq wakes up host */
804 ret = sdio_set_host_pm_flags(func, MMC_PM_WAKE_SDIO_IRQ);
805 if (ret)
806 ath6kl_err("set sdio wake irq flag failed: %d\n", ret);
807
808 return ret;
809}
810
811static int ath6kl_sdio_suspend(struct ath6kl *ar, struct cfg80211_wowlan *wow)
812{
813 struct ath6kl_sdio *ar_sdio = ath6kl_sdio_priv(ar);
814 struct sdio_func *func = ar_sdio->func;
815 mmc_pm_flag_t flags;
816 int ret;
811 817
812 if (ar->state == ATH6KL_STATE_SCHED_SCAN) { 818 if (ar->state == ATH6KL_STATE_SCHED_SCAN) {
819 ath6kl_dbg(ATH6KL_DBG_SUSPEND, "sched scan is in progress\n");
820
821 ret = ath6kl_set_sdio_pm_caps(ar);
822 if (ret)
823 goto cut_pwr;
824
813 ret = ath6kl_cfg80211_suspend(ar, 825 ret = ath6kl_cfg80211_suspend(ar,
814 ATH6KL_CFG_SUSPEND_SCHED_SCAN, 826 ATH6KL_CFG_SUSPEND_SCHED_SCAN,
815 NULL); 827 NULL);
816 if (ret) {
817 ath6kl_warn("Schedule scan suspend failed: %d", ret);
818 return ret;
819 }
820
821 ret = sdio_set_host_pm_flags(func, MMC_PM_WAKE_SDIO_IRQ);
822 if (ret) 828 if (ret)
823 ath6kl_warn("set sdio wake irq flag failed: %d\n", ret); 829 goto cut_pwr;
824 830
825 return ret; 831 return 0;
826 } 832 }
827 833
828 if (wow) { 834 if (ar->suspend_mode == WLAN_POWER_STATE_WOW ||
829 /* 835 (!ar->suspend_mode && wow)) {
830 * The host sdio controller is capable of keep power and 836
831 * sdio irq wake up at this point. It's fine to continue 837 ret = ath6kl_set_sdio_pm_caps(ar);
832 * wow suspend operation. 838 if (ret)
833 */ 839 goto cut_pwr;
840
834 ret = ath6kl_cfg80211_suspend(ar, ATH6KL_CFG_SUSPEND_WOW, wow); 841 ret = ath6kl_cfg80211_suspend(ar, ATH6KL_CFG_SUSPEND_WOW, wow);
835 if (ret) 842 if (ret)
836 return ret; 843 goto cut_pwr;
844
845 return 0;
846 }
847
848 if (ar->suspend_mode == WLAN_POWER_STATE_DEEP_SLEEP ||
849 !ar->suspend_mode) {
837 850
838 ret = sdio_set_host_pm_flags(func, MMC_PM_WAKE_SDIO_IRQ); 851 flags = sdio_get_host_pm_caps(func);
852 if (!(flags & MMC_PM_KEEP_POWER))
853 goto cut_pwr;
854
855 ret = sdio_set_host_pm_flags(func, MMC_PM_KEEP_POWER);
839 if (ret) 856 if (ret)
840 ath6kl_err("set sdio wake irq flag failed: %d\n", ret); 857 goto cut_pwr;
841 858
842 return ret; 859 ret = ath6kl_cfg80211_suspend(ar, ATH6KL_CFG_SUSPEND_DEEPSLEEP,
860 NULL);
861 if (ret)
862 goto cut_pwr;
863
864 return 0;
843 } 865 }
844 866
845deepsleep: 867cut_pwr:
846 return ath6kl_cfg80211_suspend(ar, ATH6KL_CFG_SUSPEND_DEEPSLEEP, NULL); 868 return ath6kl_cfg80211_suspend(ar, ATH6KL_CFG_SUSPEND_CUTPOWER, NULL);
847} 869}
848 870
849static int ath6kl_sdio_resume(struct ath6kl *ar) 871static int ath6kl_sdio_resume(struct ath6kl *ar)