diff options
-rw-r--r-- | net/mac80211/Makefile | 2 | ||||
-rw-r--r-- | net/mac80211/cfg.c | 17 | ||||
-rw-r--r-- | net/mac80211/ieee80211_i.h | 4 | ||||
-rw-r--r-- | net/mac80211/pm.c | 114 |
4 files changed, 137 insertions, 0 deletions
diff --git a/net/mac80211/Makefile b/net/mac80211/Makefile index 5c6fadfb6a00..58c94bb38e87 100644 --- a/net/mac80211/Makefile +++ b/net/mac80211/Makefile | |||
@@ -38,6 +38,8 @@ mac80211-$(CONFIG_MAC80211_MESH) += \ | |||
38 | mesh_plink.o \ | 38 | mesh_plink.o \ |
39 | mesh_hwmp.o | 39 | mesh_hwmp.o |
40 | 40 | ||
41 | mac80211-$(CONFIG_PM) += pm.o | ||
42 | |||
41 | # objects for PID algorithm | 43 | # objects for PID algorithm |
42 | rc80211_pid-y := rc80211_pid_algo.o | 44 | rc80211_pid-y := rc80211_pid_algo.o |
43 | rc80211_pid-$(CONFIG_MAC80211_DEBUGFS) += rc80211_pid_debugfs.o | 45 | rc80211_pid-$(CONFIG_MAC80211_DEBUGFS) += rc80211_pid_debugfs.o |
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index d1ac3ab2c515..3527de22cafb 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c | |||
@@ -1256,6 +1256,21 @@ static int ieee80211_set_mgmt_extra_ie(struct wiphy *wiphy, | |||
1256 | return ret; | 1256 | return ret; |
1257 | } | 1257 | } |
1258 | 1258 | ||
1259 | #ifdef CONFIG_PM | ||
1260 | static int ieee80211_suspend(struct wiphy *wiphy) | ||
1261 | { | ||
1262 | return __ieee80211_suspend(wiphy_priv(wiphy)); | ||
1263 | } | ||
1264 | |||
1265 | static int ieee80211_resume(struct wiphy *wiphy) | ||
1266 | { | ||
1267 | return __ieee80211_resume(wiphy_priv(wiphy)); | ||
1268 | } | ||
1269 | #else | ||
1270 | #define ieee80211_suspend NULL | ||
1271 | #define ieee80211_resume NULL | ||
1272 | #endif | ||
1273 | |||
1259 | struct cfg80211_ops mac80211_config_ops = { | 1274 | struct cfg80211_ops mac80211_config_ops = { |
1260 | .add_virtual_intf = ieee80211_add_iface, | 1275 | .add_virtual_intf = ieee80211_add_iface, |
1261 | .del_virtual_intf = ieee80211_del_iface, | 1276 | .del_virtual_intf = ieee80211_del_iface, |
@@ -1286,4 +1301,6 @@ struct cfg80211_ops mac80211_config_ops = { | |||
1286 | .set_txq_params = ieee80211_set_txq_params, | 1301 | .set_txq_params = ieee80211_set_txq_params, |
1287 | .set_channel = ieee80211_set_channel, | 1302 | .set_channel = ieee80211_set_channel, |
1288 | .set_mgmt_extra_ie = ieee80211_set_mgmt_extra_ie, | 1303 | .set_mgmt_extra_ie = ieee80211_set_mgmt_extra_ie, |
1304 | .suspend = ieee80211_suspend, | ||
1305 | .resume = ieee80211_resume, | ||
1289 | }; | 1306 | }; |
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 5eafd3affe27..faa2476a2451 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h | |||
@@ -1006,6 +1006,10 @@ void ieee80211_handle_pwr_constr(struct ieee80211_sub_if_data *sdata, | |||
1006 | u16 capab_info, u8 *pwr_constr_elem, | 1006 | u16 capab_info, u8 *pwr_constr_elem, |
1007 | u8 pwr_constr_elem_len); | 1007 | u8 pwr_constr_elem_len); |
1008 | 1008 | ||
1009 | /* Suspend/resume */ | ||
1010 | int __ieee80211_suspend(struct ieee80211_hw *hw); | ||
1011 | int __ieee80211_resume(struct ieee80211_hw *hw); | ||
1012 | |||
1009 | /* utility functions/constants */ | 1013 | /* utility functions/constants */ |
1010 | extern void *mac80211_wiphy_privid; /* for wiphy privid */ | 1014 | extern void *mac80211_wiphy_privid; /* for wiphy privid */ |
1011 | extern const unsigned char rfc1042_header[6]; | 1015 | extern const unsigned char rfc1042_header[6]; |
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 | } | ||