Commit 569cf386 authored by Jonas Jelonek's avatar Jonas Jelonek Committed by Johannes Berg
Browse files

mac80211: minstrel_ht: support ieee80211_rate_status



This patch adds support for the new struct ieee80211_rate_status and its
annotation in struct ieee80211_tx_status in minstrel_ht.

In minstrel_ht_tx_status, a check for the presence of instances of the
new struct in ieee80211_tx_status is added. Based on this, minstrel_ht
then gets and updates internal rate stats with either struct
ieee80211_rate_status or ieee80211_tx_info->status.rates.
Adjusted variants of minstrel_ht_txstat_valid, minstrel_ht_get_stats,
minstrel_{ht/vht}_get_group_idx are added which use struct
ieee80211_rate_status and struct rate_info instead of the legacy structs.

struct rate_info from cfg80211.h does not provide whether short preamble
was used for the transmission. So we retrieve this information from VIF
and STA configuration and cache it in a new flag in struct minstrel_ht_sta
per rate control instance.

Compile-Tested: current wireless-next tree with all flags on
Tested-on: Xiaomi 4A Gigabit (MediaTek MT7603E, MT7612E) with OpenWrt
                Linux 5.10.113

Signed-off-by: default avatarJonas Jelonek <jelonek.jonas@gmail.com>
Link: https://lore.kernel.org/r/20220509173958.1398201-3-jelonek.jonas@gmail.com


Signed-off-by: default avatarJohannes Berg <johannes.berg@intel.com>
parent 44fa75f2
Loading
Loading
Loading
Loading
+132 −8
Original line number Diff line number Diff line
@@ -333,6 +333,17 @@ minstrel_ht_get_group_idx(struct ieee80211_tx_rate *rate)
			 !!(rate->flags & IEEE80211_TX_RC_40_MHZ_WIDTH));
}

/*
 * Look up an MCS group index based on new cfg80211 rate_info.
 */
static int
minstrel_ht_ri_get_group_idx(struct rate_info *rate)
{
	return GROUP_IDX((rate->mcs / 8) + 1,
			 !!(rate->flags & RATE_INFO_FLAGS_SHORT_GI),
			 !!(rate->bw & RATE_INFO_BW_40));
}

static int
minstrel_vht_get_group_idx(struct ieee80211_tx_rate *rate)
{
@@ -342,6 +353,18 @@ minstrel_vht_get_group_idx(struct ieee80211_tx_rate *rate)
			     2*!!(rate->flags & IEEE80211_TX_RC_80_MHZ_WIDTH));
}

/*
 * Look up an MCS group index based on new cfg80211 rate_info.
 */
static int
minstrel_vht_ri_get_group_idx(struct rate_info *rate)
{
	return VHT_GROUP_IDX(rate->nss,
			     !!(rate->flags & RATE_INFO_FLAGS_SHORT_GI),
			     !!(rate->bw & RATE_INFO_BW_40) +
			     2*!!(rate->bw & RATE_INFO_BW_80));
}

static struct minstrel_rate_stats *
minstrel_ht_get_stats(struct minstrel_priv *mp, struct minstrel_ht_sta *mi,
		      struct ieee80211_tx_rate *rate)
@@ -385,6 +408,50 @@ minstrel_ht_get_stats(struct minstrel_priv *mp, struct minstrel_ht_sta *mi,
	return &mi->groups[group].rates[idx];
}

/*
 * Get the minstrel rate statistics for specified STA and rate info.
 */
static struct minstrel_rate_stats *
minstrel_ht_ri_get_stats(struct minstrel_priv *mp, struct minstrel_ht_sta *mi,
			  struct ieee80211_rate_status *rate_status)
{
	int group, idx;
	struct rate_info *rate = &rate_status->rate_idx;

	if (rate->flags & RATE_INFO_FLAGS_MCS) {
		group = minstrel_ht_ri_get_group_idx(rate);
		idx = rate->mcs % 8;
		goto out;
	}

	if (rate->flags & RATE_INFO_FLAGS_VHT_MCS) {
		group = minstrel_vht_ri_get_group_idx(rate);
		idx = rate->mcs;
		goto out;
	}

	group = MINSTREL_CCK_GROUP;
	for (idx = 0; idx < ARRAY_SIZE(mp->cck_rates); idx++) {
		if (rate->legacy != minstrel_cck_bitrates[ mp->cck_rates[idx] ])
			continue;

		/* short preamble */
		if ((mi->supported[group] & BIT(idx + 4)) &&
							mi->use_short_preamble)
			idx += 4;
		goto out;
	}

	group = MINSTREL_OFDM_GROUP;
	for (idx = 0; idx < ARRAY_SIZE(mp->ofdm_rates[0]); idx++)
		if (rate->legacy == minstrel_ofdm_bitrates[ mp->ofdm_rates[mi->band][idx] ])
			goto out;

	idx = 0;
out:
	return &mi->groups[group].rates[idx];
}

static inline struct minstrel_rate_stats *
minstrel_get_ratestats(struct minstrel_ht_sta *mi, int index)
{
@@ -1152,6 +1219,40 @@ minstrel_ht_txstat_valid(struct minstrel_priv *mp, struct minstrel_ht_sta *mi,
	return false;
}

/*
 * Check whether rate_status contains valid information.
 */
static bool
minstrel_ht_ri_txstat_valid(struct minstrel_priv *mp,
			    struct minstrel_ht_sta *mi,
			    struct ieee80211_rate_status *rate_status)
{
	int i;

	if (!rate_status)
		return false;
	if (!rate_status->try_count)
		return false;

	if (rate_status->rate_idx.flags & RATE_INFO_FLAGS_MCS ||
	    rate_status->rate_idx.flags & RATE_INFO_FLAGS_VHT_MCS)
		return true;

	for (i = 0; i < ARRAY_SIZE(mp->cck_rates); i++) {
		if (rate_status->rate_idx.legacy ==
		    minstrel_cck_bitrates[ mp->cck_rates[i] ])
			return true;
	}

	for (i = 0; i < ARRAY_SIZE(mp->ofdm_rates); i++) {
		if (rate_status->rate_idx.legacy ==
		    minstrel_ofdm_bitrates[ mp->ofdm_rates[mi->band][i] ])
			return true;
	}

	return false;
}

static void
minstrel_downgrade_rate(struct minstrel_ht_sta *mi, u16 *idx, bool primary)
{
@@ -1217,6 +1318,23 @@ minstrel_ht_tx_status(void *priv, struct ieee80211_supported_band *sband,
	mi->ampdu_packets++;
	mi->ampdu_len += info->status.ampdu_len;

	if (st->rates && st->n_rates) {
		last = !minstrel_ht_ri_txstat_valid(mp, mi, &(st->rates[0]));
		for (i = 0; !last; i++) {
			last = (i == st->n_rates - 1) ||
				!minstrel_ht_ri_txstat_valid(mp, mi,
							&(st->rates[i + 1]));

			rate = minstrel_ht_ri_get_stats(mp, mi,
							&(st->rates[i]));

			if (last)
				rate->success += info->status.ampdu_ack_len;

			rate->attempts += st->rates[i].try_count *
					  info->status.ampdu_len;
		}
	} else {
		last = !minstrel_ht_txstat_valid(mp, mi, &ar[0]);
		for (i = 0; !last; i++) {
			last = (i == IEEE80211_TX_MAX_RATES - 1) ||
@@ -1228,6 +1346,7 @@ minstrel_ht_tx_status(void *priv, struct ieee80211_supported_band *sband,

			rate->attempts += ar[i].count * info->status.ampdu_len;
		}
	}

	if (mp->hw->max_rates > 1) {
		/*
@@ -1583,6 +1702,7 @@ minstrel_ht_update_caps(void *priv, struct ieee80211_supported_band *sband,
	u16 ht_cap = sta->deflink.ht_cap.cap;
	struct ieee80211_sta_vht_cap *vht_cap = &sta->deflink.vht_cap;
	const struct ieee80211_rate *ctl_rate;
	struct sta_info *sta_info;
	bool ldpc, erp;
	int use_vht;
	int n_supported = 0;
@@ -1701,6 +1821,10 @@ minstrel_ht_update_caps(void *priv, struct ieee80211_supported_band *sband,
			n_supported++;
	}

	sta_info = container_of(sta, struct sta_info, sta);
	mi->use_short_preamble = test_sta_flag(sta_info, WLAN_STA_SHORT_PREAMBLE) &&
				 sta_info->sdata->vif.bss_conf.use_short_preamble;

	minstrel_ht_update_cck(mp, mi, sband, sta);
	minstrel_ht_update_ofdm(mp, mi, sband, sta);

+1 −1
Original line number Diff line number Diff line
@@ -180,7 +180,7 @@ struct minstrel_ht_sta {

	/* tx flags to add for frames for this sta */
	u32 tx_flags;

	bool use_short_preamble;
	u8 band;

	u8 sample_seq;