diff options
author | Johannes Berg <johannes@sipsolutions.net> | 2009-05-17 05:40:42 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2009-05-20 14:46:25 -0400 |
commit | 5bb644a0fd25a5e083ecbfaa92a211db99aa6ef7 (patch) | |
tree | d2a6d5ff2323db0c475be15c63bb8fc55482a1e2 /net/mac80211/util.c | |
parent | cc32abd494c0a8f76f2638e3f3a76e01c68bc9ea (diff) |
mac80211: cancel/restart all timers across suspend/resume
We forgot to cancel all timers in mac80211 when suspending.
In particular we forgot to deal with some things that can
cause hardware reconfiguration -- while it is down.
While at it we go ahead and add a warning in ieee80211_sta_work()
if its run while the suspend->resume cycle is in effect. This
should not happen and if it does it would indicate there is
a bug lurking in either mac80211 or mac80211 drivers.
With this now wpa_supplicant doesn't blink when I go to suspend
and resume where as before there where issues with some timers
running during the suspend->resume cycle. This caused a lot of
incorrect assumptions and would at times bring back the device
in an incoherent, but mostly recoverable, state.
Signed-off-by: Luis R. Rodriguez <lrodriguez@atheros.com>
Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'net/mac80211/util.c')
-rw-r--r-- | net/mac80211/util.c | 43 |
1 files changed, 43 insertions, 0 deletions
diff --git a/net/mac80211/util.c b/net/mac80211/util.c index 0689a8fbd1e..ffb6e88f2ec 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c | |||
@@ -1034,6 +1034,13 @@ int ieee80211_reconfig(struct ieee80211_local *local) | |||
1034 | struct sta_info *sta; | 1034 | struct sta_info *sta; |
1035 | unsigned long flags; | 1035 | unsigned long flags; |
1036 | int res; | 1036 | int res; |
1037 | bool from_suspend = local->suspended; | ||
1038 | |||
1039 | /* | ||
1040 | * We're going to start the hardware, at that point | ||
1041 | * we are no longer suspended and can RX frames. | ||
1042 | */ | ||
1043 | local->suspended = false; | ||
1037 | 1044 | ||
1038 | /* restart hardware */ | 1045 | /* restart hardware */ |
1039 | if (local->open_count) { | 1046 | if (local->open_count) { |
@@ -1058,6 +1065,7 @@ int ieee80211_reconfig(struct ieee80211_local *local) | |||
1058 | if (local->ops->sta_notify) { | 1065 | if (local->ops->sta_notify) { |
1059 | spin_lock_irqsave(&local->sta_lock, flags); | 1066 | spin_lock_irqsave(&local->sta_lock, flags); |
1060 | list_for_each_entry(sta, &local->sta_list, list) { | 1067 | list_for_each_entry(sta, &local->sta_list, list) { |
1068 | sdata = sta->sdata; | ||
1061 | if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) | 1069 | if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) |
1062 | sdata = container_of(sdata->bss, | 1070 | sdata = container_of(sdata->bss, |
1063 | struct ieee80211_sub_if_data, | 1071 | struct ieee80211_sub_if_data, |
@@ -1128,5 +1136,40 @@ int ieee80211_reconfig(struct ieee80211_local *local) | |||
1128 | ieee80211_wake_queues_by_reason(hw, | 1136 | ieee80211_wake_queues_by_reason(hw, |
1129 | IEEE80211_QUEUE_STOP_REASON_SUSPEND); | 1137 | IEEE80211_QUEUE_STOP_REASON_SUSPEND); |
1130 | 1138 | ||
1139 | /* | ||
1140 | * If this is for hw restart things are still running. | ||
1141 | * We may want to change that later, however. | ||
1142 | */ | ||
1143 | if (!from_suspend) | ||
1144 | return 0; | ||
1145 | |||
1146 | #ifdef CONFIG_PM | ||
1147 | local->suspended = false; | ||
1148 | |||
1149 | list_for_each_entry(sdata, &local->interfaces, list) { | ||
1150 | switch(sdata->vif.type) { | ||
1151 | case NL80211_IFTYPE_STATION: | ||
1152 | ieee80211_sta_restart(sdata); | ||
1153 | break; | ||
1154 | case NL80211_IFTYPE_ADHOC: | ||
1155 | ieee80211_ibss_restart(sdata); | ||
1156 | break; | ||
1157 | case NL80211_IFTYPE_MESH_POINT: | ||
1158 | ieee80211_mesh_restart(sdata); | ||
1159 | break; | ||
1160 | default: | ||
1161 | break; | ||
1162 | } | ||
1163 | } | ||
1164 | |||
1165 | add_timer(&local->sta_cleanup); | ||
1166 | |||
1167 | spin_lock_irqsave(&local->sta_lock, flags); | ||
1168 | list_for_each_entry(sta, &local->sta_list, list) | ||
1169 | mesh_plink_restart(sta); | ||
1170 | spin_unlock_irqrestore(&local->sta_lock, flags); | ||
1171 | #else | ||
1172 | WARN_ON(1); | ||
1173 | #endif | ||
1131 | return 0; | 1174 | return 0; |
1132 | } | 1175 | } |