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: Jonas Jelonek <jelonek.jonas@gmail.com> Link: https://lore.kernel.org/r/20220509173958.1398201-3-jelonek.jonas@gmail.com Signed-off-by: Johannes Berg <johannes.berg@intel.com>
This commit is contained in:
parent
44fa75f207
commit
569cf386ec
|
@ -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 @@ out:
|
|||
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,16 +1318,34 @@ minstrel_ht_tx_status(void *priv, struct ieee80211_supported_band *sband,
|
|||
mi->ampdu_packets++;
|
||||
mi->ampdu_len += info->status.ampdu_len;
|
||||
|
||||
last = !minstrel_ht_txstat_valid(mp, mi, &ar[0]);
|
||||
for (i = 0; !last; i++) {
|
||||
last = (i == IEEE80211_TX_MAX_RATES - 1) ||
|
||||
!minstrel_ht_txstat_valid(mp, mi, &ar[i + 1]);
|
||||
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_get_stats(mp, mi, &ar[i]);
|
||||
if (last)
|
||||
rate->success += info->status.ampdu_ack_len;
|
||||
rate = minstrel_ht_ri_get_stats(mp, mi,
|
||||
&(st->rates[i]));
|
||||
|
||||
rate->attempts += ar[i].count * info->status.ampdu_len;
|
||||
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) ||
|
||||
!minstrel_ht_txstat_valid(mp, mi, &ar[i + 1]);
|
||||
|
||||
rate = minstrel_ht_get_stats(mp, mi, &ar[i]);
|
||||
if (last)
|
||||
rate->success += info->status.ampdu_ack_len;
|
||||
|
||||
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);
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue