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 iwl_mvm_sta *mvmsta;
int count = 0;
int i;
if (!sta || IS_ERR(sta) || !sta->tdls)
continue;
+ if (vif) {
+ mvmsta = iwl_mvm_sta_from_mac80211(sta);
+ if (mvmsta->vif != vif)
+ continue;
+ }
+
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,
struct ieee80211_vif *vif,
struct ieee80211_sta *sta,
if (sta->tdls &&
(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_DEBUG_MAC80211(mvm, "refusing TDLS sta\n");
ret = -EBUSY;
}
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 &&
new_state == IEEE80211_STA_AUTH) {
/*
} else if (old_state == IEEE80211_STA_NONE &&
new_state == IEEE80211_STA_NOTEXIST) {
ret = iwl_mvm_rm_sta(mvm, vif, sta);
+ if (sta->tdls)
+ iwl_mvm_recalc_tdls_state(mvm, vif, false);
} else {
ret = -EIO;
}
}
struct iwl_power_vifs {
+ struct iwl_mvm *mvm;
struct ieee80211_vif *bf_vif;
struct ieee80211_vif *bss_vif;
struct ieee80211_vif *p2p_vif;
bool bss_active;
bool ap_active;
bool monitor_active;
+ bool bss_tdls;
+ bool p2p_tdls;
};
static void iwl_mvm_power_iterator(void *_data, u8 *mac,
/* only a single MAC of the same type */
WARN_ON(power_iterator->p2p_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->id < MAX_PHYS)
power_iterator->p2p_active = true;
/* only a single MAC of the same type */
WARN_ON(power_iterator->bss_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->id < MAX_PHYS)
power_iterator->bss_active = true;
ap_mvmvif = iwl_mvm_vif_from_mac80211(vifs->ap_vif);
/* 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;
return;
}
/* 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)
p2p_mvmvif->pm_enabled = true;
return;
int iwl_mvm_power_update_mac(struct iwl_mvm *mvm)
{
struct iwl_mvm_vif *mvmvif;
- struct iwl_power_vifs vifs = {};
+ struct iwl_power_vifs vifs = {
+ .mvm = mvm,
+ };
bool ba_enable;
int ret;