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 | |
| 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>
| -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 | ||
