aboutsummaryrefslogtreecommitdiffstats
path: root/package/kernel/mac80211/patches/subsys/311-mac80211-Use-Airtime-based-Queue-Limits-AQL-on-packe.patch
diff options
context:
space:
mode:
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.patch146
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: