Commit 0ecfe806 authored by Johannes Berg's avatar Johannes Berg Committed by John W. Linville

mac80211: fix race between connection monitor & suspend

When the connection monitor timer fires right before
suspend, the following will happen:
 timer fires -> monitor_work gets queued
 suspend calls ieee80211_sta_quiesce
 ieee80211_sta_quiesce:
  - deletes timer
  - cancels monitor_work synchronously, running it
  [note wrong order of these steps]
 monitor_work runs, re-arming the timer
 later, timer fires while system should be quiesced

This causes a warning:

WARNING: at net/mac80211/util.c:540 ieee80211_can_queue_work+0x35/0x40 [mac80211]()

but is otherwise harmless. I'm not completely sure
this is the scenario Thomas stumbled across, but it
is the only way I can right now see the warning in
a scenario like the one he reported.
Reported-by: default avatarThomas Meyer <thomas@m3y3r.de>
Signed-off-by: default avatarJohannes Berg <johannes.berg@intel.com>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent d929bbc6
...@@ -2286,6 +2286,7 @@ void ieee80211_sta_quiesce(struct ieee80211_sub_if_data *sdata) ...@@ -2286,6 +2286,7 @@ void ieee80211_sta_quiesce(struct ieee80211_sub_if_data *sdata)
cancel_work_sync(&ifmgd->request_smps_work); cancel_work_sync(&ifmgd->request_smps_work);
cancel_work_sync(&ifmgd->monitor_work);
cancel_work_sync(&ifmgd->beacon_connection_loss_work); cancel_work_sync(&ifmgd->beacon_connection_loss_work);
if (del_timer_sync(&ifmgd->timer)) if (del_timer_sync(&ifmgd->timer))
set_bit(TMR_RUNNING_TIMER, &ifmgd->timers_running); set_bit(TMR_RUNNING_TIMER, &ifmgd->timers_running);
...@@ -2294,7 +2295,6 @@ void ieee80211_sta_quiesce(struct ieee80211_sub_if_data *sdata) ...@@ -2294,7 +2295,6 @@ void ieee80211_sta_quiesce(struct ieee80211_sub_if_data *sdata)
if (del_timer_sync(&ifmgd->chswitch_timer)) if (del_timer_sync(&ifmgd->chswitch_timer))
set_bit(TMR_RUNNING_CHANSW, &ifmgd->timers_running); set_bit(TMR_RUNNING_CHANSW, &ifmgd->timers_running);
cancel_work_sync(&ifmgd->monitor_work);
/* these will just be re-established on connection */ /* these will just be re-established on connection */
del_timer_sync(&ifmgd->conn_mon_timer); del_timer_sync(&ifmgd->conn_mon_timer);
del_timer_sync(&ifmgd->bcn_mon_timer); del_timer_sync(&ifmgd->bcn_mon_timer);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment