mac80211: minstrel_ht: add flag to indicate missing/inaccurate tx A-MPDU length

Some hardware (e.g. MediaTek MT7603) cannot report A-MPDU length in tx status
information. Add support for a flag to indicate that, to allow minstrel_ht
to use a fixed value in its internal calculation (which gives better results
than just defaulting to 1).

Signed-off-by: Felix Fietkau <nbd@nbd.name>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
This commit is contained in:
Felix Fietkau 2019-01-16 22:32:12 +01:00 committed by Johannes Berg
parent a8d418d9ac
commit 77f7ffdc33
4 changed files with 29 additions and 8 deletions

View File

@ -2190,6 +2190,9 @@ struct ieee80211_txq {
* MMPDUs on station interfaces. This of course requires the driver to use * MMPDUs on station interfaces. This of course requires the driver to use
* TXQs to start with. * TXQs to start with.
* *
* @IEEE80211_HW_TX_STATUS_NO_AMPDU_LEN: Driver does not report accurate A-MPDU
* length in tx status information
*
* @NUM_IEEE80211_HW_FLAGS: number of hardware flags, used for sizing arrays * @NUM_IEEE80211_HW_FLAGS: number of hardware flags, used for sizing arrays
*/ */
enum ieee80211_hw_flags { enum ieee80211_hw_flags {
@ -2238,6 +2241,7 @@ enum ieee80211_hw_flags {
IEEE80211_HW_BUFF_MMPDU_TXQ, IEEE80211_HW_BUFF_MMPDU_TXQ,
IEEE80211_HW_SUPPORTS_VHT_EXT_NSS_BW, IEEE80211_HW_SUPPORTS_VHT_EXT_NSS_BW,
IEEE80211_HW_STA_MMPDU_TXQ, IEEE80211_HW_STA_MMPDU_TXQ,
IEEE80211_HW_TX_STATUS_NO_AMPDU_LEN,
/* keep last, obviously */ /* keep last, obviously */
NUM_IEEE80211_HW_FLAGS NUM_IEEE80211_HW_FLAGS

View File

@ -218,6 +218,7 @@ static const char *hw_flag_names[] = {
FLAG(BUFF_MMPDU_TXQ), FLAG(BUFF_MMPDU_TXQ),
FLAG(SUPPORTS_VHT_EXT_NSS_BW), FLAG(SUPPORTS_VHT_EXT_NSS_BW),
FLAG(STA_MMPDU_TXQ), FLAG(STA_MMPDU_TXQ),
FLAG(TX_STATUS_NO_AMPDU_LEN),
#undef FLAG #undef FLAG
}; };

View File

@ -294,6 +294,15 @@ minstrel_get_ratestats(struct minstrel_ht_sta *mi, int index)
return &mi->groups[index / MCS_GROUP_RATES].rates[index % MCS_GROUP_RATES]; return &mi->groups[index / MCS_GROUP_RATES].rates[index % MCS_GROUP_RATES];
} }
static unsigned int
minstrel_ht_avg_ampdu_len(struct minstrel_ht_sta *mi)
{
if (!mi->avg_ampdu_len)
return AVG_AMPDU_SIZE;
return MINSTREL_TRUNC(mi->avg_ampdu_len);
}
/* /*
* Return current throughput based on the average A-MPDU length, taking into * Return current throughput based on the average A-MPDU length, taking into
* account the expected number of retransmissions and their expected length * account the expected number of retransmissions and their expected length
@ -309,7 +318,7 @@ minstrel_ht_get_tp_avg(struct minstrel_ht_sta *mi, int group, int rate,
return 0; return 0;
if (group != MINSTREL_CCK_GROUP) if (group != MINSTREL_CCK_GROUP)
nsecs = 1000 * mi->overhead / MINSTREL_TRUNC(mi->avg_ampdu_len); nsecs = 1000 * mi->overhead / minstrel_ht_avg_ampdu_len(mi);
nsecs += minstrel_mcs_groups[group].duration[rate] << nsecs += minstrel_mcs_groups[group].duration[rate] <<
minstrel_mcs_groups[group].shift; minstrel_mcs_groups[group].shift;
@ -503,8 +512,12 @@ minstrel_ht_update_stats(struct minstrel_priv *mp, struct minstrel_ht_sta *mi)
u16 tmp_cck_tp_rate[MAX_THR_RATES], index; u16 tmp_cck_tp_rate[MAX_THR_RATES], index;
if (mi->ampdu_packets > 0) { if (mi->ampdu_packets > 0) {
mi->avg_ampdu_len = minstrel_ewma(mi->avg_ampdu_len, if (!ieee80211_hw_check(mp->hw, TX_STATUS_NO_AMPDU_LEN))
MINSTREL_FRAC(mi->ampdu_len, mi->ampdu_packets), EWMA_LEVEL); mi->avg_ampdu_len = minstrel_ewma(mi->avg_ampdu_len,
MINSTREL_FRAC(mi->ampdu_len, mi->ampdu_packets),
EWMA_LEVEL);
else
mi->avg_ampdu_len = 0;
mi->ampdu_len = 0; mi->ampdu_len = 0;
mi->ampdu_packets = 0; mi->ampdu_packets = 0;
} }
@ -709,7 +722,9 @@ minstrel_ht_tx_status(void *priv, struct ieee80211_supported_band *sband,
mi->ampdu_len += info->status.ampdu_len; mi->ampdu_len += info->status.ampdu_len;
if (!mi->sample_wait && !mi->sample_tries && mi->sample_count > 0) { if (!mi->sample_wait && !mi->sample_tries && mi->sample_count > 0) {
mi->sample_wait = 16 + 2 * MINSTREL_TRUNC(mi->avg_ampdu_len); int avg_ampdu_len = minstrel_ht_avg_ampdu_len(mi);
mi->sample_wait = 16 + 2 * avg_ampdu_len;
mi->sample_tries = 1; mi->sample_tries = 1;
mi->sample_count--; mi->sample_count--;
} }
@ -777,7 +792,7 @@ minstrel_calc_retransmit(struct minstrel_priv *mp, struct minstrel_ht_sta *mi,
unsigned int cw = mp->cw_min; unsigned int cw = mp->cw_min;
unsigned int ctime = 0; unsigned int ctime = 0;
unsigned int t_slot = 9; /* FIXME */ unsigned int t_slot = 9; /* FIXME */
unsigned int ampdu_len = MINSTREL_TRUNC(mi->avg_ampdu_len); unsigned int ampdu_len = minstrel_ht_avg_ampdu_len(mi);
unsigned int overhead = 0, overhead_rtscts = 0; unsigned int overhead = 0, overhead_rtscts = 0;
mrs = minstrel_get_ratestats(mi, index); mrs = minstrel_get_ratestats(mi, index);

View File

@ -160,9 +160,10 @@ minstrel_ht_stats_open(struct inode *inode, struct file *file)
"lookaround %d\n", "lookaround %d\n",
max(0, (int) mi->total_packets - (int) mi->sample_packets), max(0, (int) mi->total_packets - (int) mi->sample_packets),
mi->sample_packets); mi->sample_packets);
p += sprintf(p, "Average # of aggregated frames per A-MPDU: %d.%d\n", if (mi->avg_ampdu_len)
MINSTREL_TRUNC(mi->avg_ampdu_len), p += sprintf(p, "Average # of aggregated frames per A-MPDU: %d.%d\n",
MINSTREL_TRUNC(mi->avg_ampdu_len * 10) % 10); MINSTREL_TRUNC(mi->avg_ampdu_len),
MINSTREL_TRUNC(mi->avg_ampdu_len * 10) % 10);
ms->len = p - ms->buf; ms->len = p - ms->buf;
WARN_ON(ms->len + sizeof(*ms) > 32768); WARN_ON(ms->len + sizeof(*ms) > 32768);