diff options
author | Arik Nemtsov <arik@wizery.com> | 2014-05-15 04:44:40 -0400 |
---|---|---|
committer | Emmanuel Grumbach <emmanuel.grumbach@intel.com> | 2014-07-07 14:41:21 -0400 |
commit | cf7b491dbbac0e25f24265b005bc0ceff622d387 (patch) | |
tree | e5edd331c170724a8a5c712487357ab65ffdf328 /drivers/net | |
parent | 003e5236a1fcab3fc4576fe643e31a3d83027256 (diff) |
iwlwifi: mvm: disallow new TDLS stations when appropriate
HW/FW constraints dictate that TDLS should only be used when a single
phy ctx is active. We also support at most 4 TDLS peers. We don't
support TDLS on a P2P vif.
Unify and move a phy-ctx counting implementation from the power-mgmt code
in order to simplify implementation.
Signed-off-by: Arik Nemtsov <arikx.nemtsov@intel.com>
Reviewed-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
Diffstat (limited to 'drivers/net')
-rw-r--r-- | drivers/net/wireless/iwlwifi/mvm/fw-api.h | 2 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/mvm/mac80211.c | 30 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/mvm/mvm.h | 1 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/mvm/phy-ctxt.c | 26 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/mvm/power.c | 22 |
5 files changed, 60 insertions, 21 deletions
diff --git a/drivers/net/wireless/iwlwifi/mvm/fw-api.h b/drivers/net/wireless/iwlwifi/mvm/fw-api.h index 99329edcd99f..b8e4e78d601b 100644 --- a/drivers/net/wireless/iwlwifi/mvm/fw-api.h +++ b/drivers/net/wireless/iwlwifi/mvm/fw-api.h | |||
@@ -86,6 +86,8 @@ enum { | |||
86 | 86 | ||
87 | #define IWL_MVM_STATION_COUNT 16 | 87 | #define IWL_MVM_STATION_COUNT 16 |
88 | 88 | ||
89 | #define IWL_MVM_TDLS_STA_COUNT 4 | ||
90 | |||
89 | /* commands */ | 91 | /* commands */ |
90 | enum { | 92 | enum { |
91 | MVM_ALIVE = 0x1, | 93 | MVM_ALIVE = 0x1, |
diff --git a/drivers/net/wireless/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/iwlwifi/mvm/mac80211.c index 5ed6fb32087c..57945fe06216 100644 --- a/drivers/net/wireless/iwlwifi/mvm/mac80211.c +++ b/drivers/net/wireless/iwlwifi/mvm/mac80211.c | |||
@@ -1843,6 +1843,26 @@ static void iwl_mvm_sta_pre_rcu_remove(struct ieee80211_hw *hw, | |||
1843 | mutex_unlock(&mvm->mutex); | 1843 | mutex_unlock(&mvm->mutex); |
1844 | } | 1844 | } |
1845 | 1845 | ||
1846 | static int iwl_mvm_tdls_sta_count(struct iwl_mvm *mvm) | ||
1847 | { | ||
1848 | struct ieee80211_sta *sta; | ||
1849 | int count = 0; | ||
1850 | int i; | ||
1851 | |||
1852 | lockdep_assert_held(&mvm->mutex); | ||
1853 | |||
1854 | for (i = 0; i < IWL_MVM_STATION_COUNT; i++) { | ||
1855 | sta = rcu_dereference_protected(mvm->fw_id_to_mac_id[i], | ||
1856 | lockdep_is_held(&mvm->mutex)); | ||
1857 | if (!sta || IS_ERR(sta) || !sta->tdls) | ||
1858 | continue; | ||
1859 | |||
1860 | count++; | ||
1861 | } | ||
1862 | |||
1863 | return count; | ||
1864 | } | ||
1865 | |||
1846 | static int iwl_mvm_mac_sta_state(struct ieee80211_hw *hw, | 1866 | static int iwl_mvm_mac_sta_state(struct ieee80211_hw *hw, |
1847 | struct ieee80211_vif *vif, | 1867 | struct ieee80211_vif *vif, |
1848 | struct ieee80211_sta *sta, | 1868 | struct ieee80211_sta *sta, |
@@ -1881,6 +1901,16 @@ static int iwl_mvm_mac_sta_state(struct ieee80211_hw *hw, | |||
1881 | ret = -EINVAL; | 1901 | ret = -EINVAL; |
1882 | goto out_unlock; | 1902 | goto out_unlock; |
1883 | } | 1903 | } |
1904 | |||
1905 | if (sta->tdls && | ||
1906 | (vif->p2p || | ||
1907 | iwl_mvm_tdls_sta_count(mvm) == IWL_MVM_TDLS_STA_COUNT || | ||
1908 | iwl_mvm_phy_ctx_count(mvm) > 1)) { | ||
1909 | IWL_DEBUG_MAC80211(mvm, "refusing TDLS sta\n"); | ||
1910 | ret = -EBUSY; | ||
1911 | goto out_unlock; | ||
1912 | } | ||
1913 | |||
1884 | ret = iwl_mvm_add_sta(mvm, vif, sta); | 1914 | ret = iwl_mvm_add_sta(mvm, vif, sta); |
1885 | } else if (old_state == IEEE80211_STA_NONE && | 1915 | } else if (old_state == IEEE80211_STA_NONE && |
1886 | new_state == IEEE80211_STA_AUTH) { | 1916 | new_state == IEEE80211_STA_AUTH) { |
diff --git a/drivers/net/wireless/iwlwifi/mvm/mvm.h b/drivers/net/wireless/iwlwifi/mvm/mvm.h index 7b308c4834f6..c75b958736bc 100644 --- a/drivers/net/wireless/iwlwifi/mvm/mvm.h +++ b/drivers/net/wireless/iwlwifi/mvm/mvm.h | |||
@@ -838,6 +838,7 @@ void iwl_mvm_phy_ctxt_ref(struct iwl_mvm *mvm, | |||
838 | struct iwl_mvm_phy_ctxt *ctxt); | 838 | struct iwl_mvm_phy_ctxt *ctxt); |
839 | void iwl_mvm_phy_ctxt_unref(struct iwl_mvm *mvm, | 839 | void iwl_mvm_phy_ctxt_unref(struct iwl_mvm *mvm, |
840 | struct iwl_mvm_phy_ctxt *ctxt); | 840 | struct iwl_mvm_phy_ctxt *ctxt); |
841 | int iwl_mvm_phy_ctx_count(struct iwl_mvm *mvm); | ||
841 | 842 | ||
842 | /* MAC (virtual interface) programming */ | 843 | /* MAC (virtual interface) programming */ |
843 | int iwl_mvm_mac_ctxt_init(struct iwl_mvm *mvm, struct ieee80211_vif *vif); | 844 | int iwl_mvm_mac_ctxt_init(struct iwl_mvm *mvm, struct ieee80211_vif *vif); |
diff --git a/drivers/net/wireless/iwlwifi/mvm/phy-ctxt.c b/drivers/net/wireless/iwlwifi/mvm/phy-ctxt.c index 539f3a942d43..6cc243f7cf60 100644 --- a/drivers/net/wireless/iwlwifi/mvm/phy-ctxt.c +++ b/drivers/net/wireless/iwlwifi/mvm/phy-ctxt.c | |||
@@ -261,3 +261,29 @@ void iwl_mvm_phy_ctxt_unref(struct iwl_mvm *mvm, struct iwl_mvm_phy_ctxt *ctxt) | |||
261 | 261 | ||
262 | ctxt->ref--; | 262 | ctxt->ref--; |
263 | } | 263 | } |
264 | |||
265 | static void iwl_mvm_binding_iterator(void *_data, u8 *mac, | ||
266 | struct ieee80211_vif *vif) | ||
267 | { | ||
268 | unsigned long *data = _data; | ||
269 | struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); | ||
270 | |||
271 | if (!mvmvif->phy_ctxt) | ||
272 | return; | ||
273 | |||
274 | if (vif->type == NL80211_IFTYPE_STATION || | ||
275 | vif->type == NL80211_IFTYPE_AP) | ||
276 | __set_bit(mvmvif->phy_ctxt->id, data); | ||
277 | } | ||
278 | |||
279 | int iwl_mvm_phy_ctx_count(struct iwl_mvm *mvm) | ||
280 | { | ||
281 | unsigned long phy_ctxt_counter = 0; | ||
282 | |||
283 | ieee80211_iterate_active_interfaces_atomic(mvm->hw, | ||
284 | IEEE80211_IFACE_ITER_NORMAL, | ||
285 | iwl_mvm_binding_iterator, | ||
286 | &phy_ctxt_counter); | ||
287 | |||
288 | return hweight8(phy_ctxt_counter); | ||
289 | } | ||
diff --git a/drivers/net/wireless/iwlwifi/mvm/power.c b/drivers/net/wireless/iwlwifi/mvm/power.c index c182a8baf685..3b582dd6d77f 100644 --- a/drivers/net/wireless/iwlwifi/mvm/power.c +++ b/drivers/net/wireless/iwlwifi/mvm/power.c | |||
@@ -246,30 +246,10 @@ static void iwl_mvm_power_configure_uapsd(struct iwl_mvm *mvm, | |||
246 | IWL_MVM_PS_HEAVY_RX_THLD_PERCENT; | 246 | IWL_MVM_PS_HEAVY_RX_THLD_PERCENT; |
247 | } | 247 | } |
248 | 248 | ||
249 | static void iwl_mvm_binding_iterator(void *_data, u8 *mac, | ||
250 | struct ieee80211_vif *vif) | ||
251 | { | ||
252 | unsigned long *data = _data; | ||
253 | struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); | ||
254 | |||
255 | if (!mvmvif->phy_ctxt) | ||
256 | return; | ||
257 | |||
258 | if (vif->type == NL80211_IFTYPE_STATION || | ||
259 | vif->type == NL80211_IFTYPE_AP) | ||
260 | __set_bit(mvmvif->phy_ctxt->id, data); | ||
261 | } | ||
262 | |||
263 | static bool iwl_mvm_power_allow_uapsd(struct iwl_mvm *mvm, | 249 | static bool iwl_mvm_power_allow_uapsd(struct iwl_mvm *mvm, |
264 | struct ieee80211_vif *vif) | 250 | struct ieee80211_vif *vif) |
265 | { | 251 | { |
266 | struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); | 252 | struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); |
267 | unsigned long phy_ctxt_counter = 0; | ||
268 | |||
269 | ieee80211_iterate_active_interfaces_atomic(mvm->hw, | ||
270 | IEEE80211_IFACE_ITER_NORMAL, | ||
271 | iwl_mvm_binding_iterator, | ||
272 | &phy_ctxt_counter); | ||
273 | 253 | ||
274 | if (!memcmp(mvmvif->uapsd_misbehaving_bssid, vif->bss_conf.bssid, | 254 | if (!memcmp(mvmvif->uapsd_misbehaving_bssid, vif->bss_conf.bssid, |
275 | ETH_ALEN)) | 255 | ETH_ALEN)) |
@@ -291,7 +271,7 @@ static bool iwl_mvm_power_allow_uapsd(struct iwl_mvm *mvm, | |||
291 | * Avoid using uAPSD if client is in DCM - | 271 | * Avoid using uAPSD if client is in DCM - |
292 | * low latency issue in Miracast | 272 | * low latency issue in Miracast |
293 | */ | 273 | */ |
294 | if (hweight8(phy_ctxt_counter) >= 2) | 274 | if (iwl_mvm_phy_ctx_count(mvm) >= 2) |
295 | return false; | 275 | return false; |
296 | 276 | ||
297 | return true; | 277 | return true; |