|
@@ -1098,6 +1098,24 @@ static void ieee80211_chswitch_timer(unsigned long data)
|
|
|
ieee80211_queue_work(&sdata->local->hw, &sdata->u.mgd.chswitch_work);
|
|
|
}
|
|
|
|
|
|
+static void ieee80211_teardown_tdls_peers(struct ieee80211_sub_if_data *sdata)
|
|
|
+{
|
|
|
+ struct sta_info *sta;
|
|
|
+ u16 reason = WLAN_REASON_TDLS_TEARDOWN_UNSPECIFIED;
|
|
|
+
|
|
|
+ rcu_read_lock();
|
|
|
+ list_for_each_entry_rcu(sta, &sdata->local->sta_list, list) {
|
|
|
+ if (!sta->sta.tdls || sta->sdata != sdata || !sta->uploaded ||
|
|
|
+ !test_sta_flag(sta, WLAN_STA_AUTHORIZED))
|
|
|
+ continue;
|
|
|
+
|
|
|
+ ieee80211_tdls_oper_request(&sdata->vif, sta->sta.addr,
|
|
|
+ NL80211_TDLS_TEARDOWN, reason,
|
|
|
+ GFP_ATOMIC);
|
|
|
+ }
|
|
|
+ rcu_read_unlock();
|
|
|
+}
|
|
|
+
|
|
|
static void
|
|
|
ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata,
|
|
|
u64 timestamp, u32 device_timestamp,
|
|
@@ -1161,6 +1179,14 @@ ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata,
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
+ /*
|
|
|
+ * Drop all TDLS peers - either we disconnect or move to a different
|
|
|
+ * channel from this point on. There's no telling what our peer will do.
|
|
|
+ * The TDLS WIDER_BW scenario is also problematic, as peers might now
|
|
|
+ * have an incompatible wider chandef.
|
|
|
+ */
|
|
|
+ ieee80211_teardown_tdls_peers(sdata);
|
|
|
+
|
|
|
mutex_lock(&local->mtx);
|
|
|
mutex_lock(&local->chanctx_mtx);
|
|
|
conf = rcu_dereference_protected(sdata->vif.chanctx_conf,
|