1 From: Felix Fietkau <nbd@nbd.name>
2 Date: Mon, 20 Jun 2022 21:26:34 +0200
3 Subject: [PATCH] mac80211: add a per-PHY AQL limit to improve fairness
5 In order to maintain fairness, the amount of queueing needs to be limited
6 beyond the simple per-station AQL budget, otherwise the driver can simply
7 repeatedly do scheduling rounds until all queues that have not used their
8 AQL budget become eligble.
10 To be conservative, use the high AQL limit for the first txq and add half
11 of the low AQL for each subsequent queue.
13 Signed-off-by: Felix Fietkau <nbd@nbd.name>
16 --- a/net/mac80211/ieee80211_i.h
17 +++ b/net/mac80211/ieee80211_i.h
18 @@ -1215,6 +1215,7 @@ struct ieee80211_local {
19 u32 aql_txq_limit_high[IEEE80211_NUM_ACS];
21 atomic_t aql_total_pending_airtime;
22 + atomic_t aql_ac_pending_airtime[IEEE80211_NUM_ACS];
24 const struct ieee80211_ops *ops;
26 --- a/net/mac80211/main.c
27 +++ b/net/mac80211/main.c
28 @@ -712,6 +712,7 @@ struct ieee80211_hw *ieee80211_alloc_hw_
29 local->aql_txq_limit_low[i] = IEEE80211_DEFAULT_AQL_TXQ_LIMIT_L;
30 local->aql_txq_limit_high[i] =
31 IEEE80211_DEFAULT_AQL_TXQ_LIMIT_H;
32 + atomic_set(&local->aql_ac_pending_airtime[i], 0);
35 local->airtime_flags = AIRTIME_USE_TX | AIRTIME_USE_RX;
36 --- a/net/mac80211/sta_info.c
37 +++ b/net/mac80211/sta_info.c
38 @@ -1929,6 +1929,7 @@ void ieee80211_sta_update_pending_airtim
39 &sta->airtime[ac].aql_tx_pending);
41 atomic_add(tx_airtime, &local->aql_total_pending_airtime);
42 + atomic_add(tx_airtime, &local->aql_ac_pending_airtime[ac]);
46 @@ -1940,14 +1941,17 @@ void ieee80211_sta_update_pending_airtim
50 + atomic_sub(tx_airtime, &local->aql_total_pending_airtime);
51 tx_pending = atomic_sub_return(tx_airtime,
52 - &local->aql_total_pending_airtime);
53 + &local->aql_ac_pending_airtime[ac]);
54 if (WARN_ONCE(tx_pending < 0,
55 "Device %s AC %d pending airtime underflow: %u, %u",
56 wiphy_name(local->hw.wiphy), ac, tx_pending,
58 - atomic_cmpxchg(&local->aql_total_pending_airtime,
60 + atomic_cmpxchg(&local->aql_ac_pending_airtime[ac],
62 + atomic_sub(tx_pending, &local->aql_total_pending_airtime);
66 int sta_info_move_state(struct sta_info *sta,
67 --- a/net/mac80211/tx.c
68 +++ b/net/mac80211/tx.c
69 @@ -3863,6 +3863,9 @@ struct ieee80211_txq *ieee80211_next_txq
71 spin_lock_bh(&local->active_txq_lock[ac]);
73 + if (!local->schedule_round[ac])
77 txqi = list_first_entry_or_null(&local->active_txqs[ac],
79 @@ -3984,6 +3987,25 @@ bool ieee80211_txq_airtime_check(struct
81 EXPORT_SYMBOL(ieee80211_txq_airtime_check);
84 +ieee80211_txq_schedule_airtime_check(struct ieee80211_local *local, u8 ac)
86 + unsigned int num_txq = 0;
87 + struct txq_info *txq;
90 + if (!wiphy_ext_feature_isset(local->hw.wiphy, NL80211_EXT_FEATURE_AQL))
93 + list_for_each_entry(txq, &local->active_txqs[ac], schedule_order)
96 + aql_limit = (num_txq - 1) * local->aql_txq_limit_low[ac] / 2 +
97 + local->aql_txq_limit_high[ac];
99 + return atomic_read(&local->aql_ac_pending_airtime[ac]) < aql_limit;
102 bool ieee80211_txq_may_transmit(struct ieee80211_hw *hw,
103 struct ieee80211_txq *txq)
105 @@ -4000,6 +4022,9 @@ bool ieee80211_txq_may_transmit(struct i
106 if (list_empty(&txqi->schedule_order))
109 + if (!ieee80211_txq_schedule_airtime_check(local, ac))
112 list_for_each_entry_safe(iter, tmp, &local->active_txqs[ac],
115 @@ -4039,7 +4064,15 @@ void ieee80211_txq_schedule_start(struct
116 struct ieee80211_local *local = hw_to_local(hw);
118 spin_lock_bh(&local->active_txq_lock[ac]);
119 - local->schedule_round[ac]++;
121 + if (ieee80211_txq_schedule_airtime_check(local, ac)) {
122 + local->schedule_round[ac]++;
123 + if (!local->schedule_round[ac])
124 + local->schedule_round[ac]++;
126 + local->schedule_round[ac] = 0;
129 spin_unlock_bh(&local->active_txq_lock[ac]);
131 EXPORT_SYMBOL(ieee80211_txq_schedule_start);