aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211/mlme.c
diff options
context:
space:
mode:
authorJohannes Berg <johannes@sipsolutions.net>2009-05-17 05:40:42 -0400
committerJohn W. Linville <linville@tuxdriver.com>2009-05-20 14:46:25 -0400
commit5bb644a0fd25a5e083ecbfaa92a211db99aa6ef7 (patch)
treed2a6d5ff2323db0c475be15c63bb8fc55482a1e2 /net/mac80211/mlme.c
parentcc32abd494c0a8f76f2638e3f3a76e01c68bc9ea (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/mlme.c')
-rw-r--r--net/mac80211/mlme.c59
1 files changed, 59 insertions, 0 deletions
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index 41f3c1f98cc3..b61a7819867e 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -37,6 +37,9 @@
37#define IEEE80211_PROBE_IDLE_TIME (60 * HZ) 37#define IEEE80211_PROBE_IDLE_TIME (60 * HZ)
38#define IEEE80211_RETRY_AUTH_INTERVAL (1 * HZ) 38#define IEEE80211_RETRY_AUTH_INTERVAL (1 * HZ)
39 39
40#define TMR_RUNNING_TIMER 0
41#define TMR_RUNNING_CHANSW 1
42
40/* utils */ 43/* utils */
41static int ecw2cw(int ecw) 44static int ecw2cw(int ecw)
42{ 45{
@@ -521,6 +524,11 @@ static void ieee80211_chswitch_timer(unsigned long data)
521 (struct ieee80211_sub_if_data *) data; 524 (struct ieee80211_sub_if_data *) data;
522 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; 525 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
523 526
527 if (sdata->local->quiescing) {
528 set_bit(TMR_RUNNING_CHANSW, &ifmgd->timers_running);
529 return;
530 }
531
524 queue_work(sdata->local->hw.workqueue, &ifmgd->chswitch_work); 532 queue_work(sdata->local->hw.workqueue, &ifmgd->chswitch_work);
525} 533}
526 534
@@ -714,6 +722,9 @@ void ieee80211_dynamic_ps_timer(unsigned long data)
714{ 722{
715 struct ieee80211_local *local = (void *) data; 723 struct ieee80211_local *local = (void *) data;
716 724
725 if (local->quiescing)
726 return;
727
717 queue_work(local->hw.workqueue, &local->dynamic_ps_enable_work); 728 queue_work(local->hw.workqueue, &local->dynamic_ps_enable_work);
718} 729}
719 730
@@ -2108,6 +2119,11 @@ static void ieee80211_sta_timer(unsigned long data)
2108 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; 2119 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
2109 struct ieee80211_local *local = sdata->local; 2120 struct ieee80211_local *local = sdata->local;
2110 2121
2122 if (local->quiescing) {
2123 set_bit(TMR_RUNNING_TIMER, &ifmgd->timers_running);
2124 return;
2125 }
2126
2111 set_bit(IEEE80211_STA_REQ_RUN, &ifmgd->request); 2127 set_bit(IEEE80211_STA_REQ_RUN, &ifmgd->request);
2112 queue_work(local->hw.workqueue, &ifmgd->work); 2128 queue_work(local->hw.workqueue, &ifmgd->work);
2113} 2129}
@@ -2240,6 +2256,17 @@ static void ieee80211_sta_work(struct work_struct *work)
2240 2256
2241 if (WARN_ON(sdata->vif.type != NL80211_IFTYPE_STATION)) 2257 if (WARN_ON(sdata->vif.type != NL80211_IFTYPE_STATION))
2242 return; 2258 return;
2259
2260 /*
2261 * Nothing should have been stuffed into the workqueue during
2262 * the suspend->resume cycle. If this WARN is seen then there
2263 * is a bug with either the driver suspend or something in
2264 * mac80211 stuffing into the workqueue which we haven't yet
2265 * cleared during mac80211's suspend cycle.
2266 */
2267 if (WARN_ON(local->suspended))
2268 return;
2269
2243 ifmgd = &sdata->u.mgd; 2270 ifmgd = &sdata->u.mgd;
2244 2271
2245 while ((skb = skb_dequeue(&ifmgd->skb_queue))) 2272 while ((skb = skb_dequeue(&ifmgd->skb_queue)))
@@ -2307,6 +2334,38 @@ static void ieee80211_restart_sta_timer(struct ieee80211_sub_if_data *sdata)
2307 } 2334 }
2308} 2335}
2309 2336
2337#ifdef CONFIG_PM
2338void ieee80211_sta_quiesce(struct ieee80211_sub_if_data *sdata)
2339{
2340 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
2341
2342 /*
2343 * we need to use atomic bitops for the running bits
2344 * only because both timers might fire at the same
2345 * time -- the code here is properly synchronised.
2346 */
2347
2348 cancel_work_sync(&ifmgd->work);
2349 cancel_work_sync(&ifmgd->beacon_loss_work);
2350 if (del_timer_sync(&ifmgd->timer))
2351 set_bit(TMR_RUNNING_TIMER, &ifmgd->timers_running);
2352
2353 cancel_work_sync(&ifmgd->chswitch_work);
2354 if (del_timer_sync(&ifmgd->chswitch_timer))
2355 set_bit(TMR_RUNNING_CHANSW, &ifmgd->timers_running);
2356}
2357
2358void ieee80211_sta_restart(struct ieee80211_sub_if_data *sdata)
2359{
2360 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
2361
2362 if (test_and_clear_bit(TMR_RUNNING_TIMER, &ifmgd->timers_running))
2363 add_timer(&ifmgd->timer);
2364 if (test_and_clear_bit(TMR_RUNNING_CHANSW, &ifmgd->timers_running))
2365 add_timer(&ifmgd->chswitch_timer);
2366}
2367#endif
2368
2310/* interface setup */ 2369/* interface setup */
2311void ieee80211_sta_setup_sdata(struct ieee80211_sub_if_data *sdata) 2370void ieee80211_sta_setup_sdata(struct ieee80211_sub_if_data *sdata)
2312{ 2371{