summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--net/mac80211/main.c8
-rw-r--r--net/mac80211/mesh.c9
2 files changed, 17 insertions, 0 deletions
diff --git a/net/mac80211/main.c b/net/mac80211/main.c
index 522fe6176485..ebdec7106d63 100644
--- a/net/mac80211/main.c
+++ b/net/mac80211/main.c
@@ -548,6 +548,14 @@ static int ieee80211_stop(struct net_device *dev)
memset(sdata->u.sta.bssid, 0, ETH_ALEN);
del_timer_sync(&sdata->u.sta.timer);
/*
+ * If the timer fired while we waited for it, it will have
+ * requeued the work. Now the work will be running again
+ * but will not rearm the timer again because it checks
+ * whether the interface is running, which, at this point,
+ * it no longer is.
+ */
+ cancel_work_sync(&sdata->u.sta.work);
+ /*
* When we get here, the interface is marked down.
* Call synchronize_rcu() to wait for the RX path
* should it be using the interface and enqueuing
diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c
index 9e47725cc592..a0141f5ff184 100644
--- a/net/mac80211/mesh.c
+++ b/net/mac80211/mesh.c
@@ -449,6 +449,15 @@ void ieee80211_stop_mesh(struct ieee80211_sub_if_data *sdata)
{
del_timer_sync(&sdata->u.mesh.housekeeping_timer);
/*
+ * If the timer fired while we waited for it, it will have
+ * requeued the work. Now the work will be running again
+ * but will not rearm the timer again because it checks
+ * whether the interface is running, which, at this point,
+ * it no longer is.
+ */
+ cancel_work_sync(&sdata->u.mesh.work);
+
+ /*
* When we get here, the interface is marked down.
* Call synchronize_rcu() to wait for the RX path
* should it be using the interface and enqueuing