aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211/pm.c
diff options
context:
space:
mode:
authorBob Copeland <me@bobcopeland.com>2009-01-19 11:20:53 -0500
committerJohn W. Linville <linville@tuxdriver.com>2009-01-29 16:00:52 -0500
commit665af4fc8979734d8f73c9a6732be07e545ce4cc (patch)
treee6efab304166f0f4f30b75906930def19b1a3fb8 /net/mac80211/pm.c
parent0378b3f1c49d48ed524eabda7e4340163d9483c9 (diff)
mac80211: add suspend/resume callbacks
This patch introduces suspend and resume callbacks to mac80211, allowing mac80211 to quiesce its state (bringing down interfaces, removing keys, etc) in preparation for suspend. cfg80211 will call the suspend hook before the device suspend, and resume hook after the device resume. Signed-off-by: Bob Copeland <me@bobcopeland.com> Acked-by: Johannes Berg <johannes@sipsolutions.net> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'net/mac80211/pm.c')
-rw-r--r--net/mac80211/pm.c114
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
7int __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
55int __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}