mirror of https://gitee.com/openkylin/linux.git
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>
This commit is contained in:
parent
003e5236a1
commit
cf7b491dbb
|
@ -86,6 +86,8 @@ enum {
|
||||||
|
|
||||||
#define IWL_MVM_STATION_COUNT 16
|
#define IWL_MVM_STATION_COUNT 16
|
||||||
|
|
||||||
|
#define IWL_MVM_TDLS_STA_COUNT 4
|
||||||
|
|
||||||
/* commands */
|
/* commands */
|
||||||
enum {
|
enum {
|
||||||
MVM_ALIVE = 0x1,
|
MVM_ALIVE = 0x1,
|
||||||
|
|
|
@ -1843,6 +1843,26 @@ static void iwl_mvm_sta_pre_rcu_remove(struct ieee80211_hw *hw,
|
||||||
mutex_unlock(&mvm->mutex);
|
mutex_unlock(&mvm->mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int iwl_mvm_tdls_sta_count(struct iwl_mvm *mvm)
|
||||||
|
{
|
||||||
|
struct ieee80211_sta *sta;
|
||||||
|
int count = 0;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
lockdep_assert_held(&mvm->mutex);
|
||||||
|
|
||||||
|
for (i = 0; i < IWL_MVM_STATION_COUNT; i++) {
|
||||||
|
sta = rcu_dereference_protected(mvm->fw_id_to_mac_id[i],
|
||||||
|
lockdep_is_held(&mvm->mutex));
|
||||||
|
if (!sta || IS_ERR(sta) || !sta->tdls)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
static int iwl_mvm_mac_sta_state(struct ieee80211_hw *hw,
|
static int iwl_mvm_mac_sta_state(struct ieee80211_hw *hw,
|
||||||
struct ieee80211_vif *vif,
|
struct ieee80211_vif *vif,
|
||||||
struct ieee80211_sta *sta,
|
struct ieee80211_sta *sta,
|
||||||
|
@ -1881,6 +1901,16 @@ static int iwl_mvm_mac_sta_state(struct ieee80211_hw *hw,
|
||||||
ret = -EINVAL;
|
ret = -EINVAL;
|
||||||
goto out_unlock;
|
goto out_unlock;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (sta->tdls &&
|
||||||
|
(vif->p2p ||
|
||||||
|
iwl_mvm_tdls_sta_count(mvm) == IWL_MVM_TDLS_STA_COUNT ||
|
||||||
|
iwl_mvm_phy_ctx_count(mvm) > 1)) {
|
||||||
|
IWL_DEBUG_MAC80211(mvm, "refusing TDLS sta\n");
|
||||||
|
ret = -EBUSY;
|
||||||
|
goto out_unlock;
|
||||||
|
}
|
||||||
|
|
||||||
ret = iwl_mvm_add_sta(mvm, vif, sta);
|
ret = iwl_mvm_add_sta(mvm, vif, sta);
|
||||||
} else if (old_state == IEEE80211_STA_NONE &&
|
} else if (old_state == IEEE80211_STA_NONE &&
|
||||||
new_state == IEEE80211_STA_AUTH) {
|
new_state == IEEE80211_STA_AUTH) {
|
||||||
|
|
|
@ -838,6 +838,7 @@ void iwl_mvm_phy_ctxt_ref(struct iwl_mvm *mvm,
|
||||||
struct iwl_mvm_phy_ctxt *ctxt);
|
struct iwl_mvm_phy_ctxt *ctxt);
|
||||||
void iwl_mvm_phy_ctxt_unref(struct iwl_mvm *mvm,
|
void iwl_mvm_phy_ctxt_unref(struct iwl_mvm *mvm,
|
||||||
struct iwl_mvm_phy_ctxt *ctxt);
|
struct iwl_mvm_phy_ctxt *ctxt);
|
||||||
|
int iwl_mvm_phy_ctx_count(struct iwl_mvm *mvm);
|
||||||
|
|
||||||
/* MAC (virtual interface) programming */
|
/* MAC (virtual interface) programming */
|
||||||
int iwl_mvm_mac_ctxt_init(struct iwl_mvm *mvm, struct ieee80211_vif *vif);
|
int iwl_mvm_mac_ctxt_init(struct iwl_mvm *mvm, struct ieee80211_vif *vif);
|
||||||
|
|
|
@ -261,3 +261,29 @@ void iwl_mvm_phy_ctxt_unref(struct iwl_mvm *mvm, struct iwl_mvm_phy_ctxt *ctxt)
|
||||||
|
|
||||||
ctxt->ref--;
|
ctxt->ref--;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void iwl_mvm_binding_iterator(void *_data, u8 *mac,
|
||||||
|
struct ieee80211_vif *vif)
|
||||||
|
{
|
||||||
|
unsigned long *data = _data;
|
||||||
|
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
|
||||||
|
|
||||||
|
if (!mvmvif->phy_ctxt)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (vif->type == NL80211_IFTYPE_STATION ||
|
||||||
|
vif->type == NL80211_IFTYPE_AP)
|
||||||
|
__set_bit(mvmvif->phy_ctxt->id, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
int iwl_mvm_phy_ctx_count(struct iwl_mvm *mvm)
|
||||||
|
{
|
||||||
|
unsigned long phy_ctxt_counter = 0;
|
||||||
|
|
||||||
|
ieee80211_iterate_active_interfaces_atomic(mvm->hw,
|
||||||
|
IEEE80211_IFACE_ITER_NORMAL,
|
||||||
|
iwl_mvm_binding_iterator,
|
||||||
|
&phy_ctxt_counter);
|
||||||
|
|
||||||
|
return hweight8(phy_ctxt_counter);
|
||||||
|
}
|
||||||
|
|
|
@ -246,30 +246,10 @@ static void iwl_mvm_power_configure_uapsd(struct iwl_mvm *mvm,
|
||||||
IWL_MVM_PS_HEAVY_RX_THLD_PERCENT;
|
IWL_MVM_PS_HEAVY_RX_THLD_PERCENT;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void iwl_mvm_binding_iterator(void *_data, u8 *mac,
|
|
||||||
struct ieee80211_vif *vif)
|
|
||||||
{
|
|
||||||
unsigned long *data = _data;
|
|
||||||
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
|
|
||||||
|
|
||||||
if (!mvmvif->phy_ctxt)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (vif->type == NL80211_IFTYPE_STATION ||
|
|
||||||
vif->type == NL80211_IFTYPE_AP)
|
|
||||||
__set_bit(mvmvif->phy_ctxt->id, data);
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool iwl_mvm_power_allow_uapsd(struct iwl_mvm *mvm,
|
static bool iwl_mvm_power_allow_uapsd(struct iwl_mvm *mvm,
|
||||||
struct ieee80211_vif *vif)
|
struct ieee80211_vif *vif)
|
||||||
{
|
{
|
||||||
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
|
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
|
||||||
unsigned long phy_ctxt_counter = 0;
|
|
||||||
|
|
||||||
ieee80211_iterate_active_interfaces_atomic(mvm->hw,
|
|
||||||
IEEE80211_IFACE_ITER_NORMAL,
|
|
||||||
iwl_mvm_binding_iterator,
|
|
||||||
&phy_ctxt_counter);
|
|
||||||
|
|
||||||
if (!memcmp(mvmvif->uapsd_misbehaving_bssid, vif->bss_conf.bssid,
|
if (!memcmp(mvmvif->uapsd_misbehaving_bssid, vif->bss_conf.bssid,
|
||||||
ETH_ALEN))
|
ETH_ALEN))
|
||||||
|
@ -291,7 +271,7 @@ static bool iwl_mvm_power_allow_uapsd(struct iwl_mvm *mvm,
|
||||||
* Avoid using uAPSD if client is in DCM -
|
* Avoid using uAPSD if client is in DCM -
|
||||||
* low latency issue in Miracast
|
* low latency issue in Miracast
|
||||||
*/
|
*/
|
||||||
if (hweight8(phy_ctxt_counter) >= 2)
|
if (iwl_mvm_phy_ctx_count(mvm) >= 2)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
Loading…
Reference in New Issue