Search Linux Wireless

[RFC 3/3] mac80211: synchronize channel switch and scan

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

 



Do not perform actual channel switch and scan is parallel. Devices
that implement channel switch in hardware are responsible to do
synchronization by itself if needed.

Signed-off-by: Stanislaw Gruszka <sgruszka@xxxxxxxxxx>
---
 net/mac80211/ieee80211_i.h |    1 +
 net/mac80211/mlme.c        |   19 ++++++++++++++++---
 2 files changed, 17 insertions(+), 3 deletions(-)

diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index a48d40f..98b0d6c 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -378,6 +378,7 @@ enum ieee80211_sta_flags {
 	IEEE80211_STA_UAPSD_ENABLED	= BIT(7),
 	IEEE80211_STA_NULLFUNC_ACKED	= BIT(8),
 	IEEE80211_STA_RESET_SIGNAL_AVE	= BIT(9),
+	IEEE80211_STA_CSA_DEFERRED	= BIT(10),
 };
 
 struct ieee80211_mgd_auth_data {
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index 0737278..ebc60a2 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -726,6 +726,13 @@ static void ieee80211_chswitch_work(struct work_struct *work)
 	if (!ifmgd->associated)
 		goto out;
 
+	mutex_lock(&sdata->local->mtx);
+	if (sdata->local->scanning) {
+		ifmgd->flags |= IEEE80211_STA_CSA_DEFERRED;
+		mutex_unlock(&sdata->local->mtx);
+		goto out_unlock;
+	}
+
 	sdata->local->oper_channel = sdata->local->csa_channel;
 	if (!sdata->local->ops->channel_switch) {
 		/* call "hw_config" only if doing sw channel switch */
@@ -741,8 +748,11 @@ static void ieee80211_chswitch_work(struct work_struct *work)
 
 	ieee80211_wake_queues_by_reason(&sdata->local->hw,
 					IEEE80211_QUEUE_STOP_REASON_CSA);
+
+	mutex_unlock(&sdata->local->mtx);
  out:
 	ifmgd->flags &= ~IEEE80211_STA_CSA_RECEIVED;
+ out_unlock:
 	mutex_unlock(&ifmgd->mtx);
 }
 
@@ -800,9 +810,6 @@ void ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata,
 	if (!ifmgd->associated)
 		return;
 
-	if (sdata->local->scanning)
-		return;
-
 	/* Disregard subsequent beacons if we are already running a timer
 	   processing a CSA */
 
@@ -3037,12 +3044,18 @@ void ieee80211_sta_setup_sdata(struct ieee80211_sub_if_data *sdata)
 void ieee80211_mlme_notify_scan_completed(struct ieee80211_local *local)
 {
 	struct ieee80211_sub_if_data *sdata = local->scan_sdata;
+	struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
 
 	/* Restart STA timers */
 	rcu_read_lock();
 	list_for_each_entry_rcu(sdata, &local->interfaces, list)
 		ieee80211_restart_sta_timer(sdata);
 	rcu_read_unlock();
+
+	if (ifmgd->flags & IEEE80211_STA_CSA_DEFERRED) {
+		ifmgd->flags &= ~IEEE80211_STA_CSA_DEFERRED;
+		ieee80211_queue_work(&sdata->local->hw, &ifmgd->chswitch_work);
+	}
 }
 
 int ieee80211_max_network_latency(struct notifier_block *nb,
-- 
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