aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211/util.c
diff options
context:
space:
mode:
authorEmmanuel Grumbach <emmanuel.grumbach@intel.com>2015-01-22 16:32:46 -0500
committerJohannes Berg <johannes.berg@intel.com>2015-01-23 04:54:22 -0500
commit4afaff176a968457df18eeebc1aad910b6154761 (patch)
treeb72d595e376af86d6e3217a5d608fb690864cec2 /net/mac80211/util.c
parent14f2ae83d07a0a0d499d4760dd4a1bffd310b6ae (diff)
mac80211: avoid races related to suspend flow
When we go to suspend, there is complex set of states that avoids races. The quiescing variable is set whlie __ieee80211_suspend is running. Then suspended is set. The code makes sure there is no window without any of these flags. The problem is that workers can still be enqueued while we are quiescing. This leads to situations where the driver is already suspending and other flows like disassociation are handled by a worker. To fix this, we need to check quiescing and suspended flags in the worker itself and not only before enqueueing it. I also add here extensive documentation to ease the understanding of these complex issues. Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com> Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Diffstat (limited to 'net/mac80211/util.c')
-rw-r--r--net/mac80211/util.c15
1 files changed, 9 insertions, 6 deletions
diff --git a/net/mac80211/util.c b/net/mac80211/util.c
index fbd37d43dfce..c65d03f3c167 100644
--- a/net/mac80211/util.c
+++ b/net/mac80211/util.c
@@ -744,16 +744,19 @@ EXPORT_SYMBOL_GPL(wdev_to_ieee80211_vif);
744 744
745/* 745/*
746 * Nothing should have been stuffed into the workqueue during 746 * Nothing should have been stuffed into the workqueue during
747 * the suspend->resume cycle. If this WARN is seen then there 747 * the suspend->resume cycle. Since we can't check each caller
748 * is a bug with either the driver suspend or something in 748 * of this function if we are already quiescing / suspended,
749 * mac80211 stuffing into the workqueue which we haven't yet 749 * check here and don't WARN since this can actually happen when
750 * cleared during mac80211's suspend cycle. 750 * the rx path (for example) is racing against __ieee80211_suspend
751 * and suspending / quiescing was set after the rx path checked
752 * them.
751 */ 753 */
752static bool ieee80211_can_queue_work(struct ieee80211_local *local) 754static bool ieee80211_can_queue_work(struct ieee80211_local *local)
753{ 755{
754 if (WARN(local->suspended && !local->resuming, 756 if (local->quiescing || (local->suspended && !local->resuming)) {
755 "queueing ieee80211 work while going to suspend\n")) 757 pr_warn("queueing ieee80211 work while going to suspend\n");
756 return false; 758 return false;
759 }
757 760
758 return true; 761 return true;
759} 762}