diff options
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.patch | 131 |
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); |