diff options
-rw-r--r-- | drivers/net/wireless/ath/ath6kl/core.c | 12 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath6kl/core.h | 4 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath6kl/sdio.c | 86 |
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 | ||
27 | unsigned int debug_mask; | 27 | unsigned int debug_mask; |
28 | static bool suspend_cutpower; | 28 | static unsigned int suspend_mode; |
29 | static unsigned int uart_debug; | 29 | static unsigned int uart_debug; |
30 | static unsigned int ath6kl_p2p; | 30 | static unsigned int ath6kl_p2p; |
31 | static unsigned int testmode; | 31 | static unsigned int testmode; |
32 | 32 | ||
33 | module_param(debug_mask, uint, 0644); | 33 | module_param(debug_mask, uint, 0644); |
34 | module_param(suspend_cutpower, bool, 0444); | 34 | module_param(suspend_mode, uint, 0644); |
35 | module_param(uart_debug, uint, 0644); | 35 | module_param(uart_debug, uint, 0644); |
36 | module_param(ath6kl_p2p, uint, 0644); | 36 | module_param(ath6kl_p2p, uint, 0644); |
37 | module_param(testmode, uint, 0644); | 37 | module_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 | ||
202 | enum wlan_low_pwr_state { | 201 | enum 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 | ||
782 | static int ath6kl_sdio_suspend(struct ath6kl *ar, struct cfg80211_wowlan *wow) | 782 | static 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 | |||
811 | static 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 | ||
845 | deepsleep: | 867 | cut_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 | ||
849 | static int ath6kl_sdio_resume(struct ath6kl *ar) | 871 | static int ath6kl_sdio_resume(struct ath6kl *ar) |