Search Linux Wireless

[PATCH 2/2] mac80211: fixes for virtual monitor add/remove on suspend

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Change suspend/resume and add/remove virtual monitor code (called at
ieee80211_do_stop) to avoid calling drv callback while we are suspended.

Signed-off-by: Stanislaw Gruszka <sgruszka@xxxxxxxxxx>
---
 net/mac80211/iface.c |   43 +++++++++++++++++++++++--------------------
 net/mac80211/pm.c    |    4 +++-
 net/mac80211/util.c  |   12 ++++++++++--
 3 files changed, 36 insertions(+), 23 deletions(-)

diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c
index c136050..7893913 100644
--- a/net/mac80211/iface.c
+++ b/net/mac80211/iface.c
@@ -373,28 +373,30 @@ static int ieee80211_add_virtual_monitor(struct ieee80211_local *local)
 
 	ieee80211_set_default_queues(sdata);
 
-	ret = drv_add_interface(local, sdata);
-	if (WARN_ON(ret)) {
-		/* ok .. stupid driver, it asked for this! */
-		kfree(sdata);
-		goto out_unlock;
-	}
+	if (!local->suspended) {
+		ret = drv_add_interface(local, sdata);
+		if (WARN_ON(ret)) {
+			/* ok .. stupid driver, it asked for this! */
+			goto out_free;
+		}
 
-	ret = ieee80211_check_queues(sdata);
-	if (ret) {
-		kfree(sdata);
-		goto out_unlock;
-	}
+			ret = ieee80211_check_queues(sdata);
+		if (ret)
+			goto out_remove;
 
-	ret = ieee80211_vif_use_channel(sdata, &local->monitor_chandef,
-					IEEE80211_CHANCTX_EXCLUSIVE);
-	if (ret) {
-		drv_remove_interface(local, sdata);
-		kfree(sdata);
-		goto out_unlock;
+		ret = ieee80211_vif_use_channel(sdata, &local->monitor_chandef,
+						IEEE80211_CHANCTX_EXCLUSIVE);
+		if (ret)
+			goto out_remove;
 	}
 
 	rcu_assign_pointer(local->monitor_sdata, sdata);
+	goto out_unlock;
+
+ out_remove:
+	drv_remove_interface(local, sdata);
+ out_free:
+	kfree(sdata);
  out_unlock:
 	mutex_unlock(&local->iflist_mtx);
 	return ret;
@@ -417,9 +419,10 @@ static void ieee80211_del_virtual_monitor(struct ieee80211_local *local)
 	rcu_assign_pointer(local->monitor_sdata, NULL);
 	synchronize_net();
 
-	ieee80211_vif_release_channel(sdata);
-
-	drv_remove_interface(local, sdata);
+	if (!local->suspended) {
+		ieee80211_vif_release_channel(sdata);
+		drv_remove_interface(local, sdata);
+	}
 
 	kfree(sdata);
  out_unlock:
diff --git a/net/mac80211/pm.c b/net/mac80211/pm.c
index b471a67..dbe42ea 100644
--- a/net/mac80211/pm.c
+++ b/net/mac80211/pm.c
@@ -100,8 +100,10 @@ int __ieee80211_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan)
 	}
 
 	sdata = rtnl_dereference(local->monitor_sdata);
-	if (sdata)
+	if (sdata) {
+		ieee80211_vif_release_channel(sdata);
 		drv_remove_interface(local, sdata);
+	}
 
 	/*
 	 * We disconnected on all interfaces before suspend, all channel
diff --git a/net/mac80211/util.c b/net/mac80211/util.c
index b7a856e..8f30275 100644
--- a/net/mac80211/util.c
+++ b/net/mac80211/util.c
@@ -1470,8 +1470,16 @@ int ieee80211_reconfig(struct ieee80211_local *local)
 	}
 
 	sdata = rtnl_dereference(local->monitor_sdata);
-	if (sdata && ieee80211_sdata_running(sdata))
-		ieee80211_assign_chanctx(local, sdata);
+	if (sdata) {
+		res = ieee80211_vif_use_channel(sdata, &local->monitor_chandef,
+						IEEE80211_CHANCTX_EXCLUSIVE);
+		if (WARN_ON(res)) {
+			drv_remove_interface(local, sdata);
+			rcu_assign_pointer(local->monitor_sdata, NULL);
+			synchronize_net();
+			kfree(sdata);
+		}
+	}
 
 	/* add STAs back */
 	mutex_lock(&local->sta_mtx);
-- 
1.7.1

--
To unsubscribe from this list: send the line "unsubscribe linux-wireless" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Linux Host AP]     [ATH6KL]     [Linux Wireless Personal Area Network]     [Linux Bluetooth]     [Linux Netdev]     [Kernel Newbies]     [Linux Kernel]     [IDE]     [Git]     [Netfilter]     [Bugtraq]     [Yosemite Hiking]     [MIPS Linux]     [ARM Linux]     [Linux RAID]

  Powered by Linux