forked from torvalds/linux
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
mac80211: TDLS: correctly configure SMPS state
The IEEE802.11-2012 specification is vague regarding SMPS operation during TDLS. It does not define a clear way to transition between SMPS states. To avoid interop issues, set SMPS to off when TDLS peers are connected. Accomplish this by extending the definition of the AUTOMATIC state. If the driver forces a state other than OFF, disconnect all TDLS peers. While at it, avoid changing the SMPS state of the peer STA. We have no way to control it, so try and behave correctly towards it. Move the TDLS peer-teardown function to where the rest of the TDLS code resides. Signed-off-by: Arik Nemtsov <[email protected]> Signed-off-by: Johannes Berg <[email protected]>
- Loading branch information
1 parent
3633ebe
commit d51c2ea
Showing
4 changed files
with
51 additions
and
25 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4,6 +4,7 @@ | |
* Copyright 2006-2010 Johannes Berg <[email protected]> | ||
* Copyright 2014, Intel Corporation | ||
* Copyright 2014 Intel Mobile Communications GmbH | ||
* Copyright 2015 Intel Deutschland GmbH | ||
* | ||
* This file is GPLv2 as found in COPYING. | ||
*/ | ||
|
@@ -448,10 +449,6 @@ ieee80211_tdls_add_setup_start_ies(struct ieee80211_sub_if_data *sdata, | |
ieee80211_ie_build_ht_cap(pos, &ht_cap, ht_cap.cap); | ||
} else if (action_code == WLAN_TDLS_SETUP_RESPONSE && | ||
ht_cap.ht_supported && sta->sta.ht_cap.ht_supported) { | ||
/* disable SMPS in TDLS responder */ | ||
sta->sta.ht_cap.cap |= WLAN_HT_CAP_SM_PS_DISABLED | ||
<< IEEE80211_HT_CAP_SM_PS_SHIFT; | ||
|
||
/* the peer caps are already intersected with our own */ | ||
memcpy(&ht_cap, &sta->sta.ht_cap, sizeof(ht_cap)); | ||
|
||
|
@@ -1063,8 +1060,17 @@ ieee80211_tdls_mgmt_setup(struct wiphy *wiphy, struct net_device *dev, | |
{ | ||
struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
struct ieee80211_local *local = sdata->local; | ||
enum ieee80211_smps_mode smps_mode = sdata->u.mgd.driver_smps_mode; | ||
int ret; | ||
|
||
/* don't support setup with forced SMPS mode that's not off */ | ||
if (smps_mode != IEEE80211_SMPS_AUTOMATIC && | ||
smps_mode != IEEE80211_SMPS_OFF) { | ||
tdls_dbg(sdata, "Aborting TDLS setup due to SMPS mode %d\n", | ||
smps_mode); | ||
return -ENOTSUPP; | ||
} | ||
|
||
mutex_lock(&local->mtx); | ||
|
||
/* we don't support concurrent TDLS peer setups */ | ||
|
@@ -1323,6 +1329,10 @@ int ieee80211_tdls_oper(struct wiphy *wiphy, struct net_device *dev, | |
eth_zero_addr(sdata->u.mgd.tdls_peer); | ||
} | ||
|
||
if (ret == 0) | ||
ieee80211_queue_work(&sdata->local->hw, | ||
&sdata->u.mgd.request_smps_work); | ||
|
||
mutex_unlock(&local->mtx); | ||
return ret; | ||
} | ||
|
@@ -1819,3 +1829,21 @@ void ieee80211_process_tdls_channel_switch(struct ieee80211_sub_if_data *sdata, | |
return; | ||
} | ||
} | ||
|
||
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(); | ||
} |