Commit fa3d07e4 authored by Arik Nemtsov's avatar Arik Nemtsov Committed by Emmanuel Grumbach

iwlwifi: disable PSM on vifs with associated TDLS peers

The FW does not support PSM on a vif with associated TDLS peers. Disable
PSM when the first peer joins and re-enable it when the last leaves.
Signed-off-by: default avatarArik Nemtsov <arikx.nemtsov@intel.com>
Reviewed-by: default avatarJohannes Berg <johannes.berg@intel.com>
Signed-off-by: default avatarEmmanuel Grumbach <emmanuel.grumbach@intel.com>
parent 07ecd897
...@@ -1843,9 +1843,10 @@ static void iwl_mvm_sta_pre_rcu_remove(struct ieee80211_hw *hw, ...@@ -1843,9 +1843,10 @@ 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) int iwl_mvm_tdls_sta_count(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
{ {
struct ieee80211_sta *sta; struct ieee80211_sta *sta;
struct iwl_mvm_sta *mvmsta;
int count = 0; int count = 0;
int i; int i;
...@@ -1857,12 +1858,33 @@ static int iwl_mvm_tdls_sta_count(struct iwl_mvm *mvm) ...@@ -1857,12 +1858,33 @@ static int iwl_mvm_tdls_sta_count(struct iwl_mvm *mvm)
if (!sta || IS_ERR(sta) || !sta->tdls) if (!sta || IS_ERR(sta) || !sta->tdls)
continue; continue;
if (vif) {
mvmsta = iwl_mvm_sta_from_mac80211(sta);
if (mvmsta->vif != vif)
continue;
}
count++; count++;
} }
return count; return count;
} }
static void iwl_mvm_recalc_tdls_state(struct iwl_mvm *mvm,
struct ieee80211_vif *vif,
bool sta_added)
{
int tdls_sta_cnt = iwl_mvm_tdls_sta_count(mvm, vif);
/*
* Disable ps when the first TDLS sta is added and re-enable it
* when the last TDLS sta is removed
*/
if ((tdls_sta_cnt == 1 && sta_added) ||
(tdls_sta_cnt == 0 && !sta_added))
iwl_mvm_power_update_mac(mvm);
}
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,
...@@ -1904,7 +1926,8 @@ static int iwl_mvm_mac_sta_state(struct ieee80211_hw *hw, ...@@ -1904,7 +1926,8 @@ static int iwl_mvm_mac_sta_state(struct ieee80211_hw *hw,
if (sta->tdls && if (sta->tdls &&
(vif->p2p || (vif->p2p ||
iwl_mvm_tdls_sta_count(mvm) == IWL_MVM_TDLS_STA_COUNT || iwl_mvm_tdls_sta_count(mvm, NULL) ==
IWL_MVM_TDLS_STA_COUNT ||
iwl_mvm_phy_ctx_count(mvm) > 1)) { iwl_mvm_phy_ctx_count(mvm) > 1)) {
IWL_DEBUG_MAC80211(mvm, "refusing TDLS sta\n"); IWL_DEBUG_MAC80211(mvm, "refusing TDLS sta\n");
ret = -EBUSY; ret = -EBUSY;
...@@ -1912,6 +1935,8 @@ static int iwl_mvm_mac_sta_state(struct ieee80211_hw *hw, ...@@ -1912,6 +1935,8 @@ static int iwl_mvm_mac_sta_state(struct ieee80211_hw *hw,
} }
ret = iwl_mvm_add_sta(mvm, vif, sta); ret = iwl_mvm_add_sta(mvm, vif, sta);
if (sta->tdls && ret == 0)
iwl_mvm_recalc_tdls_state(mvm, vif, true);
} else if (old_state == IEEE80211_STA_NONE && } else if (old_state == IEEE80211_STA_NONE &&
new_state == IEEE80211_STA_AUTH) { new_state == IEEE80211_STA_AUTH) {
/* /*
...@@ -1946,6 +1971,8 @@ static int iwl_mvm_mac_sta_state(struct ieee80211_hw *hw, ...@@ -1946,6 +1971,8 @@ static int iwl_mvm_mac_sta_state(struct ieee80211_hw *hw,
} else if (old_state == IEEE80211_STA_NONE && } else if (old_state == IEEE80211_STA_NONE &&
new_state == IEEE80211_STA_NOTEXIST) { new_state == IEEE80211_STA_NOTEXIST) {
ret = iwl_mvm_rm_sta(mvm, vif, sta); ret = iwl_mvm_rm_sta(mvm, vif, sta);
if (sta->tdls)
iwl_mvm_recalc_tdls_state(mvm, vif, false);
} else { } else {
ret = -EIO; ret = -EIO;
} }
......
...@@ -1098,6 +1098,9 @@ void iwl_mvm_set_hw_ctkill_state(struct iwl_mvm *mvm, bool state); ...@@ -1098,6 +1098,9 @@ void iwl_mvm_set_hw_ctkill_state(struct iwl_mvm *mvm, bool state);
int iwl_mvm_sf_update(struct iwl_mvm *mvm, struct ieee80211_vif *vif, int iwl_mvm_sf_update(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
bool added_vif); bool added_vif);
/* TDLS */
int iwl_mvm_tdls_sta_count(struct iwl_mvm *mvm, struct ieee80211_vif *vif);
void iwl_mvm_nic_restart(struct iwl_mvm *mvm, bool fw_error); void iwl_mvm_nic_restart(struct iwl_mvm *mvm, bool fw_error);
#endif /* __IWL_MVM_H__ */ #endif /* __IWL_MVM_H__ */
...@@ -483,6 +483,7 @@ int iwl_mvm_power_uapsd_misbehaving_ap_notif(struct iwl_mvm *mvm, ...@@ -483,6 +483,7 @@ int iwl_mvm_power_uapsd_misbehaving_ap_notif(struct iwl_mvm *mvm,
} }
struct iwl_power_vifs { struct iwl_power_vifs {
struct iwl_mvm *mvm;
struct ieee80211_vif *bf_vif; struct ieee80211_vif *bf_vif;
struct ieee80211_vif *bss_vif; struct ieee80211_vif *bss_vif;
struct ieee80211_vif *p2p_vif; struct ieee80211_vif *p2p_vif;
...@@ -492,6 +493,8 @@ struct iwl_power_vifs { ...@@ -492,6 +493,8 @@ struct iwl_power_vifs {
bool bss_active; bool bss_active;
bool ap_active; bool ap_active;
bool monitor_active; bool monitor_active;
bool bss_tdls;
bool p2p_tdls;
}; };
static void iwl_mvm_power_iterator(void *_data, u8 *mac, static void iwl_mvm_power_iterator(void *_data, u8 *mac,
...@@ -528,6 +531,8 @@ static void iwl_mvm_power_iterator(void *_data, u8 *mac, ...@@ -528,6 +531,8 @@ static void iwl_mvm_power_iterator(void *_data, u8 *mac,
/* only a single MAC of the same type */ /* only a single MAC of the same type */
WARN_ON(power_iterator->p2p_vif); WARN_ON(power_iterator->p2p_vif);
power_iterator->p2p_vif = vif; power_iterator->p2p_vif = vif;
power_iterator->p2p_tdls =
!!iwl_mvm_tdls_sta_count(power_iterator->mvm, vif);
if (mvmvif->phy_ctxt) if (mvmvif->phy_ctxt)
if (mvmvif->phy_ctxt->id < MAX_PHYS) if (mvmvif->phy_ctxt->id < MAX_PHYS)
power_iterator->p2p_active = true; power_iterator->p2p_active = true;
...@@ -537,6 +542,8 @@ static void iwl_mvm_power_iterator(void *_data, u8 *mac, ...@@ -537,6 +542,8 @@ static void iwl_mvm_power_iterator(void *_data, u8 *mac,
/* only a single MAC of the same type */ /* only a single MAC of the same type */
WARN_ON(power_iterator->bss_vif); WARN_ON(power_iterator->bss_vif);
power_iterator->bss_vif = vif; power_iterator->bss_vif = vif;
power_iterator->bss_tdls =
!!iwl_mvm_tdls_sta_count(power_iterator->mvm, vif);
if (mvmvif->phy_ctxt) if (mvmvif->phy_ctxt)
if (mvmvif->phy_ctxt->id < MAX_PHYS) if (mvmvif->phy_ctxt->id < MAX_PHYS)
power_iterator->bss_active = true; power_iterator->bss_active = true;
...@@ -579,13 +586,15 @@ iwl_mvm_power_set_pm(struct iwl_mvm *mvm, ...@@ -579,13 +586,15 @@ iwl_mvm_power_set_pm(struct iwl_mvm *mvm,
ap_mvmvif = iwl_mvm_vif_from_mac80211(vifs->ap_vif); ap_mvmvif = iwl_mvm_vif_from_mac80211(vifs->ap_vif);
/* enable PM on bss if bss stand alone */ /* enable PM on bss if bss stand alone */
if (vifs->bss_active && !vifs->p2p_active && !vifs->ap_active) { if (vifs->bss_active && !vifs->p2p_active && !vifs->ap_active &&
!vifs->bss_tdls) {
bss_mvmvif->pm_enabled = true; bss_mvmvif->pm_enabled = true;
return; return;
} }
/* enable PM on p2p if p2p stand alone */ /* enable PM on p2p if p2p stand alone */
if (vifs->p2p_active && !vifs->bss_active && !vifs->ap_active) { if (vifs->p2p_active && !vifs->bss_active && !vifs->ap_active &&
!vifs->p2p_tdls) {
if (mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_P2P_PM) if (mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_P2P_PM)
p2p_mvmvif->pm_enabled = true; p2p_mvmvif->pm_enabled = true;
return; return;
...@@ -811,7 +820,9 @@ int iwl_mvm_disable_beacon_filter(struct iwl_mvm *mvm, ...@@ -811,7 +820,9 @@ int iwl_mvm_disable_beacon_filter(struct iwl_mvm *mvm,
int iwl_mvm_power_update_mac(struct iwl_mvm *mvm) int iwl_mvm_power_update_mac(struct iwl_mvm *mvm)
{ {
struct iwl_mvm_vif *mvmvif; struct iwl_mvm_vif *mvmvif;
struct iwl_power_vifs vifs = {}; struct iwl_power_vifs vifs = {
.mvm = mvm,
};
bool ba_enable; bool ba_enable;
int ret; int ret;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment