Commit 57974a55 authored by Gregory Greenman's avatar Gregory Greenman Committed by Johannes Berg
Browse files

wifi: iwlwifi: mvm: refactor iwl_mvm_mac_sta_state_common()



Move code handling specific state transitions into separate handlers
and adjust them for MLO. Adjust relevant callbacks as well.

Signed-off-by: default avatarGregory Greenman <gregory.greenman@intel.com>
Link: https://lore.kernel.org/r/20230328104949.5a3f8a849723.I0670d20436858a1cd3c055e03c7528db81292811@changeid


Signed-off-by: default avatarJohannes Berg <johannes.berg@intel.com>
parent 2c9b9220
Loading
Loading
Loading
Loading
+295 −135
Original line number Diff line number Diff line
@@ -2013,12 +2013,13 @@ static void iwl_mvm_parse_ppe(struct iwl_mvm *mvm,
}

static void iwl_mvm_set_pkt_ext_from_he_ppe(struct iwl_mvm *mvm,
					    struct ieee80211_sta *sta,
					    struct ieee80211_link_sta *link_sta,
					    struct iwl_he_pkt_ext_v2 *pkt_ext,
					    bool inheritance)
{
	u8 nss = (sta->deflink.he_cap.ppe_thres[0] & IEEE80211_PPE_THRES_NSS_MASK) + 1;
	u8 *ppe = &sta->deflink.he_cap.ppe_thres[0];
	u8 nss = (link_sta->he_cap.ppe_thres[0] &
		  IEEE80211_PPE_THRES_NSS_MASK) + 1;
	u8 *ppe = &link_sta->he_cap.ppe_thres[0];
	u8 ru_index_bitmap =
		u8_get_bits(*ppe,
			    IEEE80211_PPE_THRES_RU_INDEX_BITMASK_MASK);
@@ -2098,31 +2099,35 @@ static void iwl_mvm_get_optimal_ppe_info(struct iwl_he_pkt_ext_v2 *pkt_ext,
}

/* Set the pkt_ext field according to PPE Thresholds element */
int iwl_mvm_set_sta_pkt_ext(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
int iwl_mvm_set_sta_pkt_ext(struct iwl_mvm *mvm,
			    struct ieee80211_link_sta *link_sta,
			    struct iwl_he_pkt_ext_v2 *pkt_ext)
{
	u8 nominal_padding;
	int i, ret = 0;

	if (WARN_ON(!link_sta))
		return -EINVAL;

	/* Initialize the PPE thresholds to "None" (7), as described in Table
	 * 9-262ac of 80211.ax/D3.0.
	 */
	memset(pkt_ext, IWL_HE_PKT_EXT_NONE,
	       sizeof(struct iwl_he_pkt_ext_v2));

	if (sta->deflink.eht_cap.has_eht) {
	if (link_sta->eht_cap.has_eht) {
		nominal_padding =
			u8_get_bits(sta->deflink.eht_cap.eht_cap_elem.phy_cap_info[5],
			u8_get_bits(link_sta->eht_cap.eht_cap_elem.phy_cap_info[5],
				    IEEE80211_EHT_PHY_CAP5_COMMON_NOMINAL_PKT_PAD_MASK);

		/* If PPE Thresholds exists, parse them into a FW-familiar
		 * format.
		 */
		if (sta->deflink.eht_cap.eht_cap_elem.phy_cap_info[5] &
		if (link_sta->eht_cap.eht_cap_elem.phy_cap_info[5] &
		    IEEE80211_EHT_PHY_CAP5_PPE_THRESHOLD_PRESENT) {
			u8 nss = (sta->deflink.eht_cap.eht_ppe_thres[0] &
			u8 nss = (link_sta->eht_cap.eht_ppe_thres[0] &
				IEEE80211_EHT_PPE_THRES_NSS_MASK) + 1;
			u8 *ppe = &sta->deflink.eht_cap.eht_ppe_thres[0];
			u8 *ppe = &link_sta->eht_cap.eht_ppe_thres[0];
			u8 ru_index_bitmap =
				u16_get_bits(*ppe,
					     IEEE80211_EHT_PPE_THRES_RU_INDEX_BITMASK_MASK);
@@ -2131,17 +2136,17 @@ int iwl_mvm_set_sta_pkt_ext(struct iwl_mvm *mvm, struct ieee80211_sta *sta,

			iwl_mvm_parse_ppe(mvm, pkt_ext, nss, ru_index_bitmap,
					  ppe, ppe_pos_bit, true);
		/* EHT PPE Thresholds doesn't exist - set the API according
		 * to HE PPE Tresholds
		/* EHT PPE Thresholds doesn't exist - set the API according to
		 * HE PPE Tresholds
		 */
		} else if (sta->deflink.he_cap.he_cap_elem.phy_cap_info[6] &
		} else if (link_sta->he_cap.he_cap_elem.phy_cap_info[6] &
			   IEEE80211_HE_PHY_CAP6_PPE_THRESHOLD_PRESENT) {
			/* Even though HE Capabilities IE doesn't contain PPE
			 * Thresholds for BW 320Mhz, thresholds for this BW will
			 * be filled in with the same values as 160Mhz, due to
			 * the inheritance, as required.
			 */
			iwl_mvm_set_pkt_ext_from_he_ppe(mvm, sta, pkt_ext,
			iwl_mvm_set_pkt_ext_from_he_ppe(mvm, link_sta, pkt_ext,
							true);

			/* According to the requirements, for MCSs 12-13 the
@@ -2157,18 +2162,18 @@ int iwl_mvm_set_sta_pkt_ext(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
			ret = iwl_mvm_set_pkt_ext_from_nominal_padding(pkt_ext,
								       nominal_padding);
		}
	} else if (sta->deflink.he_cap.has_he) {
	} else if (link_sta->he_cap.has_he) {
		/* If PPE Thresholds exist, parse them into a FW-familiar format. */
		if (sta->deflink.he_cap.he_cap_elem.phy_cap_info[6] &
		if (link_sta->he_cap.he_cap_elem.phy_cap_info[6] &
			IEEE80211_HE_PHY_CAP6_PPE_THRESHOLD_PRESENT) {
			iwl_mvm_set_pkt_ext_from_he_ppe(mvm, sta, pkt_ext,
			iwl_mvm_set_pkt_ext_from_he_ppe(mvm, link_sta, pkt_ext,
							false);
		/* PPE Thresholds doesn't exist - set the API PPE values
		 * according to Common Nominal Packet Padding field.
		 */
		} else {
			nominal_padding =
				u8_get_bits(sta->deflink.he_cap.he_cap_elem.phy_cap_info[9],
				u8_get_bits(link_sta->he_cap.he_cap_elem.phy_cap_info[9],
					    IEEE80211_HE_PHY_CAP9_NOMINAL_PKT_PADDING_MASK);
			if (nominal_padding != IEEE80211_HE_PHY_CAP9_NOMINAL_PKT_PADDING_RESERVED)
				ret = iwl_mvm_set_pkt_ext_from_nominal_padding(pkt_ext,
@@ -2244,9 +2249,11 @@ bool iwl_mvm_is_nic_ack_enabled(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
			       IEEE80211_HE_MAC_CAP2_ACK_EN));
}

__le32 iwl_mvm_get_sta_htc_flags(struct ieee80211_sta *sta)
__le32 iwl_mvm_get_sta_htc_flags(struct ieee80211_sta *sta,
				 struct ieee80211_link_sta *link_sta)
{
	u8 *mac_cap_info = &sta->deflink.he_cap.he_cap_elem.mac_cap_info[0];
	u8 *mac_cap_info =
		&link_sta->he_cap.he_cap_elem.mac_cap_info[0];
	__le32 htc_flags = 0;

	if (mac_cap_info[0] & IEEE80211_HE_MAC_CAP0_HTC_HE)
@@ -2339,10 +2346,10 @@ static void iwl_mvm_cfg_he_sta(struct iwl_mvm *mvm,
		flags |= STA_CTXT_HE_RU_2MHZ_BLOCK;

	/* HTC flags */
	sta_ctxt_cmd.htc_flags = iwl_mvm_get_sta_htc_flags(sta);
	sta_ctxt_cmd.htc_flags = iwl_mvm_get_sta_htc_flags(sta, &sta->deflink);

	/* PPE Thresholds */
	if (!iwl_mvm_set_sta_pkt_ext(mvm, sta, &sta_ctxt_cmd.pkt_ext))
	if (!iwl_mvm_set_sta_pkt_ext(mvm, &sta->deflink, &sta_ctxt_cmd.pkt_ext))
		flags |= STA_CTXT_HE_PACKET_EXT;

	if (sta->deflink.he_cap.he_cap_elem.mac_cap_info[2] &
@@ -3497,88 +3504,108 @@ static int iwl_mvm_mac_sta_state(struct ieee80211_hw *hw,
					    &callbacks);
}

/* Common part for MLD and non-MLD modes */
int iwl_mvm_mac_sta_state_common(struct ieee80211_hw *hw,
/* FIXME: temporary making two assumptions in all sta handling functions:
 *	(1) when setting sta state, the link exists and protected
 *	(2) if a link is valid in sta then it's valid in vif (can
 *	use same index in the link array)
 */

#define iwl_mvm_rs_rate_init_all_links(mvm, mvmvif, sta, update) do {		\
	typeof(mvmvif) _mvmvif = mvmvif;					\
	unsigned int _i;							\
	for_each_mvm_vif_valid_link(_mvmvif, _i)				\
		iwl_mvm_rs_rate_init((mvm), (sta),				\
				     _mvmvif->link[_i]->phy_ctxt->channel->band,\
				     (update));					\
} while (0)

#define IWL_MVM_MIN_BEACON_INTERVAL_TU 16

static bool iwl_mvm_vif_conf_from_sta(struct iwl_mvm *mvm,
				      struct ieee80211_vif *vif,
				 struct ieee80211_sta *sta,
				 enum ieee80211_sta_state old_state,
				 enum ieee80211_sta_state new_state,
				 struct iwl_mvm_sta_state_ops *callbacks)
				      struct ieee80211_sta *sta)
{
	struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
	struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
	struct iwl_mvm_sta *mvm_sta = iwl_mvm_sta_from_mac80211(sta);
	int ret;
	unsigned int i;

	IWL_DEBUG_MAC80211(mvm, "station %pM state change %d->%d\n",
			   sta->addr, old_state, new_state);
	/* Beacon interval check - firmware will crash if the beacon
	 * interval is less than 16. We can't avoid connecting at all,
	 * so refuse the station state change, this will cause mac80211
	 * to abandon attempts to connect to this AP, and eventually
	 * wpa_s will blocklist the AP...
	 */

	/* this would be a mac80211 bug ... but don't crash */
	if (WARN_ON_ONCE(!mvmvif->deflink.phy_ctxt))
		return test_bit(IWL_MVM_STATUS_HW_RESTART_REQUESTED, &mvm->status) ? 0 : -EINVAL;
	for_each_set_bit(i, (unsigned long *)&sta->valid_links,
			 IEEE80211_MLD_MAX_NUM_LINKS) {
		struct ieee80211_link_sta *link_sta =
			rcu_dereference_protected(sta->link[i], 1);
		struct ieee80211_bss_conf *link_conf =
			rcu_dereference_protected(vif->link_conf[i], 1);

	/*
	 * If we are in a STA removal flow and in DQA mode:
	 *
	 * This is after the sync_rcu part, so the queues have already been
	 * flushed. No more TXs on their way in mac80211's path, and no more in
	 * the queues.
	 * Also, we won't be getting any new TX frames for this station.
	 * What we might have are deferred TX frames that need to be taken care
	 * of.
	 *
	 * Drop any still-queued deferred-frame before removing the STA, and
	 * make sure the worker is no longer handling frames for this STA.
	 */
	if (old_state == IEEE80211_STA_NONE &&
	    new_state == IEEE80211_STA_NOTEXIST) {
		flush_work(&mvm->add_stream_wk);
		if (!link_conf || !link_sta)
			continue;

		/*
		 * No need to make sure deferred TX indication is off since the
		 * worker will already remove it if it was on
		 */
		if (link_conf->beacon_int < IWL_MVM_MIN_BEACON_INTERVAL_TU) {
			IWL_ERR(mvm,
				"Beacon interval %d for AP %pM is too small\n",
				link_conf->beacon_int, link_sta->addr);
			return false;
		}

		/*
		 * Additionally, reset the 40 MHz capability if we disconnected
		 * from the AP now.
		 */
		iwl_mvm_reset_cca_40mhz_workaround(mvm, vif);
		link_conf->he_support = link_sta->he_cap.has_he;
	}

	mutex_lock(&mvm->mutex);
	/* track whether or not the station is associated */
	mvm_sta->sta_state = new_state;
	return true;
}

	if (old_state == IEEE80211_STA_NOTEXIST &&
	    new_state == IEEE80211_STA_NONE) {
		/*
		 * Firmware bug - it'll crash if the beacon interval is less
		 * than 16. We can't avoid connecting at all, so refuse the
		 * station state change, this will cause mac80211 to abandon
		 * attempts to connect to this AP, and eventually wpa_s will
		 * blocklist the AP...
		 */
		if (vif->type == NL80211_IFTYPE_STATION &&
		    vif->bss_conf.beacon_int < 16) {
			IWL_ERR(mvm,
				"AP %pM beacon interval is %d, refusing due to firmware bug!\n",
				sta->addr, vif->bss_conf.beacon_int);
			ret = -EINVAL;
			goto out_unlock;
static void iwl_mvm_vif_set_he_support(struct ieee80211_hw *hw,
				       struct ieee80211_vif *vif,
				       struct ieee80211_sta *sta,
				       bool is_sta)
{
	struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
	unsigned int i;

	for_each_set_bit(i, (unsigned long *)&sta->valid_links,
			 IEEE80211_MLD_MAX_NUM_LINKS) {
		struct ieee80211_link_sta *link_sta =
			rcu_dereference_protected(sta->link[i], 1);
		struct ieee80211_bss_conf *link_conf =
			rcu_dereference_protected(vif->link_conf[i], 1);

		if (!link_conf || !link_sta)
			continue;

		link_conf->he_support = link_sta->he_cap.has_he;

		if (is_sta) {
			mvmvif->link[i]->he_ru_2mhz_block = false;
			if (link_sta->he_cap.has_he)
				iwl_mvm_check_he_obss_narrow_bw_ru(hw, vif);
		}
	}
}

		if (vif->type == NL80211_IFTYPE_STATION)
			vif->bss_conf.he_support = sta->deflink.he_cap.has_he;
static int
iwl_mvm_sta_state_notexist_to_none(struct iwl_mvm *mvm,
				   struct ieee80211_vif *vif,
				   struct ieee80211_sta *sta,
				   struct iwl_mvm_sta_state_ops *callbacks)
{
	unsigned int i;
	int ret;

	lockdep_assert_held(&mvm->mutex);

	if (vif->type == NL80211_IFTYPE_STATION &&
	    !iwl_mvm_vif_conf_from_sta(mvm, vif, sta))
		return -EINVAL;

	if (sta->tdls &&
	    (vif->p2p ||
		     iwl_mvm_tdls_sta_count(mvm, NULL) ==
						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;
			goto out_unlock;
		return -EBUSY;
	}

	ret = callbacks->add_sta(mvm, vif, sta);
@@ -3588,52 +3615,86 @@ int iwl_mvm_mac_sta_state_common(struct ieee80211_hw *hw,
					   NL80211_TDLS_SETUP);
	}

		sta->deflink.agg.max_rc_amsdu_len = 1;
	} else if (old_state == IEEE80211_STA_NONE &&
		   new_state == IEEE80211_STA_AUTH) {
		/*
		 * EBS may be disabled due to previous failures reported by FW.
		 * Reset EBS status here assuming environment has been changed.
		 */
		mvm->last_ebs_successful = true;
		iwl_mvm_check_uapsd(mvm, vif, sta->addr);
		ret = 0;
	} else if (old_state == IEEE80211_STA_AUTH &&
		   new_state == IEEE80211_STA_ASSOC) {
	for (i = 0; i < ARRAY_SIZE(sta->link); i++) {
		struct ieee80211_link_sta *link_sta;

		link_sta = link_sta_dereference_protected(sta, i);
		if (!link_sta)
			continue;

		link_sta->agg.max_rc_amsdu_len = 1;
	}
	ieee80211_sta_recalc_aggregates(sta);

	return 0;
}

static int
iwl_mvm_sta_state_auth_to_assoc(struct ieee80211_hw *hw,
				struct iwl_mvm *mvm,
				struct ieee80211_vif *vif,
				struct ieee80211_sta *sta,
				struct iwl_mvm_sta_state_ops *callbacks)
{
	struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
	struct iwl_mvm_sta *mvm_sta = iwl_mvm_sta_from_mac80211(sta);
	unsigned int i;

	lockdep_assert_held(&mvm->mutex);

	if (vif->type == NL80211_IFTYPE_AP) {
			vif->bss_conf.he_support = sta->deflink.he_cap.has_he;
		iwl_mvm_vif_set_he_support(hw, vif, sta, false);
		mvmvif->ap_assoc_sta_count++;
		callbacks->mac_ctxt_changed(mvm, vif, false);

		/* since the below is not for MLD API, it's ok to use
		 * the default bss_conf
		 */
		if (!mvm->mld_api_is_used &&
		    ((vif->bss_conf.he_support &&
		      !iwlwifi_mod_params.disable_11ax) ||
		    (vif->bss_conf.eht_support &&
		     !iwlwifi_mod_params.disable_11be)))
				iwl_mvm_cfg_he_sta(mvm, vif,
						   mvm_sta->deflink.sta_id);
			iwl_mvm_cfg_he_sta(mvm, vif, mvm_sta->deflink.sta_id);
	} else if (vif->type == NL80211_IFTYPE_STATION) {
			vif->bss_conf.he_support = sta->deflink.he_cap.has_he;

			mvmvif->deflink.he_ru_2mhz_block = false;
			if (sta->deflink.he_cap.has_he)
				iwl_mvm_check_he_obss_narrow_bw_ru(hw, vif);
		iwl_mvm_vif_set_he_support(hw, vif, sta, true);

		callbacks->mac_ctxt_changed(mvm, vif, false);

			if (mvm->mld_api_is_used)
				iwl_mvm_link_changed(mvm, vif, &vif->bss_conf,
		if (!mvm->mld_api_is_used)
			goto out;

		for_each_set_bit(i, (unsigned long *)&sta->valid_links,
				 IEEE80211_MLD_MAX_NUM_LINKS) {
			struct ieee80211_bss_conf *link_conf =
				rcu_dereference_protected(vif->link_conf[i], 1);

			if (WARN_ON(!link_conf))
				return -EINVAL;

			iwl_mvm_link_changed(mvm, vif, link_conf,
					     LINK_CONTEXT_MODIFY_ALL &
					     ~LINK_CONTEXT_MODIFY_ACTIVE,
					     true);
		}
	}

		iwl_mvm_rs_rate_init(mvm, sta,
				     mvmvif->deflink.phy_ctxt->channel->band,
				     false);
		ret = callbacks->update_sta(mvm, vif, sta);
	} else if (old_state == IEEE80211_STA_ASSOC &&
		   new_state == IEEE80211_STA_AUTHORIZED) {
		ret = 0;
out:
	iwl_mvm_rs_rate_init_all_links(mvm, mvmvif, sta, false);

	return callbacks->update_sta(mvm, vif, sta);
}

static int
iwl_mvm_sta_state_assoc_to_authorized(struct iwl_mvm *mvm,
				      struct ieee80211_vif *vif,
				      struct ieee80211_sta *sta,
				      struct iwl_mvm_sta_state_ops *callbacks)
{
	struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
	struct iwl_mvm_sta *mvm_sta = iwl_mvm_sta_from_mac80211(sta);

	lockdep_assert_held(&mvm->mutex);

	/* we don't support TDLS during DCM */
	if (iwl_mvm_phy_ctx_count(mvm) > 1)
@@ -3652,20 +3713,29 @@ int iwl_mvm_mac_sta_state_common(struct ieee80211_hw *hw,
		iwl_mvm_mei_host_associated(mvm, vif, mvm_sta);
	}

		iwl_mvm_rs_rate_init(mvm, sta,
				     mvmvif->deflink.phy_ctxt->channel->band,
				     true);
	} else if (old_state == IEEE80211_STA_AUTHORIZED &&
		   new_state == IEEE80211_STA_ASSOC) {
	iwl_mvm_rs_rate_init_all_links(mvm, mvmvif, sta, true);

	return 0;
}

static int
iwl_mvm_sta_state_authorized_to_assoc(struct iwl_mvm *mvm,
				      struct ieee80211_vif *vif,
				      struct ieee80211_sta *sta,
				      struct iwl_mvm_sta_state_ops *callbacks)
{
	struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
	int ret;

	lockdep_assert_held(&mvm->mutex);

	/* once we move into assoc state, need to update rate scale to
	 * disable using wide bandwidth
	 */
		iwl_mvm_rs_rate_init(mvm, sta,
				     mvmvif->deflink.phy_ctxt->channel->band,
				     false);
	iwl_mvm_rs_rate_init_all_links(mvm, mvmvif, sta, false);

	if (!sta->tdls) {
			/*
			 * Set this but don't call iwl_mvm_mac_ctxt_changed()
		/* Set this but don't call iwl_mvm_mac_ctxt_changed()
		 * yet to avoid sending high prio again for a little
		 * time.
		 */
@@ -3677,7 +3747,97 @@ int iwl_mvm_mac_sta_state_common(struct ieee80211_hw *hw,
			!test_bit(IWL_MVM_STATUS_HW_RESTART_REQUESTED,
				  &mvm->status));
	}

	return 0;
}

/* Common part for MLD and non-MLD modes */
int iwl_mvm_mac_sta_state_common(struct ieee80211_hw *hw,
				 struct ieee80211_vif *vif,
				 struct ieee80211_sta *sta,
				 enum ieee80211_sta_state old_state,
				 enum ieee80211_sta_state new_state,
				 struct iwl_mvm_sta_state_ops *callbacks)
{
	struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
	struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
	struct iwl_mvm_sta *mvm_sta = iwl_mvm_sta_from_mac80211(sta);
	unsigned int link_id;
	int ret;

	IWL_DEBUG_MAC80211(mvm, "station %pM state change %d->%d\n",
			   sta->addr, old_state, new_state);

	/*
	 * If we are in a STA removal flow and in DQA mode:
	 *
	 * This is after the sync_rcu part, so the queues have already been
	 * flushed. No more TXs on their way in mac80211's path, and no more in
	 * the queues.
	 * Also, we won't be getting any new TX frames for this station.
	 * What we might have are deferred TX frames that need to be taken care
	 * of.
	 *
	 * Drop any still-queued deferred-frame before removing the STA, and
	 * make sure the worker is no longer handling frames for this STA.
	 */
	if (old_state == IEEE80211_STA_NONE &&
	    new_state == IEEE80211_STA_NOTEXIST) {
		flush_work(&mvm->add_stream_wk);

		/*
		 * No need to make sure deferred TX indication is off since the
		 * worker will already remove it if it was on
		 */

		/*
		 * Additionally, reset the 40 MHz capability if we disconnected
		 * from the AP now.
		 */
		iwl_mvm_reset_cca_40mhz_workaround(mvm, vif);
	}

	mutex_lock(&mvm->mutex);

	/* this would be a mac80211 bug ... but don't crash */
	for_each_mvm_vif_valid_link(mvmvif, link_id) {
		if (WARN_ON_ONCE(!mvmvif->link[link_id]->phy_ctxt)) {
			mutex_unlock(&mvm->mutex);
			return test_bit(IWL_MVM_STATUS_HW_RESTART_REQUESTED,
					&mvm->status) ? 0 : -EINVAL;
		}
	}

	/* track whether or not the station is associated */
	mvm_sta->sta_state = new_state;

	if (old_state == IEEE80211_STA_NOTEXIST &&
	    new_state == IEEE80211_STA_NONE) {
		ret = iwl_mvm_sta_state_notexist_to_none(mvm, vif, sta,
							 callbacks);
		if (ret < 0)
			goto out_unlock;
	} else if (old_state == IEEE80211_STA_NONE &&
		   new_state == IEEE80211_STA_AUTH) {
		/*
		 * EBS may be disabled due to previous failures reported by FW.
		 * Reset EBS status here assuming environment has been changed.
		 */
		mvm->last_ebs_successful = true;
		iwl_mvm_check_uapsd(mvm, vif, sta->addr);
		ret = 0;
	} else if (old_state == IEEE80211_STA_AUTH &&
		   new_state == IEEE80211_STA_ASSOC) {
		ret = iwl_mvm_sta_state_auth_to_assoc(hw, mvm, vif, sta,
						      callbacks);
	} else if (old_state == IEEE80211_STA_ASSOC &&
		   new_state == IEEE80211_STA_AUTHORIZED) {
		ret = iwl_mvm_sta_state_assoc_to_authorized(mvm, vif, sta,
							    callbacks);
	} else if (old_state == IEEE80211_STA_AUTHORIZED &&
		   new_state == IEEE80211_STA_ASSOC) {
		ret = iwl_mvm_sta_state_authorized_to_assoc(mvm, vif, sta,
							    callbacks);
	} else if (old_state == IEEE80211_STA_ASSOC &&
		   new_state == IEEE80211_STA_AUTH) {
		if (vif->type == NL80211_IFTYPE_AP) {
+249 −60

File changed.

Preview size limit exceeded, changes collapsed.

+7 −3
Original line number Diff line number Diff line
@@ -1606,10 +1606,14 @@ int iwl_mvm_flush_sta(struct iwl_mvm *mvm, void *sta, bool internal);
int iwl_mvm_flush_sta_tids(struct iwl_mvm *mvm, u32 sta_id, u16 tids);

/* Utils to extract sta related data */
__le32 iwl_mvm_get_sta_htc_flags(struct ieee80211_sta *sta);
__le32 iwl_mvm_get_sta_htc_flags(struct ieee80211_sta *sta,
				 struct ieee80211_link_sta *link_sta);
u8 iwl_mvm_get_sta_uapsd_acs(struct ieee80211_sta *sta);
u32 iwl_mvm_get_sta_ampdu_dens(struct ieee80211_sta *sta, u32 *_agg_size);
int iwl_mvm_set_sta_pkt_ext(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
u32 iwl_mvm_get_sta_ampdu_dens(struct ieee80211_link_sta *link_sta,
			       struct ieee80211_bss_conf *link_conf,
			       u32 *_agg_size);
int iwl_mvm_set_sta_pkt_ext(struct iwl_mvm *mvm,
			    struct ieee80211_link_sta *link_sta,
			    struct iwl_he_pkt_ext_v2 *pkt_ext);

void iwl_mvm_async_handlers_purge(struct iwl_mvm *mvm);
+20 −8
Original line number Diff line number Diff line
@@ -641,14 +641,25 @@ int rs_fw_tx_protection(struct iwl_mvm *mvm, struct iwl_mvm_sta *mvmsta,

void iwl_mvm_rs_add_sta(struct iwl_mvm *mvm, struct iwl_mvm_sta *mvmsta)
{
	struct iwl_lq_sta_rs_fw *lq_sta = &mvmsta->deflink.lq_sta.rs_fw;
	unsigned int link_id;

	IWL_DEBUG_RATE(mvm, "create station rate scale window\n");

	for (link_id = 0; link_id < ARRAY_SIZE(mvmsta->link); link_id++) {
		struct iwl_lq_sta_rs_fw *lq_sta;
		struct iwl_mvm_link_sta *link =
			rcu_dereference_protected(mvmsta->link[link_id],
						  lockdep_is_held(&mvm->mutex));
		if (!link)
			continue;

		lq_sta = &link->lq_sta.rs_fw;

		lq_sta->pers.drv = mvm;
	lq_sta->pers.sta_id = mvmsta->deflink.sta_id;
		lq_sta->pers.sta_id = link->sta_id;
		lq_sta->pers.chains = 0;
	memset(lq_sta->pers.chain_signal, 0, sizeof(lq_sta->pers.chain_signal));
		memset(lq_sta->pers.chain_signal, 0,
		       sizeof(lq_sta->pers.chain_signal));
		lq_sta->pers.last_rssi = S8_MIN;
		lq_sta->last_rate_n_flags = 0;

@@ -656,3 +667,4 @@ void iwl_mvm_rs_add_sta(struct iwl_mvm *mvm, struct iwl_mvm_sta *mvmsta)
		lq_sta->pers.dbg_fixed_rate = 0;
#endif
	}
}
+98 −39

File changed.

Preview size limit exceeded, changes collapsed.

Loading