2b9ff93db676c63c5380041f5fa16785a6a9e258
[openwrt/staging/blocktrron.git] /
1 From: Felix Fietkau <nbd@nbd.name>
2 Date: Wed, 16 Jan 2019 21:47:54 +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 ---
13
14 --- a/include/net/mac80211.h
15 +++ b/include/net/mac80211.h
16 @@ -2130,6 +2130,9 @@ struct ieee80211_txq {
17 * @IEEE80211_HW_NEEDS_ALIGNED4_SKBS: Driver need aligned skbs to four-byte.
18 * Padding will be added after ieee80211_hdr, before IV/LLC.
19 *
20 + * @IEEE80211_HW_TX_STATUS_NO_AMPDU_LEN: Driver does not report accurate A-MPDU
21 + * length in tx status information
22 + *
23 * @NUM_IEEE80211_HW_FLAGS: number of hardware flags, used for sizing arrays
24 */
25 enum ieee80211_hw_flags {
26 @@ -2176,6 +2179,7 @@ enum ieee80211_hw_flags {
27 IEEE80211_HW_DEAUTH_NEED_MGD_TX_PREP,
28 IEEE80211_HW_DOESNT_SUPPORT_QOS_NDP,
29 IEEE80211_HW_NEEDS_ALIGNED4_SKBS,
30 + IEEE80211_HW_TX_STATUS_NO_AMPDU_LEN,
31
32 /* keep last, obviously */
33 NUM_IEEE80211_HW_FLAGS
34 --- a/net/mac80211/debugfs.c
35 +++ b/net/mac80211/debugfs.c
36 @@ -215,6 +215,7 @@ static const char *hw_flag_names[] = {
37 FLAG(DEAUTH_NEED_MGD_TX_PREP),
38 FLAG(DOESNT_SUPPORT_QOS_NDP),
39 FLAG(NEEDS_ALIGNED4_SKBS),
40 + FLAG(TX_STATUS_NO_AMPDU_LEN),
41 #undef FLAG
42 };
43
44 --- a/net/mac80211/rc80211_minstrel_ht.c
45 +++ b/net/mac80211/rc80211_minstrel_ht.c
46 @@ -294,6 +294,15 @@ minstrel_get_ratestats(struct minstrel_h
47 return &mi->groups[index / MCS_GROUP_RATES].rates[index % MCS_GROUP_RATES];
48 }
49
50 +static unsigned int
51 +minstrel_ht_avg_ampdu_len(struct minstrel_ht_sta *mi)
52 +{
53 + if (!mi->avg_ampdu_len)
54 + return AVG_AMPDU_SIZE;
55 +
56 + return MINSTREL_TRUNC(mi->avg_ampdu_len);
57 +}
58 +
59 /*
60 * Return current throughput based on the average A-MPDU length, taking into
61 * account the expected number of retransmissions and their expected length
62 @@ -309,7 +318,7 @@ minstrel_ht_get_tp_avg(struct minstrel_h
63 return 0;
64
65 if (group != MINSTREL_CCK_GROUP)
66 - nsecs = 1000 * mi->overhead / MINSTREL_TRUNC(mi->avg_ampdu_len);
67 + nsecs = 1000 * mi->overhead / minstrel_ht_avg_ampdu_len(mi);
68
69 nsecs += minstrel_mcs_groups[group].duration[rate] <<
70 minstrel_mcs_groups[group].shift;
71 @@ -503,8 +512,12 @@ minstrel_ht_update_stats(struct minstrel
72 u16 tmp_cck_tp_rate[MAX_THR_RATES], index;
73
74 if (mi->ampdu_packets > 0) {
75 - mi->avg_ampdu_len = minstrel_ewma(mi->avg_ampdu_len,
76 - MINSTREL_FRAC(mi->ampdu_len, mi->ampdu_packets), EWMA_LEVEL);
77 + if (!ieee80211_hw_check(mp->hw, TX_STATUS_NO_AMPDU_LEN))
78 + mi->avg_ampdu_len = minstrel_ewma(mi->avg_ampdu_len,
79 + MINSTREL_FRAC(mi->ampdu_len, mi->ampdu_packets),
80 + EWMA_LEVEL);
81 + else
82 + mi->avg_ampdu_len = 0;
83 mi->ampdu_len = 0;
84 mi->ampdu_packets = 0;
85 }
86 @@ -709,7 +722,9 @@ minstrel_ht_tx_status(void *priv, struct
87 mi->ampdu_len += info->status.ampdu_len;
88
89 if (!mi->sample_wait && !mi->sample_tries && mi->sample_count > 0) {
90 - mi->sample_wait = 16 + 2 * MINSTREL_TRUNC(mi->avg_ampdu_len);
91 + int avg_ampdu_len = minstrel_ht_avg_ampdu_len(mi);
92 +
93 + mi->sample_wait = 16 + 2 * avg_ampdu_len;
94 mi->sample_tries = 1;
95 mi->sample_count--;
96 }
97 @@ -777,7 +792,7 @@ minstrel_calc_retransmit(struct minstrel
98 unsigned int cw = mp->cw_min;
99 unsigned int ctime = 0;
100 unsigned int t_slot = 9; /* FIXME */
101 - unsigned int ampdu_len = MINSTREL_TRUNC(mi->avg_ampdu_len);
102 + unsigned int ampdu_len = minstrel_ht_avg_ampdu_len(mi);
103 unsigned int overhead = 0, overhead_rtscts = 0;
104
105 mrs = minstrel_get_ratestats(mi, index);
106 --- a/net/mac80211/rc80211_minstrel_ht_debugfs.c
107 +++ b/net/mac80211/rc80211_minstrel_ht_debugfs.c
108 @@ -163,9 +163,10 @@ minstrel_ht_stats_open(struct inode *ino
109 "lookaround %d\n",
110 max(0, (int) mi->total_packets - (int) mi->sample_packets),
111 mi->sample_packets);
112 - p += sprintf(p, "Average # of aggregated frames per A-MPDU: %d.%d\n",
113 - MINSTREL_TRUNC(mi->avg_ampdu_len),
114 - MINSTREL_TRUNC(mi->avg_ampdu_len * 10) % 10);
115 + if (mi->avg_ampdu_len)
116 + p += sprintf(p, "Average # of aggregated frames per A-MPDU: %d.%d\n",
117 + MINSTREL_TRUNC(mi->avg_ampdu_len),
118 + MINSTREL_TRUNC(mi->avg_ampdu_len * 10) % 10);
119 ms->len = p - ms->buf;
120 WARN_ON(ms->len + sizeof(*ms) > 32768);
121