f221d36bf867fd8c63ba68543cfe934b328528c4
[oweals/openwrt.git] /
1 From: Felix Fietkau <nbd@nbd.name>
2 Date: Wed, 16 Jan 2019 22:32:12 +0100
3 Subject: [PATCH] mac80211: minstrel_ht: add flag to indicate
4  missing/inaccurate tx A-MPDU length
5
6 Some hardware (e.g. MediaTek MT7603) cannot report A-MPDU length in tx status
7 information. Add support for a flag to indicate that, to allow minstrel_ht
8 to use a fixed value in its internal calculation (which gives better results
9 than just defaulting to 1).
10
11 Signed-off-by: Felix Fietkau <nbd@nbd.name>
12 Signed-off-by: Johannes Berg <johannes.berg@intel.com>
13 ---
14
15 --- a/include/net/mac80211.h
16 +++ b/include/net/mac80211.h
17 @@ -2131,6 +2131,9 @@ struct ieee80211_txq {
18   * @IEEE80211_HW_DOESNT_SUPPORT_QOS_NDP: The driver (or firmware) doesn't
19   *     support QoS NDP for AP probing - that's most likely a driver bug.
20   *
21 + * @IEEE80211_HW_TX_STATUS_NO_AMPDU_LEN: Driver does not report accurate A-MPDU
22 + *     length in tx status information
23 + *
24   * @NUM_IEEE80211_HW_FLAGS: number of hardware flags, used for sizing arrays
25   */
26  enum ieee80211_hw_flags {
27 @@ -2176,6 +2179,7 @@ enum ieee80211_hw_flags {
28         IEEE80211_HW_SUPPORTS_TDLS_BUFFER_STA,
29         IEEE80211_HW_DEAUTH_NEED_MGD_TX_PREP,
30         IEEE80211_HW_DOESNT_SUPPORT_QOS_NDP,
31 +       IEEE80211_HW_TX_STATUS_NO_AMPDU_LEN,
32  
33         /* keep last, obviously */
34         NUM_IEEE80211_HW_FLAGS
35 --- a/net/mac80211/debugfs.c
36 +++ b/net/mac80211/debugfs.c
37 @@ -214,6 +214,7 @@ static const char *hw_flag_names[] = {
38         FLAG(SUPPORTS_TDLS_BUFFER_STA),
39         FLAG(DEAUTH_NEED_MGD_TX_PREP),
40         FLAG(DOESNT_SUPPORT_QOS_NDP),
41 +       FLAG(TX_STATUS_NO_AMPDU_LEN),
42  #undef FLAG
43  };
44  
45 --- a/net/mac80211/rc80211_minstrel_ht.c
46 +++ b/net/mac80211/rc80211_minstrel_ht.c
47 @@ -294,6 +294,15 @@ minstrel_get_ratestats(struct minstrel_h
48         return &mi->groups[index / MCS_GROUP_RATES].rates[index % MCS_GROUP_RATES];
49  }
50  
51 +static unsigned int
52 +minstrel_ht_avg_ampdu_len(struct minstrel_ht_sta *mi)
53 +{
54 +       if (!mi->avg_ampdu_len)
55 +               return AVG_AMPDU_SIZE;
56 +
57 +       return MINSTREL_TRUNC(mi->avg_ampdu_len);
58 +}
59 +
60  /*
61   * Return current throughput based on the average A-MPDU length, taking into
62   * account the expected number of retransmissions and their expected length
63 @@ -309,7 +318,7 @@ minstrel_ht_get_tp_avg(struct minstrel_h
64                 return 0;
65  
66         if (group != MINSTREL_CCK_GROUP)
67 -               nsecs = 1000 * mi->overhead / MINSTREL_TRUNC(mi->avg_ampdu_len);
68 +               nsecs = 1000 * mi->overhead / minstrel_ht_avg_ampdu_len(mi);
69  
70         nsecs += minstrel_mcs_groups[group].duration[rate] <<
71                  minstrel_mcs_groups[group].shift;
72 @@ -503,8 +512,12 @@ minstrel_ht_update_stats(struct minstrel
73         u16 tmp_cck_tp_rate[MAX_THR_RATES], index;
74  
75         if (mi->ampdu_packets > 0) {
76 -               mi->avg_ampdu_len = minstrel_ewma(mi->avg_ampdu_len,
77 -                       MINSTREL_FRAC(mi->ampdu_len, mi->ampdu_packets), EWMA_LEVEL);
78 +               if (!ieee80211_hw_check(mp->hw, TX_STATUS_NO_AMPDU_LEN))
79 +                       mi->avg_ampdu_len = minstrel_ewma(mi->avg_ampdu_len,
80 +                               MINSTREL_FRAC(mi->ampdu_len, mi->ampdu_packets),
81 +                                             EWMA_LEVEL);
82 +               else
83 +                       mi->avg_ampdu_len = 0;
84                 mi->ampdu_len = 0;
85                 mi->ampdu_packets = 0;
86         }
87 @@ -709,7 +722,9 @@ minstrel_ht_tx_status(void *priv, struct
88         mi->ampdu_len += info->status.ampdu_len;
89  
90         if (!mi->sample_wait && !mi->sample_tries && mi->sample_count > 0) {
91 -               mi->sample_wait = 16 + 2 * MINSTREL_TRUNC(mi->avg_ampdu_len);
92 +               int avg_ampdu_len = minstrel_ht_avg_ampdu_len(mi);
93 +
94 +               mi->sample_wait = 16 + 2 * avg_ampdu_len;
95                 mi->sample_tries = 1;
96                 mi->sample_count--;
97         }
98 @@ -777,7 +792,7 @@ minstrel_calc_retransmit(struct minstrel
99         unsigned int cw = mp->cw_min;
100         unsigned int ctime = 0;
101         unsigned int t_slot = 9; /* FIXME */
102 -       unsigned int ampdu_len = MINSTREL_TRUNC(mi->avg_ampdu_len);
103 +       unsigned int ampdu_len = minstrel_ht_avg_ampdu_len(mi);
104         unsigned int overhead = 0, overhead_rtscts = 0;
105  
106         mrs = minstrel_get_ratestats(mi, index);
107 --- a/net/mac80211/rc80211_minstrel_ht_debugfs.c
108 +++ b/net/mac80211/rc80211_minstrel_ht_debugfs.c
109 @@ -163,9 +163,10 @@ minstrel_ht_stats_open(struct inode *ino
110                         "lookaround %d\n",
111                         max(0, (int) mi->total_packets - (int) mi->sample_packets),
112                         mi->sample_packets);
113 -       p += sprintf(p, "Average # of aggregated frames per A-MPDU: %d.%d\n",
114 -               MINSTREL_TRUNC(mi->avg_ampdu_len),
115 -               MINSTREL_TRUNC(mi->avg_ampdu_len * 10) % 10);
116 +       if (mi->avg_ampdu_len)
117 +               p += sprintf(p, "Average # of aggregated frames per A-MPDU: %d.%d\n",
118 +                       MINSTREL_TRUNC(mi->avg_ampdu_len),
119 +                       MINSTREL_TRUNC(mi->avg_ampdu_len * 10) % 10);
120         ms->len = p - ms->buf;
121         WARN_ON(ms->len + sizeof(*ms) > 32768);
122