Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

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
Loading
Loading
Loading
Loading
+29 −2
Original line number Diff line number Diff line
@@ -1843,9 +1843,10 @@ static void iwl_mvm_sta_pre_rcu_remove(struct ieee80211_hw *hw,
	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;

@@ -1857,12 +1858,33 @@ static int iwl_mvm_tdls_sta_count(struct iwl_mvm *mvm)
		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,
@@ -1904,7 +1926,8 @@ static int iwl_mvm_mac_sta_state(struct ieee80211_hw *hw,

		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;
@@ -1912,6 +1935,8 @@ static int iwl_mvm_mac_sta_state(struct ieee80211_hw *hw,
		}

		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) {
		/*
@@ -1946,6 +1971,8 @@ static int iwl_mvm_mac_sta_state(struct ieee80211_hw *hw,
	} 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;
	}
+3 −0
Original line number Diff line number Diff line
@@ -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,
		      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);

#endif /* __IWL_MVM_H__ */
+14 −3
Original line number Diff line number Diff line
@@ -483,6 +483,7 @@ int iwl_mvm_power_uapsd_misbehaving_ap_notif(struct iwl_mvm *mvm,
}

struct iwl_power_vifs {
	struct iwl_mvm *mvm;
	struct ieee80211_vif *bf_vif;
	struct ieee80211_vif *bss_vif;
	struct ieee80211_vif *p2p_vif;
@@ -492,6 +493,8 @@ struct iwl_power_vifs {
	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,
@@ -528,6 +531,8 @@ 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;
@@ -537,6 +542,8 @@ static void iwl_mvm_power_iterator(void *_data, u8 *mac,
		/* 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;
@@ -579,13 +586,15 @@ iwl_mvm_power_set_pm(struct iwl_mvm *mvm,
		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;
@@ -811,7 +820,9 @@ int iwl_mvm_disable_beacon_filter(struct iwl_mvm *mvm,
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;