summary refs log tree commit diff
path: root/net/mac80211/mlme.c
diff options
context:
space:
mode:
authorSara Sharon <sara.sharon@intel.com>2019-02-06 13:17:10 +0200
committerJohannes Berg <johannes.berg@intel.com>2019-02-22 13:43:53 +0100
commitb9cc81d827ed13502ca9c8523361be26ca1d7220 (patch)
tree557b5204ff9b7cfea170afa9379fbdb1ecb4230b /net/mac80211/mlme.c
parentee145775c1eb84bb76e71639425ec44c654fb868 (diff)
downloadlinux-b9cc81d827ed13502ca9c8523361be26ca1d7220.tar.gz
mac80211: abort CSA if beacon does not include CSA IEs
In case we receive a beacon without CSA IE while we are in
the middle of channel switch - abort the operation.

Signed-off-by: Sara Sharon <sara.sharon@intel.com>
Signed-off-by: Luca Coelho <luciano.coelho@intel.com>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Diffstat (limited to 'net/mac80211/mlme.c')
-rw-r--r--net/mac80211/mlme.c43
1 files changed, 37 insertions, 6 deletions
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index 1b4938d100d5..28a275ec6700 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -1259,6 +1259,32 @@ static void ieee80211_chswitch_timer(struct timer_list *t)
 }
 
 static void
+ieee80211_sta_abort_chanswitch(struct ieee80211_sub_if_data *sdata)
+{
+	struct ieee80211_local *local = sdata->local;
+
+	if (!local->ops->abort_channel_switch)
+		return;
+
+	mutex_lock(&local->mtx);
+
+	mutex_lock(&local->chanctx_mtx);
+	ieee80211_vif_unreserve_chanctx(sdata);
+	mutex_unlock(&local->chanctx_mtx);
+
+	if (sdata->csa_block_tx)
+		ieee80211_wake_vif_queues(local, sdata,
+					  IEEE80211_QUEUE_STOP_REASON_CSA);
+
+	sdata->csa_block_tx = false;
+	sdata->vif.csa_active = false;
+
+	mutex_unlock(&local->mtx);
+
+	drv_abort_channel_switch(sdata);
+}
+
+static void
 ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata,
 				 u64 timestamp, u32 device_timestamp,
 				 struct ieee802_11_elems *elems,
@@ -1282,19 +1308,24 @@ ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata,
 	if (local->scanning)
 		return;
 
-	/* disregard subsequent announcements if we are already processing */
-	if (sdata->vif.csa_active)
-		return;
-
 	current_band = cbss->channel->band;
 	res = ieee80211_parse_ch_switch_ie(sdata, elems, current_band,
 					   ifmgd->flags,
 					   ifmgd->associated->bssid, &csa_ie);
-	if (res	< 0)
+	if (res < 0) {
 		ieee80211_queue_work(&local->hw,
 				     &ifmgd->csa_connection_drop_work);
-	if (res)
 		return;
+	}
+
+	if (res && beacon && sdata->vif.csa_active &&
+	    !ifmgd->csa_waiting_bcn) {
+		ieee80211_sta_abort_chanswitch(sdata);
+		return;
+	} else if (sdata->vif.csa_active || res) {
+		/* disregard subsequent announcements if already processing */
+		return;
+	}
 
 	if (!cfg80211_chandef_usable(local->hw.wiphy, &csa_ie.chandef,
 				     IEEE80211_CHAN_DISABLED)) {