aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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)