diff options
Diffstat (limited to 'net/mac80211/pm.c')
-rw-r--r-- | net/mac80211/pm.c | 114 |
1 files changed, 114 insertions, 0 deletions
diff --git a/net/mac80211/pm.c b/net/mac80211/pm.c new file mode 100644 index 000000000000..6d17ed7fd49b --- /dev/null +++ b/net/mac80211/pm.c | |||
@@ -0,0 +1,114 @@ | |||
1 | #include <net/mac80211.h> | ||
2 | #include <net/rtnetlink.h> | ||
3 | |||
4 | #include "ieee80211_i.h" | ||
5 | #include "led.h" | ||
6 | |||
7 | int __ieee80211_suspend(struct ieee80211_hw *hw) | ||
8 | { | ||
9 | struct ieee80211_local *local = hw_to_local(hw); | ||
10 | struct ieee80211_sub_if_data *sdata; | ||
11 | struct ieee80211_if_init_conf conf; | ||
12 | struct sta_info *sta; | ||
13 | |||
14 | flush_workqueue(local->hw.workqueue); | ||
15 | |||
16 | /* disable keys */ | ||
17 | list_for_each_entry(sdata, &local->interfaces, list) | ||
18 | ieee80211_disable_keys(sdata); | ||
19 | |||
20 | /* remove STAs */ | ||
21 | list_for_each_entry(sta, &local->sta_list, list) { | ||
22 | |||
23 | if (local->ops->sta_notify) { | ||
24 | if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) | ||
25 | sdata = container_of(sdata->bss, | ||
26 | struct ieee80211_sub_if_data, | ||
27 | u.ap); | ||
28 | |||
29 | local->ops->sta_notify(hw, &sdata->vif, | ||
30 | STA_NOTIFY_REMOVE, &sta->sta); | ||
31 | } | ||
32 | } | ||
33 | |||
34 | /* remove all interfaces */ | ||
35 | list_for_each_entry(sdata, &local->interfaces, list) { | ||
36 | |||
37 | if (sdata->vif.type != NL80211_IFTYPE_AP_VLAN && | ||
38 | sdata->vif.type != NL80211_IFTYPE_MONITOR && | ||
39 | netif_running(sdata->dev)) { | ||
40 | conf.vif = &sdata->vif; | ||
41 | conf.type = sdata->vif.type; | ||
42 | conf.mac_addr = sdata->dev->dev_addr; | ||
43 | local->ops->remove_interface(hw, &conf); | ||
44 | } | ||
45 | } | ||
46 | |||
47 | /* stop hardware */ | ||
48 | if (local->open_count) { | ||
49 | ieee80211_led_radio(local, false); | ||
50 | local->ops->stop(hw); | ||
51 | } | ||
52 | return 0; | ||
53 | } | ||
54 | |||
55 | int __ieee80211_resume(struct ieee80211_hw *hw) | ||
56 | { | ||
57 | struct ieee80211_local *local = hw_to_local(hw); | ||
58 | struct ieee80211_sub_if_data *sdata; | ||
59 | struct ieee80211_if_init_conf conf; | ||
60 | struct sta_info *sta; | ||
61 | int res; | ||
62 | |||
63 | /* restart hardware */ | ||
64 | if (local->open_count) { | ||
65 | res = local->ops->start(hw); | ||
66 | |||
67 | ieee80211_led_radio(local, hw->conf.radio_enabled); | ||
68 | } | ||
69 | |||
70 | /* add interfaces */ | ||
71 | list_for_each_entry(sdata, &local->interfaces, list) { | ||
72 | |||
73 | if (sdata->vif.type != NL80211_IFTYPE_AP_VLAN && | ||
74 | sdata->vif.type != NL80211_IFTYPE_MONITOR && | ||
75 | netif_running(sdata->dev)) { | ||
76 | conf.vif = &sdata->vif; | ||
77 | conf.type = sdata->vif.type; | ||
78 | conf.mac_addr = sdata->dev->dev_addr; | ||
79 | res = local->ops->add_interface(hw, &conf); | ||
80 | } | ||
81 | } | ||
82 | |||
83 | /* add STAs back */ | ||
84 | list_for_each_entry(sta, &local->sta_list, list) { | ||
85 | |||
86 | if (local->ops->sta_notify) { | ||
87 | if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) | ||
88 | sdata = container_of(sdata->bss, | ||
89 | struct ieee80211_sub_if_data, | ||
90 | u.ap); | ||
91 | |||
92 | local->ops->sta_notify(hw, &sdata->vif, | ||
93 | STA_NOTIFY_ADD, &sta->sta); | ||
94 | } | ||
95 | } | ||
96 | |||
97 | /* add back keys */ | ||
98 | list_for_each_entry(sdata, &local->interfaces, list) | ||
99 | if (netif_running(sdata->dev)) | ||
100 | ieee80211_enable_keys(sdata); | ||
101 | |||
102 | /* setup RTS threshold */ | ||
103 | if (local->ops->set_rts_threshold) | ||
104 | local->ops->set_rts_threshold(hw, local->rts_threshold); | ||
105 | |||
106 | /* reconfigure hardware */ | ||
107 | ieee80211_hw_config(local, ~0); | ||
108 | |||
109 | netif_addr_lock_bh(local->mdev); | ||
110 | ieee80211_configure_filter(local); | ||
111 | netif_addr_unlock_bh(local->mdev); | ||
112 | |||
113 | return 0; | ||
114 | } | ||