[Refactor and sync wifi from Openwrt]

[Description]
Refactor and sync wifi from Openwrt
1.mt76/mac80211/hostapd

[Release-log]
N/A

diff --git a/recipes-kernel/linux-mac80211/files/patches/subsys/334-mac80211-add-a-per-PHY-AQL-limit-to-improve-fairness.patch b/recipes-kernel/linux-mac80211/files/patches/subsys/334-mac80211-add-a-per-PHY-AQL-limit-to-improve-fairness.patch
new file mode 100644
index 0000000..89718a8
--- /dev/null
+++ b/recipes-kernel/linux-mac80211/files/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);