aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net
diff options
context:
space:
mode:
authorArik Nemtsov <arik@wizery.com>2014-05-15 04:44:40 -0400
committerEmmanuel Grumbach <emmanuel.grumbach@intel.com>2014-07-07 14:41:21 -0400
commitcf7b491dbbac0e25f24265b005bc0ceff622d387 (patch)
treee5edd331c170724a8a5c712487357ab65ffdf328 /drivers/net
parent003e5236a1fcab3fc4576fe643e31a3d83027256 (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.h2
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/mac80211.c30
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/mvm.h1
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/phy-ctxt.c26
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/power.c22
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 */
90enum { 92enum {
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
1846static 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
1846static int iwl_mvm_mac_sta_state(struct ieee80211_hw *hw, 1866static 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);
839void iwl_mvm_phy_ctxt_unref(struct iwl_mvm *mvm, 839void iwl_mvm_phy_ctxt_unref(struct iwl_mvm *mvm,
840 struct iwl_mvm_phy_ctxt *ctxt); 840 struct iwl_mvm_phy_ctxt *ctxt);
841int iwl_mvm_phy_ctx_count(struct iwl_mvm *mvm);
841 842
842/* MAC (virtual interface) programming */ 843/* MAC (virtual interface) programming */
843int iwl_mvm_mac_ctxt_init(struct iwl_mvm *mvm, struct ieee80211_vif *vif); 844int 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
265static 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
279int 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
249static 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
263static bool iwl_mvm_power_allow_uapsd(struct iwl_mvm *mvm, 249static 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;