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

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

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: 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 003e5236
Loading
Loading
Loading
Loading
+2 −0
Original line number Original line Diff line number Diff line
@@ -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,
+30 −0
Original line number Original line Diff line number Diff line
@@ -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) {
+1 −0
Original line number Original line Diff line number Diff line
@@ -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);
+26 −0
Original line number Original line Diff line number Diff line
@@ -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);
}
+1 −21
Original line number Original line Diff line number Diff line
@@ -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;