diff options
author | Felix Fietkau <nbd@nbd.name> | 2022-06-25 23:24:09 +0200 |
---|---|---|
committer | Johannes Berg <johannes.berg@intel.com> | 2022-07-01 10:51:48 +0200 |
commit | 8e4bac0671054ba1ad2e3d41aa568ac55f51affd (patch) | |
tree | 3f25767abf196fc9862f9549705959da38acf162 /net/mac80211/tx.c | |
parent | 8ccc07028cb7aaa6ad313f24a9442c7796416e19 (diff) | |
download | linux-8e4bac0671054ba1ad2e3d41aa568ac55f51affd.tar.gz linux-8e4bac0671054ba1ad2e3d41aa568ac55f51affd.tar.bz2 linux-8e4bac0671054ba1ad2e3d41aa568ac55f51affd.zip |
wifi: 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>
Acked-by: Toke Høiland-Jørgensen <toke@toke.dk>
Link: https://lore.kernel.org/r/20220625212411.36675-5-nbd@nbd.name
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Diffstat (limited to 'net/mac80211/tx.c')
-rw-r--r-- | net/mac80211/tx.c | 35 |
1 files changed, 34 insertions, 1 deletions
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index 71c1d2a5eef3..b2430cf8332b 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c @@ -3846,6 +3846,9 @@ struct ieee80211_txq *ieee80211_next_txq(struct ieee80211_hw *hw, u8 ac) 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, @@ -3967,6 +3970,25 @@ bool ieee80211_txq_airtime_check(struct ieee80211_hw *hw, } 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) { @@ -3983,6 +4005,9 @@ bool ieee80211_txq_may_transmit(struct ieee80211_hw *hw, 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) @@ -4022,7 +4047,15 @@ void ieee80211_txq_schedule_start(struct ieee80211_hw *hw, u8 ac) 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); |