diff options
author | Johannes Berg <johannes@sipsolutions.net> | 2009-03-13 06:44:18 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2009-03-27 20:13:03 -0400 |
commit | 827b1fb44b7e41377a5498b9d070a11dfae2c283 (patch) | |
tree | 5a54acadb35e35d64e4db0cfde5a7105c85916e2 /net | |
parent | 3e3ccb3d9b8d5a1b65b34e1be2decf213ba3bebb (diff) |
mac80211: resume properly, add suspend/resume test
When mac80211 resumes, it currently doesn't reconfigure the interfaces
entirely and also doesn't reconfigure BSS information -- fix this.
Also, to be able to test this, add a debugfs file that just calls
the suspend/resume code to see what happens when we go through that,
without needing the time-consuming suspend/resume cycle.
(Original version broke the build for CONFIG_PM=n. Define alternative
functions for that situation. -- JWL)
Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'net')
-rw-r--r-- | net/mac80211/debugfs.c | 24 | ||||
-rw-r--r-- | net/mac80211/ieee80211_i.h | 12 | ||||
-rw-r--r-- | net/mac80211/pm.c | 29 |
3 files changed, 65 insertions, 0 deletions
diff --git a/net/mac80211/debugfs.c b/net/mac80211/debugfs.c index e37f557de3f3..210b9b6fecd2 100644 --- a/net/mac80211/debugfs.c +++ b/net/mac80211/debugfs.c | |||
@@ -40,6 +40,10 @@ static const struct file_operations name## _ops = { \ | |||
40 | local->debugfs.name = debugfs_create_file(#name, 0400, phyd, \ | 40 | local->debugfs.name = debugfs_create_file(#name, 0400, phyd, \ |
41 | local, &name## _ops); | 41 | local, &name## _ops); |
42 | 42 | ||
43 | #define DEBUGFS_ADD_MODE(name, mode) \ | ||
44 | local->debugfs.name = debugfs_create_file(#name, mode, phyd, \ | ||
45 | local, &name## _ops); | ||
46 | |||
43 | #define DEBUGFS_DEL(name) \ | 47 | #define DEBUGFS_DEL(name) \ |
44 | debugfs_remove(local->debugfs.name); \ | 48 | debugfs_remove(local->debugfs.name); \ |
45 | local->debugfs.name = NULL; | 49 | local->debugfs.name = NULL; |
@@ -113,6 +117,24 @@ static const struct file_operations tsf_ops = { | |||
113 | .open = mac80211_open_file_generic | 117 | .open = mac80211_open_file_generic |
114 | }; | 118 | }; |
115 | 119 | ||
120 | static ssize_t reset_write(struct file *file, const char __user *user_buf, | ||
121 | size_t count, loff_t *ppos) | ||
122 | { | ||
123 | struct ieee80211_local *local = file->private_data; | ||
124 | |||
125 | rtnl_lock(); | ||
126 | __ieee80211_suspend(&local->hw); | ||
127 | __ieee80211_resume(&local->hw); | ||
128 | rtnl_unlock(); | ||
129 | |||
130 | return count; | ||
131 | } | ||
132 | |||
133 | static const struct file_operations reset_ops = { | ||
134 | .write = reset_write, | ||
135 | .open = mac80211_open_file_generic, | ||
136 | }; | ||
137 | |||
116 | /* statistics stuff */ | 138 | /* statistics stuff */ |
117 | 139 | ||
118 | #define DEBUGFS_STATS_FILE(name, buflen, fmt, value...) \ | 140 | #define DEBUGFS_STATS_FILE(name, buflen, fmt, value...) \ |
@@ -254,6 +276,7 @@ void debugfs_hw_add(struct ieee80211_local *local) | |||
254 | DEBUGFS_ADD(total_ps_buffered); | 276 | DEBUGFS_ADD(total_ps_buffered); |
255 | DEBUGFS_ADD(wep_iv); | 277 | DEBUGFS_ADD(wep_iv); |
256 | DEBUGFS_ADD(tsf); | 278 | DEBUGFS_ADD(tsf); |
279 | DEBUGFS_ADD_MODE(reset, 0200); | ||
257 | 280 | ||
258 | statsd = debugfs_create_dir("statistics", phyd); | 281 | statsd = debugfs_create_dir("statistics", phyd); |
259 | local->debugfs.statistics = statsd; | 282 | local->debugfs.statistics = statsd; |
@@ -308,6 +331,7 @@ void debugfs_hw_del(struct ieee80211_local *local) | |||
308 | DEBUGFS_DEL(total_ps_buffered); | 331 | DEBUGFS_DEL(total_ps_buffered); |
309 | DEBUGFS_DEL(wep_iv); | 332 | DEBUGFS_DEL(wep_iv); |
310 | DEBUGFS_DEL(tsf); | 333 | DEBUGFS_DEL(tsf); |
334 | DEBUGFS_DEL(reset); | ||
311 | 335 | ||
312 | DEBUGFS_STATS_DEL(transmitted_fragment_count); | 336 | DEBUGFS_STATS_DEL(transmitted_fragment_count); |
313 | DEBUGFS_STATS_DEL(multicast_transmitted_frame_count); | 337 | DEBUGFS_STATS_DEL(multicast_transmitted_frame_count); |
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 7b96d95f48b1..547cfac218ee 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h | |||
@@ -780,6 +780,7 @@ struct ieee80211_local { | |||
780 | struct dentry *total_ps_buffered; | 780 | struct dentry *total_ps_buffered; |
781 | struct dentry *wep_iv; | 781 | struct dentry *wep_iv; |
782 | struct dentry *tsf; | 782 | struct dentry *tsf; |
783 | struct dentry *reset; | ||
783 | struct dentry *statistics; | 784 | struct dentry *statistics; |
784 | struct local_debugfsdentries_statsdentries { | 785 | struct local_debugfsdentries_statsdentries { |
785 | struct dentry *transmitted_fragment_count; | 786 | struct dentry *transmitted_fragment_count; |
@@ -1059,8 +1060,19 @@ void ieee80211_handle_pwr_constr(struct ieee80211_sub_if_data *sdata, | |||
1059 | u8 pwr_constr_elem_len); | 1060 | u8 pwr_constr_elem_len); |
1060 | 1061 | ||
1061 | /* Suspend/resume */ | 1062 | /* Suspend/resume */ |
1063 | #ifdef CONFIG_PM | ||
1062 | int __ieee80211_suspend(struct ieee80211_hw *hw); | 1064 | int __ieee80211_suspend(struct ieee80211_hw *hw); |
1063 | int __ieee80211_resume(struct ieee80211_hw *hw); | 1065 | int __ieee80211_resume(struct ieee80211_hw *hw); |
1066 | #else | ||
1067 | static inline int __ieee80211_suspend(struct ieee80211_hw *hw) | ||
1068 | { | ||
1069 | return 0; | ||
1070 | } | ||
1071 | static inline int __ieee80211_resume(struct ieee80211_hw *hw) | ||
1072 | { | ||
1073 | return 0; | ||
1074 | } | ||
1075 | #endif | ||
1064 | 1076 | ||
1065 | /* utility functions/constants */ | 1077 | /* utility functions/constants */ |
1066 | extern void *mac80211_wiphy_privid; /* for wiphy privid */ | 1078 | extern void *mac80211_wiphy_privid; /* for wiphy privid */ |
diff --git a/net/mac80211/pm.c b/net/mac80211/pm.c index 1e6152ac6778..027302326498 100644 --- a/net/mac80211/pm.c +++ b/net/mac80211/pm.c | |||
@@ -143,6 +143,35 @@ int __ieee80211_resume(struct ieee80211_hw *hw) | |||
143 | ieee80211_configure_filter(local); | 143 | ieee80211_configure_filter(local); |
144 | netif_addr_unlock_bh(local->mdev); | 144 | netif_addr_unlock_bh(local->mdev); |
145 | 145 | ||
146 | /* Finally also reconfigure all the BSS information */ | ||
147 | list_for_each_entry(sdata, &local->interfaces, list) { | ||
148 | u32 changed = ~0; | ||
149 | if (!netif_running(sdata->dev)) | ||
150 | continue; | ||
151 | switch (sdata->vif.type) { | ||
152 | case NL80211_IFTYPE_STATION: | ||
153 | /* disable beacon change bits */ | ||
154 | changed &= ~IEEE80211_IFCC_BEACON; | ||
155 | /* fall through */ | ||
156 | case NL80211_IFTYPE_ADHOC: | ||
157 | case NL80211_IFTYPE_AP: | ||
158 | case NL80211_IFTYPE_MESH_POINT: | ||
159 | WARN_ON(ieee80211_if_config(sdata, changed)); | ||
160 | ieee80211_bss_info_change_notify(sdata, ~0); | ||
161 | break; | ||
162 | case NL80211_IFTYPE_WDS: | ||
163 | break; | ||
164 | case NL80211_IFTYPE_AP_VLAN: | ||
165 | case NL80211_IFTYPE_MONITOR: | ||
166 | /* ignore virtual */ | ||
167 | break; | ||
168 | case NL80211_IFTYPE_UNSPECIFIED: | ||
169 | case __NL80211_IFTYPE_AFTER_LAST: | ||
170 | WARN_ON(1); | ||
171 | break; | ||
172 | } | ||
173 | } | ||
174 | |||
146 | ieee80211_wake_queues_by_reason(hw, | 175 | ieee80211_wake_queues_by_reason(hw, |
147 | IEEE80211_QUEUE_STOP_REASON_SUSPEND); | 176 | IEEE80211_QUEUE_STOP_REASON_SUSPEND); |
148 | 177 | ||