mac80211: Update to version 5.4.36-1
[oweals/openwrt.git] / package / kernel / mac80211 / patches / subsys / 310-mac80211-Implement-Airtime-based-Queue-Limit-AQL.patch
1 From: Kan Yan <kyan@google.com>
2 Date: Mon, 18 Nov 2019 22:06:09 -0800
3 Subject: [PATCH] mac80211: Implement Airtime-based Queue Limit (AQL)
4 MIME-Version: 1.0
5 Content-Type: text/plain; charset=UTF-8
6 Content-Transfer-Encoding: 8bit
7
8 In order for the Fq_CoDel algorithm integrated in mac80211 layer to operate
9 effectively to control excessive queueing latency, the CoDel algorithm
10 requires an accurate measure of how long packets stays in the queue, AKA
11 sojourn time. The sojourn time measured at the mac80211 layer doesn't
12 include queueing latency in the lower layer (firmware/hardware) and CoDel
13 expects lower layer to have a short queue. However, most 802.11ac chipsets
14 offload tasks such TX aggregation to firmware or hardware, thus have a deep
15 lower layer queue.
16
17 Without a mechanism to control the lower layer queue size, packets only
18 stay in mac80211 layer transiently before being sent to firmware queue.
19 As a result, the sojourn time measured by CoDel in the mac80211 layer is
20 almost always lower than the CoDel latency target, hence CoDel does little
21 to control the latency, even when the lower layer queue causes excessive
22 latency.
23
24 The Byte Queue Limits (BQL) mechanism is commonly used to address the
25 similar issue with wired network interface. However, this method cannot be
26 applied directly to the wireless network interface. "Bytes" is not a
27 suitable measure of queue depth in the wireless network, as the data rate
28 can vary dramatically from station to station in the same network, from a
29 few Mbps to over Gbps.
30
31 This patch implements an Airtime-based Queue Limit (AQL) to make CoDel work
32 effectively with wireless drivers that utilized firmware/hardware
33 offloading. AQL allows each txq to release just enough packets to the lower
34 layer to form 1-2 large aggregations to keep hardware fully utilized and
35 retains the rest of the frames in mac80211 layer to be controlled by the
36 CoDel algorithm.
37
38 Signed-off-by: Kan Yan <kyan@google.com>
39 [ Toke: Keep API to set pending airtime internal, fix nits in commit msg ]
40 Signed-off-by: Toke Høiland-Jørgensen <toke@redhat.com>
41 Link: https://lore.kernel.org/r/20191119060610.76681-4-kyan@google.com
42 Signed-off-by: Johannes Berg <johannes.berg@intel.com>
43 ---
44
45 --- a/include/net/cfg80211.h
46 +++ b/include/net/cfg80211.h
47 @@ -2603,6 +2603,13 @@ enum wiphy_params_flags {
48  
49  #define IEEE80211_DEFAULT_AIRTIME_WEIGHT       256
50  
51 +/* The per TXQ device queue limit in airtime */
52 +#define IEEE80211_DEFAULT_AQL_TXQ_LIMIT_L      5000
53 +#define IEEE80211_DEFAULT_AQL_TXQ_LIMIT_H      12000
54 +
55 +/* The per interface airtime threshold to switch to lower queue limit */
56 +#define IEEE80211_AQL_THRESHOLD                        24000
57 +
58  /**
59   * struct cfg80211_pmksa - PMK Security Association
60   *
61 --- a/include/net/mac80211.h
62 +++ b/include/net/mac80211.h
63 @@ -5559,6 +5559,18 @@ void ieee80211_sta_register_airtime(stru
64                                     u32 tx_airtime, u32 rx_airtime);
65  
66  /**
67 + * ieee80211_txq_airtime_check - check if a txq can send frame to device
68 + *
69 + * @hw: pointer obtained from ieee80211_alloc_hw()
70 + * @txq: pointer obtained from station or virtual interface
71 + *
72 + * Return true if the AQL's airtime limit has not been reached and the txq can
73 + * continue to send more packets to the device. Otherwise return false.
74 + */
75 +bool
76 +ieee80211_txq_airtime_check(struct ieee80211_hw *hw, struct ieee80211_txq *txq);
77 +
78 +/**
79   * ieee80211_iter_keys - iterate keys programmed into the device
80   * @hw: pointer obtained from ieee80211_alloc_hw()
81   * @vif: virtual interface to iterate, may be %NULL for all
82 --- a/net/mac80211/debugfs.c
83 +++ b/net/mac80211/debugfs.c
84 @@ -148,6 +148,87 @@ static const struct file_operations aqm_
85         .llseek = default_llseek,
86  };
87  
88 +static ssize_t aql_txq_limit_read(struct file *file,
89 +                                 char __user *user_buf,
90 +                                 size_t count,
91 +                                 loff_t *ppos)
92 +{
93 +       struct ieee80211_local *local = file->private_data;
94 +       char buf[400];
95 +       int len = 0;
96 +
97 +       len = scnprintf(buf, sizeof(buf),
98 +                       "AC     AQL limit low   AQL limit high\n"
99 +                       "VO     %u              %u\n"
100 +                       "VI     %u              %u\n"
101 +                       "BE     %u              %u\n"
102 +                       "BK     %u              %u\n",
103 +                       local->aql_txq_limit_low[IEEE80211_AC_VO],
104 +                       local->aql_txq_limit_high[IEEE80211_AC_VO],
105 +                       local->aql_txq_limit_low[IEEE80211_AC_VI],
106 +                       local->aql_txq_limit_high[IEEE80211_AC_VI],
107 +                       local->aql_txq_limit_low[IEEE80211_AC_BE],
108 +                       local->aql_txq_limit_high[IEEE80211_AC_BE],
109 +                       local->aql_txq_limit_low[IEEE80211_AC_BK],
110 +                       local->aql_txq_limit_high[IEEE80211_AC_BK]);
111 +       return simple_read_from_buffer(user_buf, count, ppos,
112 +                                      buf, len);
113 +}
114 +
115 +static ssize_t aql_txq_limit_write(struct file *file,
116 +                                  const char __user *user_buf,
117 +                                  size_t count,
118 +                                  loff_t *ppos)
119 +{
120 +       struct ieee80211_local *local = file->private_data;
121 +       char buf[100];
122 +       size_t len;
123 +       u32 ac, q_limit_low, q_limit_high, q_limit_low_old, q_limit_high_old;
124 +       struct sta_info *sta;
125 +
126 +       if (count > sizeof(buf))
127 +               return -EINVAL;
128 +
129 +       if (copy_from_user(buf, user_buf, count))
130 +               return -EFAULT;
131 +
132 +       buf[sizeof(buf) - 1] = 0;
133 +       len = strlen(buf);
134 +       if (len > 0 && buf[len - 1] == '\n')
135 +               buf[len - 1] = 0;
136 +
137 +       if (sscanf(buf, "%u %u %u", &ac, &q_limit_low, &q_limit_high) != 3)
138 +               return -EINVAL;
139 +
140 +       if (ac >= IEEE80211_NUM_ACS)
141 +               return -EINVAL;
142 +
143 +       q_limit_low_old = local->aql_txq_limit_low[ac];
144 +       q_limit_high_old = local->aql_txq_limit_high[ac];
145 +
146 +       local->aql_txq_limit_low[ac] = q_limit_low;
147 +       local->aql_txq_limit_high[ac] = q_limit_high;
148 +
149 +       mutex_lock(&local->sta_mtx);
150 +       list_for_each_entry(sta, &local->sta_list, list) {
151 +               /* If a sta has customized queue limits, keep it */
152 +               if (sta->airtime[ac].aql_limit_low == q_limit_low_old &&
153 +                   sta->airtime[ac].aql_limit_high == q_limit_high_old) {
154 +                       sta->airtime[ac].aql_limit_low = q_limit_low;
155 +                       sta->airtime[ac].aql_limit_high = q_limit_high;
156 +               }
157 +       }
158 +       mutex_unlock(&local->sta_mtx);
159 +       return count;
160 +}
161 +
162 +static const struct file_operations aql_txq_limit_ops = {
163 +       .write = aql_txq_limit_write,
164 +       .read = aql_txq_limit_read,
165 +       .open = simple_open,
166 +       .llseek = default_llseek,
167 +};
168 +
169  static ssize_t force_tx_status_read(struct file *file,
170                                     char __user *user_buf,
171                                     size_t count,
172 @@ -441,6 +522,10 @@ void debugfs_hw_add(struct ieee80211_loc
173         debugfs_create_u16("airtime_flags", 0600,
174                            phyd, &local->airtime_flags);
175  
176 +       DEBUGFS_ADD(aql_txq_limit);
177 +       debugfs_create_u32("aql_threshold", 0600,
178 +                          phyd, &local->aql_threshold);
179 +
180         statsd = debugfs_create_dir("statistics", phyd);
181  
182         /* if the dir failed, don't put all the other things into the root! */
183 --- a/net/mac80211/debugfs_sta.c
184 +++ b/net/mac80211/debugfs_sta.c
185 @@ -198,10 +198,12 @@ static ssize_t sta_airtime_read(struct f
186  {
187         struct sta_info *sta = file->private_data;
188         struct ieee80211_local *local = sta->sdata->local;
189 -       size_t bufsz = 200;
190 +       size_t bufsz = 400;
191         char *buf = kzalloc(bufsz, GFP_KERNEL), *p = buf;
192         u64 rx_airtime = 0, tx_airtime = 0;
193         s64 deficit[IEEE80211_NUM_ACS];
194 +       u32 q_depth[IEEE80211_NUM_ACS];
195 +       u32 q_limit_l[IEEE80211_NUM_ACS], q_limit_h[IEEE80211_NUM_ACS];
196         ssize_t rv;
197         int ac;
198  
199 @@ -213,19 +215,22 @@ static ssize_t sta_airtime_read(struct f
200                 rx_airtime += sta->airtime[ac].rx_airtime;
201                 tx_airtime += sta->airtime[ac].tx_airtime;
202                 deficit[ac] = sta->airtime[ac].deficit;
203 +               q_limit_l[ac] = sta->airtime[ac].aql_limit_low;
204 +               q_limit_h[ac] = sta->airtime[ac].aql_limit_high;
205                 spin_unlock_bh(&local->active_txq_lock[ac]);
206 +               q_depth[ac] = atomic_read(&sta->airtime[ac].aql_tx_pending);
207         }
208  
209         p += scnprintf(p, bufsz + buf - p,
210                 "RX: %llu us\nTX: %llu us\nWeight: %u\n"
211 -               "Deficit: VO: %lld us VI: %lld us BE: %lld us BK: %lld us\n",
212 -               rx_airtime,
213 -               tx_airtime,
214 -               sta->airtime_weight,
215 -               deficit[0],
216 -               deficit[1],
217 -               deficit[2],
218 -               deficit[3]);
219 +               "Deficit: VO: %lld us VI: %lld us BE: %lld us BK: %lld us\n"
220 +               "Q depth: VO: %u us VI: %u us BE: %u us BK: %u us\n"
221 +               "Q limit[low/high]: VO: %u/%u VI: %u/%u BE: %u/%u BK: %u/%u\n",
222 +               rx_airtime, tx_airtime, sta->airtime_weight,
223 +               deficit[0], deficit[1], deficit[2], deficit[3],
224 +               q_depth[0], q_depth[1], q_depth[2], q_depth[3],
225 +               q_limit_l[0], q_limit_h[0], q_limit_l[1], q_limit_h[1],
226 +               q_limit_l[2], q_limit_h[2], q_limit_l[3], q_limit_h[3]),
227  
228         rv = simple_read_from_buffer(userbuf, count, ppos, buf, p - buf);
229         kfree(buf);
230 @@ -237,7 +242,25 @@ static ssize_t sta_airtime_write(struct
231  {
232         struct sta_info *sta = file->private_data;
233         struct ieee80211_local *local = sta->sdata->local;
234 -       int ac;
235 +       u32 ac, q_limit_l, q_limit_h;
236 +       char _buf[100] = {}, *buf = _buf;
237 +
238 +       if (count > sizeof(_buf))
239 +               return -EINVAL;
240 +
241 +       if (copy_from_user(buf, userbuf, count))
242 +               return -EFAULT;
243 +
244 +       buf[sizeof(_buf) - 1] = '\0';
245 +       if (sscanf(buf, "queue limit %u %u %u", &ac, &q_limit_l, &q_limit_h)
246 +           != 3)
247 +               return -EINVAL;
248 +
249 +       if (ac >= IEEE80211_NUM_ACS)
250 +               return -EINVAL;
251 +
252 +       sta->airtime[ac].aql_limit_low = q_limit_l;
253 +       sta->airtime[ac].aql_limit_high = q_limit_h;
254  
255         for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) {
256                 spin_lock_bh(&local->active_txq_lock[ac]);
257 --- a/net/mac80211/ieee80211_i.h
258 +++ b/net/mac80211/ieee80211_i.h
259 @@ -1142,6 +1142,10 @@ struct ieee80211_local {
260         u16 schedule_round[IEEE80211_NUM_ACS];
261  
262         u16 airtime_flags;
263 +       u32 aql_txq_limit_low[IEEE80211_NUM_ACS];
264 +       u32 aql_txq_limit_high[IEEE80211_NUM_ACS];
265 +       u32 aql_threshold;
266 +       atomic_t aql_total_pending_airtime;
267  
268         const struct ieee80211_ops *ops;
269  
270 --- a/net/mac80211/main.c
271 +++ b/net/mac80211/main.c
272 @@ -669,8 +669,16 @@ struct ieee80211_hw *ieee80211_alloc_hw_
273         for (i = 0; i < IEEE80211_NUM_ACS; i++) {
274                 INIT_LIST_HEAD(&local->active_txqs[i]);
275                 spin_lock_init(&local->active_txq_lock[i]);
276 +               local->aql_txq_limit_low[i] = IEEE80211_DEFAULT_AQL_TXQ_LIMIT_L;
277 +               local->aql_txq_limit_high[i] =
278 +                       IEEE80211_DEFAULT_AQL_TXQ_LIMIT_H;
279         }
280 -       local->airtime_flags = AIRTIME_USE_TX | AIRTIME_USE_RX;
281 +
282 +       local->airtime_flags = AIRTIME_USE_TX |
283 +                              AIRTIME_USE_RX |
284 +                              AIRTIME_USE_AQL;
285 +       local->aql_threshold = IEEE80211_AQL_THRESHOLD;
286 +       atomic_set(&local->aql_total_pending_airtime, 0);
287  
288         INIT_LIST_HEAD(&local->chanctx_list);
289         mutex_init(&local->chanctx_mtx);
290 --- a/net/mac80211/sta_info.c
291 +++ b/net/mac80211/sta_info.c
292 @@ -411,6 +411,9 @@ struct sta_info *sta_info_alloc(struct i
293                 skb_queue_head_init(&sta->ps_tx_buf[i]);
294                 skb_queue_head_init(&sta->tx_filtered[i]);
295                 sta->airtime[i].deficit = sta->airtime_weight;
296 +               atomic_set(&sta->airtime[i].aql_tx_pending, 0);
297 +               sta->airtime[i].aql_limit_low = local->aql_txq_limit_low[i];
298 +               sta->airtime[i].aql_limit_high = local->aql_txq_limit_high[i];
299         }
300  
301         for (i = 0; i < IEEE80211_NUM_TIDS; i++)
302 @@ -1913,6 +1916,41 @@ void ieee80211_sta_register_airtime(stru
303  }
304  EXPORT_SYMBOL(ieee80211_sta_register_airtime);
305  
306 +void ieee80211_sta_update_pending_airtime(struct ieee80211_local *local,
307 +                                         struct sta_info *sta, u8 ac,
308 +                                         u16 tx_airtime, bool tx_completed)
309 +{
310 +       int tx_pending;
311 +
312 +       if (!tx_completed) {
313 +               if (sta)
314 +                       atomic_add(tx_airtime,
315 +                                  &sta->airtime[ac].aql_tx_pending);
316 +
317 +               atomic_add(tx_airtime, &local->aql_total_pending_airtime);
318 +               return;
319 +       }
320 +
321 +       if (sta) {
322 +               tx_pending = atomic_sub_return(tx_airtime,
323 +                                              &sta->airtime[ac].aql_tx_pending);
324 +               if (WARN_ONCE(tx_pending < 0,
325 +                             "STA %pM AC %d txq pending airtime underflow: %u, %u",
326 +                             sta->addr, ac, tx_pending, tx_airtime))
327 +                       atomic_cmpxchg(&sta->airtime[ac].aql_tx_pending,
328 +                                      tx_pending, 0);
329 +       }
330 +
331 +       tx_pending = atomic_sub_return(tx_airtime,
332 +                                      &local->aql_total_pending_airtime);
333 +       if (WARN_ONCE(tx_pending < 0,
334 +                     "Device %s AC %d pending airtime underflow: %u, %u",
335 +                     wiphy_name(local->hw.wiphy), ac, tx_pending,
336 +                     tx_airtime))
337 +               atomic_cmpxchg(&local->aql_total_pending_airtime,
338 +                              tx_pending, 0);
339 +}
340 +
341  int sta_info_move_state(struct sta_info *sta,
342                         enum ieee80211_sta_state new_state)
343  {
344 --- a/net/mac80211/sta_info.h
345 +++ b/net/mac80211/sta_info.h
346 @@ -128,13 +128,21 @@ enum ieee80211_agg_stop_reason {
347  /* Debugfs flags to enable/disable use of RX/TX airtime in scheduler */
348  #define AIRTIME_USE_TX         BIT(0)
349  #define AIRTIME_USE_RX         BIT(1)
350 +#define AIRTIME_USE_AQL                BIT(2)
351  
352  struct airtime_info {
353         u64 rx_airtime;
354         u64 tx_airtime;
355         s64 deficit;
356 +       atomic_t aql_tx_pending; /* Estimated airtime for frames pending */
357 +       u32 aql_limit_low;
358 +       u32 aql_limit_high;
359  };
360  
361 +void ieee80211_sta_update_pending_airtime(struct ieee80211_local *local,
362 +                                         struct sta_info *sta, u8 ac,
363 +                                         u16 tx_airtime, bool tx_completed);
364 +
365  struct sta_info;
366  
367  /**
368 --- a/net/mac80211/tx.c
369 +++ b/net/mac80211/tx.c
370 @@ -3700,7 +3700,8 @@ struct ieee80211_txq *ieee80211_next_txq
371  {
372         struct ieee80211_local *local = hw_to_local(hw);
373         struct ieee80211_txq *ret = NULL;
374 -       struct txq_info *txqi = NULL;
375 +       struct txq_info *txqi = NULL, *head = NULL;
376 +       bool found_eligible_txq = false;
377  
378         spin_lock_bh(&local->active_txq_lock[ac]);
379  
380 @@ -3711,13 +3712,30 @@ struct ieee80211_txq *ieee80211_next_txq
381         if (!txqi)
382                 goto out;
383  
384 +       if (txqi == head) {
385 +               if (!found_eligible_txq)
386 +                       goto out;
387 +               else
388 +                       found_eligible_txq = false;
389 +       }
390 +
391 +       if (!head)
392 +               head = txqi;
393 +
394         if (txqi->txq.sta) {
395                 struct sta_info *sta = container_of(txqi->txq.sta,
396 -                                               struct sta_info, sta);
397 +                                                   struct sta_info, sta);
398 +               bool aql_check = ieee80211_txq_airtime_check(hw, &txqi->txq);
399 +               s64 deficit = sta->airtime[txqi->txq.ac].deficit;
400  
401 -               if (sta->airtime[txqi->txq.ac].deficit < 0) {
402 +               if (aql_check)
403 +                       found_eligible_txq = true;
404 +
405 +               if (deficit < 0)
406                         sta->airtime[txqi->txq.ac].deficit +=
407                                 sta->airtime_weight;
408 +
409 +               if (deficit < 0 || !aql_check) {
410                         list_move_tail(&txqi->schedule_order,
411                                        &local->active_txqs[txqi->txq.ac]);
412                         goto begin;
413 @@ -3771,6 +3789,33 @@ void __ieee80211_schedule_txq(struct iee
414  }
415  EXPORT_SYMBOL(__ieee80211_schedule_txq);
416  
417 +bool ieee80211_txq_airtime_check(struct ieee80211_hw *hw,
418 +                                struct ieee80211_txq *txq)
419 +{
420 +       struct sta_info *sta;
421 +       struct ieee80211_local *local = hw_to_local(hw);
422 +
423 +       if (!(local->airtime_flags & AIRTIME_USE_AQL))
424 +               return true;
425 +
426 +       if (!txq->sta)
427 +               return true;
428 +
429 +       sta = container_of(txq->sta, struct sta_info, sta);
430 +       if (atomic_read(&sta->airtime[txq->ac].aql_tx_pending) <
431 +           sta->airtime[txq->ac].aql_limit_low)
432 +               return true;
433 +
434 +       if (atomic_read(&local->aql_total_pending_airtime) <
435 +           local->aql_threshold &&
436 +           atomic_read(&sta->airtime[txq->ac].aql_tx_pending) <
437 +           sta->airtime[txq->ac].aql_limit_high)
438 +               return true;
439 +
440 +       return false;
441 +}
442 +EXPORT_SYMBOL(ieee80211_txq_airtime_check);
443 +
444  bool ieee80211_txq_may_transmit(struct ieee80211_hw *hw,
445                                 struct ieee80211_txq *txq)
446  {