aboutsummaryrefslogtreecommitdiffstats
path: root/package/kernel/mac80211/patches/subsys/334-mac80211-add-a-per-PHY-AQL-limit-to-improve-fairness.patch
diff options
context:
space:
mode:
Diffstat (limited to 'package/kernel/mac80211/patches/subsys/334-mac80211-add-a-per-PHY-AQL-limit-to-improve-fairness.patch')
-rw-r--r--package/kernel/mac80211/patches/subsys/334-mac80211-add-a-per-PHY-AQL-limit-to-improve-fairness.patch131
1 files changed, 131 insertions, 0 deletions
diff --git a/package/kernel/mac80211/patches/subsys/334-mac80211-add-a-per-PHY-AQL-limit-to-improve-fairness.patch b/package/kernel/mac80211/patches/subsys/334-mac80211-add-a-per-PHY-AQL-limit-to-improve-fairness.patch
new file mode 100644
index 0000000000..89718a8273
--- /dev/null
+++ b/package/kernel/mac80211/patches/subsys/334-mac80211-add-a-per-PHY-AQL-limit-to-improve-fairness.patch
@@ -0,0 +1,131 @@
+From: Felix Fietkau <nbd@nbd.name>
+Date: Mon, 20 Jun 2022 21:26:34 +0200
+Subject: [PATCH] mac80211: add a per-PHY AQL limit to improve fairness
+
+In order to maintain fairness, the amount of queueing needs to be limited
+beyond the simple per-station AQL budget, otherwise the driver can simply
+repeatedly do scheduling rounds until all queues that have not used their
+AQL budget become eligble.
+
+To be conservative, use the high AQL limit for the first txq and add half
+of the low AQL for each subsequent queue.
+
+Signed-off-by: Felix Fietkau <nbd@nbd.name>
+---
+
+--- a/net/mac80211/ieee80211_i.h
++++ b/net/mac80211/ieee80211_i.h
+@@ -1211,6 +1211,7 @@ struct ieee80211_local {
+ u32 aql_txq_limit_high[IEEE80211_NUM_ACS];
+ u32 aql_threshold;
+ atomic_t aql_total_pending_airtime;
++ atomic_t aql_ac_pending_airtime[IEEE80211_NUM_ACS];
+
+ const struct ieee80211_ops *ops;
+
+--- a/net/mac80211/main.c
++++ b/net/mac80211/main.c
+@@ -712,6 +712,7 @@ struct ieee80211_hw *ieee80211_alloc_hw_
+ local->aql_txq_limit_low[i] = IEEE80211_DEFAULT_AQL_TXQ_LIMIT_L;
+ local->aql_txq_limit_high[i] =
+ IEEE80211_DEFAULT_AQL_TXQ_LIMIT_H;
++ atomic_set(&local->aql_ac_pending_airtime[i], 0);
+ }
+
+ local->airtime_flags = AIRTIME_USE_TX | AIRTIME_USE_RX;
+--- a/net/mac80211/sta_info.c
++++ b/net/mac80211/sta_info.c
+@@ -1929,6 +1929,7 @@ void ieee80211_sta_update_pending_airtim
+ &sta->airtime[ac].aql_tx_pending);
+
+ atomic_add(tx_airtime, &local->aql_total_pending_airtime);
++ atomic_add(tx_airtime, &local->aql_ac_pending_airtime[ac]);
+ return;
+ }
+
+@@ -1940,14 +1941,17 @@ void ieee80211_sta_update_pending_airtim
+ tx_pending, 0);
+ }
+
++ atomic_sub(tx_airtime, &local->aql_total_pending_airtime);
+ tx_pending = atomic_sub_return(tx_airtime,
+- &local->aql_total_pending_airtime);
++ &local->aql_ac_pending_airtime[ac]);
+ if (WARN_ONCE(tx_pending < 0,
+ "Device %s AC %d pending airtime underflow: %u, %u",
+ wiphy_name(local->hw.wiphy), ac, tx_pending,
+- tx_airtime))
+- atomic_cmpxchg(&local->aql_total_pending_airtime,
++ tx_airtime)) {
++ atomic_cmpxchg(&local->aql_ac_pending_airtime[ac],
+ tx_pending, 0);
++ atomic_sub(tx_pending, &local->aql_total_pending_airtime);
++ }
+ }
+
+ int sta_info_move_state(struct sta_info *sta,
+--- a/net/mac80211/tx.c
++++ b/net/mac80211/tx.c
+@@ -3863,6 +3863,9 @@ struct ieee80211_txq *ieee80211_next_txq
+
+ spin_lock_bh(&local->active_txq_lock[ac]);
+
++ if (!local->schedule_round[ac])
++ goto out;
++
+ begin:
+ txqi = list_first_entry_or_null(&local->active_txqs[ac],
+ struct txq_info,
+@@ -3984,6 +3987,25 @@ bool ieee80211_txq_airtime_check(struct
+ }
+ EXPORT_SYMBOL(ieee80211_txq_airtime_check);
+
++static bool
++ieee80211_txq_schedule_airtime_check(struct ieee80211_local *local, u8 ac)
++{
++ unsigned int num_txq = 0;
++ struct txq_info *txq;
++ u32 aql_limit;
++
++ if (!wiphy_ext_feature_isset(local->hw.wiphy, NL80211_EXT_FEATURE_AQL))
++ return true;
++
++ list_for_each_entry(txq, &local->active_txqs[ac], schedule_order)
++ num_txq++;
++
++ aql_limit = (num_txq - 1) * local->aql_txq_limit_low[ac] / 2 +
++ local->aql_txq_limit_high[ac];
++
++ return atomic_read(&local->aql_ac_pending_airtime[ac]) < aql_limit;
++}
++
+ bool ieee80211_txq_may_transmit(struct ieee80211_hw *hw,
+ struct ieee80211_txq *txq)
+ {
+@@ -4000,6 +4022,9 @@ bool ieee80211_txq_may_transmit(struct i
+ if (list_empty(&txqi->schedule_order))
+ goto out;
+
++ if (!ieee80211_txq_schedule_airtime_check(local, ac))
++ goto out;
++
+ list_for_each_entry_safe(iter, tmp, &local->active_txqs[ac],
+ schedule_order) {
+ if (iter == txqi)
+@@ -4039,7 +4064,15 @@ void ieee80211_txq_schedule_start(struct
+ struct ieee80211_local *local = hw_to_local(hw);
+
+ spin_lock_bh(&local->active_txq_lock[ac]);
+- local->schedule_round[ac]++;
++
++ if (ieee80211_txq_schedule_airtime_check(local, ac)) {
++ local->schedule_round[ac]++;
++ if (!local->schedule_round[ac])
++ local->schedule_round[ac]++;
++ } else {
++ local->schedule_round[ac] = 0;
++ }
++
+ spin_unlock_bh(&local->active_txq_lock[ac]);
+ }
+ EXPORT_SYMBOL(ieee80211_txq_schedule_start);