OSDN Git Service

Merge tag 'wireless-drivers-2020-01-23' of git://git.kernel.org/pub/scm/linux/kernel...
[tomoyo/tomoyo-test1.git] / drivers / net / wireless / mediatek / mt76 / airtime.c
1 // SPDX-License-Identifier: ISC
2 /*
3  * Copyright (C) 2019 Felix Fietkau <nbd@nbd.name>
4  */
5
6 #include "mt76.h"
7
8 #define AVG_PKT_SIZE    1024
9
10 /* Number of bits for an average sized packet */
11 #define MCS_NBITS (AVG_PKT_SIZE << 3)
12
13 /* Number of symbols for a packet with (bps) bits per symbol */
14 #define MCS_NSYMS(bps) DIV_ROUND_UP(MCS_NBITS, (bps))
15
16 /* Transmission time (1024 usec) for a packet containing (syms) * symbols */
17 #define MCS_SYMBOL_TIME(sgi, syms)                                      \
18         (sgi ?                                                          \
19           ((syms) * 18 * 1024 + 4 * 1024) / 5 : /* syms * 3.6 us */     \
20           ((syms) * 1024) << 2                  /* syms * 4 us */       \
21         )
22
23 /* Transmit duration for the raw data part of an average sized packet */
24 #define MCS_DURATION(streams, sgi, bps) \
25         MCS_SYMBOL_TIME(sgi, MCS_NSYMS((streams) * (bps)))
26
27 #define BW_20                   0
28 #define BW_40                   1
29 #define BW_80                   2
30
31 /*
32  * Define group sort order: HT40 -> SGI -> #streams
33  */
34 #define MT_MAX_STREAMS          4
35 #define MT_HT_STREAM_GROUPS     4 /* BW(=2) * SGI(=2) */
36 #define MT_VHT_STREAM_GROUPS    6 /* BW(=3) * SGI(=2) */
37
38 #define MT_HT_GROUPS_NB (MT_MAX_STREAMS *               \
39                                  MT_HT_STREAM_GROUPS)
40 #define MT_VHT_GROUPS_NB        (MT_MAX_STREAMS *               \
41                                  MT_VHT_STREAM_GROUPS)
42 #define MT_GROUPS_NB    (MT_HT_GROUPS_NB +      \
43                                  MT_VHT_GROUPS_NB)
44
45 #define MT_HT_GROUP_0   0
46 #define MT_VHT_GROUP_0  (MT_HT_GROUP_0 + MT_HT_GROUPS_NB)
47
48 #define MCS_GROUP_RATES         10
49
50 #define HT_GROUP_IDX(_streams, _sgi, _ht40)     \
51         MT_HT_GROUP_0 +                 \
52         MT_MAX_STREAMS * 2 * _ht40 +    \
53         MT_MAX_STREAMS * _sgi + \
54         _streams - 1
55
56 #define _MAX(a, b) (((a)>(b))?(a):(b))
57
58 #define GROUP_SHIFT(duration)                                           \
59         _MAX(0, 16 - __builtin_clz(duration))
60
61 /* MCS rate information for an MCS group */
62 #define __MCS_GROUP(_streams, _sgi, _ht40, _s)                          \
63         [HT_GROUP_IDX(_streams, _sgi, _ht40)] = {                       \
64         .shift = _s,                                                    \
65         .duration = {                                                   \
66                 MCS_DURATION(_streams, _sgi, _ht40 ? 54 : 26) >> _s,    \
67                 MCS_DURATION(_streams, _sgi, _ht40 ? 108 : 52) >> _s,   \
68                 MCS_DURATION(_streams, _sgi, _ht40 ? 162 : 78) >> _s,   \
69                 MCS_DURATION(_streams, _sgi, _ht40 ? 216 : 104) >> _s,  \
70                 MCS_DURATION(_streams, _sgi, _ht40 ? 324 : 156) >> _s,  \
71                 MCS_DURATION(_streams, _sgi, _ht40 ? 432 : 208) >> _s,  \
72                 MCS_DURATION(_streams, _sgi, _ht40 ? 486 : 234) >> _s,  \
73                 MCS_DURATION(_streams, _sgi, _ht40 ? 540 : 260) >> _s   \
74         }                                                               \
75 }
76
77 #define MCS_GROUP_SHIFT(_streams, _sgi, _ht40)                          \
78         GROUP_SHIFT(MCS_DURATION(_streams, _sgi, _ht40 ? 54 : 26))
79
80 #define MCS_GROUP(_streams, _sgi, _ht40)                                \
81         __MCS_GROUP(_streams, _sgi, _ht40,                              \
82                     MCS_GROUP_SHIFT(_streams, _sgi, _ht40))
83
84 #define VHT_GROUP_IDX(_streams, _sgi, _bw)                              \
85         (MT_VHT_GROUP_0 +                                               \
86          MT_MAX_STREAMS * 2 * (_bw) +                           \
87          MT_MAX_STREAMS * (_sgi) +                              \
88          (_streams) - 1)
89
90 #define BW2VBPS(_bw, r3, r2, r1)                                        \
91         (_bw == BW_80 ? r3 : _bw == BW_40 ? r2 : r1)
92
93 #define __VHT_GROUP(_streams, _sgi, _bw, _s)                            \
94         [VHT_GROUP_IDX(_streams, _sgi, _bw)] = {                        \
95         .shift = _s,                                                    \
96         .duration = {                                                   \
97                 MCS_DURATION(_streams, _sgi,                            \
98                              BW2VBPS(_bw,  117,  54,  26)) >> _s,       \
99                 MCS_DURATION(_streams, _sgi,                            \
100                              BW2VBPS(_bw,  234, 108,  52)) >> _s,       \
101                 MCS_DURATION(_streams, _sgi,                            \
102                              BW2VBPS(_bw,  351, 162,  78)) >> _s,       \
103                 MCS_DURATION(_streams, _sgi,                            \
104                              BW2VBPS(_bw,  468, 216, 104)) >> _s,       \
105                 MCS_DURATION(_streams, _sgi,                            \
106                              BW2VBPS(_bw,  702, 324, 156)) >> _s,       \
107                 MCS_DURATION(_streams, _sgi,                            \
108                              BW2VBPS(_bw,  936, 432, 208)) >> _s,       \
109                 MCS_DURATION(_streams, _sgi,                            \
110                              BW2VBPS(_bw, 1053, 486, 234)) >> _s,       \
111                 MCS_DURATION(_streams, _sgi,                            \
112                              BW2VBPS(_bw, 1170, 540, 260)) >> _s,       \
113                 MCS_DURATION(_streams, _sgi,                            \
114                              BW2VBPS(_bw, 1404, 648, 312)) >> _s,       \
115                 MCS_DURATION(_streams, _sgi,                            \
116                              BW2VBPS(_bw, 1560, 720, 346)) >> _s        \
117         }                                                               \
118 }
119
120 #define VHT_GROUP_SHIFT(_streams, _sgi, _bw)                            \
121         GROUP_SHIFT(MCS_DURATION(_streams, _sgi,                        \
122                                  BW2VBPS(_bw,  117,  54,  26)))
123
124 #define VHT_GROUP(_streams, _sgi, _bw)                                  \
125         __VHT_GROUP(_streams, _sgi, _bw,                                \
126                     VHT_GROUP_SHIFT(_streams, _sgi, _bw))
127
128 struct mcs_group {
129         u8 shift;
130         u16 duration[MCS_GROUP_RATES];
131 };
132
133 static const struct mcs_group airtime_mcs_groups[] = {
134         MCS_GROUP(1, 0, BW_20),
135         MCS_GROUP(2, 0, BW_20),
136         MCS_GROUP(3, 0, BW_20),
137         MCS_GROUP(4, 0, BW_20),
138
139         MCS_GROUP(1, 1, BW_20),
140         MCS_GROUP(2, 1, BW_20),
141         MCS_GROUP(3, 1, BW_20),
142         MCS_GROUP(4, 1, BW_20),
143
144         MCS_GROUP(1, 0, BW_40),
145         MCS_GROUP(2, 0, BW_40),
146         MCS_GROUP(3, 0, BW_40),
147         MCS_GROUP(4, 0, BW_40),
148
149         MCS_GROUP(1, 1, BW_40),
150         MCS_GROUP(2, 1, BW_40),
151         MCS_GROUP(3, 1, BW_40),
152         MCS_GROUP(4, 1, BW_40),
153
154         VHT_GROUP(1, 0, BW_20),
155         VHT_GROUP(2, 0, BW_20),
156         VHT_GROUP(3, 0, BW_20),
157         VHT_GROUP(4, 0, BW_20),
158
159         VHT_GROUP(1, 1, BW_20),
160         VHT_GROUP(2, 1, BW_20),
161         VHT_GROUP(3, 1, BW_20),
162         VHT_GROUP(4, 1, BW_20),
163
164         VHT_GROUP(1, 0, BW_40),
165         VHT_GROUP(2, 0, BW_40),
166         VHT_GROUP(3, 0, BW_40),
167         VHT_GROUP(4, 0, BW_40),
168
169         VHT_GROUP(1, 1, BW_40),
170         VHT_GROUP(2, 1, BW_40),
171         VHT_GROUP(3, 1, BW_40),
172         VHT_GROUP(4, 1, BW_40),
173
174         VHT_GROUP(1, 0, BW_80),
175         VHT_GROUP(2, 0, BW_80),
176         VHT_GROUP(3, 0, BW_80),
177         VHT_GROUP(4, 0, BW_80),
178
179         VHT_GROUP(1, 1, BW_80),
180         VHT_GROUP(2, 1, BW_80),
181         VHT_GROUP(3, 1, BW_80),
182         VHT_GROUP(4, 1, BW_80),
183 };
184
185 static u32
186 mt76_calc_legacy_rate_duration(const struct ieee80211_rate *rate, bool short_pre,
187                                int len)
188 {
189         u32 duration;
190
191         switch (rate->hw_value >> 8) {
192         case MT_PHY_TYPE_CCK:
193                 duration = 144 + 48; /* preamble + PLCP */
194                 if (short_pre)
195                         duration >>= 1;
196
197                 duration += 10; /* SIFS */
198                 break;
199         case MT_PHY_TYPE_OFDM:
200                 duration = 20 + 16; /* premable + SIFS */
201                 break;
202         default:
203                 WARN_ON_ONCE(1);
204                 return 0;
205         }
206
207         len <<= 3;
208         duration += (len * 10) / rate->bitrate;
209
210         return duration;
211 }
212
213 u32 mt76_calc_rx_airtime(struct mt76_dev *dev, struct mt76_rx_status *status,
214                          int len)
215 {
216         struct ieee80211_supported_band *sband;
217         const struct ieee80211_rate *rate;
218         bool sgi = status->enc_flags & RX_ENC_FLAG_SHORT_GI;
219         bool sp = status->enc_flags & RX_ENC_FLAG_SHORTPRE;
220         int bw, streams;
221         u32 duration;
222         int group, idx;
223
224         switch (status->bw) {
225         case RATE_INFO_BW_20:
226                 bw = BW_20;
227                 break;
228         case RATE_INFO_BW_40:
229                 bw = BW_40;
230                 break;
231         case RATE_INFO_BW_80:
232                 bw = BW_80;
233                 break;
234         default:
235                 WARN_ON_ONCE(1);
236                 return 0;
237         }
238
239         switch (status->encoding) {
240         case RX_ENC_LEGACY:
241                 if (WARN_ON_ONCE(status->band > NL80211_BAND_5GHZ))
242                         return 0;
243
244                 sband = dev->hw->wiphy->bands[status->band];
245                 if (!sband || status->rate_idx >= sband->n_bitrates)
246                         return 0;
247
248                 rate = &sband->bitrates[status->rate_idx];
249
250                 return mt76_calc_legacy_rate_duration(rate, sp, len);
251         case RX_ENC_VHT:
252                 streams = status->nss;
253                 idx = status->rate_idx;
254                 group = VHT_GROUP_IDX(streams, sgi, bw);
255                 break;
256         case RX_ENC_HT:
257                 streams = ((status->rate_idx >> 3) & 3) + 1;
258                 idx = status->rate_idx & 7;
259                 group = HT_GROUP_IDX(streams, sgi, bw);
260                 break;
261         default:
262                 WARN_ON_ONCE(1);
263                 return 0;
264         }
265
266         if (WARN_ON_ONCE(streams > 4))
267                 return 0;
268
269         duration = airtime_mcs_groups[group].duration[idx];
270         duration <<= airtime_mcs_groups[group].shift;
271         duration *= len;
272         duration /= AVG_PKT_SIZE;
273         duration /= 1024;
274
275         duration += 36 + (streams << 2);
276
277         return duration;
278 }
279
280 u32 mt76_calc_tx_airtime(struct mt76_dev *dev, struct ieee80211_tx_info *info,
281                          int len)
282 {
283         struct mt76_rx_status stat = {
284                 .band = info->band,
285         };
286         u32 duration = 0;
287         int i;
288
289         for (i = 0; i < ARRAY_SIZE(info->status.rates); i++) {
290                 struct ieee80211_tx_rate *rate = &info->status.rates[i];
291                 u32 cur_duration;
292
293                 if (rate->idx < 0 || !rate->count)
294                         break;
295
296                 if (rate->flags & IEEE80211_TX_RC_80_MHZ_WIDTH)
297                         stat.bw = RATE_INFO_BW_80;
298                 else if (rate->flags & IEEE80211_TX_RC_40_MHZ_WIDTH)
299                         stat.bw = RATE_INFO_BW_40;
300                 else
301                         stat.bw = RATE_INFO_BW_20;
302
303                 stat.enc_flags = 0;
304                 if (rate->flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE)
305                         stat.enc_flags |= RX_ENC_FLAG_SHORTPRE;
306                 if (rate->flags & IEEE80211_TX_RC_SHORT_GI)
307                         stat.enc_flags |= RX_ENC_FLAG_SHORT_GI;
308
309                 stat.rate_idx = rate->idx;
310                 if (rate->flags & IEEE80211_TX_RC_VHT_MCS) {
311                         stat.encoding = RX_ENC_VHT;
312                         stat.rate_idx = ieee80211_rate_get_vht_mcs(rate);
313                         stat.nss = ieee80211_rate_get_vht_nss(rate);
314                 } else if (rate->flags & IEEE80211_TX_RC_MCS) {
315                         stat.encoding = RX_ENC_HT;
316                 } else {
317                         stat.encoding = RX_ENC_LEGACY;
318                 }
319
320                 cur_duration = mt76_calc_rx_airtime(dev, &stat, len);
321                 duration += cur_duration * rate->count;
322         }
323
324         return duration;
325 }
326 EXPORT_SYMBOL_GPL(mt76_calc_tx_airtime);