aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211
diff options
context:
space:
mode:
authorJohannes Berg <johannes@sipsolutions.net>2009-11-19 08:29:39 -0500
committerJohn W. Linville <linville@tuxdriver.com>2009-11-19 11:08:39 -0500
commitceb99fe071eb688255798d89be337affffa2b103 (patch)
tree443cdf6d6fffab53db16006e44fd6506d814fd86 /net/mac80211
parent8ade00824607fcfa8842572012d4393b40a74a94 (diff)
mac80211: fix resume
When mac80211 resumes, it currently first sets suspended to false so the driver can start doing things and we can receive frames. However, if we actually receive frames then it can end up starting some work which adds timers and then later runs into a BUG_ON in the timer code because it tries add_timer() on a pending timer. Fix this by keeping track of the resuming process by introducing a new variable 'resuming' which gets set to true early on instead of setting 'suspended' to false, and allow queueing work but not receiving frames while resuming. Reported-by: Maxim Levitsky <maximlevitsky@gmail.com> Signed-off-by: Johannes Berg <johannes@sipsolutions.net> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'net/mac80211')
-rw-r--r--net/mac80211/ieee80211_i.h8
-rw-r--r--net/mac80211/util.c19
2 files changed, 17 insertions, 10 deletions
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index 588005c84a6d..a910bf1f092f 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -662,6 +662,14 @@ struct ieee80211_local {
662 bool suspended; 662 bool suspended;
663 663
664 /* 664 /*
665 * Resuming is true while suspended, but when we're reprogramming the
666 * hardware -- at that time it's allowed to use ieee80211_queue_work()
667 * again even though some other parts of the stack are still suspended
668 * and we still drop received frames to avoid waking the stack.
669 */
670 bool resuming;
671
672 /*
665 * quiescing is true during the suspend process _only_ to 673 * quiescing is true during the suspend process _only_ to
666 * ease timer cancelling etc. 674 * ease timer cancelling etc.
667 */ 675 */
diff --git a/net/mac80211/util.c b/net/mac80211/util.c
index aeb65b3d2295..e6c08da8da26 100644
--- a/net/mac80211/util.c
+++ b/net/mac80211/util.c
@@ -520,9 +520,9 @@ EXPORT_SYMBOL_GPL(ieee80211_iterate_active_interfaces_atomic);
520 */ 520 */
521static bool ieee80211_can_queue_work(struct ieee80211_local *local) 521static bool ieee80211_can_queue_work(struct ieee80211_local *local)
522{ 522{
523 if (WARN(local->suspended, "queueing ieee80211 work while " 523 if (WARN(local->suspended && !local->resuming,
524 "going to suspend\n")) 524 "queueing ieee80211 work while going to suspend\n"))
525 return false; 525 return false;
526 526
527 return true; 527 return true;
528} 528}
@@ -1025,13 +1025,9 @@ int ieee80211_reconfig(struct ieee80211_local *local)
1025 struct sta_info *sta; 1025 struct sta_info *sta;
1026 unsigned long flags; 1026 unsigned long flags;
1027 int res; 1027 int res;
1028 bool from_suspend = local->suspended;
1029 1028
1030 /* 1029 if (local->suspended)
1031 * We're going to start the hardware, at that point 1030 local->resuming = true;
1032 * we are no longer suspended and can RX frames.
1033 */
1034 local->suspended = false;
1035 1031
1036 /* restart hardware */ 1032 /* restart hardware */
1037 if (local->open_count) { 1033 if (local->open_count) {
@@ -1129,11 +1125,14 @@ int ieee80211_reconfig(struct ieee80211_local *local)
1129 * If this is for hw restart things are still running. 1125 * If this is for hw restart things are still running.
1130 * We may want to change that later, however. 1126 * We may want to change that later, however.
1131 */ 1127 */
1132 if (!from_suspend) 1128 if (!local->suspended)
1133 return 0; 1129 return 0;
1134 1130
1135#ifdef CONFIG_PM 1131#ifdef CONFIG_PM
1132 /* first set suspended false, then resuming */
1136 local->suspended = false; 1133 local->suspended = false;
1134 mb();
1135 local->resuming = false;
1137 1136
1138 list_for_each_entry(sdata, &local->interfaces, list) { 1137 list_for_each_entry(sdata, &local->interfaces, list) {
1139 switch(sdata->vif.type) { 1138 switch(sdata->vif.type) {