Commit 9213f809 authored by Benjamin Berg's avatar Benjamin Berg Committed by Johannes Berg
Browse files

wifi: iwlwifi: mvm: use appropriate link for rate selection



We were still using the deflink in most cases, update the code to use
the appropriate link.

Signed-off-by: default avatarBenjamin Berg <benjamin.berg@intel.com>
Signed-off-by: default avatarGregory Greenman <gregory.greenman@intel.com>
Link: https://lore.kernel.org/r/20230329100039.fa1025502fb4.Iaba0c64740fdcf04a521e2f213bd3f3e27862472@changeid


Signed-off-by: default avatarJohannes Berg <johannes.berg@intel.com>
parent 0d504ca1
Loading
Loading
Loading
Loading
+61 −48
Original line number Diff line number Diff line
@@ -9,9 +9,9 @@
#include "iwl-op-mode.h"
#include "mvm.h"

static u8 rs_fw_bw_from_sta_bw(const struct ieee80211_sta *sta)
static u8 rs_fw_bw_from_sta_bw(const struct ieee80211_link_sta *link_sta)
{
	switch (sta->deflink.bandwidth) {
	switch (link_sta->bandwidth) {
	case IEEE80211_STA_RX_BW_320:
		return IWL_TLC_MNG_CH_WIDTH_320MHZ;
	case IEEE80211_STA_RX_BW_160:
@@ -38,11 +38,11 @@ static u8 rs_fw_set_active_chains(u8 chains)
	return fw_chains;
}

static u8 rs_fw_sgi_cw_support(struct ieee80211_sta *sta)
static u8 rs_fw_sgi_cw_support(struct ieee80211_link_sta *link_sta)
{
	struct ieee80211_sta_ht_cap *ht_cap = &sta->deflink.ht_cap;
	struct ieee80211_sta_vht_cap *vht_cap = &sta->deflink.vht_cap;
	struct ieee80211_sta_he_cap *he_cap = &sta->deflink.he_cap;
	struct ieee80211_sta_ht_cap *ht_cap = &link_sta->ht_cap;
	struct ieee80211_sta_vht_cap *vht_cap = &link_sta->vht_cap;
	struct ieee80211_sta_he_cap *he_cap = &link_sta->he_cap;
	u8 supp = 0;

	if (he_cap->has_he)
@@ -61,12 +61,12 @@ static u8 rs_fw_sgi_cw_support(struct ieee80211_sta *sta)
}

static u16 rs_fw_get_config_flags(struct iwl_mvm *mvm,
				  struct ieee80211_sta *sta,
				  struct ieee80211_link_sta *link_sta,
				  struct ieee80211_supported_band *sband)
{
	struct ieee80211_sta_ht_cap *ht_cap = &sta->deflink.ht_cap;
	struct ieee80211_sta_vht_cap *vht_cap = &sta->deflink.vht_cap;
	struct ieee80211_sta_he_cap *he_cap = &sta->deflink.he_cap;
	struct ieee80211_sta_ht_cap *ht_cap = &link_sta->ht_cap;
	struct ieee80211_sta_vht_cap *vht_cap = &link_sta->vht_cap;
	struct ieee80211_sta_he_cap *he_cap = &link_sta->he_cap;
	bool vht_ena = vht_cap->vht_supported;
	u16 flags = 0;

@@ -132,20 +132,20 @@ int rs_fw_vht_highest_rx_mcs_index(const struct ieee80211_sta_vht_cap *vht_cap,
}

static void
rs_fw_vht_set_enabled_rates(const struct ieee80211_sta *sta,
rs_fw_vht_set_enabled_rates(const struct ieee80211_link_sta *link_sta,
			    const struct ieee80211_sta_vht_cap *vht_cap,
			    struct iwl_tlc_config_cmd_v4 *cmd)
{
	u16 supp;
	int i, highest_mcs;
	u8 max_nss = sta->deflink.rx_nss;
	u8 max_nss = link_sta->rx_nss;
	struct ieee80211_vht_cap ieee_vht_cap = {
		.vht_cap_info = cpu_to_le32(vht_cap->cap),
		.supp_mcs = vht_cap->vht_mcs,
	};

	/* the station support only a single receive chain */
	if (sta->deflink.smps_mode == IEEE80211_SMPS_STATIC)
	if (link_sta->smps_mode == IEEE80211_SMPS_STATIC)
		max_nss = 1;

	for (i = 0; i < max_nss && i < IWL_TLC_NSS_MAX; i++) {
@@ -156,7 +156,7 @@ rs_fw_vht_set_enabled_rates(const struct ieee80211_sta *sta,
			continue;

		supp = BIT(highest_mcs + 1) - 1;
		if (sta->deflink.bandwidth == IEEE80211_STA_RX_BW_20)
		if (link_sta->bandwidth == IEEE80211_STA_RX_BW_20)
			supp &= ~BIT(IWL_TLC_MNG_HT_RATE_MCS9);

		cmd->ht_rates[i][IWL_TLC_MCS_PER_BW_80] = cpu_to_le16(supp);
@@ -165,7 +165,7 @@ rs_fw_vht_set_enabled_rates(const struct ieee80211_sta *sta,
		 * configuration is supported - only for MCS 0 since we already
		 * decoded the MCS bits anyway ourselves.
		 */
		if (sta->deflink.bandwidth == IEEE80211_STA_RX_BW_160 &&
		if (link_sta->bandwidth == IEEE80211_STA_RX_BW_160 &&
		    ieee80211_get_vht_max_nss(&ieee_vht_cap,
					      IEEE80211_VHT_CHANWIDTH_160MHZ,
					      0, true, nss) >= nss)
@@ -192,11 +192,11 @@ static u16 rs_fw_he_ieee80211_mcs_to_rs_mcs(u16 mcs)
}

static void
rs_fw_he_set_enabled_rates(const struct ieee80211_sta *sta,
rs_fw_he_set_enabled_rates(const struct ieee80211_link_sta *link_sta,
			   struct ieee80211_supported_band *sband,
			   struct iwl_tlc_config_cmd_v4 *cmd)
{
	const struct ieee80211_sta_he_cap *he_cap = &sta->deflink.he_cap;
	const struct ieee80211_sta_he_cap *he_cap = &link_sta->he_cap;
	u16 mcs_160 = le16_to_cpu(he_cap->he_mcs_nss_supp.rx_mcs_160);
	u16 mcs_80 = le16_to_cpu(he_cap->he_mcs_nss_supp.rx_mcs_80);
	u16 tx_mcs_80 =
@@ -204,10 +204,10 @@ rs_fw_he_set_enabled_rates(const struct ieee80211_sta *sta,
	u16 tx_mcs_160 =
		le16_to_cpu(sband->iftype_data->he_cap.he_mcs_nss_supp.tx_mcs_160);
	int i;
	u8 nss = sta->deflink.rx_nss;
	u8 nss = link_sta->rx_nss;

	/* the station support only a single receive chain */
	if (sta->deflink.smps_mode == IEEE80211_SMPS_STATIC)
	if (link_sta->smps_mode == IEEE80211_SMPS_STATIC)
		nss = 1;

	for (i = 0; i < nss && i < IWL_TLC_NSS_MAX; i++) {
@@ -282,13 +282,14 @@ rs_fw_rs_mcs2eht_mcs(enum IWL_TLC_MCS_PER_BW bw,
	}
}

static void rs_fw_eht_set_enabled_rates(const struct ieee80211_sta *sta,
static void
rs_fw_eht_set_enabled_rates(const struct ieee80211_link_sta *link_sta,
			    struct ieee80211_supported_band *sband,
			    struct iwl_tlc_config_cmd_v4 *cmd)
{
	/* peer RX mcs capa */
	const struct ieee80211_eht_mcs_nss_supp *eht_rx_mcs =
		&sta->deflink.eht_cap.eht_mcs_nss_supp;
		&link_sta->eht_cap.eht_mcs_nss_supp;
	/* our TX mcs capa */
	const struct ieee80211_eht_mcs_nss_supp *eht_tx_mcs =
		&sband->iftype_data->eht_cap.eht_mcs_nss_supp;
@@ -298,7 +299,7 @@ static void rs_fw_eht_set_enabled_rates(const struct ieee80211_sta *sta,
	struct ieee80211_eht_mcs_nss_supp_20mhz_only mcs_tx_20;

	/* peer is 20Mhz only */
	if (!(sta->deflink.he_cap.he_cap_elem.phy_cap_info[0] &
	if (!(link_sta->he_cap.he_cap_elem.phy_cap_info[0] &
	      IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_MASK_ALL)) {
		mcs_rx_20 = eht_rx_mcs->only_20mhz;
	} else {
@@ -354,25 +355,25 @@ static void rs_fw_eht_set_enabled_rates(const struct ieee80211_sta *sta,
	}

	/* the station support only a single receive chain */
	if (sta->deflink.smps_mode == IEEE80211_SMPS_STATIC ||
	    sta->deflink.rx_nss < 2)
	if (link_sta->smps_mode == IEEE80211_SMPS_STATIC ||
	    link_sta->rx_nss < 2)
		memset(cmd->ht_rates[IWL_TLC_NSS_2], 0,
		       sizeof(cmd->ht_rates[IWL_TLC_NSS_2]));
}

static void rs_fw_set_supp_rates(struct ieee80211_sta *sta,
static void rs_fw_set_supp_rates(struct ieee80211_link_sta *link_sta,
				 struct ieee80211_supported_band *sband,
				 struct iwl_tlc_config_cmd_v4 *cmd)
{
	int i;
	u16 supp = 0;
	unsigned long tmp; /* must be unsigned long for for_each_set_bit */
	const struct ieee80211_sta_ht_cap *ht_cap = &sta->deflink.ht_cap;
	const struct ieee80211_sta_vht_cap *vht_cap = &sta->deflink.vht_cap;
	const struct ieee80211_sta_he_cap *he_cap = &sta->deflink.he_cap;
	const struct ieee80211_sta_ht_cap *ht_cap = &link_sta->ht_cap;
	const struct ieee80211_sta_vht_cap *vht_cap = &link_sta->vht_cap;
	const struct ieee80211_sta_he_cap *he_cap = &link_sta->he_cap;

	/* non HT rates */
	tmp = sta->deflink.supp_rates[sband->band];
	tmp = link_sta->supp_rates[sband->band];
	for_each_set_bit(i, &tmp, BITS_PER_LONG)
		supp |= BIT(sband->bitrates[i].hw_value);

@@ -380,22 +381,22 @@ static void rs_fw_set_supp_rates(struct ieee80211_sta *sta,
	cmd->mode = IWL_TLC_MNG_MODE_NON_HT;

	/* HT/VHT rates */
	if (sta->deflink.eht_cap.has_eht) {
	if (link_sta->eht_cap.has_eht) {
		cmd->mode = IWL_TLC_MNG_MODE_EHT;
		rs_fw_eht_set_enabled_rates(sta, sband, cmd);
		rs_fw_eht_set_enabled_rates(link_sta, sband, cmd);
	} else if (he_cap->has_he) {
		cmd->mode = IWL_TLC_MNG_MODE_HE;
		rs_fw_he_set_enabled_rates(sta, sband, cmd);
		rs_fw_he_set_enabled_rates(link_sta, sband, cmd);
	} else if (vht_cap->vht_supported) {
		cmd->mode = IWL_TLC_MNG_MODE_VHT;
		rs_fw_vht_set_enabled_rates(sta, vht_cap, cmd);
		rs_fw_vht_set_enabled_rates(link_sta, vht_cap, cmd);
	} else if (ht_cap->ht_supported) {
		cmd->mode = IWL_TLC_MNG_MODE_HT;
		cmd->ht_rates[IWL_TLC_NSS_1][IWL_TLC_MCS_PER_BW_80] =
			cpu_to_le16(ht_cap->mcs.rx_mask[0]);

		/* the station support only a single receive chain */
		if (sta->deflink.smps_mode == IEEE80211_SMPS_STATIC)
		if (link_sta->smps_mode == IEEE80211_SMPS_STATIC)
			cmd->ht_rates[IWL_TLC_NSS_2][IWL_TLC_MCS_PER_BW_80] =
				0;
		else
@@ -410,15 +411,18 @@ void iwl_mvm_tlc_update_notif(struct iwl_mvm *mvm,
	struct iwl_rx_packet *pkt = rxb_addr(rxb);
	struct iwl_tlc_update_notif *notif;
	struct ieee80211_sta *sta;
	struct ieee80211_link_sta *link_sta;
	struct iwl_mvm_sta *mvmsta;
	struct iwl_mvm_link_sta *mvm_link_sta;
	struct iwl_lq_sta_rs_fw *lq_sta;
	u32 flags;

	rcu_read_lock();

	notif = (void *)pkt->data;
	link_sta = rcu_dereference(mvm->fw_id_to_link_sta[notif->sta_id]);
	sta = rcu_dereference(mvm->fw_id_to_mac_id[notif->sta_id]);
	if (IS_ERR_OR_NULL(sta)) {
	if (IS_ERR_OR_NULL(sta) || !link_sta) {
		/* can happen in remove station flow where mvm removed internally
		 * the station before removing from FW
		 */
@@ -438,7 +442,14 @@ void iwl_mvm_tlc_update_notif(struct iwl_mvm *mvm,

	flags = le32_to_cpu(notif->flags);

	lq_sta = &mvmsta->deflink.lq_sta.rs_fw;
	mvm_link_sta = rcu_dereference(mvmsta->link[link_sta->link_id]);
	if (!mvm_link_sta) {
		IWL_DEBUG_RATE(mvm,
			       "Invalid mvmsta RCU pointer for link (%d) of  sta id (%d) in TLC notification\n",
			       link_sta->link_id, notif->sta_id);
		goto out;
	}
	lq_sta = &mvm_link_sta->lq_sta.rs_fw;

	if (flags & IWL_TLC_NOTIF_FLAG_RATE) {
		char pretty_rate[100];
@@ -465,9 +476,9 @@ void iwl_mvm_tlc_update_notif(struct iwl_mvm *mvm,
		u16 size = le32_to_cpu(notif->amsdu_size);
		int i;

		if (sta->deflink.agg.max_amsdu_len < size) {
		if (link_sta->agg.max_amsdu_len < size) {
			/*
			 * In debug sta->deflink.agg.max_amsdu_len < size
			 * In debug link_sta->agg.max_amsdu_len < size
			 * so also check with orig_amsdu_len which holds the
			 * original data before debugfs changed the value
			 */
@@ -477,18 +488,18 @@ void iwl_mvm_tlc_update_notif(struct iwl_mvm *mvm,

		mvmsta->amsdu_enabled = le32_to_cpu(notif->amsdu_enabled);
		mvmsta->max_amsdu_len = size;
		sta->deflink.agg.max_rc_amsdu_len = mvmsta->max_amsdu_len;
		link_sta->agg.max_rc_amsdu_len = mvmsta->max_amsdu_len;

		for (i = 0; i < IWL_MAX_TID_COUNT; i++) {
			if (mvmsta->amsdu_enabled & BIT(i))
				sta->deflink.agg.max_tid_amsdu_len[i] =
				link_sta->agg.max_tid_amsdu_len[i] =
					iwl_mvm_max_amsdu_size(mvm, sta, i);
			else
				/*
				 * Not so elegant, but this will effectively
				 * prevent AMSDU on this TID
				 */
				sta->deflink.agg.max_tid_amsdu_len[i] = 1;
				link_sta->agg.max_tid_amsdu_len[i] = 1;
		}

		IWL_DEBUG_RATE(mvm,
@@ -511,7 +522,7 @@ u16 rs_fw_get_max_amsdu_len(struct ieee80211_sta *sta,
		return IEEE80211_MAX_MPDU_LEN_VHT_3895;

	if (link_conf->chandef.chan->band == NL80211_BAND_6GHZ) {
		switch (le16_get_bits(sta->deflink.he_6ghz_capa.capa,
		switch (le16_get_bits(link_sta->he_6ghz_capa.capa,
				      IEEE80211_HE_6GHZ_CAP_MAX_MPDU_LEN)) {
		case IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_11454:
			return IEEE80211_MAX_MPDU_LEN_VHT_11454;
@@ -560,10 +571,12 @@ void rs_fw_rate_init(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
	struct iwl_lq_sta_rs_fw *lq_sta;
	struct iwl_tlc_config_cmd_v4 cfg_cmd = {
		.max_ch_width = update ?
			rs_fw_bw_from_sta_bw(sta) : IWL_TLC_MNG_CH_WIDTH_20MHZ,
		.flags = cpu_to_le16(rs_fw_get_config_flags(mvm, sta, sband)),
			rs_fw_bw_from_sta_bw(link_sta) :
			IWL_TLC_MNG_CH_WIDTH_20MHZ,
		.flags = cpu_to_le16(rs_fw_get_config_flags(mvm, link_sta,
							    sband)),
		.chains = rs_fw_set_active_chains(iwl_mvm_get_valid_tx_ant(mvm)),
		.sgi_ch_width_supp = rs_fw_sgi_cw_support(sta),
		.sgi_ch_width_supp = rs_fw_sgi_cw_support(link_sta),
		.max_mpdu_len = iwl_mvm_is_csum_supported(mvm) ?
				cpu_to_le16(max_amsdu_len) : 0,
	};
@@ -588,7 +601,7 @@ void rs_fw_rate_init(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
#ifdef CONFIG_IWLWIFI_DEBUGFS
	iwl_mvm_reset_frame_stats(mvm);
#endif
	rs_fw_set_supp_rates(sta, sband, &cfg_cmd);
	rs_fw_set_supp_rates(link_sta, sband, &cfg_cmd);

	/*
	 * since TLC offload works with one mode we can assume