diff options
Diffstat (limited to 'package/kernel/mac80211/patches/subsys/311-mac80211-Use-Airtime-based-Queue-Limits-AQL-on-packe.patch')
-rw-r--r-- | package/kernel/mac80211/patches/subsys/311-mac80211-Use-Airtime-based-Queue-Limits-AQL-on-packe.patch | 146 |
1 files changed, 146 insertions, 0 deletions
diff --git a/package/kernel/mac80211/patches/subsys/311-mac80211-Use-Airtime-based-Queue-Limits-AQL-on-packe.patch b/package/kernel/mac80211/patches/subsys/311-mac80211-Use-Airtime-based-Queue-Limits-AQL-on-packe.patch new file mode 100644 index 0000000000..3069d624f5 --- /dev/null +++ b/package/kernel/mac80211/patches/subsys/311-mac80211-Use-Airtime-based-Queue-Limits-AQL-on-packe.patch @@ -0,0 +1,146 @@ +From: =?UTF-8?q?Toke=20H=C3=B8iland-J=C3=B8rgensen?= <toke@redhat.com> +Date: Mon, 18 Nov 2019 22:06:10 -0800 +Subject: [PATCH] mac80211: Use Airtime-based Queue Limits (AQL) on packet + dequeue +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +The previous commit added the ability to throttle stations when they queue +too much airtime in the hardware. This commit enables the functionality by +calculating the expected airtime usage of each packet that is dequeued from +the TXQs in mac80211, and accounting that as pending airtime. + +The estimated airtime for each skb is stored in the tx_info, so we can +subtract the same amount from the running total when the skb is freed or +recycled. The throttling mechanism relies on this accounting to be +accurate (i.e., that we are not freeing skbs without subtracting any +airtime they were accounted for), so we put the subtraction into +ieee80211_report_used_skb(). As an optimisation, we also subtract the +airtime on regular TX completion, zeroing out the value stored in the +packet afterwards, to avoid having to do an expensive lookup of the station +from the packet data on every packet. + +This patch does *not* include any mechanism to wake a throttled TXQ again, +on the assumption that this will happen anyway as a side effect of whatever +freed the skb (most commonly a TX completion). + +Signed-off-by: Toke Høiland-Jørgensen <toke@redhat.com> +Link: https://lore.kernel.org/r/20191119060610.76681-5-kyan@google.com +Signed-off-by: Johannes Berg <johannes.berg@intel.com> +--- + +--- a/include/net/mac80211.h ++++ b/include/net/mac80211.h +@@ -1060,6 +1060,22 @@ struct ieee80211_tx_info { + }; + }; + ++static inline u16 ++ieee80211_info_set_tx_time_est(struct ieee80211_tx_info *info, u16 tx_time_est) ++{ ++ /* We only have 10 bits in tx_time_est, so store airtime ++ * in increments of 4us and clamp the maximum to 2**12-1 ++ */ ++ info->tx_time_est = min_t(u16, tx_time_est, 4095) >> 2; ++ return info->tx_time_est << 2; ++} ++ ++static inline u16 ++ieee80211_info_get_tx_time_est(struct ieee80211_tx_info *info) ++{ ++ return info->tx_time_est << 2; ++} ++ + /** + * struct ieee80211_tx_status - extended tx staus info for rate control + * +--- a/net/mac80211/status.c ++++ b/net/mac80211/status.c +@@ -670,12 +670,26 @@ static void ieee80211_report_used_skb(st + struct sk_buff *skb, bool dropped) + { + struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); ++ u16 tx_time_est = ieee80211_info_get_tx_time_est(info); + struct ieee80211_hdr *hdr = (void *)skb->data; + bool acked = info->flags & IEEE80211_TX_STAT_ACK; + + if (dropped) + acked = false; + ++ if (tx_time_est) { ++ struct sta_info *sta; ++ ++ rcu_read_lock(); ++ ++ sta = sta_info_get_by_addrs(local, hdr->addr1, hdr->addr2); ++ ieee80211_sta_update_pending_airtime(local, sta, ++ skb_get_queue_mapping(skb), ++ tx_time_est, ++ true); ++ rcu_read_unlock(); ++ } ++ + if (info->flags & IEEE80211_TX_INTFL_MLME_CONN_TX) { + struct ieee80211_sub_if_data *sdata; + +@@ -885,6 +899,7 @@ static void __ieee80211_tx_status(struct + struct ieee80211_bar *bar; + int shift = 0; + int tid = IEEE80211_NUM_TIDS; ++ u16 tx_time_est; + + rates_idx = ieee80211_tx_get_rates(hw, info, &retry_count); + +@@ -996,6 +1011,17 @@ static void __ieee80211_tx_status(struct + ieee80211_sta_register_airtime(&sta->sta, tid, + info->status.tx_time, 0); + ++ if ((tx_time_est = ieee80211_info_get_tx_time_est(info)) > 0) { ++ /* Do this here to avoid the expensive lookup of the sta ++ * in ieee80211_report_used_skb(). ++ */ ++ ieee80211_sta_update_pending_airtime(local, sta, ++ skb_get_queue_mapping(skb), ++ tx_time_est, ++ true); ++ ieee80211_info_set_tx_time_est(info, 0); ++ } ++ + if (ieee80211_hw_check(&local->hw, REPORTS_TX_ACK_STATUS)) { + if (acked) { + if (sta->status_stats.lost_packets) +--- a/net/mac80211/tx.c ++++ b/net/mac80211/tx.c +@@ -3544,6 +3544,9 @@ struct sk_buff *ieee80211_tx_dequeue(str + + WARN_ON_ONCE(softirq_count() == 0); + ++ if (!ieee80211_txq_airtime_check(hw, txq)) ++ return NULL; ++ + begin: + spin_lock_bh(&fq->lock); + +@@ -3654,6 +3657,21 @@ begin: + } + + IEEE80211_SKB_CB(skb)->control.vif = vif; ++ ++ if (local->airtime_flags & AIRTIME_USE_AQL) { ++ u32 airtime; ++ ++ airtime = ieee80211_calc_expected_tx_airtime(hw, vif, txq->sta, ++ skb->len); ++ if (airtime) { ++ airtime = ieee80211_info_set_tx_time_est(info, airtime); ++ ieee80211_sta_update_pending_airtime(local, tx.sta, ++ txq->ac, ++ airtime, ++ false); ++ } ++ } ++ + return skb; + + out: |