diff options
-rw-r--r-- | drivers/net/wireless/ath/ath6kl/cfg80211.c | 14 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath6kl/core.h | 1 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath6kl/hif-ops.h | 5 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath6kl/hif.h | 1 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath6kl/main.c | 35 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath6kl/sdio.c | 26 |
6 files changed, 82 insertions, 0 deletions
diff --git a/drivers/net/wireless/ath/ath6kl/cfg80211.c b/drivers/net/wireless/ath/ath6kl/cfg80211.c index b2b70e6618f..9128aa3c2b6 100644 --- a/drivers/net/wireless/ath/ath6kl/cfg80211.c +++ b/drivers/net/wireless/ath/ath6kl/cfg80211.c | |||
@@ -17,6 +17,7 @@ | |||
17 | #include "core.h" | 17 | #include "core.h" |
18 | #include "cfg80211.h" | 18 | #include "cfg80211.h" |
19 | #include "debug.h" | 19 | #include "debug.h" |
20 | #include "hif-ops.h" | ||
20 | 21 | ||
21 | #define RATETAB_ENT(_rate, _rateid, _flags) { \ | 22 | #define RATETAB_ENT(_rate, _rateid, _flags) { \ |
22 | .bitrate = (_rate), \ | 23 | .bitrate = (_rate), \ |
@@ -1424,6 +1425,16 @@ static int ath6kl_flush_pmksa(struct wiphy *wiphy, struct net_device *netdev) | |||
1424 | return 0; | 1425 | return 0; |
1425 | } | 1426 | } |
1426 | 1427 | ||
1428 | #ifdef CONFIG_PM | ||
1429 | static int ar6k_cfg80211_suspend(struct wiphy *wiphy, | ||
1430 | struct cfg80211_wowlan *wow) | ||
1431 | { | ||
1432 | struct ath6kl *ar = wiphy_priv(wiphy); | ||
1433 | |||
1434 | return ath6kl_hif_suspend(ar); | ||
1435 | } | ||
1436 | #endif | ||
1437 | |||
1427 | static struct cfg80211_ops ath6kl_cfg80211_ops = { | 1438 | static struct cfg80211_ops ath6kl_cfg80211_ops = { |
1428 | .change_virtual_intf = ath6kl_cfg80211_change_iface, | 1439 | .change_virtual_intf = ath6kl_cfg80211_change_iface, |
1429 | .scan = ath6kl_cfg80211_scan, | 1440 | .scan = ath6kl_cfg80211_scan, |
@@ -1443,6 +1454,9 @@ static struct cfg80211_ops ath6kl_cfg80211_ops = { | |||
1443 | .set_pmksa = ath6kl_set_pmksa, | 1454 | .set_pmksa = ath6kl_set_pmksa, |
1444 | .del_pmksa = ath6kl_del_pmksa, | 1455 | .del_pmksa = ath6kl_del_pmksa, |
1445 | .flush_pmksa = ath6kl_flush_pmksa, | 1456 | .flush_pmksa = ath6kl_flush_pmksa, |
1457 | #ifdef CONFIG_PM | ||
1458 | .suspend = ar6k_cfg80211_suspend, | ||
1459 | #endif | ||
1446 | }; | 1460 | }; |
1447 | 1461 | ||
1448 | struct wireless_dev *ath6kl_cfg80211_init(struct device *dev) | 1462 | struct wireless_dev *ath6kl_cfg80211_init(struct device *dev) |
diff --git a/drivers/net/wireless/ath/ath6kl/core.h b/drivers/net/wireless/ath/ath6kl/core.h index a1aa2ef398f..4405ab56bb8 100644 --- a/drivers/net/wireless/ath/ath6kl/core.h +++ b/drivers/net/wireless/ath/ath6kl/core.h | |||
@@ -544,6 +544,7 @@ void ath6kl_pspoll_event(struct ath6kl *ar, u8 aid); | |||
544 | 544 | ||
545 | void ath6kl_dtimexpiry_event(struct ath6kl *ar); | 545 | void ath6kl_dtimexpiry_event(struct ath6kl *ar); |
546 | void ath6kl_disconnect(struct ath6kl *ar); | 546 | void ath6kl_disconnect(struct ath6kl *ar); |
547 | void ath6kl_deep_sleep_enable(struct ath6kl *ar); | ||
547 | void aggr_recv_delba_req_evt(struct ath6kl *ar, u8 tid); | 548 | void aggr_recv_delba_req_evt(struct ath6kl *ar, u8 tid); |
548 | void aggr_recv_addba_req_evt(struct ath6kl *ar, u8 tid, u16 seq_no, | 549 | void aggr_recv_addba_req_evt(struct ath6kl *ar, u8 tid, u16 seq_no, |
549 | u8 win_sz); | 550 | u8 win_sz); |
diff --git a/drivers/net/wireless/ath/ath6kl/hif-ops.h b/drivers/net/wireless/ath/ath6kl/hif-ops.h index c923979776a..d6c898f3d0b 100644 --- a/drivers/net/wireless/ath/ath6kl/hif-ops.h +++ b/drivers/net/wireless/ath/ath6kl/hif-ops.h | |||
@@ -69,4 +69,9 @@ static inline void ath6kl_hif_cleanup_scatter(struct ath6kl *ar) | |||
69 | return ar->hif_ops->cleanup_scatter(ar); | 69 | return ar->hif_ops->cleanup_scatter(ar); |
70 | } | 70 | } |
71 | 71 | ||
72 | static inline int ath6kl_hif_suspend(struct ath6kl *ar) | ||
73 | { | ||
74 | return ar->hif_ops->suspend(ar); | ||
75 | } | ||
76 | |||
72 | #endif | 77 | #endif |
diff --git a/drivers/net/wireless/ath/ath6kl/hif.h b/drivers/net/wireless/ath/ath6kl/hif.h index 5ceff54775a..797e2d1d9bf 100644 --- a/drivers/net/wireless/ath/ath6kl/hif.h +++ b/drivers/net/wireless/ath/ath6kl/hif.h | |||
@@ -202,6 +202,7 @@ struct ath6kl_hif_ops { | |||
202 | int (*scat_req_rw) (struct ath6kl *ar, | 202 | int (*scat_req_rw) (struct ath6kl *ar, |
203 | struct hif_scatter_req *scat_req); | 203 | struct hif_scatter_req *scat_req); |
204 | void (*cleanup_scatter)(struct ath6kl *ar); | 204 | void (*cleanup_scatter)(struct ath6kl *ar); |
205 | int (*suspend)(struct ath6kl *ar); | ||
205 | }; | 206 | }; |
206 | 207 | ||
207 | #endif | 208 | #endif |
diff --git a/drivers/net/wireless/ath/ath6kl/main.c b/drivers/net/wireless/ath/ath6kl/main.c index 868838bb6b8..b64b2a35756 100644 --- a/drivers/net/wireless/ath/ath6kl/main.c +++ b/drivers/net/wireless/ath/ath6kl/main.c | |||
@@ -795,6 +795,41 @@ void ath6kl_disconnect(struct ath6kl *ar) | |||
795 | } | 795 | } |
796 | } | 796 | } |
797 | 797 | ||
798 | void ath6kl_deep_sleep_enable(struct ath6kl *ar) | ||
799 | { | ||
800 | switch (ar->sme_state) { | ||
801 | case SME_CONNECTING: | ||
802 | cfg80211_connect_result(ar->net_dev, ar->bssid, NULL, 0, | ||
803 | NULL, 0, | ||
804 | WLAN_STATUS_UNSPECIFIED_FAILURE, | ||
805 | GFP_KERNEL); | ||
806 | break; | ||
807 | case SME_CONNECTED: | ||
808 | default: | ||
809 | /* | ||
810 | * FIXME: oddly enough smeState is in DISCONNECTED during | ||
811 | * suspend, why? Need to send disconnected event in that | ||
812 | * state. | ||
813 | */ | ||
814 | cfg80211_disconnected(ar->net_dev, 0, NULL, 0, GFP_KERNEL); | ||
815 | break; | ||
816 | } | ||
817 | |||
818 | if (test_bit(CONNECTED, &ar->flag) || | ||
819 | test_bit(CONNECT_PEND, &ar->flag)) | ||
820 | ath6kl_wmi_disconnect_cmd(ar->wmi); | ||
821 | |||
822 | ar->sme_state = SME_DISCONNECTED; | ||
823 | |||
824 | /* disable scanning */ | ||
825 | if (ath6kl_wmi_scanparams_cmd(ar->wmi, 0xFFFF, 0, 0, 0, 0, 0, 0, 0, | ||
826 | 0, 0) != 0) | ||
827 | printk(KERN_WARNING "ath6kl: failed to disable scan " | ||
828 | "during suspend\n"); | ||
829 | |||
830 | ath6kl_cfg80211_scan_complete_event(ar, -ECANCELED); | ||
831 | } | ||
832 | |||
798 | /* WMI Event handlers */ | 833 | /* WMI Event handlers */ |
799 | 834 | ||
800 | static const char *get_hw_id_string(u32 id) | 835 | static const char *get_hw_id_string(u32 id) |
diff --git a/drivers/net/wireless/ath/ath6kl/sdio.c b/drivers/net/wireless/ath/ath6kl/sdio.c index f393090ecef..852a0ccc803 100644 --- a/drivers/net/wireless/ath/ath6kl/sdio.c +++ b/drivers/net/wireless/ath/ath6kl/sdio.c | |||
@@ -726,6 +726,31 @@ static int ath6kl_sdio_enable_scatter(struct ath6kl *ar) | |||
726 | return 0; | 726 | return 0; |
727 | } | 727 | } |
728 | 728 | ||
729 | static int ath6kl_sdio_suspend(struct ath6kl *ar) | ||
730 | { | ||
731 | struct ath6kl_sdio *ar_sdio = ath6kl_sdio_priv(ar); | ||
732 | struct sdio_func *func = ar_sdio->func; | ||
733 | mmc_pm_flag_t flags; | ||
734 | int ret; | ||
735 | |||
736 | flags = sdio_get_host_pm_caps(func); | ||
737 | |||
738 | if (!(flags & MMC_PM_KEEP_POWER)) | ||
739 | /* as host doesn't support keep power we need to bail out */ | ||
740 | return -EINVAL; | ||
741 | |||
742 | ret = sdio_set_host_pm_flags(func, MMC_PM_KEEP_POWER); | ||
743 | if (ret) { | ||
744 | printk(KERN_ERR "ath6kl: set sdio pm flags failed: %d\n", | ||
745 | ret); | ||
746 | return ret; | ||
747 | } | ||
748 | |||
749 | ath6kl_deep_sleep_enable(ar); | ||
750 | |||
751 | return 0; | ||
752 | } | ||
753 | |||
729 | static const struct ath6kl_hif_ops ath6kl_sdio_ops = { | 754 | static const struct ath6kl_hif_ops ath6kl_sdio_ops = { |
730 | .read_write_sync = ath6kl_sdio_read_write_sync, | 755 | .read_write_sync = ath6kl_sdio_read_write_sync, |
731 | .write_async = ath6kl_sdio_write_async, | 756 | .write_async = ath6kl_sdio_write_async, |
@@ -736,6 +761,7 @@ static const struct ath6kl_hif_ops ath6kl_sdio_ops = { | |||
736 | .enable_scatter = ath6kl_sdio_enable_scatter, | 761 | .enable_scatter = ath6kl_sdio_enable_scatter, |
737 | .scat_req_rw = ath6kl_sdio_async_rw_scatter, | 762 | .scat_req_rw = ath6kl_sdio_async_rw_scatter, |
738 | .cleanup_scatter = ath6kl_sdio_cleanup_scatter, | 763 | .cleanup_scatter = ath6kl_sdio_cleanup_scatter, |
764 | .suspend = ath6kl_sdio_suspend, | ||
739 | }; | 765 | }; |
740 | 766 | ||
741 | static int ath6kl_sdio_probe(struct sdio_func *func, | 767 | static int ath6kl_sdio_probe(struct sdio_func *func, |