mac80211: minstrel_ht: add flag to indicate missing/inaccurate tx A-MPDU length
authorFelix Fietkau <nbd@nbd.name>
Wed, 16 Jan 2019 21:32:12 +0000 (22:32 +0100)
committerJohannes Berg <johannes.berg@intel.com>
Sat, 19 Jan 2019 08:56:56 +0000 (09:56 +0100)
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>
include/net/mac80211.h
net/mac80211/debugfs.c
net/mac80211/rc80211_minstrel_ht.c
net/mac80211/rc80211_minstrel_ht_debugfs.c

index 5d36eacf401e42a916696659b6a2b48773c4e877..a285c2bfd14e1ef37731daf14e8edc86e4174af5 100644 (file)
@@ -2190,6 +2190,9 @@ struct ieee80211_txq {
  *     MMPDUs on station interfaces. This of course requires the driver to use
  *     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
  */
 enum ieee80211_hw_flags {
@@ -2238,6 +2241,7 @@ enum ieee80211_hw_flags {
        IEEE80211_HW_BUFF_MMPDU_TXQ,
        IEEE80211_HW_SUPPORTS_VHT_EXT_NSS_BW,
        IEEE80211_HW_STA_MMPDU_TXQ,
+       IEEE80211_HW_TX_STATUS_NO_AMPDU_LEN,
 
        /* keep last, obviously */
        NUM_IEEE80211_HW_FLAGS
index 81c5fec2eae7270cb16d09c31798c9e30a55d484..343ad0a915e474850cd9cc86638cec1e3ba4781f 100644 (file)
@@ -218,6 +218,7 @@ static const char *hw_flag_names[] = {
        FLAG(BUFF_MMPDU_TXQ),
        FLAG(SUPPORTS_VHT_EXT_NSS_BW),
        FLAG(STA_MMPDU_TXQ),
+       FLAG(TX_STATUS_NO_AMPDU_LEN),
 #undef FLAG
 };
 
index f466ec37d161faf3aeaaf84fdf2f6b95788fb4ca..ccaf951e4e3122c1291f88f12dded5341f712b09 100644 (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];
 }
 
+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
  * 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;
 
        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] <<
                 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;
 
        if (mi->ampdu_packets > 0) {
-               mi->avg_ampdu_len = minstrel_ewma(mi->avg_ampdu_len,
-                       MINSTREL_FRAC(mi->ampdu_len, mi->ampdu_packets), EWMA_LEVEL);
+               if (!ieee80211_hw_check(mp->hw, TX_STATUS_NO_AMPDU_LEN))
+                       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_packets = 0;
        }
@@ -709,7 +722,9 @@ minstrel_ht_tx_status(void *priv, struct ieee80211_supported_band *sband,
        mi->ampdu_len += info->status.ampdu_len;
 
        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_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 ctime = 0;
        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;
 
        mrs = minstrel_get_ratestats(mi, index);
index 57820a5f2c16c3c88cf565cbb643485e27759ae7..31641d0b0f5cd25fff4eb7672a00fd37f285daeb 100644 (file)
@@ -160,9 +160,10 @@ minstrel_ht_stats_open(struct inode *inode, struct file *file)
                        "lookaround %d\n",
                        max(0, (int) mi->total_packets - (int) mi->sample_packets),
                        mi->sample_packets);
-       p += sprintf(p, "Average # of aggregated frames per A-MPDU: %d.%d\n",
-               MINSTREL_TRUNC(mi->avg_ampdu_len),
-               MINSTREL_TRUNC(mi->avg_ampdu_len * 10) % 10);
+       if (mi->avg_ampdu_len)
+               p += sprintf(p, "Average # of aggregated frames per A-MPDU: %d.%d\n",
+                       MINSTREL_TRUNC(mi->avg_ampdu_len),
+                       MINSTREL_TRUNC(mi->avg_ampdu_len * 10) % 10);
        ms->len = p - ms->buf;
        WARN_ON(ms->len + sizeof(*ms) > 32768);