summaryrefslogtreecommitdiffstats
path: root/package/kernel/mac80211/patches/subsys
diff options
context:
space:
mode:
authorFelix Fietkau <nbd@nbd.name>2023-08-30 12:31:44 +0200
committerFelix Fietkau <nbd@nbd.name>2023-09-11 14:29:36 +0200
commitf861292abcb77655a9792ead47d397d31f1c356e (patch)
treeafe289bd9fbc0d62f176a99f05da31f1426ac943 /package/kernel/mac80211/patches/subsys
parent69f12c2f23c6d32a5fdda2385b4156c9b8bfae22 (diff)
downloadopenwrt-f861292abcb77655a9792ead47d397d31f1c356e.tar.gz
openwrt-f861292abcb77655a9792ead47d397d31f1c356e.tar.bz2
openwrt-f861292abcb77655a9792ead47d397d31f1c356e.zip
mac80211: update to version 6.5
Signed-off-by: Felix Fietkau <nbd@nbd.name>
Diffstat (limited to 'package/kernel/mac80211/patches/subsys')
-rw-r--r--package/kernel/mac80211/patches/subsys/110-mac80211_keep_keys_on_stop_ap.patch2
-rw-r--r--package/kernel/mac80211/patches/subsys/210-ap_scan.patch2
-rw-r--r--package/kernel/mac80211/patches/subsys/301-mac80211-sta-randomize-BA-session-dialog-token-alloc.patch2
-rw-r--r--package/kernel/mac80211/patches/subsys/305-mac80211-increase-quantum-for-airtime-scheduler.patch8
-rw-r--r--package/kernel/mac80211/patches/subsys/306-01-v6.2-wifi-mac80211-add-internal-handler-for-wake_tx_queue.patch183
-rw-r--r--package/kernel/mac80211/patches/subsys/306-02-v6.2-wifi-mac80211-add-wake_tx_queue-callback-to-drivers.patch396
-rw-r--r--package/kernel/mac80211/patches/subsys/306-03-v6.2-wifi-mac80211-Drop-support-for-TX-push-path.patch683
-rw-r--r--package/kernel/mac80211/patches/subsys/306-04-v6.2-wifi-realtek-remove-duplicated-wake_tx_queue.patch32
-rw-r--r--package/kernel/mac80211/patches/subsys/310-mac80211-split-mesh-fast-tx-cache-into-local-proxied.patch (renamed from package/kernel/mac80211/patches/subsys/338-mac80211-split-mesh-fast-tx-cache-into-local-proxied.patch)14
-rw-r--r--package/kernel/mac80211/patches/subsys/310-v6.2-mac80211-add-support-for-restricting-netdev-features.patch506
-rw-r--r--package/kernel/mac80211/patches/subsys/311-v6.2-wifi-mac80211-fix-and-simplify-unencrypted-drop-chec.patch87
-rw-r--r--package/kernel/mac80211/patches/subsys/312-v6.3-wifi-cfg80211-move-A-MSDU-check-in-ieee80211_data_to.patch25
-rw-r--r--package/kernel/mac80211/patches/subsys/313-v6.3-wifi-cfg80211-factor-out-bridge-tunnel-RFC1042-heade.patch76
-rw-r--r--package/kernel/mac80211/patches/subsys/314-v6.3-wifi-mac80211-remove-mesh-forwarding-congestion-chec.patch54
-rw-r--r--package/kernel/mac80211/patches/subsys/315-v6.3-wifi-mac80211-fix-receiving-A-MSDU-frames-on-mesh-in.patch762
-rw-r--r--package/kernel/mac80211/patches/subsys/316-v6.3-wifi-mac80211-add-a-workaround-for-receiving-non-sta.patch145
-rw-r--r--package/kernel/mac80211/patches/subsys/318-wifi-mac80211-fix-race-in-mesh-sequence-number-assig.patch37
-rw-r--r--package/kernel/mac80211/patches/subsys/319-wifi-mac80211-mesh-fast-xmit-support.patch850
-rw-r--r--package/kernel/mac80211/patches/subsys/320-wifi-mac80211-use-mesh-header-cache-to-speed-up-mesh.patch132
-rw-r--r--package/kernel/mac80211/patches/subsys/321-mac80211-fix-mesh-forwarding.patch32
-rw-r--r--package/kernel/mac80211/patches/subsys/322-wifi-mac80211-fix-mesh-path-discovery-based-on-unica.patch52
-rw-r--r--package/kernel/mac80211/patches/subsys/323-v6.3-wifi-mac80211-Add-VHT-MU-MIMO-related-flags-in-ieee8.patch68
-rw-r--r--package/kernel/mac80211/patches/subsys/324-v6.3-wifi-mac80211-Add-HE-MU-MIMO-related-flags-in-ieee80.patch68
-rw-r--r--package/kernel/mac80211/patches/subsys/325-wifi-mac80211-introduce-ieee80211_refresh_tx_agg_ses.patch60
-rw-r--r--package/kernel/mac80211/patches/subsys/326-wifi-mac80211-add-mesh-fast-rx-support.patch77
-rw-r--r--package/kernel/mac80211/patches/subsys/327-wifi-mac80211-add-support-for-letting-drivers-regist.patch149
-rw-r--r--package/kernel/mac80211/patches/subsys/329-wifi-mac80211-fix-receiving-mesh-packets-in-forwardi.patch50
-rw-r--r--package/kernel/mac80211/patches/subsys/330-wifi-ieee80211-correctly-mark-FTM-frames-non-buffera.patch134
-rw-r--r--package/kernel/mac80211/patches/subsys/331-wifi-mac80211-flush-queues-on-STA-removal.patch36
-rw-r--r--package/kernel/mac80211/patches/subsys/332-wifi-iwlwifi-mvm-support-flush-on-AP-interfaces.patch34
-rw-r--r--package/kernel/mac80211/patches/subsys/333-wifi-mac80211-add-flush_sta-method.patch91
-rw-r--r--package/kernel/mac80211/patches/subsys/334-wifi-iwlwifi-mvm-support-new-flush_sta-method.patch53
-rw-r--r--package/kernel/mac80211/patches/subsys/335-wifi-mac80211-add-LDPC-related-flags-in-ieee80211_bs.patch62
-rw-r--r--package/kernel/mac80211/patches/subsys/336-v6.4-wifi-mac80211-generate-EMA-beacons-in-AP-mode.patch372
-rw-r--r--package/kernel/mac80211/patches/subsys/337-mac80211-fix-sband-iftype-data-lookup-for-AP_VLAN.patch23
-rw-r--r--package/kernel/mac80211/patches/subsys/339-wifi-cfg80211-fix-receving-mesh-packets-without-RFC1.patch25
-rw-r--r--package/kernel/mac80211/patches/subsys/400-allow-ibss-mixed.patch2
37 files changed, 15 insertions, 5369 deletions
diff --git a/package/kernel/mac80211/patches/subsys/110-mac80211_keep_keys_on_stop_ap.patch b/package/kernel/mac80211/patches/subsys/110-mac80211_keep_keys_on_stop_ap.patch
index 4d4a2a8f5e..e3349dabd0 100644
--- a/package/kernel/mac80211/patches/subsys/110-mac80211_keep_keys_on_stop_ap.patch
+++ b/package/kernel/mac80211/patches/subsys/110-mac80211_keep_keys_on_stop_ap.patch
@@ -9,7 +9,7 @@ Used for AP+STA support in OpenWrt - preserve AP mode keys across STA reconnect
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
-@@ -1519,7 +1519,6 @@ static int ieee80211_stop_ap(struct wiph
+@@ -1632,7 +1632,6 @@ static int ieee80211_stop_ap(struct wiph
link_conf->bssid_indicator = 0;
__sta_info_flush(sdata, true);
diff --git a/package/kernel/mac80211/patches/subsys/210-ap_scan.patch b/package/kernel/mac80211/patches/subsys/210-ap_scan.patch
index 10b842d9af..25b844a21b 100644
--- a/package/kernel/mac80211/patches/subsys/210-ap_scan.patch
+++ b/package/kernel/mac80211/patches/subsys/210-ap_scan.patch
@@ -8,7 +8,7 @@ Subject: [PATCH] mac80211: allow scans in access point mode (for site survey)
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
-@@ -2727,6 +2727,8 @@ static int ieee80211_scan(struct wiphy *
+@@ -2843,6 +2843,8 @@ static int ieee80211_scan(struct wiphy *
*/
fallthrough;
case NL80211_IFTYPE_AP:
diff --git a/package/kernel/mac80211/patches/subsys/301-mac80211-sta-randomize-BA-session-dialog-token-alloc.patch b/package/kernel/mac80211/patches/subsys/301-mac80211-sta-randomize-BA-session-dialog-token-alloc.patch
index 63b2177471..ffa5c17e48 100644
--- a/package/kernel/mac80211/patches/subsys/301-mac80211-sta-randomize-BA-session-dialog-token-alloc.patch
+++ b/package/kernel/mac80211/patches/subsys/301-mac80211-sta-randomize-BA-session-dialog-token-alloc.patch
@@ -28,7 +28,7 @@ Signed-off-by: Johannes Berg <johannes.berg@intel.com>
--- a/net/mac80211/sta_info.c
+++ b/net/mac80211/sta_info.c
-@@ -554,6 +554,7 @@ __sta_info_alloc(struct ieee80211_sub_if
+@@ -558,6 +558,7 @@ __sta_info_alloc(struct ieee80211_sub_if
INIT_WORK(&sta->drv_deliver_wk, sta_deliver_ps_frames);
INIT_WORK(&sta->ampdu_mlme.work, ieee80211_ba_session_work);
mutex_init(&sta->ampdu_mlme.mtx);
diff --git a/package/kernel/mac80211/patches/subsys/305-mac80211-increase-quantum-for-airtime-scheduler.patch b/package/kernel/mac80211/patches/subsys/305-mac80211-increase-quantum-for-airtime-scheduler.patch
index 0ac972955f..a27925e64e 100644
--- a/package/kernel/mac80211/patches/subsys/305-mac80211-increase-quantum-for-airtime-scheduler.patch
+++ b/package/kernel/mac80211/patches/subsys/305-mac80211-increase-quantum-for-airtime-scheduler.patch
@@ -12,7 +12,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
-@@ -90,6 +90,8 @@ extern const u8 ieee80211_ac_to_qos_mask
+@@ -92,6 +92,8 @@ extern const u8 ieee80211_ac_to_qos_mask
*/
#define AIRTIME_ACTIVE_DURATION (HZ / 10)
@@ -23,7 +23,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
-@@ -3984,7 +3984,7 @@ struct ieee80211_txq *ieee80211_next_txq
+@@ -4059,7 +4059,7 @@ struct ieee80211_txq *ieee80211_next_txq
if (deficit < 0)
sta->airtime[txqi->txq.ac].deficit +=
@@ -32,7 +32,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
if (deficit < 0 || !aql_check) {
list_move_tail(&txqi->schedule_order,
-@@ -4127,7 +4127,8 @@ bool ieee80211_txq_may_transmit(struct i
+@@ -4202,7 +4202,8 @@ bool ieee80211_txq_may_transmit(struct i
}
sta = container_of(iter->txq.sta, struct sta_info, sta);
if (ieee80211_sta_deficit(sta, ac) < 0)
@@ -42,7 +42,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
list_move_tail(&iter->schedule_order, &local->active_txqs[ac]);
}
-@@ -4135,7 +4136,7 @@ bool ieee80211_txq_may_transmit(struct i
+@@ -4210,7 +4211,7 @@ bool ieee80211_txq_may_transmit(struct i
if (sta->airtime[ac].deficit >= 0)
goto out;
diff --git a/package/kernel/mac80211/patches/subsys/306-01-v6.2-wifi-mac80211-add-internal-handler-for-wake_tx_queue.patch b/package/kernel/mac80211/patches/subsys/306-01-v6.2-wifi-mac80211-add-internal-handler-for-wake_tx_queue.patch
deleted file mode 100644
index d14ba05e69..0000000000
--- a/package/kernel/mac80211/patches/subsys/306-01-v6.2-wifi-mac80211-add-internal-handler-for-wake_tx_queue.patch
+++ /dev/null
@@ -1,183 +0,0 @@
-From: Alexander Wetzel <alexander@wetzel-home.de>
-Date: Sun, 9 Oct 2022 18:30:38 +0200
-Subject: [PATCH] wifi: mac80211: add internal handler for wake_tx_queue
-
-Start to align the TX handling to only use internal TX queues (iTXQs):
-
-Provide a handler for drivers not having a custom wake_tx_queue
-callback and update the documentation.
-
-Signed-off-by: Alexander Wetzel <alexander@wetzel-home.de>
-Signed-off-by: Johannes Berg <johannes.berg@intel.com>
----
-
---- a/include/net/mac80211.h
-+++ b/include/net/mac80211.h
-@@ -89,15 +89,13 @@
- /**
- * DOC: mac80211 software tx queueing
- *
-- * mac80211 provides an optional intermediate queueing implementation designed
-- * to allow the driver to keep hardware queues short and provide some fairness
-- * between different stations/interfaces.
-- * In this model, the driver pulls data frames from the mac80211 queue instead
-- * of letting mac80211 push them via drv_tx().
-- * Other frames (e.g. control or management) are still pushed using drv_tx().
-+ * mac80211 uses an intermediate queueing implementation, designed to allow the
-+ * driver to keep hardware queues short and to provide some fairness between
-+ * different stations/interfaces.
- *
-- * Drivers indicate that they use this model by implementing the .wake_tx_queue
-- * driver operation.
-+ * Drivers must provide the .wake_tx_queue driver operation by either
-+ * linking it to ieee80211_handle_wake_tx_queue() or implementing a custom
-+ * handler.
- *
- * Intermediate queues (struct ieee80211_txq) are kept per-sta per-tid, with
- * another per-sta for non-data/non-mgmt and bufferable management frames, and
-@@ -106,9 +104,12 @@
- * The driver is expected to initialize its private per-queue data for stations
- * and interfaces in the .add_interface and .sta_add ops.
- *
-- * The driver can't access the queue directly. To dequeue a frame from a
-- * txq, it calls ieee80211_tx_dequeue(). Whenever mac80211 adds a new frame to a
-- * queue, it calls the .wake_tx_queue driver op.
-+ * The driver can't access the internal TX queues (iTXQs) directly.
-+ * Whenever mac80211 adds a new frame to a queue, it calls the .wake_tx_queue
-+ * driver op.
-+ * Drivers implementing a custom .wake_tx_queue op can get them by calling
-+ * ieee80211_tx_dequeue(). Drivers using ieee80211_handle_wake_tx_queue() will
-+ * simply get the individual frames pushed via the .tx driver operation.
- *
- * Drivers can optionally delegate responsibility for scheduling queues to
- * mac80211, to take advantage of airtime fairness accounting. In this case, to
-@@ -2248,8 +2249,8 @@ struct ieee80211_link_sta {
- * For non MLO STA it will point to the deflink data. For MLO STA
- * ieee80211_sta_recalc_aggregates() must be called to update it.
- * @support_p2p_ps: indicates whether the STA supports P2P PS mechanism or not.
-- * @txq: per-TID data TX queues (if driver uses the TXQ abstraction); note that
-- * the last entry (%IEEE80211_NUM_TIDS) is used for non-data frames
-+ * @txq: per-TID data TX queues; note that the last entry (%IEEE80211_NUM_TIDS)
-+ * is used for non-data frames
- * @deflink: This holds the default link STA information, for non MLO STA all link
- * specific STA information is accessed through @deflink or through
- * link[0] which points to address of @deflink. For MLO Link STA
-@@ -5687,7 +5688,7 @@ void ieee80211_key_replay(struct ieee802
- * @hw: pointer as obtained from ieee80211_alloc_hw().
- * @queue: queue number (counted from zero).
- *
-- * Drivers should use this function instead of netif_wake_queue.
-+ * Drivers must use this function instead of netif_wake_queue.
- */
- void ieee80211_wake_queue(struct ieee80211_hw *hw, int queue);
-
-@@ -5696,7 +5697,7 @@ void ieee80211_wake_queue(struct ieee802
- * @hw: pointer as obtained from ieee80211_alloc_hw().
- * @queue: queue number (counted from zero).
- *
-- * Drivers should use this function instead of netif_stop_queue.
-+ * Drivers must use this function instead of netif_stop_queue.
- */
- void ieee80211_stop_queue(struct ieee80211_hw *hw, int queue);
-
-@@ -5705,7 +5706,7 @@ void ieee80211_stop_queue(struct ieee802
- * @hw: pointer as obtained from ieee80211_alloc_hw().
- * @queue: queue number (counted from zero).
- *
-- * Drivers should use this function instead of netif_stop_queue.
-+ * Drivers must use this function instead of netif_queue_stopped.
- *
- * Return: %true if the queue is stopped. %false otherwise.
- */
-@@ -5716,7 +5717,7 @@ int ieee80211_queue_stopped(struct ieee8
- * ieee80211_stop_queues - stop all queues
- * @hw: pointer as obtained from ieee80211_alloc_hw().
- *
-- * Drivers should use this function instead of netif_stop_queue.
-+ * Drivers must use this function instead of netif_tx_stop_all_queues.
- */
- void ieee80211_stop_queues(struct ieee80211_hw *hw);
-
-@@ -5724,7 +5725,7 @@ void ieee80211_stop_queues(struct ieee80
- * ieee80211_wake_queues - wake all queues
- * @hw: pointer as obtained from ieee80211_alloc_hw().
- *
-- * Drivers should use this function instead of netif_wake_queue.
-+ * Drivers must use this function instead of netif_tx_wake_all_queues.
- */
- void ieee80211_wake_queues(struct ieee80211_hw *hw);
-
-@@ -6946,6 +6947,18 @@ static inline struct sk_buff *ieee80211_
- }
-
- /**
-+ * ieee80211_handle_wake_tx_queue - mac80211 handler for wake_tx_queue callback
-+ *
-+ * @hw: pointer as obtained from wake_tx_queue() callback().
-+ * @txq: pointer as obtained from wake_tx_queue() callback().
-+ *
-+ * Drivers can use this function for the mandatory mac80211 wake_tx_queue
-+ * callback in struct ieee80211_ops. They should not call this function.
-+ */
-+void ieee80211_handle_wake_tx_queue(struct ieee80211_hw *hw,
-+ struct ieee80211_txq *txq);
-+
-+/**
- * ieee80211_next_txq - get next tx queue to pull packets from
- *
- * @hw: pointer as obtained from ieee80211_alloc_hw()
---- a/net/mac80211/util.c
-+++ b/net/mac80211/util.c
-@@ -288,6 +288,52 @@ __le16 ieee80211_ctstoself_duration(stru
- }
- EXPORT_SYMBOL(ieee80211_ctstoself_duration);
-
-+static void wake_tx_push_queue(struct ieee80211_local *local,
-+ struct ieee80211_sub_if_data *sdata,
-+ struct ieee80211_txq *queue)
-+{
-+ int q = sdata->vif.hw_queue[queue->ac];
-+ struct ieee80211_tx_control control = {
-+ .sta = queue->sta,
-+ };
-+ struct sk_buff *skb;
-+ unsigned long flags;
-+ bool q_stopped;
-+
-+ while (1) {
-+ spin_lock_irqsave(&local->queue_stop_reason_lock, flags);
-+ q_stopped = local->queue_stop_reasons[q];
-+ spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags);
-+
-+ if (q_stopped)
-+ break;
-+
-+ skb = ieee80211_tx_dequeue(&local->hw, queue);
-+ if (!skb)
-+ break;
-+
-+ drv_tx(local, &control, skb);
-+ }
-+}
-+
-+/* wake_tx_queue handler for driver not implementing a custom one*/
-+void ieee80211_handle_wake_tx_queue(struct ieee80211_hw *hw,
-+ struct ieee80211_txq *txq)
-+{
-+ struct ieee80211_local *local = hw_to_local(hw);
-+ struct ieee80211_sub_if_data *sdata = vif_to_sdata(txq->vif);
-+ struct ieee80211_txq *queue;
-+
-+ /* Use ieee80211_next_txq() for airtime fairness accounting */
-+ ieee80211_txq_schedule_start(hw, txq->ac);
-+ while ((queue = ieee80211_next_txq(hw, txq->ac))) {
-+ wake_tx_push_queue(local, sdata, queue);
-+ ieee80211_return_txq(hw, queue, false);
-+ }
-+ ieee80211_txq_schedule_end(hw, txq->ac);
-+}
-+EXPORT_SYMBOL(ieee80211_handle_wake_tx_queue);
-+
- static void __ieee80211_wake_txqs(struct ieee80211_sub_if_data *sdata, int ac)
- {
- struct ieee80211_local *local = sdata->local;
diff --git a/package/kernel/mac80211/patches/subsys/306-02-v6.2-wifi-mac80211-add-wake_tx_queue-callback-to-drivers.patch b/package/kernel/mac80211/patches/subsys/306-02-v6.2-wifi-mac80211-add-wake_tx_queue-callback-to-drivers.patch
deleted file mode 100644
index fee038d90c..0000000000
--- a/package/kernel/mac80211/patches/subsys/306-02-v6.2-wifi-mac80211-add-wake_tx_queue-callback-to-drivers.patch
+++ /dev/null
@@ -1,396 +0,0 @@
-From: Alexander Wetzel <alexander@wetzel-home.de>
-Date: Sun, 9 Oct 2022 18:30:39 +0200
-Subject: [PATCH] wifi: mac80211: add wake_tx_queue callback to drivers
-
-mac80211 is fully switching over to the internal TX queue (iTXQ)
-implementation. Update all drivers not yet providing the now mandatory
-wake_tx_queue() callback.
-
-As an side effect the netdev interfaces of all updated drivers will
-switch to the noqueue qdisc.
-
-Signed-off-by: Alexander Wetzel <alexander@wetzel-home.de>
-[add staging drivers]
-Signed-off-by: Johannes Berg <johannes.berg@intel.com>
----
-
---- a/drivers/net/wireless/admtek/adm8211.c
-+++ b/drivers/net/wireless/admtek/adm8211.c
-@@ -1760,6 +1760,7 @@ static int adm8211_alloc_rings(struct ie
-
- static const struct ieee80211_ops adm8211_ops = {
- .tx = adm8211_tx,
-+ .wake_tx_queue = ieee80211_handle_wake_tx_queue,
- .start = adm8211_start,
- .stop = adm8211_stop,
- .add_interface = adm8211_add_interface,
---- a/drivers/net/wireless/ath/ar5523/ar5523.c
-+++ b/drivers/net/wireless/ath/ar5523/ar5523.c
-@@ -1361,6 +1361,7 @@ static const struct ieee80211_ops ar5523
- .start = ar5523_start,
- .stop = ar5523_stop,
- .tx = ar5523_tx,
-+ .wake_tx_queue = ieee80211_handle_wake_tx_queue,
- .set_rts_threshold = ar5523_set_rts_threshold,
- .add_interface = ar5523_add_interface,
- .remove_interface = ar5523_remove_interface,
---- a/drivers/net/wireless/ath/ath11k/mac.c
-+++ b/drivers/net/wireless/ath/ath11k/mac.c
-@@ -8587,6 +8587,7 @@ err_fallback:
-
- static const struct ieee80211_ops ath11k_ops = {
- .tx = ath11k_mac_op_tx,
-+ .wake_tx_queue = ieee80211_handle_wake_tx_queue,
- .start = ath11k_mac_op_start,
- .stop = ath11k_mac_op_stop,
- .reconfig_complete = ath11k_mac_op_reconfig_complete,
---- a/drivers/net/wireless/ath/ath5k/mac80211-ops.c
-+++ b/drivers/net/wireless/ath/ath5k/mac80211-ops.c
-@@ -781,6 +781,7 @@ static int ath5k_set_ringparam(struct ie
-
- const struct ieee80211_ops ath5k_hw_ops = {
- .tx = ath5k_tx,
-+ .wake_tx_queue = ieee80211_handle_wake_tx_queue,
- .start = ath5k_start,
- .stop = ath5k_stop,
- .add_interface = ath5k_add_interface,
---- a/drivers/net/wireless/ath/ath9k/htc_drv_main.c
-+++ b/drivers/net/wireless/ath/ath9k/htc_drv_main.c
-@@ -1870,6 +1870,7 @@ static void ath9k_htc_channel_switch_bea
-
- struct ieee80211_ops ath9k_htc_ops = {
- .tx = ath9k_htc_tx,
-+ .wake_tx_queue = ieee80211_handle_wake_tx_queue,
- .start = ath9k_htc_start,
- .stop = ath9k_htc_stop,
- .add_interface = ath9k_htc_add_interface,
---- a/drivers/net/wireless/ath/carl9170/main.c
-+++ b/drivers/net/wireless/ath/carl9170/main.c
-@@ -1715,6 +1715,7 @@ static const struct ieee80211_ops carl91
- .start = carl9170_op_start,
- .stop = carl9170_op_stop,
- .tx = carl9170_op_tx,
-+ .wake_tx_queue = ieee80211_handle_wake_tx_queue,
- .flush = carl9170_op_flush,
- .add_interface = carl9170_op_add_interface,
- .remove_interface = carl9170_op_remove_interface,
---- a/drivers/net/wireless/ath/wcn36xx/main.c
-+++ b/drivers/net/wireless/ath/wcn36xx/main.c
-@@ -1362,6 +1362,7 @@ static const struct ieee80211_ops wcn36x
- .prepare_multicast = wcn36xx_prepare_multicast,
- .configure_filter = wcn36xx_configure_filter,
- .tx = wcn36xx_tx,
-+ .wake_tx_queue = ieee80211_handle_wake_tx_queue,
- .set_key = wcn36xx_set_key,
- .hw_scan = wcn36xx_hw_scan,
- .cancel_hw_scan = wcn36xx_cancel_hw_scan,
---- a/drivers/net/wireless/atmel/at76c50x-usb.c
-+++ b/drivers/net/wireless/atmel/at76c50x-usb.c
-@@ -2187,6 +2187,7 @@ static int at76_set_key(struct ieee80211
-
- static const struct ieee80211_ops at76_ops = {
- .tx = at76_mac80211_tx,
-+ .wake_tx_queue = ieee80211_handle_wake_tx_queue,
- .add_interface = at76_add_interface,
- .remove_interface = at76_remove_interface,
- .config = at76_config,
---- a/drivers/net/wireless/broadcom/b43/main.c
-+++ b/drivers/net/wireless/broadcom/b43/main.c
-@@ -5171,6 +5171,7 @@ static int b43_op_get_survey(struct ieee
-
- static const struct ieee80211_ops b43_hw_ops = {
- .tx = b43_op_tx,
-+ .wake_tx_queue = ieee80211_handle_wake_tx_queue,
- .conf_tx = b43_op_conf_tx,
- .add_interface = b43_op_add_interface,
- .remove_interface = b43_op_remove_interface,
---- a/drivers/net/wireless/broadcom/b43legacy/main.c
-+++ b/drivers/net/wireless/broadcom/b43legacy/main.c
-@@ -3532,6 +3532,7 @@ static int b43legacy_op_get_survey(struc
-
- static const struct ieee80211_ops b43legacy_hw_ops = {
- .tx = b43legacy_op_tx,
-+ .wake_tx_queue = ieee80211_handle_wake_tx_queue,
- .conf_tx = b43legacy_op_conf_tx,
- .add_interface = b43legacy_op_add_interface,
- .remove_interface = b43legacy_op_remove_interface,
---- a/drivers/net/wireless/broadcom/brcm80211/brcmsmac/mac80211_if.c
-+++ b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/mac80211_if.c
-@@ -962,6 +962,7 @@ static int brcms_ops_beacon_set_tim(stru
-
- static const struct ieee80211_ops brcms_ops = {
- .tx = brcms_ops_tx,
-+ .wake_tx_queue = ieee80211_handle_wake_tx_queue,
- .start = brcms_ops_start,
- .stop = brcms_ops_stop,
- .add_interface = brcms_ops_add_interface,
---- a/drivers/net/wireless/intel/iwlegacy/3945-mac.c
-+++ b/drivers/net/wireless/intel/iwlegacy/3945-mac.c
-@@ -3439,6 +3439,7 @@ static const struct attribute_group il39
-
- static struct ieee80211_ops il3945_mac_ops __ro_after_init = {
- .tx = il3945_mac_tx,
-+ .wake_tx_queue = ieee80211_handle_wake_tx_queue,
- .start = il3945_mac_start,
- .stop = il3945_mac_stop,
- .add_interface = il_mac_add_interface,
---- a/drivers/net/wireless/intel/iwlegacy/4965-mac.c
-+++ b/drivers/net/wireless/intel/iwlegacy/4965-mac.c
-@@ -6308,6 +6308,7 @@ il4965_tx_queue_set_status(struct il_pri
-
- static const struct ieee80211_ops il4965_mac_ops = {
- .tx = il4965_mac_tx,
-+ .wake_tx_queue = ieee80211_handle_wake_tx_queue,
- .start = il4965_mac_start,
- .stop = il4965_mac_stop,
- .add_interface = il_mac_add_interface,
---- a/drivers/net/wireless/intel/iwlwifi/dvm/mac80211.c
-+++ b/drivers/net/wireless/intel/iwlwifi/dvm/mac80211.c
-@@ -1571,6 +1571,7 @@ static void iwlagn_mac_sta_notify(struct
-
- const struct ieee80211_ops iwlagn_hw_ops = {
- .tx = iwlagn_mac_tx,
-+ .wake_tx_queue = ieee80211_handle_wake_tx_queue,
- .start = iwlagn_mac_start,
- .stop = iwlagn_mac_stop,
- #ifdef CONFIG_PM_SLEEP
---- a/drivers/net/wireless/intersil/p54/main.c
-+++ b/drivers/net/wireless/intersil/p54/main.c
-@@ -705,6 +705,7 @@ static void p54_set_coverage_class(struc
-
- static const struct ieee80211_ops p54_ops = {
- .tx = p54_tx_80211,
-+ .wake_tx_queue = ieee80211_handle_wake_tx_queue,
- .start = p54_start,
- .stop = p54_stop,
- .add_interface = p54_add_interface,
---- a/drivers/net/wireless/mac80211_hwsim.c
-+++ b/drivers/net/wireless/mac80211_hwsim.c
-@@ -3109,6 +3109,7 @@ static int mac80211_hwsim_change_sta_lin
-
- #define HWSIM_COMMON_OPS \
- .tx = mac80211_hwsim_tx, \
-+ .wake_tx_queue = ieee80211_handle_wake_tx_queue, \
- .start = mac80211_hwsim_start, \
- .stop = mac80211_hwsim_stop, \
- .add_interface = mac80211_hwsim_add_interface, \
---- a/drivers/net/wireless/marvell/libertas_tf/main.c
-+++ b/drivers/net/wireless/marvell/libertas_tf/main.c
-@@ -474,6 +474,7 @@ static int lbtf_op_get_survey(struct iee
-
- static const struct ieee80211_ops lbtf_ops = {
- .tx = lbtf_op_tx,
-+ .wake_tx_queue = ieee80211_handle_wake_tx_queue,
- .start = lbtf_op_start,
- .stop = lbtf_op_stop,
- .add_interface = lbtf_op_add_interface,
---- a/drivers/net/wireless/marvell/mwl8k.c
-+++ b/drivers/net/wireless/marvell/mwl8k.c
-@@ -5611,6 +5611,7 @@ static void mwl8k_sw_scan_complete(struc
-
- static const struct ieee80211_ops mwl8k_ops = {
- .tx = mwl8k_tx,
-+ .wake_tx_queue = ieee80211_handle_wake_tx_queue,
- .start = mwl8k_start,
- .stop = mwl8k_stop,
- .add_interface = mwl8k_add_interface,
---- a/drivers/net/wireless/mediatek/mt7601u/main.c
-+++ b/drivers/net/wireless/mediatek/mt7601u/main.c
-@@ -406,6 +406,7 @@ out:
-
- const struct ieee80211_ops mt7601u_ops = {
- .tx = mt7601u_tx,
-+ .wake_tx_queue = ieee80211_handle_wake_tx_queue,
- .start = mt7601u_start,
- .stop = mt7601u_stop,
- .add_interface = mt7601u_add_interface,
---- a/drivers/net/wireless/ralink/rt2x00/rt2400pci.c
-+++ b/drivers/net/wireless/ralink/rt2x00/rt2400pci.c
-@@ -1706,6 +1706,7 @@ static int rt2400pci_tx_last_beacon(stru
-
- static const struct ieee80211_ops rt2400pci_mac80211_ops = {
- .tx = rt2x00mac_tx,
-+ .wake_tx_queue = ieee80211_handle_wake_tx_queue,
- .start = rt2x00mac_start,
- .stop = rt2x00mac_stop,
- .add_interface = rt2x00mac_add_interface,
---- a/drivers/net/wireless/ralink/rt2x00/rt2500pci.c
-+++ b/drivers/net/wireless/ralink/rt2x00/rt2500pci.c
-@@ -2004,6 +2004,7 @@ static int rt2500pci_tx_last_beacon(stru
-
- static const struct ieee80211_ops rt2500pci_mac80211_ops = {
- .tx = rt2x00mac_tx,
-+ .wake_tx_queue = ieee80211_handle_wake_tx_queue,
- .start = rt2x00mac_start,
- .stop = rt2x00mac_stop,
- .add_interface = rt2x00mac_add_interface,
---- a/drivers/net/wireless/ralink/rt2x00/rt2500usb.c
-+++ b/drivers/net/wireless/ralink/rt2x00/rt2500usb.c
-@@ -1795,6 +1795,7 @@ static int rt2500usb_probe_hw(struct rt2
-
- static const struct ieee80211_ops rt2500usb_mac80211_ops = {
- .tx = rt2x00mac_tx,
-+ .wake_tx_queue = ieee80211_handle_wake_tx_queue,
- .start = rt2x00mac_start,
- .stop = rt2x00mac_stop,
- .add_interface = rt2x00mac_add_interface,
---- a/drivers/net/wireless/ralink/rt2x00/rt2800pci.c
-+++ b/drivers/net/wireless/ralink/rt2x00/rt2800pci.c
-@@ -288,6 +288,7 @@ static int rt2800pci_read_eeprom(struct
-
- static const struct ieee80211_ops rt2800pci_mac80211_ops = {
- .tx = rt2x00mac_tx,
-+ .wake_tx_queue = ieee80211_handle_wake_tx_queue,
- .start = rt2x00mac_start,
- .stop = rt2x00mac_stop,
- .add_interface = rt2x00mac_add_interface,
---- a/drivers/net/wireless/ralink/rt2x00/rt2800soc.c
-+++ b/drivers/net/wireless/ralink/rt2x00/rt2800soc.c
-@@ -133,6 +133,7 @@ static int rt2800soc_write_firmware(stru
-
- static const struct ieee80211_ops rt2800soc_mac80211_ops = {
- .tx = rt2x00mac_tx,
-+ .wake_tx_queue = ieee80211_handle_wake_tx_queue,
- .start = rt2x00mac_start,
- .stop = rt2x00mac_stop,
- .add_interface = rt2x00mac_add_interface,
---- a/drivers/net/wireless/ralink/rt2x00/rt2800usb.c
-+++ b/drivers/net/wireless/ralink/rt2x00/rt2800usb.c
-@@ -630,6 +630,7 @@ static int rt2800usb_probe_hw(struct rt2
-
- static const struct ieee80211_ops rt2800usb_mac80211_ops = {
- .tx = rt2x00mac_tx,
-+ .wake_tx_queue = ieee80211_handle_wake_tx_queue,
- .start = rt2x00mac_start,
- .stop = rt2x00mac_stop,
- .add_interface = rt2x00mac_add_interface,
---- a/drivers/net/wireless/ralink/rt2x00/rt61pci.c
-+++ b/drivers/net/wireless/ralink/rt2x00/rt61pci.c
-@@ -2873,6 +2873,7 @@ static u64 rt61pci_get_tsf(struct ieee80
-
- static const struct ieee80211_ops rt61pci_mac80211_ops = {
- .tx = rt2x00mac_tx,
-+ .wake_tx_queue = ieee80211_handle_wake_tx_queue,
- .start = rt2x00mac_start,
- .stop = rt2x00mac_stop,
- .add_interface = rt2x00mac_add_interface,
---- a/drivers/net/wireless/ralink/rt2x00/rt73usb.c
-+++ b/drivers/net/wireless/ralink/rt2x00/rt73usb.c
-@@ -2292,6 +2292,7 @@ static u64 rt73usb_get_tsf(struct ieee80
-
- static const struct ieee80211_ops rt73usb_mac80211_ops = {
- .tx = rt2x00mac_tx,
-+ .wake_tx_queue = ieee80211_handle_wake_tx_queue,
- .start = rt2x00mac_start,
- .stop = rt2x00mac_stop,
- .add_interface = rt2x00mac_add_interface,
---- a/drivers/net/wireless/realtek/rtl818x/rtl8180/dev.c
-+++ b/drivers/net/wireless/realtek/rtl818x/rtl8180/dev.c
-@@ -1608,6 +1608,7 @@ static void rtl8180_configure_filter(str
-
- static const struct ieee80211_ops rtl8180_ops = {
- .tx = rtl8180_tx,
-+ .wake_tx_queue = ieee80211_handle_wake_tx_queue,
- .start = rtl8180_start,
- .stop = rtl8180_stop,
- .add_interface = rtl8180_add_interface,
---- a/drivers/net/wireless/realtek/rtl818x/rtl8187/dev.c
-+++ b/drivers/net/wireless/realtek/rtl818x/rtl8187/dev.c
-@@ -1378,6 +1378,7 @@ static int rtl8187_conf_tx(struct ieee80
-
- static const struct ieee80211_ops rtl8187_ops = {
- .tx = rtl8187_tx,
-+ .wake_tx_queue = ieee80211_handle_wake_tx_queue,
- .start = rtl8187_start,
- .stop = rtl8187_stop,
- .add_interface = rtl8187_add_interface,
---- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c
-+++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c
-@@ -6548,6 +6548,7 @@ static void rtl8xxxu_stop(struct ieee802
-
- static const struct ieee80211_ops rtl8xxxu_ops = {
- .tx = rtl8xxxu_tx,
-+ .wake_tx_queue = ieee80211_handle_wake_tx_queue,
- .add_interface = rtl8xxxu_add_interface,
- .remove_interface = rtl8xxxu_remove_interface,
- .config = rtl8xxxu_config,
---- a/drivers/net/wireless/realtek/rtlwifi/core.c
-+++ b/drivers/net/wireless/realtek/rtlwifi/core.c
-@@ -1912,6 +1912,7 @@ const struct ieee80211_ops rtl_ops = {
- .start = rtl_op_start,
- .stop = rtl_op_stop,
- .tx = rtl_op_tx,
-+ .wake_tx_queue = ieee80211_handle_wake_tx_queue,
- .add_interface = rtl_op_add_interface,
- .remove_interface = rtl_op_remove_interface,
- .change_interface = rtl_op_change_interface,
---- a/drivers/net/wireless/realtek/rtw88/mac80211.c
-+++ b/drivers/net/wireless/realtek/rtw88/mac80211.c
-@@ -896,6 +896,7 @@ static void rtw_ops_sta_rc_update(struct
-
- const struct ieee80211_ops rtw_ops = {
- .tx = rtw_ops_tx,
-+ .wake_tx_queue = ieee80211_handle_wake_tx_queue,
- .wake_tx_queue = rtw_ops_wake_tx_queue,
- .start = rtw_ops_start,
- .stop = rtw_ops_stop,
---- a/drivers/net/wireless/realtek/rtw89/mac80211.c
-+++ b/drivers/net/wireless/realtek/rtw89/mac80211.c
-@@ -918,6 +918,7 @@ static int rtw89_ops_set_tid_config(stru
-
- const struct ieee80211_ops rtw89_ops = {
- .tx = rtw89_ops_tx,
-+ .wake_tx_queue = ieee80211_handle_wake_tx_queue,
- .wake_tx_queue = rtw89_ops_wake_tx_queue,
- .start = rtw89_ops_start,
- .stop = rtw89_ops_stop,
---- a/drivers/net/wireless/rsi/rsi_91x_mac80211.c
-+++ b/drivers/net/wireless/rsi/rsi_91x_mac80211.c
-@@ -1958,6 +1958,7 @@ static int rsi_mac80211_resume(struct ie
-
- static const struct ieee80211_ops mac80211_ops = {
- .tx = rsi_mac80211_tx,
-+ .wake_tx_queue = ieee80211_handle_wake_tx_queue,
- .start = rsi_mac80211_start,
- .stop = rsi_mac80211_stop,
- .add_interface = rsi_mac80211_add_interface,
---- a/drivers/net/wireless/st/cw1200/main.c
-+++ b/drivers/net/wireless/st/cw1200/main.c
-@@ -209,6 +209,7 @@ static const struct ieee80211_ops cw1200
- .remove_interface = cw1200_remove_interface,
- .change_interface = cw1200_change_interface,
- .tx = cw1200_tx,
-+ .wake_tx_queue = ieee80211_handle_wake_tx_queue,
- .hw_scan = cw1200_hw_scan,
- .set_tim = cw1200_set_tim,
- .sta_notify = cw1200_sta_notify,
---- a/drivers/net/wireless/ti/wl1251/main.c
-+++ b/drivers/net/wireless/ti/wl1251/main.c
-@@ -1359,6 +1359,7 @@ static const struct ieee80211_ops wl1251
- .prepare_multicast = wl1251_op_prepare_multicast,
- .configure_filter = wl1251_op_configure_filter,
- .tx = wl1251_op_tx,
-+ .wake_tx_queue = ieee80211_handle_wake_tx_queue,
- .set_key = wl1251_op_set_key,
- .hw_scan = wl1251_op_hw_scan,
- .bss_info_changed = wl1251_op_bss_info_changed,
---- a/drivers/net/wireless/ti/wlcore/main.c
-+++ b/drivers/net/wireless/ti/wlcore/main.c
-@@ -5942,6 +5942,7 @@ static const struct ieee80211_ops wl1271
- .prepare_multicast = wl1271_op_prepare_multicast,
- .configure_filter = wl1271_op_configure_filter,
- .tx = wl1271_op_tx,
-+ .wake_tx_queue = ieee80211_handle_wake_tx_queue,
- .set_key = wlcore_op_set_key,
- .hw_scan = wl1271_op_hw_scan,
- .cancel_hw_scan = wl1271_op_cancel_hw_scan,
---- a/drivers/net/wireless/zydas/zd1211rw/zd_mac.c
-+++ b/drivers/net/wireless/zydas/zd1211rw/zd_mac.c
-@@ -1344,6 +1344,7 @@ static u64 zd_op_get_tsf(struct ieee8021
-
- static const struct ieee80211_ops zd_ops = {
- .tx = zd_op_tx,
-+ .wake_tx_queue = ieee80211_handle_wake_tx_queue,
- .start = zd_op_start,
- .stop = zd_op_stop,
- .add_interface = zd_op_add_interface,
diff --git a/package/kernel/mac80211/patches/subsys/306-03-v6.2-wifi-mac80211-Drop-support-for-TX-push-path.patch b/package/kernel/mac80211/patches/subsys/306-03-v6.2-wifi-mac80211-Drop-support-for-TX-push-path.patch
deleted file mode 100644
index f9f9977cee..0000000000
--- a/package/kernel/mac80211/patches/subsys/306-03-v6.2-wifi-mac80211-Drop-support-for-TX-push-path.patch
+++ /dev/null
@@ -1,683 +0,0 @@
-From: Alexander Wetzel <alexander@wetzel-home.de>
-Date: Sun, 9 Oct 2022 18:30:40 +0200
-Subject: [PATCH] wifi: mac80211: Drop support for TX push path
-
-All drivers are now using mac80211 internal queues (iTXQs).
-Drop mac80211 internal support for the old push path.
-
-Signed-off-by: Alexander Wetzel <alexander@wetzel-home.de>
-Signed-off-by: Johannes Berg <johannes.berg@intel.com>
----
-
---- a/net/mac80211/cfg.c
-+++ b/net/mac80211/cfg.c
-@@ -4346,9 +4346,6 @@ static int ieee80211_get_txq_stats(struc
- struct ieee80211_sub_if_data *sdata;
- int ret = 0;
-
-- if (!local->ops->wake_tx_queue)
-- return 1;
--
- spin_lock_bh(&local->fq.lock);
- rcu_read_lock();
-
---- a/net/mac80211/debugfs.c
-+++ b/net/mac80211/debugfs.c
-@@ -663,9 +663,7 @@ void debugfs_hw_add(struct ieee80211_loc
- DEBUGFS_ADD_MODE(force_tx_status, 0600);
- DEBUGFS_ADD_MODE(aql_enable, 0600);
- DEBUGFS_ADD(aql_pending);
--
-- if (local->ops->wake_tx_queue)
-- DEBUGFS_ADD_MODE(aqm, 0600);
-+ DEBUGFS_ADD_MODE(aqm, 0600);
-
- DEBUGFS_ADD_MODE(airtime_flags, 0600);
-
---- a/net/mac80211/debugfs_netdev.c
-+++ b/net/mac80211/debugfs_netdev.c
-@@ -677,8 +677,7 @@ static void add_common_files(struct ieee
- DEBUGFS_ADD(rc_rateidx_vht_mcs_mask_5ghz);
- DEBUGFS_ADD(hw_queues);
-
-- if (sdata->local->ops->wake_tx_queue &&
-- sdata->vif.type != NL80211_IFTYPE_P2P_DEVICE &&
-+ if (sdata->vif.type != NL80211_IFTYPE_P2P_DEVICE &&
- sdata->vif.type != NL80211_IFTYPE_NAN)
- DEBUGFS_ADD(aqm);
- }
---- a/net/mac80211/debugfs_sta.c
-+++ b/net/mac80211/debugfs_sta.c
-@@ -1057,10 +1057,8 @@ void ieee80211_sta_debugfs_add(struct st
- DEBUGFS_ADD_COUNTER(rx_fragments, deflink.rx_stats.fragments);
- DEBUGFS_ADD_COUNTER(tx_filtered, deflink.status_stats.filtered);
-
-- if (local->ops->wake_tx_queue) {
-- DEBUGFS_ADD(aqm);
-- DEBUGFS_ADD(airtime);
-- }
-+ DEBUGFS_ADD(aqm);
-+ DEBUGFS_ADD(airtime);
-
- if (wiphy_ext_feature_isset(local->hw.wiphy,
- NL80211_EXT_FEATURE_AQL))
---- a/net/mac80211/ieee80211_i.h
-+++ b/net/mac80211/ieee80211_i.h
-@@ -2294,7 +2294,6 @@ void ieee80211_wake_queue_by_reason(stru
- void ieee80211_stop_queue_by_reason(struct ieee80211_hw *hw, int queue,
- enum queue_stop_reason reason,
- bool refcounted);
--void ieee80211_propagate_queue_wake(struct ieee80211_local *local, int queue);
- void ieee80211_add_pending_skb(struct ieee80211_local *local,
- struct sk_buff *skb);
- void ieee80211_add_pending_skbs(struct ieee80211_local *local,
---- a/net/mac80211/iface.c
-+++ b/net/mac80211/iface.c
-@@ -460,12 +460,6 @@ static void ieee80211_do_stop(struct iee
- if (cancel_scan)
- ieee80211_scan_cancel(local);
-
-- /*
-- * Stop TX on this interface first.
-- */
-- if (!local->ops->wake_tx_queue && sdata->dev)
-- netif_tx_stop_all_queues(sdata->dev);
--
- ieee80211_roc_purge(local, sdata);
-
- switch (sdata->vif.type) {
-@@ -813,13 +807,6 @@ static void ieee80211_uninit(struct net_
- ieee80211_teardown_sdata(IEEE80211_DEV_TO_SUB_IF(dev));
- }
-
--static u16 ieee80211_netdev_select_queue(struct net_device *dev,
-- struct sk_buff *skb,
-- struct net_device *sb_dev)
--{
-- return ieee80211_select_queue(IEEE80211_DEV_TO_SUB_IF(dev), skb);
--}
--
- static void
- ieee80211_get_stats64(struct net_device *dev, struct rtnl_link_stats64 *stats)
- {
-@@ -833,7 +820,6 @@ static const struct net_device_ops ieee8
- .ndo_start_xmit = ieee80211_subif_start_xmit,
- .ndo_set_rx_mode = ieee80211_set_multicast_list,
- .ndo_set_mac_address = ieee80211_change_mac,
-- .ndo_select_queue = ieee80211_netdev_select_queue,
- .ndo_get_stats64 = ieee80211_get_stats64,
- };
-
-@@ -941,7 +927,6 @@ static const struct net_device_ops ieee8
- .ndo_start_xmit = ieee80211_subif_start_xmit_8023,
- .ndo_set_rx_mode = ieee80211_set_multicast_list,
- .ndo_set_mac_address = ieee80211_change_mac,
-- .ndo_select_queue = ieee80211_netdev_select_queue,
- .ndo_get_stats64 = ieee80211_get_stats64,
- .ndo_fill_forward_path = ieee80211_netdev_fill_forward_path,
- };
-@@ -1443,35 +1428,6 @@ int ieee80211_do_open(struct wireless_de
-
- ieee80211_recalc_ps(local);
-
-- if (sdata->vif.type == NL80211_IFTYPE_MONITOR ||
-- sdata->vif.type == NL80211_IFTYPE_AP_VLAN ||
-- local->ops->wake_tx_queue) {
-- /* XXX: for AP_VLAN, actually track AP queues */
-- if (dev)
-- netif_tx_start_all_queues(dev);
-- } else if (dev) {
-- unsigned long flags;
-- int n_acs = IEEE80211_NUM_ACS;
-- int ac;
--
-- if (local->hw.queues < IEEE80211_NUM_ACS)
-- n_acs = 1;
--
-- spin_lock_irqsave(&local->queue_stop_reason_lock, flags);
-- if (sdata->vif.cab_queue == IEEE80211_INVAL_HW_QUEUE ||
-- (local->queue_stop_reasons[sdata->vif.cab_queue] == 0 &&
-- skb_queue_empty(&local->pending[sdata->vif.cab_queue]))) {
-- for (ac = 0; ac < n_acs; ac++) {
-- int ac_queue = sdata->vif.hw_queue[ac];
--
-- if (local->queue_stop_reasons[ac_queue] == 0 &&
-- skb_queue_empty(&local->pending[ac_queue]))
-- netif_start_subqueue(dev, ac);
-- }
-- }
-- spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags);
-- }
--
- set_bit(SDATA_STATE_RUNNING, &sdata->state);
-
- return 0;
-@@ -1501,17 +1457,12 @@ static void ieee80211_if_setup(struct ne
- {
- ether_setup(dev);
- dev->priv_flags &= ~IFF_TX_SKB_SHARING;
-+ dev->priv_flags |= IFF_NO_QUEUE;
- dev->netdev_ops = &ieee80211_dataif_ops;
- dev->needs_free_netdev = true;
- dev->priv_destructor = ieee80211_if_free;
- }
-
--static void ieee80211_if_setup_no_queue(struct net_device *dev)
--{
-- ieee80211_if_setup(dev);
-- dev->priv_flags |= IFF_NO_QUEUE;
--}
--
- static void ieee80211_iface_process_skb(struct ieee80211_local *local,
- struct ieee80211_sub_if_data *sdata,
- struct sk_buff *skb)
-@@ -2096,9 +2047,7 @@ int ieee80211_if_add(struct ieee80211_lo
- struct net_device *ndev = NULL;
- struct ieee80211_sub_if_data *sdata = NULL;
- struct txq_info *txqi;
-- void (*if_setup)(struct net_device *dev);
- int ret, i;
-- int txqs = 1;
-
- ASSERT_RTNL();
-
-@@ -2121,30 +2070,18 @@ int ieee80211_if_add(struct ieee80211_lo
- sizeof(void *));
- int txq_size = 0;
-
-- if (local->ops->wake_tx_queue &&
-- type != NL80211_IFTYPE_AP_VLAN &&
-+ if (type != NL80211_IFTYPE_AP_VLAN &&
- (type != NL80211_IFTYPE_MONITOR ||
- (params->flags & MONITOR_FLAG_ACTIVE)))
- txq_size += sizeof(struct txq_info) +
- local->hw.txq_data_size;
-
-- if (local->ops->wake_tx_queue) {
-- if_setup = ieee80211_if_setup_no_queue;
-- } else {
-- if_setup = ieee80211_if_setup;
-- if (local->hw.queues >= IEEE80211_NUM_ACS)
-- txqs = IEEE80211_NUM_ACS;
-- }
--
- ndev = alloc_netdev_mqs(size + txq_size,
- name, name_assign_type,
-- if_setup, txqs, 1);
-+ ieee80211_if_setup, 1, 1);
- if (!ndev)
- return -ENOMEM;
-
-- if (!local->ops->wake_tx_queue && local->hw.wiphy->tx_queue_len)
-- ndev->tx_queue_len = local->hw.wiphy->tx_queue_len;
--
- dev_net_set(ndev, wiphy_net(local->hw.wiphy));
-
- ndev->tstats = netdev_alloc_pcpu_stats(struct pcpu_sw_netstats);
---- a/net/mac80211/main.c
-+++ b/net/mac80211/main.c
-@@ -630,7 +630,7 @@ struct ieee80211_hw *ieee80211_alloc_hw_
-
- if (WARN_ON(!ops->tx || !ops->start || !ops->stop || !ops->config ||
- !ops->add_interface || !ops->remove_interface ||
-- !ops->configure_filter))
-+ !ops->configure_filter || !ops->wake_tx_queue))
- return NULL;
-
- if (WARN_ON(ops->sta_state && (ops->sta_add || ops->sta_remove)))
-@@ -719,9 +719,7 @@ struct ieee80211_hw *ieee80211_alloc_hw_
- if (!ops->set_key)
- wiphy->flags |= WIPHY_FLAG_IBSS_RSN;
-
-- if (ops->wake_tx_queue)
-- wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_TXQS);
--
-+ wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_TXQS);
- wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_RRM);
-
- wiphy->bss_priv_size = sizeof(struct ieee80211_bss);
-@@ -834,10 +832,7 @@ struct ieee80211_hw *ieee80211_alloc_hw_
- atomic_set(&local->agg_queue_stop[i], 0);
- }
- tasklet_setup(&local->tx_pending_tasklet, ieee80211_tx_pending);
--
-- if (ops->wake_tx_queue)
-- tasklet_setup(&local->wake_txqs_tasklet, ieee80211_wake_txqs);
--
-+ tasklet_setup(&local->wake_txqs_tasklet, ieee80211_wake_txqs);
- tasklet_setup(&local->tasklet, ieee80211_tasklet_handler);
-
- skb_queue_head_init(&local->skb_queue);
---- a/net/mac80211/rx.c
-+++ b/net/mac80211/rx.c
-@@ -1571,9 +1571,6 @@ static void sta_ps_start(struct sta_info
-
- ieee80211_clear_fast_xmit(sta);
-
-- if (!sta->sta.txq[0])
-- return;
--
- for (tid = 0; tid < IEEE80211_NUM_TIDS; tid++) {
- struct ieee80211_txq *txq = sta->sta.txq[tid];
- struct txq_info *txqi = to_txq_info(txq);
---- a/net/mac80211/sta_info.c
-+++ b/net/mac80211/sta_info.c
-@@ -140,17 +140,15 @@ static void __cleanup_single_sta(struct
- atomic_dec(&ps->num_sta_ps);
- }
-
-- if (sta->sta.txq[0]) {
-- for (i = 0; i < ARRAY_SIZE(sta->sta.txq); i++) {
-- struct txq_info *txqi;
-+ for (i = 0; i < ARRAY_SIZE(sta->sta.txq); i++) {
-+ struct txq_info *txqi;
-
-- if (!sta->sta.txq[i])
-- continue;
-+ if (!sta->sta.txq[i])
-+ continue;
-
-- txqi = to_txq_info(sta->sta.txq[i]);
-+ txqi = to_txq_info(sta->sta.txq[i]);
-
-- ieee80211_txq_purge(local, txqi);
-- }
-+ ieee80211_txq_purge(local, txqi);
- }
-
- for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) {
-@@ -425,8 +423,7 @@ void sta_info_free(struct ieee80211_loca
-
- sta_dbg(sta->sdata, "Destroyed STA %pM\n", sta->sta.addr);
-
-- if (sta->sta.txq[0])
-- kfree(to_txq_info(sta->sta.txq[0]));
-+ kfree(to_txq_info(sta->sta.txq[0]));
- kfree(rcu_dereference_raw(sta->sta.rates));
- #ifdef CPTCFG_MAC80211_MESH
- kfree(sta->mesh);
-@@ -527,6 +524,8 @@ __sta_info_alloc(struct ieee80211_sub_if
- struct ieee80211_local *local = sdata->local;
- struct ieee80211_hw *hw = &local->hw;
- struct sta_info *sta;
-+ void *txq_data;
-+ int size;
- int i;
-
- sta = kzalloc(sizeof(*sta) + hw->sta_data_size, gfp);
-@@ -597,21 +596,18 @@ __sta_info_alloc(struct ieee80211_sub_if
-
- sta->last_connected = ktime_get_seconds();
-
-- if (local->ops->wake_tx_queue) {
-- void *txq_data;
-- int size = sizeof(struct txq_info) +
-- ALIGN(hw->txq_data_size, sizeof(void *));
-+ size = sizeof(struct txq_info) +
-+ ALIGN(hw->txq_data_size, sizeof(void *));
-
-- txq_data = kcalloc(ARRAY_SIZE(sta->sta.txq), size, gfp);
-- if (!txq_data)
-- goto free;
-+ txq_data = kcalloc(ARRAY_SIZE(sta->sta.txq), size, gfp);
-+ if (!txq_data)
-+ goto free;
-
-- for (i = 0; i < ARRAY_SIZE(sta->sta.txq); i++) {
-- struct txq_info *txq = txq_data + i * size;
-+ for (i = 0; i < ARRAY_SIZE(sta->sta.txq); i++) {
-+ struct txq_info *txq = txq_data + i * size;
-
-- /* might not do anything for the bufferable MMPDU TXQ */
-- ieee80211_txq_init(sdata, sta, txq, i);
-- }
-+ /* might not do anything for the (bufferable) MMPDU TXQ */
-+ ieee80211_txq_init(sdata, sta, txq, i);
- }
-
- if (sta_prepare_rate_control(local, sta, gfp))
-@@ -685,8 +681,7 @@ __sta_info_alloc(struct ieee80211_sub_if
- return sta;
-
- free_txq:
-- if (sta->sta.txq[0])
-- kfree(to_txq_info(sta->sta.txq[0]));
-+ kfree(to_txq_info(sta->sta.txq[0]));
- free:
- sta_info_free_link(&sta->deflink);
- #ifdef CPTCFG_MAC80211_MESH
-@@ -1960,9 +1955,6 @@ ieee80211_sta_ps_deliver_response(struct
- * TIM recalculation.
- */
-
-- if (!sta->sta.txq[0])
-- return;
--
- for (tid = 0; tid < ARRAY_SIZE(sta->sta.txq); tid++) {
- if (!sta->sta.txq[tid] ||
- !(driver_release_tids & BIT(tid)) ||
-@@ -2447,7 +2439,7 @@ static void sta_set_tidstats(struct sta_
- tidstats->tx_msdu_failed = sta->deflink.status_stats.msdu_failed[tid];
- }
-
-- if (local->ops->wake_tx_queue && tid < IEEE80211_NUM_TIDS) {
-+ if (tid < IEEE80211_NUM_TIDS) {
- spin_lock_bh(&local->fq.lock);
- rcu_read_lock();
-
-@@ -2775,9 +2767,6 @@ unsigned long ieee80211_sta_last_active(
-
- static void sta_update_codel_params(struct sta_info *sta, u32 thr)
- {
-- if (!sta->sdata->local->ops->wake_tx_queue)
-- return;
--
- if (thr && thr < STA_SLOW_THRESHOLD * sta->local->num_sta) {
- sta->cparams.target = MS2TIME(50);
- sta->cparams.interval = MS2TIME(300);
---- a/net/mac80211/tdls.c
-+++ b/net/mac80211/tdls.c
-@@ -1016,7 +1016,6 @@ ieee80211_tdls_prep_mgmt_packet(struct w
- skb->priority = 256 + 5;
- break;
- }
-- skb_set_queue_mapping(skb, ieee80211_select_queue(sdata, skb));
-
- /*
- * Set the WLAN_TDLS_TEARDOWN flag to indicate a teardown in progress.
---- a/net/mac80211/tx.c
-+++ b/net/mac80211/tx.c
-@@ -1600,9 +1600,6 @@ int ieee80211_txq_setup_flows(struct iee
- bool supp_vht = false;
- enum nl80211_band band;
-
-- if (!local->ops->wake_tx_queue)
-- return 0;
--
- ret = fq_init(fq, 4096);
- if (ret)
- return ret;
-@@ -1650,9 +1647,6 @@ void ieee80211_txq_teardown_flows(struct
- {
- struct fq *fq = &local->fq;
-
-- if (!local->ops->wake_tx_queue)
-- return;
--
- kfree(local->cvars);
- local->cvars = NULL;
-
-@@ -1669,8 +1663,7 @@ static bool ieee80211_queue_skb(struct i
- struct ieee80211_vif *vif;
- struct txq_info *txqi;
-
-- if (!local->ops->wake_tx_queue ||
-- sdata->vif.type == NL80211_IFTYPE_MONITOR)
-+ if (sdata->vif.type == NL80211_IFTYPE_MONITOR)
- return false;
-
- if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
-@@ -4193,12 +4186,7 @@ void __ieee80211_subif_start_xmit(struct
- if (IS_ERR(sta))
- sta = NULL;
-
-- if (local->ops->wake_tx_queue) {
-- u16 queue = __ieee80211_select_queue(sdata, sta, skb);
-- skb_set_queue_mapping(skb, queue);
-- skb_get_hash(skb);
-- }
--
-+ skb_set_queue_mapping(skb, ieee80211_select_queue(sdata, sta, skb));
- ieee80211_aggr_check(sdata, sta, skb);
-
- sk_pacing_shift_update(skb->sk, sdata->local->hw.tx_sk_pacing_shift);
-@@ -4509,11 +4497,7 @@ static void ieee80211_8023_xmit(struct i
- struct tid_ampdu_tx *tid_tx;
- u8 tid;
-
-- if (local->ops->wake_tx_queue) {
-- u16 queue = __ieee80211_select_queue(sdata, sta, skb);
-- skb_set_queue_mapping(skb, queue);
-- skb_get_hash(skb);
-- }
-+ skb_set_queue_mapping(skb, ieee80211_select_queue(sdata, sta, skb));
-
- if (unlikely(test_bit(SCAN_SW_SCANNING, &local->scanning)) &&
- test_bit(SDATA_STATE_OFFCHANNEL, &sdata->state))
-@@ -4767,9 +4751,6 @@ void ieee80211_tx_pending(struct tasklet
- if (!txok)
- break;
- }
--
-- if (skb_queue_empty(&local->pending[i]))
-- ieee80211_propagate_queue_wake(local, i);
- }
- spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags);
-
-@@ -5962,10 +5943,9 @@ int ieee80211_tx_control_port(struct wip
- }
-
- if (!IS_ERR(sta)) {
-- u16 queue = __ieee80211_select_queue(sdata, sta, skb);
-+ u16 queue = ieee80211_select_queue(sdata, sta, skb);
-
- skb_set_queue_mapping(skb, queue);
-- skb_get_hash(skb);
-
- /*
- * for MLO STA, the SA should be the AP MLD address, but
---- a/net/mac80211/util.c
-+++ b/net/mac80211/util.c
-@@ -444,39 +444,6 @@ void ieee80211_wake_txqs(struct tasklet_
- spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags);
- }
-
--void ieee80211_propagate_queue_wake(struct ieee80211_local *local, int queue)
--{
-- struct ieee80211_sub_if_data *sdata;
-- int n_acs = IEEE80211_NUM_ACS;
--
-- if (local->ops->wake_tx_queue)
-- return;
--
-- if (local->hw.queues < IEEE80211_NUM_ACS)
-- n_acs = 1;
--
-- list_for_each_entry_rcu(sdata, &local->interfaces, list) {
-- int ac;
--
-- if (!sdata->dev)
-- continue;
--
-- if (sdata->vif.cab_queue != IEEE80211_INVAL_HW_QUEUE &&
-- local->queue_stop_reasons[sdata->vif.cab_queue] != 0)
-- continue;
--
-- for (ac = 0; ac < n_acs; ac++) {
-- int ac_queue = sdata->vif.hw_queue[ac];
--
-- if (ac_queue == queue ||
-- (sdata->vif.cab_queue == queue &&
-- local->queue_stop_reasons[ac_queue] == 0 &&
-- skb_queue_empty(&local->pending[ac_queue])))
-- netif_wake_subqueue(sdata->dev, ac);
-- }
-- }
--}
--
- static void __ieee80211_wake_queue(struct ieee80211_hw *hw, int queue,
- enum queue_stop_reason reason,
- bool refcounted,
-@@ -507,11 +474,7 @@ static void __ieee80211_wake_queue(struc
- /* someone still has this queue stopped */
- return;
-
-- if (skb_queue_empty(&local->pending[queue])) {
-- rcu_read_lock();
-- ieee80211_propagate_queue_wake(local, queue);
-- rcu_read_unlock();
-- } else
-+ if (!skb_queue_empty(&local->pending[queue]))
- tasklet_schedule(&local->tx_pending_tasklet);
-
- /*
-@@ -521,12 +484,10 @@ static void __ieee80211_wake_queue(struc
- * release someone's lock, but it is fine because all the callers of
- * __ieee80211_wake_queue call it right before releasing the lock.
- */
-- if (local->ops->wake_tx_queue) {
-- if (reason == IEEE80211_QUEUE_STOP_REASON_DRIVER)
-- tasklet_schedule(&local->wake_txqs_tasklet);
-- else
-- _ieee80211_wake_txqs(local, flags);
-- }
-+ if (reason == IEEE80211_QUEUE_STOP_REASON_DRIVER)
-+ tasklet_schedule(&local->wake_txqs_tasklet);
-+ else
-+ _ieee80211_wake_txqs(local, flags);
- }
-
- void ieee80211_wake_queue_by_reason(struct ieee80211_hw *hw, int queue,
-@@ -554,8 +515,6 @@ static void __ieee80211_stop_queue(struc
- bool refcounted)
- {
- struct ieee80211_local *local = hw_to_local(hw);
-- struct ieee80211_sub_if_data *sdata;
-- int n_acs = IEEE80211_NUM_ACS;
-
- trace_stop_queue(local, queue, reason);
-
-@@ -567,27 +526,7 @@ static void __ieee80211_stop_queue(struc
- else
- local->q_stop_reasons[queue][reason]++;
-
-- if (__test_and_set_bit(reason, &local->queue_stop_reasons[queue]))
-- return;
--
-- if (local->hw.queues < IEEE80211_NUM_ACS)
-- n_acs = 1;
--
-- rcu_read_lock();
-- list_for_each_entry_rcu(sdata, &local->interfaces, list) {
-- int ac;
--
-- if (!sdata->dev)
-- continue;
--
-- for (ac = 0; ac < n_acs; ac++) {
-- if (!local->ops->wake_tx_queue &&
-- (sdata->vif.hw_queue[ac] == queue ||
-- sdata->vif.cab_queue == queue))
-- netif_stop_subqueue(sdata->dev, ac);
-- }
-- }
-- rcu_read_unlock();
-+ set_bit(reason, &local->queue_stop_reasons[queue]);
- }
-
- void ieee80211_stop_queue_by_reason(struct ieee80211_hw *hw, int queue,
---- a/net/mac80211/wme.c
-+++ b/net/mac80211/wme.c
-@@ -122,6 +122,9 @@ u16 ieee80211_select_queue_80211(struct
- struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
- u8 *p;
-
-+ /* Ensure hash is set prior to potential SW encryption */
-+ skb_get_hash(skb);
-+
- if ((info->control.flags & IEEE80211_TX_CTRL_DONT_REORDER) ||
- local->hw.queues < IEEE80211_NUM_ACS)
- return 0;
-@@ -141,13 +144,16 @@ u16 ieee80211_select_queue_80211(struct
- return ieee80211_downgrade_queue(sdata, NULL, skb);
- }
-
--u16 __ieee80211_select_queue(struct ieee80211_sub_if_data *sdata,
-- struct sta_info *sta, struct sk_buff *skb)
-+u16 ieee80211_select_queue(struct ieee80211_sub_if_data *sdata,
-+ struct sta_info *sta, struct sk_buff *skb)
- {
- const struct ethhdr *eth = (void *)skb->data;
- struct mac80211_qos_map *qos_map;
- bool qos;
-
-+ /* Ensure hash is set prior to potential SW encryption */
-+ skb_get_hash(skb);
-+
- /* all mesh/ocb stations are required to support WME */
- if ((sdata->vif.type == NL80211_IFTYPE_MESH_POINT &&
- !is_multicast_ether_addr(eth->h_dest)) ||
-@@ -178,59 +184,6 @@ u16 __ieee80211_select_queue(struct ieee
- return ieee80211_downgrade_queue(sdata, sta, skb);
- }
-
--
--/* Indicate which queue to use. */
--u16 ieee80211_select_queue(struct ieee80211_sub_if_data *sdata,
-- struct sk_buff *skb)
--{
-- struct ieee80211_local *local = sdata->local;
-- struct sta_info *sta = NULL;
-- const u8 *ra = NULL;
-- u16 ret;
--
-- /* when using iTXQ, we can do this later */
-- if (local->ops->wake_tx_queue)
-- return 0;
--
-- if (local->hw.queues < IEEE80211_NUM_ACS || skb->len < 6) {
-- skb->priority = 0; /* required for correct WPA/11i MIC */
-- return 0;
-- }
--
-- rcu_read_lock();
-- switch (sdata->vif.type) {
-- case NL80211_IFTYPE_AP_VLAN:
-- sta = rcu_dereference(sdata->u.vlan.sta);
-- if (sta)
-- break;
-- fallthrough;
-- case NL80211_IFTYPE_AP:
-- ra = skb->data;
-- break;
-- case NL80211_IFTYPE_STATION:
-- /* might be a TDLS station */
-- sta = sta_info_get(sdata, skb->data);
-- if (sta)
-- break;
--
-- ra = sdata->deflink.u.mgd.bssid;
-- break;
-- case NL80211_IFTYPE_ADHOC:
-- ra = skb->data;
-- break;
-- default:
-- break;
-- }
--
-- if (!sta && ra && !is_multicast_ether_addr(ra))
-- sta = sta_info_get(sdata, ra);
--
-- ret = __ieee80211_select_queue(sdata, sta, skb);
--
-- rcu_read_unlock();
-- return ret;
--}
--
- /**
- * ieee80211_set_qos_hdr - Fill in the QoS header if there is one.
- *
---- a/net/mac80211/wme.h
-+++ b/net/mac80211/wme.h
-@@ -13,10 +13,8 @@
- u16 ieee80211_select_queue_80211(struct ieee80211_sub_if_data *sdata,
- struct sk_buff *skb,
- struct ieee80211_hdr *hdr);
--u16 __ieee80211_select_queue(struct ieee80211_sub_if_data *sdata,
-- struct sta_info *sta, struct sk_buff *skb);
- u16 ieee80211_select_queue(struct ieee80211_sub_if_data *sdata,
-- struct sk_buff *skb);
-+ struct sta_info *sta, struct sk_buff *skb);
- void ieee80211_set_qos_hdr(struct ieee80211_sub_if_data *sdata,
- struct sk_buff *skb);
-
diff --git a/package/kernel/mac80211/patches/subsys/306-04-v6.2-wifi-realtek-remove-duplicated-wake_tx_queue.patch b/package/kernel/mac80211/patches/subsys/306-04-v6.2-wifi-realtek-remove-duplicated-wake_tx_queue.patch
deleted file mode 100644
index f0dfc75a78..0000000000
--- a/package/kernel/mac80211/patches/subsys/306-04-v6.2-wifi-realtek-remove-duplicated-wake_tx_queue.patch
+++ /dev/null
@@ -1,32 +0,0 @@
-From: Johannes Berg <johannes.berg@intel.com>
-Date: Mon, 10 Oct 2022 19:17:46 +0200
-Subject: [PATCH] wifi: realtek: remove duplicated wake_tx_queue
-
-By accident, the previous patch duplicated the initialization
-of the wake_tx_queue callback. Fix that by removing the new
-initializations.
-
-Fixes: a790cc3a4fad ("wifi: mac80211: add wake_tx_queue callback to drivers")
-Signed-off-by: Johannes Berg <johannes.berg@intel.com>
----
-
---- a/drivers/net/wireless/realtek/rtw88/mac80211.c
-+++ b/drivers/net/wireless/realtek/rtw88/mac80211.c
-@@ -896,7 +896,6 @@ static void rtw_ops_sta_rc_update(struct
-
- const struct ieee80211_ops rtw_ops = {
- .tx = rtw_ops_tx,
-- .wake_tx_queue = ieee80211_handle_wake_tx_queue,
- .wake_tx_queue = rtw_ops_wake_tx_queue,
- .start = rtw_ops_start,
- .stop = rtw_ops_stop,
---- a/drivers/net/wireless/realtek/rtw89/mac80211.c
-+++ b/drivers/net/wireless/realtek/rtw89/mac80211.c
-@@ -918,7 +918,6 @@ static int rtw89_ops_set_tid_config(stru
-
- const struct ieee80211_ops rtw89_ops = {
- .tx = rtw89_ops_tx,
-- .wake_tx_queue = ieee80211_handle_wake_tx_queue,
- .wake_tx_queue = rtw89_ops_wake_tx_queue,
- .start = rtw89_ops_start,
- .stop = rtw89_ops_stop,
diff --git a/package/kernel/mac80211/patches/subsys/338-mac80211-split-mesh-fast-tx-cache-into-local-proxied.patch b/package/kernel/mac80211/patches/subsys/310-mac80211-split-mesh-fast-tx-cache-into-local-proxied.patch
index f7391a5809..f362751e0a 100644
--- a/package/kernel/mac80211/patches/subsys/338-mac80211-split-mesh-fast-tx-cache-into-local-proxied.patch
+++ b/package/kernel/mac80211/patches/subsys/310-mac80211-split-mesh-fast-tx-cache-into-local-proxied.patch
@@ -14,7 +14,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
--- a/net/mac80211/mesh.c
+++ b/net/mac80211/mesh.c
-@@ -703,6 +703,9 @@ bool ieee80211_mesh_xmit_fast(struct iee
+@@ -765,6 +765,9 @@ bool ieee80211_mesh_xmit_fast(struct iee
struct sk_buff *skb, u32 ctrl_flags)
{
struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
@@ -24,7 +24,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
struct ieee80211_mesh_fast_tx *entry;
struct ieee80211s_hdr *meshhdr;
u8 sa[ETH_ALEN] __aligned(2);
-@@ -738,7 +741,10 @@ bool ieee80211_mesh_xmit_fast(struct iee
+@@ -800,7 +803,10 @@ bool ieee80211_mesh_xmit_fast(struct iee
return false;
}
@@ -38,7 +38,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
--- a/net/mac80211/mesh.h
+++ b/net/mac80211/mesh.h
-@@ -133,9 +133,33 @@ struct mesh_path {
+@@ -134,9 +134,33 @@ struct mesh_path {
#define MESH_FAST_TX_CACHE_TIMEOUT 8000 /* msecs */
/**
@@ -73,7 +73,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
* @fast_tx: base fast_tx data
* @hdr: cached mesh and rfc1042 headers
* @hdrlen: length of mesh + rfc1042
-@@ -146,7 +170,7 @@ struct mesh_path {
+@@ -147,7 +171,7 @@ struct mesh_path {
*/
struct ieee80211_mesh_fast_tx {
struct rhash_head rhash;
@@ -82,7 +82,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
struct ieee80211_fast_tx fast_tx;
u8 hdr[sizeof(struct ieee80211s_hdr) + sizeof(rfc1042_header)];
-@@ -329,7 +353,8 @@ void mesh_path_tx_root_frame(struct ieee
+@@ -334,7 +358,8 @@ void mesh_path_tx_root_frame(struct ieee
bool mesh_action_is_path_sel(struct ieee80211_mgmt *mgmt);
struct ieee80211_mesh_fast_tx *
@@ -189,7 +189,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
-@@ -2726,7 +2726,10 @@ ieee80211_rx_mesh_fast_forward(struct ie
+@@ -2727,7 +2727,10 @@ ieee80211_rx_mesh_fast_forward(struct ie
struct sk_buff *skb, int hdrlen)
{
struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
@@ -201,7 +201,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
struct ieee80211s_hdr *mesh_hdr;
struct tid_ampdu_tx *tid_tx;
struct sta_info *sta;
-@@ -2735,9 +2738,13 @@ ieee80211_rx_mesh_fast_forward(struct ie
+@@ -2736,9 +2739,13 @@ ieee80211_rx_mesh_fast_forward(struct ie
mesh_hdr = (struct ieee80211s_hdr *)(skb->data + sizeof(eth));
if ((mesh_hdr->flags & MESH_FLAGS_AE) == MESH_FLAGS_AE_A5_A6)
diff --git a/package/kernel/mac80211/patches/subsys/310-v6.2-mac80211-add-support-for-restricting-netdev-features.patch b/package/kernel/mac80211/patches/subsys/310-v6.2-mac80211-add-support-for-restricting-netdev-features.patch
deleted file mode 100644
index 812b12189c..0000000000
--- a/package/kernel/mac80211/patches/subsys/310-v6.2-mac80211-add-support-for-restricting-netdev-features.patch
+++ /dev/null
@@ -1,506 +0,0 @@
-From: Felix Fietkau <nbd@nbd.name>
-Date: Sun, 9 Oct 2022 20:15:46 +0200
-Subject: [PATCH] mac80211: add support for restricting netdev features per vif
-
-This can be used to selectively disable feature flags for checksum offload,
-scatter/gather or GSO by changing vif->netdev_features.
-Removing features from vif->netdev_features does not affect the netdev
-features themselves, but instead fixes up skbs in the tx path so that the
-offloads are not needed in the driver.
-
-Aside from making it easier to deal with vif type based hardware limitations,
-this also makes it possible to optimize performance on hardware without native
-GSO support by declaring GSO support in hw->netdev_features and removing it
-from vif->netdev_features. This allows mac80211 to handle GSO segmentation
-after the sta lookup, but before itxq enqueue, thus reducing the number of
-unnecessary sta lookups, as well as some other per-packet processing.
-
-Signed-off-by: Felix Fietkau <nbd@nbd.name>
----
-
---- a/include/net/fq_impl.h
-+++ b/include/net/fq_impl.h
-@@ -200,6 +200,7 @@ static void fq_tin_enqueue(struct fq *fq
- fq_skb_free_t free_func)
- {
- struct fq_flow *flow;
-+ struct sk_buff *next;
- bool oom;
-
- lockdep_assert_held(&fq->lock);
-@@ -214,11 +215,15 @@ static void fq_tin_enqueue(struct fq *fq
- }
-
- flow->tin = tin;
-- flow->backlog += skb->len;
-- tin->backlog_bytes += skb->len;
-- tin->backlog_packets++;
-- fq->memory_usage += skb->truesize;
-- fq->backlog++;
-+ skb_list_walk_safe(skb, skb, next) {
-+ skb_mark_not_on_list(skb);
-+ flow->backlog += skb->len;
-+ tin->backlog_bytes += skb->len;
-+ tin->backlog_packets++;
-+ fq->memory_usage += skb->truesize;
-+ fq->backlog++;
-+ __skb_queue_tail(&flow->queue, skb);
-+ }
-
- if (list_empty(&flow->flowchain)) {
- flow->deficit = fq->quantum;
-@@ -226,7 +231,6 @@ static void fq_tin_enqueue(struct fq *fq
- &tin->new_flows);
- }
-
-- __skb_queue_tail(&flow->queue, skb);
- oom = (fq->memory_usage > fq->memory_limit);
- while (fq->backlog > fq->limit || oom) {
- flow = fq_find_fattest_flow(fq);
---- a/include/net/mac80211.h
-+++ b/include/net/mac80211.h
-@@ -1807,6 +1807,10 @@ struct ieee80211_vif_cfg {
- * @addr: address of this interface
- * @p2p: indicates whether this AP or STA interface is a p2p
- * interface, i.e. a GO or p2p-sta respectively
-+ * @netdev_features: tx netdev features supported by the hardware for this
-+ * vif. mac80211 initializes this to hw->netdev_features, and the driver
-+ * can mask out specific tx features. mac80211 will handle software fixup
-+ * for masked offloads (GSO, CSUM)
- * @driver_flags: flags/capabilities the driver has for this interface,
- * these need to be set (or cleared) when the interface is added
- * or, if supported by the driver, the interface type is changed
-@@ -1846,6 +1850,7 @@ struct ieee80211_vif {
-
- struct ieee80211_txq *txq;
-
-+ netdev_features_t netdev_features;
- u32 driver_flags;
- u32 offload_flags;
-
---- a/net/mac80211/iface.c
-+++ b/net/mac80211/iface.c
-@@ -2181,6 +2181,7 @@ int ieee80211_if_add(struct ieee80211_lo
- ndev->priv_flags |= IFF_LIVE_ADDR_CHANGE;
- ndev->hw_features |= ndev->features &
- MAC80211_SUPPORTED_FEATURES_TX;
-+ sdata->vif.netdev_features = local->hw.netdev_features;
-
- netdev_set_default_ethtool_ops(ndev, &ieee80211_ethtool_ops);
-
---- a/net/mac80211/tx.c
-+++ b/net/mac80211/tx.c
-@@ -1356,7 +1356,11 @@ static struct txq_info *ieee80211_get_tx
-
- static void ieee80211_set_skb_enqueue_time(struct sk_buff *skb)
- {
-- IEEE80211_SKB_CB(skb)->control.enqueue_time = codel_get_time();
-+ struct sk_buff *next;
-+ codel_time_t now = codel_get_time();
-+
-+ skb_list_walk_safe(skb, skb, next)
-+ IEEE80211_SKB_CB(skb)->control.enqueue_time = now;
- }
-
- static u32 codel_skb_len_func(const struct sk_buff *skb)
-@@ -3579,55 +3583,79 @@ ieee80211_xmit_fast_finish(struct ieee80
- return TX_CONTINUE;
- }
-
--static bool ieee80211_xmit_fast(struct ieee80211_sub_if_data *sdata,
-- struct sta_info *sta,
-- struct ieee80211_fast_tx *fast_tx,
-- struct sk_buff *skb)
-+static netdev_features_t
-+ieee80211_sdata_netdev_features(struct ieee80211_sub_if_data *sdata)
- {
-- struct ieee80211_local *local = sdata->local;
-- u16 ethertype = (skb->data[12] << 8) | skb->data[13];
-- int extra_head = fast_tx->hdr_len - (ETH_HLEN - 2);
-- int hw_headroom = sdata->local->hw.extra_tx_headroom;
-- struct ethhdr eth;
-- struct ieee80211_tx_info *info;
-- struct ieee80211_hdr *hdr = (void *)fast_tx->hdr;
-- struct ieee80211_tx_data tx;
-- ieee80211_tx_result r;
-- struct tid_ampdu_tx *tid_tx = NULL;
-- u8 tid = IEEE80211_NUM_TIDS;
-+ if (sdata->vif.type != NL80211_IFTYPE_AP_VLAN)
-+ return sdata->vif.netdev_features;
-
-- /* control port protocol needs a lot of special handling */
-- if (cpu_to_be16(ethertype) == sdata->control_port_protocol)
-- return false;
-+ if (!sdata->bss)
-+ return 0;
-
-- /* only RFC 1042 SNAP */
-- if (ethertype < ETH_P_802_3_MIN)
-- return false;
-+ sdata = container_of(sdata->bss, struct ieee80211_sub_if_data, u.ap);
-+ return sdata->vif.netdev_features;
-+}
-
-- /* don't handle TX status request here either */
-- if (skb->sk && skb_shinfo(skb)->tx_flags & SKBTX_WIFI_STATUS)
-- return false;
-+static struct sk_buff *
-+ieee80211_tx_skb_fixup(struct sk_buff *skb, netdev_features_t features)
-+{
-+ if (skb_is_gso(skb)) {
-+ struct sk_buff *segs;
-
-- if (hdr->frame_control & cpu_to_le16(IEEE80211_STYPE_QOS_DATA)) {
-- tid = skb->priority & IEEE80211_QOS_CTL_TAG1D_MASK;
-- tid_tx = rcu_dereference(sta->ampdu_mlme.tid_tx[tid]);
-- if (tid_tx) {
-- if (!test_bit(HT_AGG_STATE_OPERATIONAL, &tid_tx->state))
-- return false;
-- if (tid_tx->timeout)
-- tid_tx->last_tx = jiffies;
-- }
-+ segs = skb_gso_segment(skb, features);
-+ if (!segs)
-+ return skb;
-+ if (IS_ERR(segs))
-+ goto free;
-+
-+ consume_skb(skb);
-+ return segs;
- }
-
-- /* after this point (skb is modified) we cannot return false */
-+ if (skb_needs_linearize(skb, features) && __skb_linearize(skb))
-+ goto free;
-+
-+ if (skb->ip_summed == CHECKSUM_PARTIAL) {
-+ int ofs = skb_checksum_start_offset(skb);
-+
-+ if (skb->encapsulation)
-+ skb_set_inner_transport_header(skb, ofs);
-+ else
-+ skb_set_transport_header(skb, ofs);
-+
-+ if (skb_csum_hwoffload_help(skb, features))
-+ goto free;
-+ }
-+
-+ skb_mark_not_on_list(skb);
-+ return skb;
-+
-+free:
-+ kfree_skb(skb);
-+ return NULL;
-+}
-+
-+static void __ieee80211_xmit_fast(struct ieee80211_sub_if_data *sdata,
-+ struct sta_info *sta,
-+ struct ieee80211_fast_tx *fast_tx,
-+ struct sk_buff *skb, u8 tid, bool ampdu)
-+{
-+ struct ieee80211_local *local = sdata->local;
-+ struct ieee80211_hdr *hdr = (void *)fast_tx->hdr;
-+ struct ieee80211_tx_info *info;
-+ struct ieee80211_tx_data tx;
-+ ieee80211_tx_result r;
-+ int hw_headroom = sdata->local->hw.extra_tx_headroom;
-+ int extra_head = fast_tx->hdr_len - (ETH_HLEN - 2);
-+ struct ethhdr eth;
-
- skb = skb_share_check(skb, GFP_ATOMIC);
- if (unlikely(!skb))
-- return true;
-+ return;
-
- if ((hdr->frame_control & cpu_to_le16(IEEE80211_STYPE_QOS_DATA)) &&
- ieee80211_amsdu_aggregate(sdata, sta, fast_tx, skb))
-- return true;
-+ return;
-
- /* will not be crypto-handled beyond what we do here, so use false
- * as the may-encrypt argument for the resize to not account for
-@@ -3636,10 +3664,8 @@ static bool ieee80211_xmit_fast(struct i
- if (unlikely(ieee80211_skb_resize(sdata, skb,
- max_t(int, extra_head + hw_headroom -
- skb_headroom(skb), 0),
-- ENCRYPT_NO))) {
-- kfree_skb(skb);
-- return true;
-- }
-+ ENCRYPT_NO)))
-+ goto free;
-
- memcpy(&eth, skb->data, ETH_HLEN - 2);
- hdr = skb_push(skb, extra_head);
-@@ -3653,7 +3679,7 @@ static bool ieee80211_xmit_fast(struct i
- info->control.vif = &sdata->vif;
- info->flags = IEEE80211_TX_CTL_FIRST_FRAGMENT |
- IEEE80211_TX_CTL_DONTFRAG |
-- (tid_tx ? IEEE80211_TX_CTL_AMPDU : 0);
-+ (ampdu ? IEEE80211_TX_CTL_AMPDU : 0);
- info->control.flags = IEEE80211_TX_CTRL_FAST_XMIT |
- u32_encode_bits(IEEE80211_LINK_UNSPECIFIED,
- IEEE80211_TX_CTRL_MLO_LINK);
-@@ -3677,16 +3703,14 @@ static bool ieee80211_xmit_fast(struct i
- tx.key = fast_tx->key;
-
- if (ieee80211_queue_skb(local, sdata, sta, skb))
-- return true;
-+ return;
-
- tx.skb = skb;
- r = ieee80211_xmit_fast_finish(sdata, sta, fast_tx->pn_offs,
- fast_tx->key, &tx);
- tx.skb = NULL;
-- if (r == TX_DROP) {
-- kfree_skb(skb);
-- return true;
-- }
-+ if (r == TX_DROP)
-+ goto free;
-
- if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
- sdata = container_of(sdata->bss,
-@@ -3694,6 +3718,56 @@ static bool ieee80211_xmit_fast(struct i
-
- __skb_queue_tail(&tx.skbs, skb);
- ieee80211_tx_frags(local, &sdata->vif, sta, &tx.skbs, false);
-+ return;
-+
-+free:
-+ kfree_skb(skb);
-+}
-+
-+static bool ieee80211_xmit_fast(struct ieee80211_sub_if_data *sdata,
-+ struct sta_info *sta,
-+ struct ieee80211_fast_tx *fast_tx,
-+ struct sk_buff *skb)
-+{
-+ u16 ethertype = (skb->data[12] << 8) | skb->data[13];
-+ struct ieee80211_hdr *hdr = (void *)fast_tx->hdr;
-+ struct tid_ampdu_tx *tid_tx = NULL;
-+ struct sk_buff *next;
-+ u8 tid = IEEE80211_NUM_TIDS;
-+
-+ /* control port protocol needs a lot of special handling */
-+ if (cpu_to_be16(ethertype) == sdata->control_port_protocol)
-+ return false;
-+
-+ /* only RFC 1042 SNAP */
-+ if (ethertype < ETH_P_802_3_MIN)
-+ return false;
-+
-+ /* don't handle TX status request here either */
-+ if (skb->sk && skb_shinfo(skb)->tx_flags & SKBTX_WIFI_STATUS)
-+ return false;
-+
-+ if (hdr->frame_control & cpu_to_le16(IEEE80211_STYPE_QOS_DATA)) {
-+ tid = skb->priority & IEEE80211_QOS_CTL_TAG1D_MASK;
-+ tid_tx = rcu_dereference(sta->ampdu_mlme.tid_tx[tid]);
-+ if (tid_tx) {
-+ if (!test_bit(HT_AGG_STATE_OPERATIONAL, &tid_tx->state))
-+ return false;
-+ if (tid_tx->timeout)
-+ tid_tx->last_tx = jiffies;
-+ }
-+ }
-+
-+ /* after this point (skb is modified) we cannot return false */
-+ skb = ieee80211_tx_skb_fixup(skb, ieee80211_sdata_netdev_features(sdata));
-+ if (!skb)
-+ return true;
-+
-+ skb_list_walk_safe(skb, skb, next) {
-+ skb_mark_not_on_list(skb);
-+ __ieee80211_xmit_fast(sdata, sta, fast_tx, skb, tid, tid_tx);
-+ }
-+
- return true;
- }
-
-@@ -4201,31 +4275,14 @@ void __ieee80211_subif_start_xmit(struct
- goto out;
- }
-
-- if (skb_is_gso(skb)) {
-- struct sk_buff *segs;
--
-- segs = skb_gso_segment(skb, 0);
-- if (IS_ERR(segs)) {
-- goto out_free;
-- } else if (segs) {
-- consume_skb(skb);
-- skb = segs;
-- }
-- } else {
-- /* we cannot process non-linear frames on this path */
-- if (skb_linearize(skb))
-- goto out_free;
--
-- /* the frame could be fragmented, software-encrypted, and other
-- * things so we cannot really handle checksum offload with it -
-- * fix it up in software before we handle anything else.
-- */
-- if (skb->ip_summed == CHECKSUM_PARTIAL) {
-- skb_set_transport_header(skb,
-- skb_checksum_start_offset(skb));
-- if (skb_checksum_help(skb))
-- goto out_free;
-- }
-+ /* the frame could be fragmented, software-encrypted, and other
-+ * things so we cannot really handle checksum or GSO offload.
-+ * fix it up in software before we handle anything else.
-+ */
-+ skb = ieee80211_tx_skb_fixup(skb, 0);
-+ if (!skb) {
-+ len = 0;
-+ goto out;
- }
-
- skb_list_walk_safe(skb, skb, next) {
-@@ -4443,9 +4500,11 @@ normal:
- return NETDEV_TX_OK;
- }
-
--static bool ieee80211_tx_8023(struct ieee80211_sub_if_data *sdata,
-- struct sk_buff *skb, struct sta_info *sta,
-- bool txpending)
-+
-+
-+static bool __ieee80211_tx_8023(struct ieee80211_sub_if_data *sdata,
-+ struct sk_buff *skb, struct sta_info *sta,
-+ bool txpending)
- {
- struct ieee80211_local *local = sdata->local;
- struct ieee80211_tx_control control = {};
-@@ -4454,14 +4513,6 @@ static bool ieee80211_tx_8023(struct iee
- unsigned long flags;
- int q = info->hw_queue;
-
-- if (sta)
-- sk_pacing_shift_update(skb->sk, local->hw.tx_sk_pacing_shift);
--
-- ieee80211_tpt_led_trig_tx(local, skb->len);
--
-- if (ieee80211_queue_skb(local, sdata, sta, skb))
-- return true;
--
- spin_lock_irqsave(&local->queue_stop_reason_lock, flags);
-
- if (local->queue_stop_reasons[q] ||
-@@ -4488,6 +4539,26 @@ static bool ieee80211_tx_8023(struct iee
- return true;
- }
-
-+static bool ieee80211_tx_8023(struct ieee80211_sub_if_data *sdata,
-+ struct sk_buff *skb, struct sta_info *sta,
-+ bool txpending)
-+{
-+ struct ieee80211_local *local = sdata->local;
-+ struct sk_buff *next;
-+ bool ret = true;
-+
-+ if (ieee80211_queue_skb(local, sdata, sta, skb))
-+ return true;
-+
-+ skb_list_walk_safe(skb, skb, next) {
-+ skb_mark_not_on_list(skb);
-+ if (!__ieee80211_tx_8023(sdata, skb, sta, txpending))
-+ ret = false;
-+ }
-+
-+ return ret;
-+}
-+
- static void ieee80211_8023_xmit(struct ieee80211_sub_if_data *sdata,
- struct net_device *dev, struct sta_info *sta,
- struct ieee80211_key *key, struct sk_buff *skb)
-@@ -4495,9 +4566,13 @@ static void ieee80211_8023_xmit(struct i
- struct ieee80211_tx_info *info;
- struct ieee80211_local *local = sdata->local;
- struct tid_ampdu_tx *tid_tx;
-+ struct sk_buff *seg, *next;
-+ unsigned int skbs = 0, len = 0;
-+ u16 queue;
- u8 tid;
-
-- skb_set_queue_mapping(skb, ieee80211_select_queue(sdata, sta, skb));
-+ queue = ieee80211_select_queue(sdata, sta, skb);
-+ skb_set_queue_mapping(skb, queue);
-
- if (unlikely(test_bit(SCAN_SW_SCANNING, &local->scanning)) &&
- test_bit(SDATA_STATE_OFFCHANNEL, &sdata->state))
-@@ -4507,9 +4582,6 @@ static void ieee80211_8023_xmit(struct i
- if (unlikely(!skb))
- return;
-
-- info = IEEE80211_SKB_CB(skb);
-- memset(info, 0, sizeof(*info));
--
- ieee80211_aggr_check(sdata, sta, skb);
-
- tid = skb->priority & IEEE80211_QOS_CTL_TAG1D_MASK;
-@@ -4523,22 +4595,20 @@ static void ieee80211_8023_xmit(struct i
- return;
- }
-
-- info->flags |= IEEE80211_TX_CTL_AMPDU;
- if (tid_tx->timeout)
- tid_tx->last_tx = jiffies;
- }
-
-- if (unlikely(skb->sk &&
-- skb_shinfo(skb)->tx_flags & SKBTX_WIFI_STATUS))
-- info->ack_frame_id = ieee80211_store_ack_skb(local, skb,
-- &info->flags, NULL);
-+ skb = ieee80211_tx_skb_fixup(skb, ieee80211_sdata_netdev_features(sdata));
-+ if (!skb)
-+ return;
-
-- info->hw_queue = sdata->vif.hw_queue[skb_get_queue_mapping(skb)];
-+ info = IEEE80211_SKB_CB(skb);
-+ memset(info, 0, sizeof(*info));
-+ if (tid_tx)
-+ info->flags |= IEEE80211_TX_CTL_AMPDU;
-
-- dev_sw_netstats_tx_add(dev, 1, skb->len);
--
-- sta->deflink.tx_stats.bytes[skb_get_queue_mapping(skb)] += skb->len;
-- sta->deflink.tx_stats.packets[skb_get_queue_mapping(skb)]++;
-+ info->hw_queue = sdata->vif.hw_queue[queue];
-
- if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
- sdata = container_of(sdata->bss,
-@@ -4550,6 +4620,24 @@ static void ieee80211_8023_xmit(struct i
- if (key)
- info->control.hw_key = &key->conf;
-
-+ skb_list_walk_safe(skb, seg, next) {
-+ skbs++;
-+ len += seg->len;
-+ if (seg != skb)
-+ memcpy(IEEE80211_SKB_CB(seg), info, sizeof(*info));
-+ }
-+
-+ if (unlikely(skb->sk &&
-+ skb_shinfo(skb)->tx_flags & SKBTX_WIFI_STATUS))
-+ info->ack_frame_id = ieee80211_store_ack_skb(local, skb,
-+ &info->flags, NULL);
-+
-+ dev_sw_netstats_tx_add(dev, skbs, len);
-+ sta->deflink.tx_stats.packets[queue] += skbs;
-+ sta->deflink.tx_stats.bytes[queue] += len;
-+
-+ ieee80211_tpt_led_trig_tx(local, len);
-+
- ieee80211_tx_8023(sdata, skb, sta, false);
-
- return;
-@@ -4591,6 +4679,7 @@ netdev_tx_t ieee80211_subif_start_xmit_8
- key->conf.cipher == WLAN_CIPHER_SUITE_TKIP))
- goto skip_offload;
-
-+ sk_pacing_shift_update(skb->sk, sdata->local->hw.tx_sk_pacing_shift);
- ieee80211_8023_xmit(sdata, dev, sta, key, skb);
- goto out;
-
diff --git a/package/kernel/mac80211/patches/subsys/311-v6.2-wifi-mac80211-fix-and-simplify-unencrypted-drop-chec.patch b/package/kernel/mac80211/patches/subsys/311-v6.2-wifi-mac80211-fix-and-simplify-unencrypted-drop-chec.patch
deleted file mode 100644
index 804b02eb30..0000000000
--- a/package/kernel/mac80211/patches/subsys/311-v6.2-wifi-mac80211-fix-and-simplify-unencrypted-drop-chec.patch
+++ /dev/null
@@ -1,87 +0,0 @@
-From: Felix Fietkau <nbd@nbd.name>
-Date: Thu, 1 Dec 2022 14:57:30 +0100
-Subject: [PATCH] wifi: mac80211: fix and simplify unencrypted drop check for
- mesh
-
-ieee80211_drop_unencrypted is called from ieee80211_rx_h_mesh_fwding and
-ieee80211_frame_allowed.
-
-Since ieee80211_rx_h_mesh_fwding can forward packets for other mesh nodes
-and is called earlier, it needs to check the decryptions status and if the
-packet is using the control protocol on its own, instead of deferring to
-the later call from ieee80211_frame_allowed.
-
-Because of that, ieee80211_drop_unencrypted has a mesh specific check
-that skips over the mesh header in order to check the payload protocol.
-This code is invalid when called from ieee80211_frame_allowed, since that
-happens after the 802.11->802.3 conversion.
-
-Fix this by moving the mesh specific check directly into
-ieee80211_rx_h_mesh_fwding.
-
-Signed-off-by: Felix Fietkau <nbd@nbd.name>
-Link: https://lore.kernel.org/r/20221201135730.19723-1-nbd@nbd.name
-Signed-off-by: Johannes Berg <johannes.berg@intel.com>
----
-
---- a/net/mac80211/rx.c
-+++ b/net/mac80211/rx.c
-@@ -2403,7 +2403,6 @@ static int ieee80211_802_1x_port_control
-
- static int ieee80211_drop_unencrypted(struct ieee80211_rx_data *rx, __le16 fc)
- {
-- struct ieee80211_hdr *hdr = (void *)rx->skb->data;
- struct sk_buff *skb = rx->skb;
- struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb);
-
-@@ -2414,31 +2413,6 @@ static int ieee80211_drop_unencrypted(st
- if (status->flag & RX_FLAG_DECRYPTED)
- return 0;
-
-- /* check mesh EAPOL frames first */
-- if (unlikely(rx->sta && ieee80211_vif_is_mesh(&rx->sdata->vif) &&
-- ieee80211_is_data(fc))) {
-- struct ieee80211s_hdr *mesh_hdr;
-- u16 hdr_len = ieee80211_hdrlen(fc);
-- u16 ethertype_offset;
-- __be16 ethertype;
--
-- if (!ether_addr_equal(hdr->addr1, rx->sdata->vif.addr))
-- goto drop_check;
--
-- /* make sure fixed part of mesh header is there, also checks skb len */
-- if (!pskb_may_pull(rx->skb, hdr_len + 6))
-- goto drop_check;
--
-- mesh_hdr = (struct ieee80211s_hdr *)(skb->data + hdr_len);
-- ethertype_offset = hdr_len + ieee80211_get_mesh_hdrlen(mesh_hdr) +
-- sizeof(rfc1042_header);
--
-- if (skb_copy_bits(rx->skb, ethertype_offset, &ethertype, 2) == 0 &&
-- ethertype == rx->sdata->control_port_protocol)
-- return 0;
-- }
--
--drop_check:
- /* Drop unencrypted frames if key is set. */
- if (unlikely(!ieee80211_has_protected(fc) &&
- !ieee80211_is_any_nullfunc(fc) &&
-@@ -2892,8 +2866,16 @@ ieee80211_rx_h_mesh_fwding(struct ieee80
- hdr = (struct ieee80211_hdr *) skb->data;
- mesh_hdr = (struct ieee80211s_hdr *) (skb->data + hdrlen);
-
-- if (ieee80211_drop_unencrypted(rx, hdr->frame_control))
-- return RX_DROP_MONITOR;
-+ if (ieee80211_drop_unencrypted(rx, hdr->frame_control)) {
-+ int offset = hdrlen + ieee80211_get_mesh_hdrlen(mesh_hdr) +
-+ sizeof(rfc1042_header);
-+ __be16 ethertype;
-+
-+ if (!ether_addr_equal(hdr->addr1, rx->sdata->vif.addr) ||
-+ skb_copy_bits(rx->skb, offset, &ethertype, 2) != 0 ||
-+ ethertype != rx->sdata->control_port_protocol)
-+ return RX_DROP_MONITOR;
-+ }
-
- /* frame is in RMC, don't forward */
- if (ieee80211_is_data(hdr->frame_control) &&
diff --git a/package/kernel/mac80211/patches/subsys/312-v6.3-wifi-cfg80211-move-A-MSDU-check-in-ieee80211_data_to.patch b/package/kernel/mac80211/patches/subsys/312-v6.3-wifi-cfg80211-move-A-MSDU-check-in-ieee80211_data_to.patch
deleted file mode 100644
index f668905cca..0000000000
--- a/package/kernel/mac80211/patches/subsys/312-v6.3-wifi-cfg80211-move-A-MSDU-check-in-ieee80211_data_to.patch
+++ /dev/null
@@ -1,25 +0,0 @@
-From: Felix Fietkau <nbd@nbd.name>
-Date: Fri, 2 Dec 2022 13:53:11 +0100
-Subject: [PATCH] wifi: cfg80211: move A-MSDU check in
- ieee80211_data_to_8023_exthdr
-
-When parsing the outer A-MSDU header, don't check for inner bridge tunnel
-or RFC1042 headers. This is handled by ieee80211_amsdu_to_8023s already.
-
-Signed-off-by: Felix Fietkau <nbd@nbd.name>
----
-
---- a/net/wireless/util.c
-+++ b/net/wireless/util.c
-@@ -631,8 +631,9 @@ int ieee80211_data_to_8023_exthdr(struct
- break;
- }
-
-- if (likely(skb_copy_bits(skb, hdrlen, &payload, sizeof(payload)) == 0 &&
-- ((!is_amsdu && ether_addr_equal(payload.hdr, rfc1042_header) &&
-+ if (likely(!is_amsdu &&
-+ skb_copy_bits(skb, hdrlen, &payload, sizeof(payload)) == 0 &&
-+ ((ether_addr_equal(payload.hdr, rfc1042_header) &&
- payload.proto != htons(ETH_P_AARP) &&
- payload.proto != htons(ETH_P_IPX)) ||
- ether_addr_equal(payload.hdr, bridge_tunnel_header)))) {
diff --git a/package/kernel/mac80211/patches/subsys/313-v6.3-wifi-cfg80211-factor-out-bridge-tunnel-RFC1042-heade.patch b/package/kernel/mac80211/patches/subsys/313-v6.3-wifi-cfg80211-factor-out-bridge-tunnel-RFC1042-heade.patch
deleted file mode 100644
index 8641057869..0000000000
--- a/package/kernel/mac80211/patches/subsys/313-v6.3-wifi-cfg80211-factor-out-bridge-tunnel-RFC1042-heade.patch
+++ /dev/null
@@ -1,76 +0,0 @@
-From: Felix Fietkau <nbd@nbd.name>
-Date: Fri, 2 Dec 2022 13:54:15 +0100
-Subject: [PATCH] wifi: cfg80211: factor out bridge tunnel / RFC1042 header
- check
-
-The same check is done in multiple places, unify it.
-
-Signed-off-by: Felix Fietkau <nbd@nbd.name>
----
-
---- a/net/wireless/util.c
-+++ b/net/wireless/util.c
-@@ -542,6 +542,21 @@ unsigned int ieee80211_get_mesh_hdrlen(s
- }
- EXPORT_SYMBOL(ieee80211_get_mesh_hdrlen);
-
-+static bool ieee80211_get_8023_tunnel_proto(const void *hdr, __be16 *proto)
-+{
-+ const __be16 *hdr_proto = hdr + ETH_ALEN;
-+
-+ if (!(ether_addr_equal(hdr, rfc1042_header) &&
-+ *hdr_proto != htons(ETH_P_AARP) &&
-+ *hdr_proto != htons(ETH_P_IPX)) &&
-+ !ether_addr_equal(hdr, bridge_tunnel_header))
-+ return false;
-+
-+ *proto = *hdr_proto;
-+
-+ return true;
-+}
-+
- int ieee80211_data_to_8023_exthdr(struct sk_buff *skb, struct ethhdr *ehdr,
- const u8 *addr, enum nl80211_iftype iftype,
- u8 data_offset, bool is_amsdu)
-@@ -633,14 +648,9 @@ int ieee80211_data_to_8023_exthdr(struct
-
- if (likely(!is_amsdu &&
- skb_copy_bits(skb, hdrlen, &payload, sizeof(payload)) == 0 &&
-- ((ether_addr_equal(payload.hdr, rfc1042_header) &&
-- payload.proto != htons(ETH_P_AARP) &&
-- payload.proto != htons(ETH_P_IPX)) ||
-- ether_addr_equal(payload.hdr, bridge_tunnel_header)))) {
-- /* remove RFC1042 or Bridge-Tunnel encapsulation and
-- * replace EtherType */
-+ ieee80211_get_8023_tunnel_proto(&payload, &tmp.h_proto))) {
-+ /* remove RFC1042 or Bridge-Tunnel encapsulation */
- hdrlen += ETH_ALEN + 2;
-- tmp.h_proto = payload.proto;
- skb_postpull_rcsum(skb, &payload, ETH_ALEN + 2);
- } else {
- tmp.h_proto = htons(skb->len - hdrlen);
-@@ -756,8 +766,6 @@ void ieee80211_amsdu_to_8023s(struct sk_
- {
- unsigned int hlen = ALIGN(extra_headroom, 4);
- struct sk_buff *frame = NULL;
-- u16 ethertype;
-- u8 *payload;
- int offset = 0, remaining;
- struct ethhdr eth;
- bool reuse_frag = skb->head_frag && !skb_has_frag_list(skb);
-@@ -811,14 +819,8 @@ void ieee80211_amsdu_to_8023s(struct sk_
- frame->dev = skb->dev;
- frame->priority = skb->priority;
-
-- payload = frame->data;
-- ethertype = (payload[6] << 8) | payload[7];
-- if (likely((ether_addr_equal(payload, rfc1042_header) &&
-- ethertype != ETH_P_AARP && ethertype != ETH_P_IPX) ||
-- ether_addr_equal(payload, bridge_tunnel_header))) {
-- eth.h_proto = htons(ethertype);
-+ if (likely(ieee80211_get_8023_tunnel_proto(frame->data, &eth.h_proto)))
- skb_pull(frame, ETH_ALEN + 2);
-- }
-
- memcpy(skb_push(frame, sizeof(eth)), &eth, sizeof(eth));
- __skb_queue_tail(list, frame);
diff --git a/package/kernel/mac80211/patches/subsys/314-v6.3-wifi-mac80211-remove-mesh-forwarding-congestion-chec.patch b/package/kernel/mac80211/patches/subsys/314-v6.3-wifi-mac80211-remove-mesh-forwarding-congestion-chec.patch
deleted file mode 100644
index 515176f0de..0000000000
--- a/package/kernel/mac80211/patches/subsys/314-v6.3-wifi-mac80211-remove-mesh-forwarding-congestion-chec.patch
+++ /dev/null
@@ -1,54 +0,0 @@
-From: Felix Fietkau <nbd@nbd.name>
-Date: Fri, 2 Dec 2022 17:01:46 +0100
-Subject: [PATCH] wifi: mac80211: remove mesh forwarding congestion check
-
-Now that all drivers use iTXQ, it does not make sense to check to drop
-tx forwarding packets when the driver has stopped the queues.
-fq_codel will take care of dropping packets when the queues fill up
-
-Signed-off-by: Felix Fietkau <nbd@nbd.name>
----
-
---- a/net/mac80211/debugfs_netdev.c
-+++ b/net/mac80211/debugfs_netdev.c
-@@ -603,8 +603,6 @@ IEEE80211_IF_FILE(fwded_mcast, u.mesh.ms
- IEEE80211_IF_FILE(fwded_unicast, u.mesh.mshstats.fwded_unicast, DEC);
- IEEE80211_IF_FILE(fwded_frames, u.mesh.mshstats.fwded_frames, DEC);
- IEEE80211_IF_FILE(dropped_frames_ttl, u.mesh.mshstats.dropped_frames_ttl, DEC);
--IEEE80211_IF_FILE(dropped_frames_congestion,
-- u.mesh.mshstats.dropped_frames_congestion, DEC);
- IEEE80211_IF_FILE(dropped_frames_no_route,
- u.mesh.mshstats.dropped_frames_no_route, DEC);
-
-@@ -740,7 +738,6 @@ static void add_mesh_stats(struct ieee80
- MESHSTATS_ADD(fwded_frames);
- MESHSTATS_ADD(dropped_frames_ttl);
- MESHSTATS_ADD(dropped_frames_no_route);
-- MESHSTATS_ADD(dropped_frames_congestion);
- #undef MESHSTATS_ADD
- }
-
---- a/net/mac80211/ieee80211_i.h
-+++ b/net/mac80211/ieee80211_i.h
-@@ -329,7 +329,6 @@ struct mesh_stats {
- __u32 fwded_frames; /* Mesh total forwarded frames */
- __u32 dropped_frames_ttl; /* Not transmitted since mesh_ttl == 0*/
- __u32 dropped_frames_no_route; /* Not transmitted, no route found */
-- __u32 dropped_frames_congestion;/* Not forwarded due to congestion */
- };
-
- #define PREQ_Q_F_START 0x1
---- a/net/mac80211/rx.c
-+++ b/net/mac80211/rx.c
-@@ -2926,11 +2926,6 @@ ieee80211_rx_h_mesh_fwding(struct ieee80
- return RX_CONTINUE;
-
- ac = ieee802_1d_to_ac[skb->priority];
-- q = sdata->vif.hw_queue[ac];
-- if (ieee80211_queue_stopped(&local->hw, q)) {
-- IEEE80211_IFSTA_MESH_CTR_INC(ifmsh, dropped_frames_congestion);
-- return RX_DROP_MONITOR;
-- }
- skb_set_queue_mapping(skb, ac);
-
- if (!--mesh_hdr->ttl) {
diff --git a/package/kernel/mac80211/patches/subsys/315-v6.3-wifi-mac80211-fix-receiving-A-MSDU-frames-on-mesh-in.patch b/package/kernel/mac80211/patches/subsys/315-v6.3-wifi-mac80211-fix-receiving-A-MSDU-frames-on-mesh-in.patch
deleted file mode 100644
index 59b799b6b1..0000000000
--- a/package/kernel/mac80211/patches/subsys/315-v6.3-wifi-mac80211-fix-receiving-A-MSDU-frames-on-mesh-in.patch
+++ /dev/null
@@ -1,762 +0,0 @@
-From 986e43b19ae9176093da35e0a844e65c8bf9ede7 Mon Sep 17 00:00:00 2001
-From: Felix Fietkau <nbd@nbd.name>
-Date: Mon, 13 Feb 2023 11:08:54 +0100
-Subject: [PATCH] wifi: mac80211: fix receiving A-MSDU frames on mesh
- interfaces
-
-The current mac80211 mesh A-MSDU receive path fails to parse A-MSDU packets
-on mesh interfaces, because it assumes that the Mesh Control field is always
-directly after the 802.11 header.
-802.11-2020 9.3.2.2.2 Figure 9-70 shows that the Mesh Control field is
-actually part of the A-MSDU subframe header.
-This makes more sense, since it allows packets for multiple different
-destinations to be included in the same A-MSDU, as long as RA and TID are
-still the same.
-Another issue is the fact that the A-MSDU subframe length field was apparently
-accidentally defined as little-endian in the standard.
-
-In order to fix this, the mesh forwarding path needs happen at a different
-point in the receive path.
-
-ieee80211_data_to_8023_exthdr is changed to ignore the mesh control field
-and leave it in after the ethernet header. This also affects the source/dest
-MAC address fields, which now in the case of mesh point to the mesh SA/DA.
-
-ieee80211_amsdu_to_8023s is changed to deal with the endian difference and
-to add the Mesh Control length to the subframe length, since it's not covered
-by the MSDU length field.
-
-With these changes, the mac80211 will get the same packet structure for
-converted regular data packets and unpacked A-MSDU subframes.
-
-The mesh forwarding checks are now only performed after the A-MSDU decap.
-For locally received packets, the Mesh Control header is stripped away.
-For forwarded packets, a new 802.11 header gets added.
-
-Signed-off-by: Felix Fietkau <nbd@nbd.name>
-Link: https://lore.kernel.org/r/20230213100855.34315-4-nbd@nbd.name
-[fix fortify build error]
-Signed-off-by: Johannes Berg <johannes.berg@intel.com>
----
- .../wireless/marvell/mwifiex/11n_rxreorder.c | 2 +-
- include/net/cfg80211.h | 27 +-
- net/mac80211/rx.c | 350 ++++++++++--------
- net/wireless/util.c | 120 +++---
- 4 files changed, 297 insertions(+), 202 deletions(-)
-
---- a/drivers/net/wireless/marvell/mwifiex/11n_rxreorder.c
-+++ b/drivers/net/wireless/marvell/mwifiex/11n_rxreorder.c
-@@ -33,7 +33,7 @@ static int mwifiex_11n_dispatch_amsdu_pk
- skb_trim(skb, le16_to_cpu(local_rx_pd->rx_pkt_length));
-
- ieee80211_amsdu_to_8023s(skb, &list, priv->curr_addr,
-- priv->wdev.iftype, 0, NULL, NULL);
-+ priv->wdev.iftype, 0, NULL, NULL, false);
-
- while (!skb_queue_empty(&list)) {
- struct rx_packet_hdr *rx_hdr;
---- a/include/net/cfg80211.h
-+++ b/include/net/cfg80211.h
-@@ -6208,11 +6208,36 @@ static inline int ieee80211_data_to_8023
- * @extra_headroom: The hardware extra headroom for SKBs in the @list.
- * @check_da: DA to check in the inner ethernet header, or NULL
- * @check_sa: SA to check in the inner ethernet header, or NULL
-+ * @mesh_control: A-MSDU subframe header includes the mesh control field
- */
- void ieee80211_amsdu_to_8023s(struct sk_buff *skb, struct sk_buff_head *list,
- const u8 *addr, enum nl80211_iftype iftype,
- const unsigned int extra_headroom,
-- const u8 *check_da, const u8 *check_sa);
-+ const u8 *check_da, const u8 *check_sa,
-+ bool mesh_control);
-+
-+/**
-+ * ieee80211_get_8023_tunnel_proto - get RFC1042 or bridge tunnel encap protocol
-+ *
-+ * Check for RFC1042 or bridge tunnel header and fetch the encapsulated
-+ * protocol.
-+ *
-+ * @hdr: pointer to the MSDU payload
-+ * @proto: destination pointer to store the protocol
-+ * Return: true if encapsulation was found
-+ */
-+bool ieee80211_get_8023_tunnel_proto(const void *hdr, __be16 *proto);
-+
-+/**
-+ * ieee80211_strip_8023_mesh_hdr - strip mesh header from converted 802.3 frames
-+ *
-+ * Strip the mesh header, which was left in by ieee80211_data_to_8023 as part
-+ * of the MSDU data. Also move any source/destination addresses from the mesh
-+ * header to the ethernet header (if present).
-+ *
-+ * @skb: The 802.3 frame with embedded mesh header
-+ */
-+int ieee80211_strip_8023_mesh_hdr(struct sk_buff *skb);
-
- /**
- * cfg80211_classify8021d - determine the 802.1p/1d tag for a data frame
---- a/net/mac80211/rx.c
-+++ b/net/mac80211/rx.c
-@@ -2720,6 +2720,174 @@ ieee80211_deliver_skb(struct ieee80211_r
- }
- }
-
-+static ieee80211_rx_result
-+ieee80211_rx_mesh_data(struct ieee80211_sub_if_data *sdata, struct sta_info *sta,
-+ struct sk_buff *skb)
-+{
-+#ifdef CPTCFG_MAC80211_MESH
-+ struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
-+ struct ieee80211_local *local = sdata->local;
-+ uint16_t fc = IEEE80211_FTYPE_DATA | IEEE80211_STYPE_QOS_DATA;
-+ struct ieee80211_hdr hdr = {
-+ .frame_control = cpu_to_le16(fc)
-+ };
-+ struct ieee80211_hdr *fwd_hdr;
-+ struct ieee80211s_hdr *mesh_hdr;
-+ struct ieee80211_tx_info *info;
-+ struct sk_buff *fwd_skb;
-+ struct ethhdr *eth;
-+ bool multicast;
-+ int tailroom = 0;
-+ int hdrlen, mesh_hdrlen;
-+ u8 *qos;
-+
-+ if (!ieee80211_vif_is_mesh(&sdata->vif))
-+ return RX_CONTINUE;
-+
-+ if (!pskb_may_pull(skb, sizeof(*eth) + 6))
-+ return RX_DROP_MONITOR;
-+
-+ mesh_hdr = (struct ieee80211s_hdr *)(skb->data + sizeof(*eth));
-+ mesh_hdrlen = ieee80211_get_mesh_hdrlen(mesh_hdr);
-+
-+ if (!pskb_may_pull(skb, sizeof(*eth) + mesh_hdrlen))
-+ return RX_DROP_MONITOR;
-+
-+ eth = (struct ethhdr *)skb->data;
-+ multicast = is_multicast_ether_addr(eth->h_dest);
-+
-+ mesh_hdr = (struct ieee80211s_hdr *)(eth + 1);
-+ if (!mesh_hdr->ttl)
-+ return RX_DROP_MONITOR;
-+
-+ /* frame is in RMC, don't forward */
-+ if (is_multicast_ether_addr(eth->h_dest) &&
-+ mesh_rmc_check(sdata, eth->h_source, mesh_hdr))
-+ return RX_DROP_MONITOR;
-+
-+ /* Frame has reached destination. Don't forward */
-+ if (ether_addr_equal(sdata->vif.addr, eth->h_dest))
-+ goto rx_accept;
-+
-+ if (!ifmsh->mshcfg.dot11MeshForwarding) {
-+ if (is_multicast_ether_addr(eth->h_dest))
-+ goto rx_accept;
-+
-+ return RX_DROP_MONITOR;
-+ }
-+
-+ /* forward packet */
-+ if (sdata->crypto_tx_tailroom_needed_cnt)
-+ tailroom = IEEE80211_ENCRYPT_TAILROOM;
-+
-+ if (!--mesh_hdr->ttl) {
-+ if (multicast)
-+ goto rx_accept;
-+
-+ IEEE80211_IFSTA_MESH_CTR_INC(ifmsh, dropped_frames_ttl);
-+ return RX_DROP_MONITOR;
-+ }
-+
-+ if (mesh_hdr->flags & MESH_FLAGS_AE) {
-+ struct mesh_path *mppath;
-+ char *proxied_addr;
-+
-+ if (multicast)
-+ proxied_addr = mesh_hdr->eaddr1;
-+ else if ((mesh_hdr->flags & MESH_FLAGS_AE) == MESH_FLAGS_AE_A5_A6)
-+ /* has_a4 already checked in ieee80211_rx_mesh_check */
-+ proxied_addr = mesh_hdr->eaddr2;
-+ else
-+ return RX_DROP_MONITOR;
-+
-+ rcu_read_lock();
-+ mppath = mpp_path_lookup(sdata, proxied_addr);
-+ if (!mppath) {
-+ mpp_path_add(sdata, proxied_addr, eth->h_source);
-+ } else {
-+ spin_lock_bh(&mppath->state_lock);
-+ if (!ether_addr_equal(mppath->mpp, eth->h_source))
-+ memcpy(mppath->mpp, eth->h_source, ETH_ALEN);
-+ mppath->exp_time = jiffies;
-+ spin_unlock_bh(&mppath->state_lock);
-+ }
-+ rcu_read_unlock();
-+ }
-+
-+ skb_set_queue_mapping(skb, ieee802_1d_to_ac[skb->priority]);
-+
-+ ieee80211_fill_mesh_addresses(&hdr, &hdr.frame_control,
-+ eth->h_dest, eth->h_source);
-+ hdrlen = ieee80211_hdrlen(hdr.frame_control);
-+ if (multicast) {
-+ int extra_head = sizeof(struct ieee80211_hdr) - sizeof(*eth);
-+
-+ fwd_skb = skb_copy_expand(skb, local->tx_headroom + extra_head +
-+ IEEE80211_ENCRYPT_HEADROOM,
-+ tailroom, GFP_ATOMIC);
-+ if (!fwd_skb)
-+ goto rx_accept;
-+ } else {
-+ fwd_skb = skb;
-+ skb = NULL;
-+
-+ if (skb_cow_head(fwd_skb, hdrlen - sizeof(struct ethhdr)))
-+ return RX_DROP_UNUSABLE;
-+ }
-+
-+ fwd_hdr = skb_push(fwd_skb, hdrlen - sizeof(struct ethhdr));
-+ memcpy(fwd_hdr, &hdr, hdrlen - 2);
-+ qos = ieee80211_get_qos_ctl(fwd_hdr);
-+ qos[0] = qos[1] = 0;
-+
-+ skb_reset_mac_header(fwd_skb);
-+ hdrlen += mesh_hdrlen;
-+ if (ieee80211_get_8023_tunnel_proto(fwd_skb->data + hdrlen,
-+ &fwd_skb->protocol))
-+ hdrlen += ETH_ALEN;
-+ else
-+ fwd_skb->protocol = htons(fwd_skb->len - hdrlen);
-+ skb_set_network_header(fwd_skb, hdrlen);
-+
-+ info = IEEE80211_SKB_CB(fwd_skb);
-+ memset(info, 0, sizeof(*info));
-+ info->control.flags |= IEEE80211_TX_INTCFL_NEED_TXPROCESSING;
-+ info->control.vif = &sdata->vif;
-+ info->control.jiffies = jiffies;
-+ if (multicast) {
-+ IEEE80211_IFSTA_MESH_CTR_INC(ifmsh, fwded_mcast);
-+ memcpy(fwd_hdr->addr2, sdata->vif.addr, ETH_ALEN);
-+ /* update power mode indication when forwarding */
-+ ieee80211_mps_set_frame_flags(sdata, NULL, fwd_hdr);
-+ } else if (!mesh_nexthop_lookup(sdata, fwd_skb)) {
-+ /* mesh power mode flags updated in mesh_nexthop_lookup */
-+ IEEE80211_IFSTA_MESH_CTR_INC(ifmsh, fwded_unicast);
-+ } else {
-+ /* unable to resolve next hop */
-+ if (sta)
-+ mesh_path_error_tx(sdata, ifmsh->mshcfg.element_ttl,
-+ hdr.addr3, 0,
-+ WLAN_REASON_MESH_PATH_NOFORWARD,
-+ sta->sta.addr);
-+ IEEE80211_IFSTA_MESH_CTR_INC(ifmsh, dropped_frames_no_route);
-+ kfree_skb(fwd_skb);
-+ goto rx_accept;
-+ }
-+
-+ IEEE80211_IFSTA_MESH_CTR_INC(ifmsh, fwded_frames);
-+ fwd_skb->dev = sdata->dev;
-+ ieee80211_add_pending_skb(local, fwd_skb);
-+
-+rx_accept:
-+ if (!skb)
-+ return RX_QUEUED;
-+
-+ ieee80211_strip_8023_mesh_hdr(skb);
-+#endif
-+
-+ return RX_CONTINUE;
-+}
-+
- static ieee80211_rx_result debug_noinline
- __ieee80211_rx_h_amsdu(struct ieee80211_rx_data *rx, u8 data_offset)
- {
-@@ -2728,8 +2896,10 @@ __ieee80211_rx_h_amsdu(struct ieee80211_
- struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
- __le16 fc = hdr->frame_control;
- struct sk_buff_head frame_list;
-+ static ieee80211_rx_result res;
- struct ethhdr ethhdr;
- const u8 *check_da = ethhdr.h_dest, *check_sa = ethhdr.h_source;
-+ bool mesh = false;
-
- if (unlikely(ieee80211_has_a4(hdr->frame_control))) {
- check_da = NULL;
-@@ -2746,6 +2916,8 @@ __ieee80211_rx_h_amsdu(struct ieee80211_
- break;
- case NL80211_IFTYPE_MESH_POINT:
- check_sa = NULL;
-+ check_da = NULL;
-+ mesh = true;
- break;
- default:
- break;
-@@ -2763,17 +2935,29 @@ __ieee80211_rx_h_amsdu(struct ieee80211_
- ieee80211_amsdu_to_8023s(skb, &frame_list, dev->dev_addr,
- rx->sdata->vif.type,
- rx->local->hw.extra_tx_headroom,
-- check_da, check_sa);
-+ check_da, check_sa, mesh);
-
- while (!skb_queue_empty(&frame_list)) {
- rx->skb = __skb_dequeue(&frame_list);
-
-- if (!ieee80211_frame_allowed(rx, fc)) {
-- dev_kfree_skb(rx->skb);
-+ res = ieee80211_rx_mesh_data(rx->sdata, rx->sta, rx->skb);
-+ switch (res) {
-+ case RX_QUEUED:
- continue;
-+ case RX_CONTINUE:
-+ break;
-+ default:
-+ goto free;
- }
-
-+ if (!ieee80211_frame_allowed(rx, fc))
-+ goto free;
-+
- ieee80211_deliver_skb(rx);
-+ continue;
-+
-+free:
-+ dev_kfree_skb(rx->skb);
- }
-
- return RX_QUEUED;
-@@ -2806,6 +2990,8 @@ ieee80211_rx_h_amsdu(struct ieee80211_rx
- if (!rx->sdata->u.mgd.use_4addr)
- return RX_DROP_UNUSABLE;
- break;
-+ case NL80211_IFTYPE_MESH_POINT:
-+ break;
- default:
- return RX_DROP_UNUSABLE;
- }
-@@ -2834,155 +3020,6 @@ ieee80211_rx_h_amsdu(struct ieee80211_rx
- return __ieee80211_rx_h_amsdu(rx, 0);
- }
-
--#ifdef CPTCFG_MAC80211_MESH
--static ieee80211_rx_result
--ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx)
--{
-- struct ieee80211_hdr *fwd_hdr, *hdr;
-- struct ieee80211_tx_info *info;
-- struct ieee80211s_hdr *mesh_hdr;
-- struct sk_buff *skb = rx->skb, *fwd_skb;
-- struct ieee80211_local *local = rx->local;
-- struct ieee80211_sub_if_data *sdata = rx->sdata;
-- struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
-- u16 ac, q, hdrlen;
-- int tailroom = 0;
--
-- hdr = (struct ieee80211_hdr *) skb->data;
-- hdrlen = ieee80211_hdrlen(hdr->frame_control);
--
-- /* make sure fixed part of mesh header is there, also checks skb len */
-- if (!pskb_may_pull(rx->skb, hdrlen + 6))
-- return RX_DROP_MONITOR;
--
-- mesh_hdr = (struct ieee80211s_hdr *) (skb->data + hdrlen);
--
-- /* make sure full mesh header is there, also checks skb len */
-- if (!pskb_may_pull(rx->skb,
-- hdrlen + ieee80211_get_mesh_hdrlen(mesh_hdr)))
-- return RX_DROP_MONITOR;
--
-- /* reload pointers */
-- hdr = (struct ieee80211_hdr *) skb->data;
-- mesh_hdr = (struct ieee80211s_hdr *) (skb->data + hdrlen);
--
-- if (ieee80211_drop_unencrypted(rx, hdr->frame_control)) {
-- int offset = hdrlen + ieee80211_get_mesh_hdrlen(mesh_hdr) +
-- sizeof(rfc1042_header);
-- __be16 ethertype;
--
-- if (!ether_addr_equal(hdr->addr1, rx->sdata->vif.addr) ||
-- skb_copy_bits(rx->skb, offset, &ethertype, 2) != 0 ||
-- ethertype != rx->sdata->control_port_protocol)
-- return RX_DROP_MONITOR;
-- }
--
-- /* frame is in RMC, don't forward */
-- if (ieee80211_is_data(hdr->frame_control) &&
-- is_multicast_ether_addr(hdr->addr1) &&
-- mesh_rmc_check(rx->sdata, hdr->addr3, mesh_hdr))
-- return RX_DROP_MONITOR;
--
-- if (!ieee80211_is_data(hdr->frame_control))
-- return RX_CONTINUE;
--
-- if (!mesh_hdr->ttl)
-- return RX_DROP_MONITOR;
--
-- if (mesh_hdr->flags & MESH_FLAGS_AE) {
-- struct mesh_path *mppath;
-- char *proxied_addr;
-- char *mpp_addr;
--
-- if (is_multicast_ether_addr(hdr->addr1)) {
-- mpp_addr = hdr->addr3;
-- proxied_addr = mesh_hdr->eaddr1;
-- } else if ((mesh_hdr->flags & MESH_FLAGS_AE) ==
-- MESH_FLAGS_AE_A5_A6) {
-- /* has_a4 already checked in ieee80211_rx_mesh_check */
-- mpp_addr = hdr->addr4;
-- proxied_addr = mesh_hdr->eaddr2;
-- } else {
-- return RX_DROP_MONITOR;
-- }
--
-- rcu_read_lock();
-- mppath = mpp_path_lookup(sdata, proxied_addr);
-- if (!mppath) {
-- mpp_path_add(sdata, proxied_addr, mpp_addr);
-- } else {
-- spin_lock_bh(&mppath->state_lock);
-- if (!ether_addr_equal(mppath->mpp, mpp_addr))
-- memcpy(mppath->mpp, mpp_addr, ETH_ALEN);
-- mppath->exp_time = jiffies;
-- spin_unlock_bh(&mppath->state_lock);
-- }
-- rcu_read_unlock();
-- }
--
-- /* Frame has reached destination. Don't forward */
-- if (!is_multicast_ether_addr(hdr->addr1) &&
-- ether_addr_equal(sdata->vif.addr, hdr->addr3))
-- return RX_CONTINUE;
--
-- ac = ieee802_1d_to_ac[skb->priority];
-- skb_set_queue_mapping(skb, ac);
--
-- if (!--mesh_hdr->ttl) {
-- if (!is_multicast_ether_addr(hdr->addr1))
-- IEEE80211_IFSTA_MESH_CTR_INC(ifmsh,
-- dropped_frames_ttl);
-- goto out;
-- }
--
-- if (!ifmsh->mshcfg.dot11MeshForwarding)
-- goto out;
--
-- if (sdata->crypto_tx_tailroom_needed_cnt)
-- tailroom = IEEE80211_ENCRYPT_TAILROOM;
--
-- fwd_skb = skb_copy_expand(skb, local->tx_headroom +
-- IEEE80211_ENCRYPT_HEADROOM,
-- tailroom, GFP_ATOMIC);
-- if (!fwd_skb)
-- goto out;
--
-- fwd_skb->dev = sdata->dev;
-- fwd_hdr = (struct ieee80211_hdr *) fwd_skb->data;
-- fwd_hdr->frame_control &= ~cpu_to_le16(IEEE80211_FCTL_RETRY);
-- info = IEEE80211_SKB_CB(fwd_skb);
-- memset(info, 0, sizeof(*info));
-- info->control.flags |= IEEE80211_TX_INTCFL_NEED_TXPROCESSING;
-- info->control.vif = &rx->sdata->vif;
-- info->control.jiffies = jiffies;
-- if (is_multicast_ether_addr(fwd_hdr->addr1)) {
-- IEEE80211_IFSTA_MESH_CTR_INC(ifmsh, fwded_mcast);
-- memcpy(fwd_hdr->addr2, sdata->vif.addr, ETH_ALEN);
-- /* update power mode indication when forwarding */
-- ieee80211_mps_set_frame_flags(sdata, NULL, fwd_hdr);
-- } else if (!mesh_nexthop_lookup(sdata, fwd_skb)) {
-- /* mesh power mode flags updated in mesh_nexthop_lookup */
-- IEEE80211_IFSTA_MESH_CTR_INC(ifmsh, fwded_unicast);
-- } else {
-- /* unable to resolve next hop */
-- mesh_path_error_tx(sdata, ifmsh->mshcfg.element_ttl,
-- fwd_hdr->addr3, 0,
-- WLAN_REASON_MESH_PATH_NOFORWARD,
-- fwd_hdr->addr2);
-- IEEE80211_IFSTA_MESH_CTR_INC(ifmsh, dropped_frames_no_route);
-- kfree_skb(fwd_skb);
-- return RX_DROP_MONITOR;
-- }
--
-- IEEE80211_IFSTA_MESH_CTR_INC(ifmsh, fwded_frames);
-- ieee80211_add_pending_skb(local, fwd_skb);
-- out:
-- if (is_multicast_ether_addr(hdr->addr1))
-- return RX_CONTINUE;
-- return RX_DROP_MONITOR;
--}
--#endif
--
- static ieee80211_rx_result debug_noinline
- ieee80211_rx_h_data(struct ieee80211_rx_data *rx)
- {
-@@ -2991,6 +3028,7 @@ ieee80211_rx_h_data(struct ieee80211_rx_
- struct net_device *dev = sdata->dev;
- struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data;
- __le16 fc = hdr->frame_control;
-+ static ieee80211_rx_result res;
- bool port_control;
- int err;
-
-@@ -3017,6 +3055,10 @@ ieee80211_rx_h_data(struct ieee80211_rx_
- if (unlikely(err))
- return RX_DROP_UNUSABLE;
-
-+ res = ieee80211_rx_mesh_data(rx->sdata, rx->sta, rx->skb);
-+ if (res != RX_CONTINUE)
-+ return res;
-+
- if (!ieee80211_frame_allowed(rx, fc))
- return RX_DROP_MONITOR;
-
-@@ -3987,10 +4029,6 @@ static void ieee80211_rx_handlers(struct
- CALL_RXH(ieee80211_rx_h_defragment);
- CALL_RXH(ieee80211_rx_h_michael_mic_verify);
- /* must be after MMIC verify so header is counted in MPDU mic */
--#ifdef CPTCFG_MAC80211_MESH
-- if (ieee80211_vif_is_mesh(&rx->sdata->vif))
-- CALL_RXH(ieee80211_rx_h_mesh_fwding);
--#endif
- CALL_RXH(ieee80211_rx_h_amsdu);
- CALL_RXH(ieee80211_rx_h_data);
-
---- a/net/wireless/util.c
-+++ b/net/wireless/util.c
-@@ -542,7 +542,7 @@ unsigned int ieee80211_get_mesh_hdrlen(s
- }
- EXPORT_SYMBOL(ieee80211_get_mesh_hdrlen);
-
--static bool ieee80211_get_8023_tunnel_proto(const void *hdr, __be16 *proto)
-+bool ieee80211_get_8023_tunnel_proto(const void *hdr, __be16 *proto)
- {
- const __be16 *hdr_proto = hdr + ETH_ALEN;
-
-@@ -556,6 +556,49 @@ static bool ieee80211_get_8023_tunnel_pr
-
- return true;
- }
-+EXPORT_SYMBOL(ieee80211_get_8023_tunnel_proto);
-+
-+int ieee80211_strip_8023_mesh_hdr(struct sk_buff *skb)
-+{
-+ const void *mesh_addr;
-+ struct {
-+ struct ethhdr eth;
-+ u8 flags;
-+ } payload;
-+ int hdrlen;
-+ int ret;
-+
-+ ret = skb_copy_bits(skb, 0, &payload, sizeof(payload));
-+ if (ret)
-+ return ret;
-+
-+ hdrlen = sizeof(payload.eth) + __ieee80211_get_mesh_hdrlen(payload.flags);
-+
-+ if (likely(pskb_may_pull(skb, hdrlen + 8) &&
-+ ieee80211_get_8023_tunnel_proto(skb->data + hdrlen,
-+ &payload.eth.h_proto)))
-+ hdrlen += ETH_ALEN + 2;
-+ else if (!pskb_may_pull(skb, hdrlen))
-+ return -EINVAL;
-+
-+ mesh_addr = skb->data + sizeof(payload.eth) + ETH_ALEN;
-+ switch (payload.flags & MESH_FLAGS_AE) {
-+ case MESH_FLAGS_AE_A4:
-+ memcpy(&payload.eth.h_source, mesh_addr, ETH_ALEN);
-+ break;
-+ case MESH_FLAGS_AE_A5_A6:
-+ memcpy(&payload.eth, mesh_addr, 2 * ETH_ALEN);
-+ break;
-+ default:
-+ break;
-+ }
-+
-+ pskb_pull(skb, hdrlen - sizeof(payload.eth));
-+ memcpy(skb->data, &payload.eth, sizeof(payload.eth));
-+
-+ return 0;
-+}
-+EXPORT_SYMBOL(ieee80211_strip_8023_mesh_hdr);
-
- int ieee80211_data_to_8023_exthdr(struct sk_buff *skb, struct ethhdr *ehdr,
- const u8 *addr, enum nl80211_iftype iftype,
-@@ -568,7 +611,6 @@ int ieee80211_data_to_8023_exthdr(struct
- } payload;
- struct ethhdr tmp;
- u16 hdrlen;
-- u8 mesh_flags = 0;
-
- if (unlikely(!ieee80211_is_data_present(hdr->frame_control)))
- return -1;
-@@ -589,12 +631,6 @@ int ieee80211_data_to_8023_exthdr(struct
- memcpy(tmp.h_dest, ieee80211_get_DA(hdr), ETH_ALEN);
- memcpy(tmp.h_source, ieee80211_get_SA(hdr), ETH_ALEN);
-
-- if (iftype == NL80211_IFTYPE_MESH_POINT &&
-- skb_copy_bits(skb, hdrlen, &mesh_flags, 1) < 0)
-- return -1;
--
-- mesh_flags &= MESH_FLAGS_AE;
--
- switch (hdr->frame_control &
- cpu_to_le16(IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS)) {
- case cpu_to_le16(IEEE80211_FCTL_TODS):
-@@ -608,17 +644,6 @@ int ieee80211_data_to_8023_exthdr(struct
- iftype != NL80211_IFTYPE_AP_VLAN &&
- iftype != NL80211_IFTYPE_STATION))
- return -1;
-- if (iftype == NL80211_IFTYPE_MESH_POINT) {
-- if (mesh_flags == MESH_FLAGS_AE_A4)
-- return -1;
-- if (mesh_flags == MESH_FLAGS_AE_A5_A6 &&
-- skb_copy_bits(skb, hdrlen +
-- offsetof(struct ieee80211s_hdr, eaddr1),
-- tmp.h_dest, 2 * ETH_ALEN) < 0)
-- return -1;
--
-- hdrlen += __ieee80211_get_mesh_hdrlen(mesh_flags);
-- }
- break;
- case cpu_to_le16(IEEE80211_FCTL_FROMDS):
- if ((iftype != NL80211_IFTYPE_STATION &&
-@@ -627,16 +652,6 @@ int ieee80211_data_to_8023_exthdr(struct
- (is_multicast_ether_addr(tmp.h_dest) &&
- ether_addr_equal(tmp.h_source, addr)))
- return -1;
-- if (iftype == NL80211_IFTYPE_MESH_POINT) {
-- if (mesh_flags == MESH_FLAGS_AE_A5_A6)
-- return -1;
-- if (mesh_flags == MESH_FLAGS_AE_A4 &&
-- skb_copy_bits(skb, hdrlen +
-- offsetof(struct ieee80211s_hdr, eaddr1),
-- tmp.h_source, ETH_ALEN) < 0)
-- return -1;
-- hdrlen += __ieee80211_get_mesh_hdrlen(mesh_flags);
-- }
- break;
- case cpu_to_le16(0):
- if (iftype != NL80211_IFTYPE_ADHOC &&
-@@ -646,7 +661,7 @@ int ieee80211_data_to_8023_exthdr(struct
- break;
- }
-
-- if (likely(!is_amsdu &&
-+ if (likely(!is_amsdu && iftype != NL80211_IFTYPE_MESH_POINT &&
- skb_copy_bits(skb, hdrlen, &payload, sizeof(payload)) == 0 &&
- ieee80211_get_8023_tunnel_proto(&payload, &tmp.h_proto))) {
- /* remove RFC1042 or Bridge-Tunnel encapsulation */
-@@ -722,7 +737,8 @@ __ieee80211_amsdu_copy_frag(struct sk_bu
-
- static struct sk_buff *
- __ieee80211_amsdu_copy(struct sk_buff *skb, unsigned int hlen,
-- int offset, int len, bool reuse_frag)
-+ int offset, int len, bool reuse_frag,
-+ int min_len)
- {
- struct sk_buff *frame;
- int cur_len = len;
-@@ -736,7 +752,7 @@ __ieee80211_amsdu_copy(struct sk_buff *s
- * in the stack later.
- */
- if (reuse_frag)
-- cur_len = min_t(int, len, 32);
-+ cur_len = min_t(int, len, min_len);
-
- /*
- * Allocate and reserve two bytes more for payload
-@@ -746,6 +762,7 @@ __ieee80211_amsdu_copy(struct sk_buff *s
- if (!frame)
- return NULL;
-
-+ frame->priority = skb->priority;
- skb_reserve(frame, hlen + sizeof(struct ethhdr) + 2);
- skb_copy_bits(skb, offset, skb_put(frame, cur_len), cur_len);
-
-@@ -762,23 +779,37 @@ __ieee80211_amsdu_copy(struct sk_buff *s
- void ieee80211_amsdu_to_8023s(struct sk_buff *skb, struct sk_buff_head *list,
- const u8 *addr, enum nl80211_iftype iftype,
- const unsigned int extra_headroom,
-- const u8 *check_da, const u8 *check_sa)
-+ const u8 *check_da, const u8 *check_sa,
-+ bool mesh_control)
- {
- unsigned int hlen = ALIGN(extra_headroom, 4);
- struct sk_buff *frame = NULL;
- int offset = 0, remaining;
-- struct ethhdr eth;
-+ struct {
-+ struct ethhdr eth;
-+ uint8_t flags;
-+ } hdr;
- bool reuse_frag = skb->head_frag && !skb_has_frag_list(skb);
- bool reuse_skb = false;
- bool last = false;
-+ int copy_len = sizeof(hdr.eth);
-+
-+ if (iftype == NL80211_IFTYPE_MESH_POINT)
-+ copy_len = sizeof(hdr);
-
- while (!last) {
- unsigned int subframe_len;
-- int len;
-+ int len, mesh_len = 0;
- u8 padding;
-
-- skb_copy_bits(skb, offset, &eth, sizeof(eth));
-- len = ntohs(eth.h_proto);
-+ skb_copy_bits(skb, offset, &hdr, copy_len);
-+ if (iftype == NL80211_IFTYPE_MESH_POINT)
-+ mesh_len = __ieee80211_get_mesh_hdrlen(hdr.flags);
-+ if (mesh_control)
-+ len = le16_to_cpu(*(__le16 *)&hdr.eth.h_proto) + mesh_len;
-+ else
-+ len = ntohs(hdr.eth.h_proto);
-+
- subframe_len = sizeof(struct ethhdr) + len;
- padding = (4 - subframe_len) & 0x3;
-
-@@ -787,16 +818,16 @@ void ieee80211_amsdu_to_8023s(struct sk_
- if (subframe_len > remaining)
- goto purge;
- /* mitigate A-MSDU aggregation injection attacks */
-- if (ether_addr_equal(eth.h_dest, rfc1042_header))
-+ if (ether_addr_equal(hdr.eth.h_dest, rfc1042_header))
- goto purge;
-
- offset += sizeof(struct ethhdr);
- last = remaining <= subframe_len + padding;
-
- /* FIXME: should we really accept multicast DA? */
-- if ((check_da && !is_multicast_ether_addr(eth.h_dest) &&
-- !ether_addr_equal(check_da, eth.h_dest)) ||
-- (check_sa && !ether_addr_equal(check_sa, eth.h_source))) {
-+ if ((check_da && !is_multicast_ether_addr(hdr.eth.h_dest) &&
-+ !ether_addr_equal(check_da, hdr.eth.h_dest)) ||
-+ (check_sa && !ether_addr_equal(check_sa, hdr.eth.h_source))) {
- offset += len + padding;
- continue;
- }
-@@ -808,7 +839,7 @@ void ieee80211_amsdu_to_8023s(struct sk_
- reuse_skb = true;
- } else {
- frame = __ieee80211_amsdu_copy(skb, hlen, offset, len,
-- reuse_frag);
-+ reuse_frag, 32 + mesh_len);
- if (!frame)
- goto purge;
-
-@@ -819,10 +850,11 @@ void ieee80211_amsdu_to_8023s(struct sk_
- frame->dev = skb->dev;
- frame->priority = skb->priority;
-
-- if (likely(ieee80211_get_8023_tunnel_proto(frame->data, &eth.h_proto)))
-+ if (likely(iftype != NL80211_IFTYPE_MESH_POINT &&
-+ ieee80211_get_8023_tunnel_proto(frame->data, &hdr.eth.h_proto)))
- skb_pull(frame, ETH_ALEN + 2);
-
-- memcpy(skb_push(frame, sizeof(eth)), &eth, sizeof(eth));
-+ memcpy(skb_push(frame, sizeof(hdr.eth)), &hdr.eth, sizeof(hdr.eth));
- __skb_queue_tail(list, frame);
- }
-
diff --git a/package/kernel/mac80211/patches/subsys/316-v6.3-wifi-mac80211-add-a-workaround-for-receiving-non-sta.patch b/package/kernel/mac80211/patches/subsys/316-v6.3-wifi-mac80211-add-a-workaround-for-receiving-non-sta.patch
deleted file mode 100644
index 6dc98ae16a..0000000000
--- a/package/kernel/mac80211/patches/subsys/316-v6.3-wifi-mac80211-add-a-workaround-for-receiving-non-sta.patch
+++ /dev/null
@@ -1,145 +0,0 @@
-From: Felix Fietkau <nbd@nbd.name>
-Date: Fri, 9 Dec 2022 21:15:04 +0100
-Subject: [PATCH] wifi: mac80211: add a workaround for receiving
- non-standard mesh A-MSDU
-
-At least ath10k and ath11k supported hardware (maybe more) does not implement
-mesh A-MSDU aggregation in a standard compliant way.
-802.11-2020 9.3.2.2.2 declares that the Mesh Control field is part of the
-A-MSDU header. As such, its length must not be included in the subframe
-length field.
-Hardware affected by this bug treats the mesh control field as part of the
-MSDU data and sets the length accordingly.
-In order to avoid packet loss, keep track of which stations are affected
-by this and take it into account when converting A-MSDU to 802.3 + mesh control
-packets.
-
-Signed-off-by: Felix Fietkau <nbd@nbd.name>
----
-
---- a/include/net/cfg80211.h
-+++ b/include/net/cfg80211.h
-@@ -6194,6 +6194,19 @@ static inline int ieee80211_data_to_8023
- }
-
- /**
-+ * ieee80211_is_valid_amsdu - check if subframe lengths of an A-MSDU are valid
-+ *
-+ * This is used to detect non-standard A-MSDU frames, e.g. the ones generated
-+ * by ath10k and ath11k, where the subframe length includes the length of the
-+ * mesh control field.
-+ *
-+ * @skb: The input A-MSDU frame without any headers.
-+ * @mesh_hdr: use standard compliant mesh A-MSDU subframe header
-+ * Returns: true if subframe header lengths are valid for the @mesh_hdr mode
-+ */
-+bool ieee80211_is_valid_amsdu(struct sk_buff *skb, bool mesh_hdr);
-+
-+/**
- * ieee80211_amsdu_to_8023s - decode an IEEE 802.11n A-MSDU frame
- *
- * Decode an IEEE 802.11 A-MSDU and convert it to a list of 802.3 frames.
---- a/net/mac80211/rx.c
-+++ b/net/mac80211/rx.c
-@@ -2899,7 +2899,6 @@ __ieee80211_rx_h_amsdu(struct ieee80211_
- static ieee80211_rx_result res;
- struct ethhdr ethhdr;
- const u8 *check_da = ethhdr.h_dest, *check_sa = ethhdr.h_source;
-- bool mesh = false;
-
- if (unlikely(ieee80211_has_a4(hdr->frame_control))) {
- check_da = NULL;
-@@ -2917,7 +2916,6 @@ __ieee80211_rx_h_amsdu(struct ieee80211_
- case NL80211_IFTYPE_MESH_POINT:
- check_sa = NULL;
- check_da = NULL;
-- mesh = true;
- break;
- default:
- break;
-@@ -2932,10 +2930,21 @@ __ieee80211_rx_h_amsdu(struct ieee80211_
- data_offset, true))
- return RX_DROP_UNUSABLE;
-
-+ if (rx->sta && rx->sta->amsdu_mesh_control < 0) {
-+ bool valid_std = ieee80211_is_valid_amsdu(skb, true);
-+ bool valid_nonstd = ieee80211_is_valid_amsdu(skb, false);
-+
-+ if (valid_std && !valid_nonstd)
-+ rx->sta->amsdu_mesh_control = 1;
-+ else if (valid_nonstd && !valid_std)
-+ rx->sta->amsdu_mesh_control = 0;
-+ }
-+
- ieee80211_amsdu_to_8023s(skb, &frame_list, dev->dev_addr,
- rx->sdata->vif.type,
- rx->local->hw.extra_tx_headroom,
-- check_da, check_sa, mesh);
-+ check_da, check_sa,
-+ rx->sta->amsdu_mesh_control);
-
- while (!skb_queue_empty(&frame_list)) {
- rx->skb = __skb_dequeue(&frame_list);
---- a/net/mac80211/sta_info.c
-+++ b/net/mac80211/sta_info.c
-@@ -591,6 +591,9 @@ __sta_info_alloc(struct ieee80211_sub_if
-
- sta->sta_state = IEEE80211_STA_NONE;
-
-+ if (sdata->vif.type == NL80211_IFTYPE_MESH_POINT)
-+ sta->amsdu_mesh_control = -1;
-+
- /* Mark TID as unreserved */
- sta->reserved_tid = IEEE80211_TID_UNRESERVED;
-
---- a/net/mac80211/sta_info.h
-+++ b/net/mac80211/sta_info.h
-@@ -702,6 +702,7 @@ struct sta_info {
- struct codel_params cparams;
-
- u8 reserved_tid;
-+ s8 amsdu_mesh_control;
-
- struct cfg80211_chan_def tdls_chandef;
-
---- a/net/wireless/util.c
-+++ b/net/wireless/util.c
-@@ -776,6 +776,38 @@ __ieee80211_amsdu_copy(struct sk_buff *s
- return frame;
- }
-
-+bool ieee80211_is_valid_amsdu(struct sk_buff *skb, bool mesh_hdr)
-+{
-+ int offset = 0, remaining, subframe_len, padding;
-+
-+ for (offset = 0; offset < skb->len; offset += subframe_len + padding) {
-+ struct {
-+ __be16 len;
-+ u8 mesh_flags;
-+ } hdr;
-+ u16 len;
-+
-+ if (skb_copy_bits(skb, offset + 2 * ETH_ALEN, &hdr, sizeof(hdr)) < 0)
-+ return false;
-+
-+ if (mesh_hdr)
-+ len = le16_to_cpu(*(__le16 *)&hdr.len) +
-+ __ieee80211_get_mesh_hdrlen(hdr.mesh_flags);
-+ else
-+ len = ntohs(hdr.len);
-+
-+ subframe_len = sizeof(struct ethhdr) + len;
-+ padding = (4 - subframe_len) & 0x3;
-+ remaining = skb->len - offset;
-+
-+ if (subframe_len > remaining)
-+ return false;
-+ }
-+
-+ return true;
-+}
-+EXPORT_SYMBOL(ieee80211_is_valid_amsdu);
-+
- void ieee80211_amsdu_to_8023s(struct sk_buff *skb, struct sk_buff_head *list,
- const u8 *addr, enum nl80211_iftype iftype,
- const unsigned int extra_headroom,
diff --git a/package/kernel/mac80211/patches/subsys/318-wifi-mac80211-fix-race-in-mesh-sequence-number-assig.patch b/package/kernel/mac80211/patches/subsys/318-wifi-mac80211-fix-race-in-mesh-sequence-number-assig.patch
deleted file mode 100644
index 7d01ffdfff..0000000000
--- a/package/kernel/mac80211/patches/subsys/318-wifi-mac80211-fix-race-in-mesh-sequence-number-assig.patch
+++ /dev/null
@@ -1,37 +0,0 @@
-From: Felix Fietkau <nbd@nbd.name>
-Date: Wed, 15 Feb 2023 15:21:37 +0100
-Subject: [PATCH] wifi: mac80211: fix race in mesh sequence number
- assignment
-
-Since the sequence number is shared across different tx queues, it needs
-to be atomic in order to avoid accidental duplicate assignment
-
-Signed-off-by: Felix Fietkau <nbd@nbd.name>
----
-
---- a/net/mac80211/ieee80211_i.h
-+++ b/net/mac80211/ieee80211_i.h
-@@ -696,7 +696,7 @@ struct ieee80211_if_mesh {
- struct mesh_stats mshstats;
- struct mesh_config mshcfg;
- atomic_t estab_plinks;
-- u32 mesh_seqnum;
-+ atomic_t mesh_seqnum;
- bool accepting_plinks;
- int num_gates;
- struct beacon_data __rcu *beacon;
---- a/net/mac80211/mesh.c
-+++ b/net/mac80211/mesh.c
-@@ -752,10 +752,8 @@ unsigned int ieee80211_new_mesh_header(s
-
- meshhdr->ttl = sdata->u.mesh.mshcfg.dot11MeshTTL;
-
-- /* FIXME: racy -- TX on multiple queues can be concurrent */
-- put_unaligned(cpu_to_le32(sdata->u.mesh.mesh_seqnum), &meshhdr->seqnum);
-- sdata->u.mesh.mesh_seqnum++;
--
-+ put_unaligned_le32(atomic_inc_return(&sdata->u.mesh.mesh_seqnum),
-+ &meshhdr->seqnum);
- if (addr4or5 && !addr6) {
- meshhdr->flags |= MESH_FLAGS_AE_A4;
- memcpy(meshhdr->eaddr1, addr4or5, ETH_ALEN);
diff --git a/package/kernel/mac80211/patches/subsys/319-wifi-mac80211-mesh-fast-xmit-support.patch b/package/kernel/mac80211/patches/subsys/319-wifi-mac80211-mesh-fast-xmit-support.patch
deleted file mode 100644
index 968d2885f2..0000000000
--- a/package/kernel/mac80211/patches/subsys/319-wifi-mac80211-mesh-fast-xmit-support.patch
+++ /dev/null
@@ -1,850 +0,0 @@
-From: Felix Fietkau <nbd@nbd.name>
-Date: Sun, 26 Feb 2023 13:53:08 +0100
-Subject: [PATCH] wifi: mac80211: mesh fast xmit support
-
-Previously, fast xmit only worked on interface types where initially a
-sta lookup is performed, and a cached header can be attached to the sta,
-requiring only some fields to be updated at runtime.
-
-This technique is not directly applicable for a mesh device type due
-to the dynamic nature of the topology and protocol. There are more
-addresses that need to be filled, and there is an extra header with a
-dynamic length based on the addressing mode.
-
-Change the code to cache entries contain a copy of the mesh subframe header +
-bridge tunnel header, as well as an embedded struct ieee80211_fast_tx, which
-contains the information for building the 802.11 header.
-
-Add a mesh specific early fast xmit call, which looks up a cached entry and
-adds only the mesh subframe header, before passing it over to the generic
-fast xmit code.
-
-To ensure the changes in network are reflected in these cached headers,
-flush affected cached entries on path changes, as well as other conditions
-that currently trigger a fast xmit check in other modes (key changes etc.)
-
-This code is loosely based on a previous implementation by:
-Sriram R <quic_srirrama@quicinc.com>
-
-Signed-off-by: Ryder Lee <ryder.lee@mediatek.com>
-Signed-off-by: Felix Fietkau <nbd@nbd.name>
----
-
---- a/net/mac80211/ieee80211_i.h
-+++ b/net/mac80211/ieee80211_i.h
-@@ -37,6 +37,7 @@
- extern const struct cfg80211_ops mac80211_config_ops;
-
- struct ieee80211_local;
-+struct ieee80211_mesh_fast_tx;
-
- /* Maximum number of broadcast/multicast frames to buffer when some of the
- * associated stations are using power saving. */
-@@ -656,6 +657,19 @@ struct mesh_table {
- atomic_t entries; /* Up to MAX_MESH_NEIGHBOURS */
- };
-
-+/**
-+ * struct mesh_tx_cache - mesh fast xmit header cache
-+ *
-+ * @rht: hash table containing struct ieee80211_mesh_fast_tx, using skb DA as key
-+ * @walk_head: linked list containing all ieee80211_mesh_fast_tx objects
-+ * @walk_lock: lock protecting walk_head and rht
-+ */
-+struct mesh_tx_cache {
-+ struct rhashtable rht;
-+ struct hlist_head walk_head;
-+ spinlock_t walk_lock;
-+};
-+
- struct ieee80211_if_mesh {
- struct timer_list housekeeping_timer;
- struct timer_list mesh_path_timer;
-@@ -734,6 +748,7 @@ struct ieee80211_if_mesh {
- struct mesh_table mpp_paths; /* Store paths for MPP&MAP */
- int mesh_paths_generation;
- int mpp_paths_generation;
-+ struct mesh_tx_cache tx_cache;
- };
-
- #ifdef CPTCFG_MAC80211_MESH
-@@ -2002,6 +2017,11 @@ int ieee80211_tx_control_port(struct wip
- int link_id, u64 *cookie);
- int ieee80211_probe_mesh_link(struct wiphy *wiphy, struct net_device *dev,
- const u8 *buf, size_t len);
-+void __ieee80211_xmit_fast(struct ieee80211_sub_if_data *sdata,
-+ struct sta_info *sta,
-+ struct ieee80211_fast_tx *fast_tx,
-+ struct sk_buff *skb, bool ampdu,
-+ const u8 *da, const u8 *sa);
-
- /* HT */
- void ieee80211_apply_htcap_overrides(struct ieee80211_sub_if_data *sdata,
---- a/net/mac80211/mesh.c
-+++ b/net/mac80211/mesh.c
-@@ -10,6 +10,7 @@
- #include <asm/unaligned.h>
- #include "ieee80211_i.h"
- #include "mesh.h"
-+#include "wme.h"
- #include "driver-ops.h"
-
- static int mesh_allocated;
-@@ -698,6 +699,95 @@ ieee80211_mesh_update_bss_params(struct
- __le32_to_cpu(he_oper->he_oper_params);
- }
-
-+bool ieee80211_mesh_xmit_fast(struct ieee80211_sub_if_data *sdata,
-+ struct sk_buff *skb, u32 ctrl_flags)
-+{
-+ struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
-+ struct ieee80211_mesh_fast_tx *entry;
-+ struct ieee80211s_hdr *meshhdr;
-+ u8 sa[ETH_ALEN] __aligned(2);
-+ struct tid_ampdu_tx *tid_tx;
-+ struct sta_info *sta;
-+ bool copy_sa = false;
-+ u16 ethertype;
-+ u8 tid;
-+
-+ if (ctrl_flags & IEEE80211_TX_CTRL_SKIP_MPATH_LOOKUP)
-+ return false;
-+
-+ if (ifmsh->mshcfg.dot11MeshNolearn)
-+ return false;
-+
-+ /* Add support for these cases later */
-+ if (ifmsh->ps_peers_light_sleep || ifmsh->ps_peers_deep_sleep)
-+ return false;
-+
-+ if (is_multicast_ether_addr(skb->data))
-+ return false;
-+
-+ ethertype = (skb->data[12] << 8) | skb->data[13];
-+ if (ethertype < ETH_P_802_3_MIN)
-+ return false;
-+
-+ if (skb->sk && skb_shinfo(skb)->tx_flags & SKBTX_WIFI_STATUS)
-+ return false;
-+
-+ if (skb->ip_summed == CHECKSUM_PARTIAL) {
-+ skb_set_transport_header(skb, skb_checksum_start_offset(skb));
-+ if (skb_checksum_help(skb))
-+ return false;
-+ }
-+
-+ entry = mesh_fast_tx_get(sdata, skb->data);
-+ if (!entry)
-+ return false;
-+
-+ if (skb_headroom(skb) < entry->hdrlen + entry->fast_tx.hdr_len)
-+ return false;
-+
-+ sta = rcu_dereference(entry->mpath->next_hop);
-+ if (!sta)
-+ return false;
-+
-+ tid = skb->priority & IEEE80211_QOS_CTL_TAG1D_MASK;
-+ tid_tx = rcu_dereference(sta->ampdu_mlme.tid_tx[tid]);
-+ if (tid_tx) {
-+ if (!test_bit(HT_AGG_STATE_OPERATIONAL, &tid_tx->state))
-+ return false;
-+ if (tid_tx->timeout)
-+ tid_tx->last_tx = jiffies;
-+ }
-+
-+ skb = skb_share_check(skb, GFP_ATOMIC);
-+ if (!skb)
-+ return true;
-+
-+ skb_set_queue_mapping(skb, ieee80211_select_queue(sdata, sta, skb));
-+
-+ meshhdr = (struct ieee80211s_hdr *)entry->hdr;
-+ if ((meshhdr->flags & MESH_FLAGS_AE) == MESH_FLAGS_AE_A5_A6) {
-+ /* preserve SA from eth header for 6-addr frames */
-+ ether_addr_copy(sa, skb->data + ETH_ALEN);
-+ copy_sa = true;
-+ }
-+
-+ memcpy(skb_push(skb, entry->hdrlen - 2 * ETH_ALEN), entry->hdr,
-+ entry->hdrlen);
-+
-+ meshhdr = (struct ieee80211s_hdr *)skb->data;
-+ put_unaligned_le32(atomic_inc_return(&sdata->u.mesh.mesh_seqnum),
-+ &meshhdr->seqnum);
-+ meshhdr->ttl = sdata->u.mesh.mshcfg.dot11MeshTTL;
-+ if (copy_sa)
-+ ether_addr_copy(meshhdr->eaddr2, sa);
-+
-+ skb_push(skb, 2 * ETH_ALEN);
-+ __ieee80211_xmit_fast(sdata, sta, &entry->fast_tx, skb, tid_tx,
-+ entry->mpath->dst, sdata->vif.addr);
-+
-+ return true;
-+}
-+
- /**
- * ieee80211_fill_mesh_addresses - fill addresses of a locally originated mesh frame
- * @hdr: 802.11 frame header
-@@ -780,6 +870,8 @@ static void ieee80211_mesh_housekeeping(
- changed = mesh_accept_plinks_update(sdata);
- ieee80211_mbss_info_change_notify(sdata, changed);
-
-+ mesh_fast_tx_gc(sdata);
-+
- mod_timer(&ifmsh->housekeeping_timer,
- round_jiffies(jiffies +
- IEEE80211_MESH_HOUSEKEEPING_INTERVAL));
---- a/net/mac80211/mesh.h
-+++ b/net/mac80211/mesh.h
-@@ -122,11 +122,41 @@ struct mesh_path {
- u8 rann_snd_addr[ETH_ALEN];
- u32 rann_metric;
- unsigned long last_preq_to_root;
-+ unsigned long fast_tx_check;
- bool is_root;
- bool is_gate;
- u32 path_change_count;
- };
-
-+#define MESH_FAST_TX_CACHE_MAX_SIZE 512
-+#define MESH_FAST_TX_CACHE_THRESHOLD_SIZE 384
-+#define MESH_FAST_TX_CACHE_TIMEOUT 8000 /* msecs */
-+
-+/**
-+ * struct ieee80211_mesh_fast_tx - cached mesh fast tx entry
-+ * @rhash: rhashtable pointer
-+ * @addr_key: The Ethernet DA which is the key for this entry
-+ * @fast_tx: base fast_tx data
-+ * @hdr: cached mesh and rfc1042 headers
-+ * @hdrlen: length of mesh + rfc1042
-+ * @walk_list: list containing all the fast tx entries
-+ * @mpath: mesh path corresponding to the Mesh DA
-+ * @mppath: MPP entry corresponding to this DA
-+ * @timestamp: Last used time of this entry
-+ */
-+struct ieee80211_mesh_fast_tx {
-+ struct rhash_head rhash;
-+ u8 addr_key[ETH_ALEN] __aligned(2);
-+
-+ struct ieee80211_fast_tx fast_tx;
-+ u8 hdr[sizeof(struct ieee80211s_hdr) + sizeof(rfc1042_header)];
-+ u16 hdrlen;
-+
-+ struct mesh_path *mpath, *mppath;
-+ struct hlist_node walk_list;
-+ unsigned long timestamp;
-+};
-+
- /* Recent multicast cache */
- /* RMC_BUCKETS must be a power of 2, maximum 256 */
- #define RMC_BUCKETS 256
-@@ -298,6 +328,20 @@ void mesh_path_discard_frame(struct ieee
- void mesh_path_tx_root_frame(struct ieee80211_sub_if_data *sdata);
-
- bool mesh_action_is_path_sel(struct ieee80211_mgmt *mgmt);
-+struct ieee80211_mesh_fast_tx *
-+mesh_fast_tx_get(struct ieee80211_sub_if_data *sdata, const u8 *addr);
-+bool ieee80211_mesh_xmit_fast(struct ieee80211_sub_if_data *sdata,
-+ struct sk_buff *skb, u32 ctrl_flags);
-+void mesh_fast_tx_cache(struct ieee80211_sub_if_data *sdata,
-+ struct sk_buff *skb, struct mesh_path *mpath);
-+void mesh_fast_tx_gc(struct ieee80211_sub_if_data *sdata);
-+void mesh_fast_tx_flush_addr(struct ieee80211_sub_if_data *sdata,
-+ const u8 *addr);
-+void mesh_fast_tx_flush_mpath(struct mesh_path *mpath);
-+void mesh_fast_tx_flush_sta(struct ieee80211_sub_if_data *sdata,
-+ struct sta_info *sta);
-+void mesh_path_refresh(struct ieee80211_sub_if_data *sdata,
-+ struct mesh_path *mpath, const u8 *addr);
-
- #ifdef CPTCFG_MAC80211_MESH
- static inline
---- a/net/mac80211/mesh_hwmp.c
-+++ b/net/mac80211/mesh_hwmp.c
-@@ -394,6 +394,7 @@ static u32 hwmp_route_info_get(struct ie
- u32 orig_sn, orig_metric;
- unsigned long orig_lifetime, exp_time;
- u32 last_hop_metric, new_metric;
-+ bool flush_mpath = false;
- bool process = true;
- u8 hopcount;
-
-@@ -491,8 +492,10 @@ static u32 hwmp_route_info_get(struct ie
- }
-
- if (fresh_info) {
-- if (rcu_access_pointer(mpath->next_hop) != sta)
-+ if (rcu_access_pointer(mpath->next_hop) != sta) {
- mpath->path_change_count++;
-+ flush_mpath = true;
-+ }
- mesh_path_assign_nexthop(mpath, sta);
- mpath->flags |= MESH_PATH_SN_VALID;
- mpath->metric = new_metric;
-@@ -502,6 +505,8 @@ static u32 hwmp_route_info_get(struct ie
- mpath->hop_count = hopcount;
- mesh_path_activate(mpath);
- spin_unlock_bh(&mpath->state_lock);
-+ if (flush_mpath)
-+ mesh_fast_tx_flush_mpath(mpath);
- ewma_mesh_fail_avg_init(&sta->mesh->fail_avg);
- /* init it at a low value - 0 start is tricky */
- ewma_mesh_fail_avg_add(&sta->mesh->fail_avg, 1);
-@@ -539,8 +544,10 @@ static u32 hwmp_route_info_get(struct ie
- }
-
- if (fresh_info) {
-- if (rcu_access_pointer(mpath->next_hop) != sta)
-+ if (rcu_access_pointer(mpath->next_hop) != sta) {
- mpath->path_change_count++;
-+ flush_mpath = true;
-+ }
- mesh_path_assign_nexthop(mpath, sta);
- mpath->metric = last_hop_metric;
- mpath->exp_time = time_after(mpath->exp_time, exp_time)
-@@ -548,6 +555,8 @@ static u32 hwmp_route_info_get(struct ie
- mpath->hop_count = 1;
- mesh_path_activate(mpath);
- spin_unlock_bh(&mpath->state_lock);
-+ if (flush_mpath)
-+ mesh_fast_tx_flush_mpath(mpath);
- ewma_mesh_fail_avg_init(&sta->mesh->fail_avg);
- /* init it at a low value - 0 start is tricky */
- ewma_mesh_fail_avg_add(&sta->mesh->fail_avg, 1);
-@@ -1215,6 +1224,20 @@ static int mesh_nexthop_lookup_nolearn(s
- return 0;
- }
-
-+void mesh_path_refresh(struct ieee80211_sub_if_data *sdata,
-+ struct mesh_path *mpath, const u8 *addr)
-+{
-+ if (mpath->flags & (MESH_PATH_REQ_QUEUED | MESH_PATH_FIXED |
-+ MESH_PATH_RESOLVING))
-+ return;
-+
-+ if (time_after(jiffies,
-+ mpath->exp_time -
-+ msecs_to_jiffies(sdata->u.mesh.mshcfg.path_refresh_time)) &&
-+ (!addr || ether_addr_equal(sdata->vif.addr, addr)))
-+ mesh_queue_preq(mpath, PREQ_Q_F_START | PREQ_Q_F_REFRESH);
-+}
-+
- /**
- * mesh_nexthop_lookup - put the appropriate next hop on a mesh frame. Calling
- * this function is considered "using" the associated mpath, so preempt a path
-@@ -1242,19 +1265,15 @@ int mesh_nexthop_lookup(struct ieee80211
- if (!mpath || !(mpath->flags & MESH_PATH_ACTIVE))
- return -ENOENT;
-
-- if (time_after(jiffies,
-- mpath->exp_time -
-- msecs_to_jiffies(sdata->u.mesh.mshcfg.path_refresh_time)) &&
-- ether_addr_equal(sdata->vif.addr, hdr->addr4) &&
-- !(mpath->flags & MESH_PATH_RESOLVING) &&
-- !(mpath->flags & MESH_PATH_FIXED))
-- mesh_queue_preq(mpath, PREQ_Q_F_START | PREQ_Q_F_REFRESH);
-+ mesh_path_refresh(sdata, mpath, hdr->addr4);
-
- next_hop = rcu_dereference(mpath->next_hop);
- if (next_hop) {
- memcpy(hdr->addr1, next_hop->sta.addr, ETH_ALEN);
- memcpy(hdr->addr2, sdata->vif.addr, ETH_ALEN);
- ieee80211_mps_set_frame_flags(sdata, next_hop, hdr);
-+ if (ieee80211_hw_check(&sdata->local->hw, SUPPORT_FAST_XMIT))
-+ mesh_fast_tx_cache(sdata, skb, mpath);
- return 0;
- }
-
---- a/net/mac80211/mesh_pathtbl.c
-+++ b/net/mac80211/mesh_pathtbl.c
-@@ -14,6 +14,7 @@
- #include "wme.h"
- #include "ieee80211_i.h"
- #include "mesh.h"
-+#include <linux/rhashtable.h>
-
- static void mesh_path_free_rcu(struct mesh_table *tbl, struct mesh_path *mpath);
-
-@@ -32,6 +33,41 @@ static const struct rhashtable_params me
- .hashfn = mesh_table_hash,
- };
-
-+static const struct rhashtable_params fast_tx_rht_params = {
-+ .nelem_hint = 10,
-+ .automatic_shrinking = true,
-+ .key_len = ETH_ALEN,
-+ .key_offset = offsetof(struct ieee80211_mesh_fast_tx, addr_key),
-+ .head_offset = offsetof(struct ieee80211_mesh_fast_tx, rhash),
-+ .hashfn = mesh_table_hash,
-+};
-+
-+static void __mesh_fast_tx_entry_free(void *ptr, void *tblptr)
-+{
-+ struct ieee80211_mesh_fast_tx *entry = ptr;
-+
-+ kfree_rcu(entry, fast_tx.rcu_head);
-+}
-+
-+static void mesh_fast_tx_deinit(struct ieee80211_sub_if_data *sdata)
-+{
-+ struct mesh_tx_cache *cache;
-+
-+ cache = &sdata->u.mesh.tx_cache;
-+ rhashtable_free_and_destroy(&cache->rht,
-+ __mesh_fast_tx_entry_free, NULL);
-+}
-+
-+static void mesh_fast_tx_init(struct ieee80211_sub_if_data *sdata)
-+{
-+ struct mesh_tx_cache *cache;
-+
-+ cache = &sdata->u.mesh.tx_cache;
-+ rhashtable_init(&cache->rht, &fast_tx_rht_params);
-+ INIT_HLIST_HEAD(&cache->walk_head);
-+ spin_lock_init(&cache->walk_lock);
-+}
-+
- static inline bool mpath_expired(struct mesh_path *mpath)
- {
- return (mpath->flags & MESH_PATH_ACTIVE) &&
-@@ -381,6 +417,243 @@ struct mesh_path *mesh_path_new(struct i
- return new_mpath;
- }
-
-+static void mesh_fast_tx_entry_free(struct mesh_tx_cache *cache,
-+ struct ieee80211_mesh_fast_tx *entry)
-+{
-+ hlist_del_rcu(&entry->walk_list);
-+ rhashtable_remove_fast(&cache->rht, &entry->rhash, fast_tx_rht_params);
-+ kfree_rcu(entry, fast_tx.rcu_head);
-+}
-+
-+struct ieee80211_mesh_fast_tx *
-+mesh_fast_tx_get(struct ieee80211_sub_if_data *sdata, const u8 *addr)
-+{
-+ struct ieee80211_mesh_fast_tx *entry;
-+ struct mesh_tx_cache *cache;
-+
-+ cache = &sdata->u.mesh.tx_cache;
-+ entry = rhashtable_lookup(&cache->rht, addr, fast_tx_rht_params);
-+ if (!entry)
-+ return NULL;
-+
-+ if (!(entry->mpath->flags & MESH_PATH_ACTIVE) ||
-+ mpath_expired(entry->mpath)) {
-+ spin_lock_bh(&cache->walk_lock);
-+ entry = rhashtable_lookup(&cache->rht, addr, fast_tx_rht_params);
-+ if (entry)
-+ mesh_fast_tx_entry_free(cache, entry);
-+ spin_unlock_bh(&cache->walk_lock);
-+ return NULL;
-+ }
-+
-+ mesh_path_refresh(sdata, entry->mpath, NULL);
-+ if (entry->mppath)
-+ entry->mppath->exp_time = jiffies;
-+ entry->timestamp = jiffies;
-+
-+ return entry;
-+}
-+
-+void mesh_fast_tx_cache(struct ieee80211_sub_if_data *sdata,
-+ struct sk_buff *skb, struct mesh_path *mpath)
-+{
-+ struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
-+ struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
-+ struct ieee80211_mesh_fast_tx *entry, *prev;
-+ struct ieee80211_mesh_fast_tx build = {};
-+ struct ieee80211s_hdr *meshhdr;
-+ struct mesh_tx_cache *cache;
-+ struct ieee80211_key *key;
-+ struct mesh_path *mppath;
-+ struct sta_info *sta;
-+ u8 *qc;
-+
-+ if (sdata->noack_map ||
-+ !ieee80211_is_data_qos(hdr->frame_control))
-+ return;
-+
-+ build.fast_tx.hdr_len = ieee80211_hdrlen(hdr->frame_control);
-+ meshhdr = (struct ieee80211s_hdr *)(skb->data + build.fast_tx.hdr_len);
-+ build.hdrlen = ieee80211_get_mesh_hdrlen(meshhdr);
-+
-+ cache = &sdata->u.mesh.tx_cache;
-+ if (atomic_read(&cache->rht.nelems) >= MESH_FAST_TX_CACHE_MAX_SIZE)
-+ return;
-+
-+ sta = rcu_dereference(mpath->next_hop);
-+ if (!sta)
-+ return;
-+
-+ if ((meshhdr->flags & MESH_FLAGS_AE) == MESH_FLAGS_AE_A5_A6) {
-+ /* This is required to keep the mppath alive */
-+ mppath = mpp_path_lookup(sdata, meshhdr->eaddr1);
-+ if (!mppath)
-+ return;
-+ build.mppath = mppath;
-+ } else if (ieee80211_has_a4(hdr->frame_control)) {
-+ mppath = mpath;
-+ } else {
-+ return;
-+ }
-+
-+ /* rate limit, in case fast xmit can't be enabled */
-+ if (mppath->fast_tx_check == jiffies)
-+ return;
-+
-+ mppath->fast_tx_check = jiffies;
-+
-+ /*
-+ * Same use of the sta lock as in ieee80211_check_fast_xmit, in order
-+ * to protect against concurrent sta key updates.
-+ */
-+ spin_lock_bh(&sta->lock);
-+ key = rcu_access_pointer(sta->ptk[sta->ptk_idx]);
-+ if (!key)
-+ key = rcu_access_pointer(sdata->default_unicast_key);
-+ build.fast_tx.key = key;
-+
-+ if (key) {
-+ bool gen_iv, iv_spc;
-+
-+ gen_iv = key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_IV;
-+ iv_spc = key->conf.flags & IEEE80211_KEY_FLAG_PUT_IV_SPACE;
-+
-+ if (!(key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE) ||
-+ (key->flags & KEY_FLAG_TAINTED))
-+ goto unlock_sta;
-+
-+ switch (key->conf.cipher) {
-+ case WLAN_CIPHER_SUITE_CCMP:
-+ case WLAN_CIPHER_SUITE_CCMP_256:
-+ if (gen_iv)
-+ build.fast_tx.pn_offs = build.fast_tx.hdr_len;
-+ if (gen_iv || iv_spc)
-+ build.fast_tx.hdr_len += IEEE80211_CCMP_HDR_LEN;
-+ break;
-+ case WLAN_CIPHER_SUITE_GCMP:
-+ case WLAN_CIPHER_SUITE_GCMP_256:
-+ if (gen_iv)
-+ build.fast_tx.pn_offs = build.fast_tx.hdr_len;
-+ if (gen_iv || iv_spc)
-+ build.fast_tx.hdr_len += IEEE80211_GCMP_HDR_LEN;
-+ break;
-+ default:
-+ goto unlock_sta;
-+ }
-+ }
-+
-+ memcpy(build.addr_key, mppath->dst, ETH_ALEN);
-+ build.timestamp = jiffies;
-+ build.fast_tx.band = info->band;
-+ build.fast_tx.da_offs = offsetof(struct ieee80211_hdr, addr3);
-+ build.fast_tx.sa_offs = offsetof(struct ieee80211_hdr, addr4);
-+ build.mpath = mpath;
-+ memcpy(build.hdr, meshhdr, build.hdrlen);
-+ memcpy(build.hdr + build.hdrlen, rfc1042_header, sizeof(rfc1042_header));
-+ build.hdrlen += sizeof(rfc1042_header);
-+ memcpy(build.fast_tx.hdr, hdr, build.fast_tx.hdr_len);
-+
-+ hdr = (struct ieee80211_hdr *)build.fast_tx.hdr;
-+ if (build.fast_tx.key)
-+ hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_PROTECTED);
-+
-+ qc = ieee80211_get_qos_ctl(hdr);
-+ qc[1] |= IEEE80211_QOS_CTL_MESH_CONTROL_PRESENT >> 8;
-+
-+ entry = kmemdup(&build, sizeof(build), GFP_ATOMIC);
-+ if (!entry)
-+ goto unlock_sta;
-+
-+ spin_lock(&cache->walk_lock);
-+ prev = rhashtable_lookup_get_insert_fast(&cache->rht,
-+ &entry->rhash,
-+ fast_tx_rht_params);
-+ if (unlikely(IS_ERR(prev))) {
-+ kfree(entry);
-+ goto unlock_cache;
-+ }
-+
-+ /*
-+ * replace any previous entry in the hash table, in case we're
-+ * replacing it with a different type (e.g. mpath -> mpp)
-+ */
-+ if (unlikely(prev)) {
-+ rhashtable_replace_fast(&cache->rht, &prev->rhash,
-+ &entry->rhash, fast_tx_rht_params);
-+ hlist_del_rcu(&prev->walk_list);
-+ kfree_rcu(prev, fast_tx.rcu_head);
-+ }
-+
-+ hlist_add_head(&entry->walk_list, &cache->walk_head);
-+
-+unlock_cache:
-+ spin_unlock(&cache->walk_lock);
-+unlock_sta:
-+ spin_unlock_bh(&sta->lock);
-+}
-+
-+void mesh_fast_tx_gc(struct ieee80211_sub_if_data *sdata)
-+{
-+ unsigned long timeout = msecs_to_jiffies(MESH_FAST_TX_CACHE_TIMEOUT);
-+ struct mesh_tx_cache *cache;
-+ struct ieee80211_mesh_fast_tx *entry;
-+ struct hlist_node *n;
-+
-+ cache = &sdata->u.mesh.tx_cache;
-+ if (atomic_read(&cache->rht.nelems) < MESH_FAST_TX_CACHE_THRESHOLD_SIZE)
-+ return;
-+
-+ spin_lock_bh(&cache->walk_lock);
-+ hlist_for_each_entry_safe(entry, n, &cache->walk_head, walk_list)
-+ if (!time_is_after_jiffies(entry->timestamp + timeout))
-+ mesh_fast_tx_entry_free(cache, entry);
-+ spin_unlock_bh(&cache->walk_lock);
-+}
-+
-+void mesh_fast_tx_flush_mpath(struct mesh_path *mpath)
-+{
-+ struct ieee80211_sub_if_data *sdata = mpath->sdata;
-+ struct mesh_tx_cache *cache = &sdata->u.mesh.tx_cache;
-+ struct ieee80211_mesh_fast_tx *entry;
-+ struct hlist_node *n;
-+
-+ cache = &sdata->u.mesh.tx_cache;
-+ spin_lock_bh(&cache->walk_lock);
-+ hlist_for_each_entry_safe(entry, n, &cache->walk_head, walk_list)
-+ if (entry->mpath == mpath)
-+ mesh_fast_tx_entry_free(cache, entry);
-+ spin_unlock_bh(&cache->walk_lock);
-+}
-+
-+void mesh_fast_tx_flush_sta(struct ieee80211_sub_if_data *sdata,
-+ struct sta_info *sta)
-+{
-+ struct mesh_tx_cache *cache = &sdata->u.mesh.tx_cache;
-+ struct ieee80211_mesh_fast_tx *entry;
-+ struct hlist_node *n;
-+
-+ cache = &sdata->u.mesh.tx_cache;
-+ spin_lock_bh(&cache->walk_lock);
-+ hlist_for_each_entry_safe(entry, n, &cache->walk_head, walk_list)
-+ if (rcu_access_pointer(entry->mpath->next_hop) == sta)
-+ mesh_fast_tx_entry_free(cache, entry);
-+ spin_unlock_bh(&cache->walk_lock);
-+}
-+
-+void mesh_fast_tx_flush_addr(struct ieee80211_sub_if_data *sdata,
-+ const u8 *addr)
-+{
-+ struct mesh_tx_cache *cache = &sdata->u.mesh.tx_cache;
-+ struct ieee80211_mesh_fast_tx *entry;
-+
-+ cache = &sdata->u.mesh.tx_cache;
-+ spin_lock_bh(&cache->walk_lock);
-+ entry = rhashtable_lookup(&cache->rht, addr, fast_tx_rht_params);
-+ if (entry)
-+ mesh_fast_tx_entry_free(cache, entry);
-+ spin_unlock_bh(&cache->walk_lock);
-+}
-+
- /**
- * mesh_path_add - allocate and add a new path to the mesh path table
- * @dst: destination address of the path (ETH_ALEN length)
-@@ -464,6 +737,8 @@ int mpp_path_add(struct ieee80211_sub_if
-
- if (ret)
- kfree(new_mpath);
-+ else
-+ mesh_fast_tx_flush_addr(sdata, dst);
-
- sdata->u.mesh.mpp_paths_generation++;
- return ret;
-@@ -523,6 +798,10 @@ static void __mesh_path_del(struct mesh_
- {
- hlist_del_rcu(&mpath->walk_list);
- rhashtable_remove_fast(&tbl->rhead, &mpath->rhash, mesh_rht_params);
-+ if (tbl == &mpath->sdata->u.mesh.mpp_paths)
-+ mesh_fast_tx_flush_addr(mpath->sdata, mpath->dst);
-+ else
-+ mesh_fast_tx_flush_mpath(mpath);
- mesh_path_free_rcu(tbl, mpath);
- }
-
-@@ -747,6 +1026,7 @@ void mesh_path_fix_nexthop(struct mesh_p
- mpath->exp_time = 0;
- mpath->flags = MESH_PATH_FIXED | MESH_PATH_SN_VALID;
- mesh_path_activate(mpath);
-+ mesh_fast_tx_flush_mpath(mpath);
- spin_unlock_bh(&mpath->state_lock);
- ewma_mesh_fail_avg_init(&next_hop->mesh->fail_avg);
- /* init it at a low value - 0 start is tricky */
-@@ -758,6 +1038,7 @@ void mesh_pathtbl_init(struct ieee80211_
- {
- mesh_table_init(&sdata->u.mesh.mesh_paths);
- mesh_table_init(&sdata->u.mesh.mpp_paths);
-+ mesh_fast_tx_init(sdata);
- }
-
- static
-@@ -785,6 +1066,7 @@ void mesh_path_expire(struct ieee80211_s
-
- void mesh_pathtbl_unregister(struct ieee80211_sub_if_data *sdata)
- {
-+ mesh_fast_tx_deinit(sdata);
- mesh_table_free(&sdata->u.mesh.mesh_paths);
- mesh_table_free(&sdata->u.mesh.mpp_paths);
- }
---- a/net/mac80211/rx.c
-+++ b/net/mac80211/rx.c
-@@ -2791,6 +2791,7 @@ ieee80211_rx_mesh_data(struct ieee80211_
- if (mesh_hdr->flags & MESH_FLAGS_AE) {
- struct mesh_path *mppath;
- char *proxied_addr;
-+ bool update = false;
-
- if (multicast)
- proxied_addr = mesh_hdr->eaddr1;
-@@ -2806,11 +2807,18 @@ ieee80211_rx_mesh_data(struct ieee80211_
- mpp_path_add(sdata, proxied_addr, eth->h_source);
- } else {
- spin_lock_bh(&mppath->state_lock);
-- if (!ether_addr_equal(mppath->mpp, eth->h_source))
-+ if (!ether_addr_equal(mppath->mpp, eth->h_source)) {
- memcpy(mppath->mpp, eth->h_source, ETH_ALEN);
-+ update = true;
-+ }
- mppath->exp_time = jiffies;
- spin_unlock_bh(&mppath->state_lock);
- }
-+
-+ /* flush fast xmit cache if the address path changed */
-+ if (update)
-+ mesh_fast_tx_flush_addr(sdata, proxied_addr);
-+
- rcu_read_unlock();
- }
-
---- a/net/mac80211/tx.c
-+++ b/net/mac80211/tx.c
-@@ -3022,6 +3022,9 @@ void ieee80211_check_fast_xmit(struct st
- if (!ieee80211_hw_check(&local->hw, SUPPORT_FAST_XMIT))
- return;
-
-+ if (ieee80211_vif_is_mesh(&sdata->vif))
-+ mesh_fast_tx_flush_sta(sdata, sta);
-+
- /* Locking here protects both the pointer itself, and against concurrent
- * invocations winning data access races to, e.g., the key pointer that
- * is used.
-@@ -3403,6 +3406,9 @@ static bool ieee80211_amsdu_aggregate(st
- if (sdata->vif.offload_flags & IEEE80211_OFFLOAD_ENCAP_ENABLED)
- return false;
-
-+ if (ieee80211_vif_is_mesh(&sdata->vif))
-+ return false;
-+
- if (skb_is_gso(skb))
- return false;
-
-@@ -3635,10 +3641,11 @@ free:
- return NULL;
- }
-
--static void __ieee80211_xmit_fast(struct ieee80211_sub_if_data *sdata,
-- struct sta_info *sta,
-- struct ieee80211_fast_tx *fast_tx,
-- struct sk_buff *skb, u8 tid, bool ampdu)
-+void __ieee80211_xmit_fast(struct ieee80211_sub_if_data *sdata,
-+ struct sta_info *sta,
-+ struct ieee80211_fast_tx *fast_tx,
-+ struct sk_buff *skb, bool ampdu,
-+ const u8 *da, const u8 *sa)
- {
- struct ieee80211_local *local = sdata->local;
- struct ieee80211_hdr *hdr = (void *)fast_tx->hdr;
-@@ -3647,7 +3654,6 @@ static void __ieee80211_xmit_fast(struct
- ieee80211_tx_result r;
- int hw_headroom = sdata->local->hw.extra_tx_headroom;
- int extra_head = fast_tx->hdr_len - (ETH_HLEN - 2);
-- struct ethhdr eth;
-
- skb = skb_share_check(skb, GFP_ATOMIC);
- if (unlikely(!skb))
-@@ -3667,11 +3673,10 @@ static void __ieee80211_xmit_fast(struct
- ENCRYPT_NO)))
- goto free;
-
-- memcpy(&eth, skb->data, ETH_HLEN - 2);
- hdr = skb_push(skb, extra_head);
- memcpy(skb->data, fast_tx->hdr, fast_tx->hdr_len);
-- memcpy(skb->data + fast_tx->da_offs, eth.h_dest, ETH_ALEN);
-- memcpy(skb->data + fast_tx->sa_offs, eth.h_source, ETH_ALEN);
-+ memcpy(skb->data + fast_tx->da_offs, da, ETH_ALEN);
-+ memcpy(skb->data + fast_tx->sa_offs, sa, ETH_ALEN);
-
- info = IEEE80211_SKB_CB(skb);
- memset(info, 0, sizeof(*info));
-@@ -3690,7 +3695,8 @@ static void __ieee80211_xmit_fast(struct
- #endif
-
- if (hdr->frame_control & cpu_to_le16(IEEE80211_STYPE_QOS_DATA)) {
-- tid = skb->priority & IEEE80211_QOS_CTL_TAG1D_MASK;
-+ u8 tid = skb->priority & IEEE80211_QOS_CTL_TAG1D_MASK;
-+
- *ieee80211_get_qos_ctl(hdr) = tid;
- }
-
-@@ -3733,6 +3739,7 @@ static bool ieee80211_xmit_fast(struct i
- struct ieee80211_hdr *hdr = (void *)fast_tx->hdr;
- struct tid_ampdu_tx *tid_tx = NULL;
- struct sk_buff *next;
-+ struct ethhdr eth;
- u8 tid = IEEE80211_NUM_TIDS;
-
- /* control port protocol needs a lot of special handling */
-@@ -3758,6 +3765,8 @@ static bool ieee80211_xmit_fast(struct i
- }
- }
-
-+ memcpy(&eth, skb->data, ETH_HLEN - 2);
-+
- /* after this point (skb is modified) we cannot return false */
- skb = ieee80211_tx_skb_fixup(skb, ieee80211_sdata_netdev_features(sdata));
- if (!skb)
-@@ -3765,7 +3774,8 @@ static bool ieee80211_xmit_fast(struct i
-
- skb_list_walk_safe(skb, skb, next) {
- skb_mark_not_on_list(skb);
-- __ieee80211_xmit_fast(sdata, sta, fast_tx, skb, tid, tid_tx);
-+ __ieee80211_xmit_fast(sdata, sta, fast_tx, skb, tid_tx,
-+ eth.h_dest, eth.h_source);
- }
-
- return true;
-@@ -4252,8 +4262,15 @@ void __ieee80211_subif_start_xmit(struct
- return;
- }
-
-+ sk_pacing_shift_update(skb->sk, sdata->local->hw.tx_sk_pacing_shift);
-+
- rcu_read_lock();
-
-+ if (ieee80211_vif_is_mesh(&sdata->vif) &&
-+ ieee80211_hw_check(&local->hw, SUPPORT_FAST_XMIT) &&
-+ ieee80211_mesh_xmit_fast(sdata, skb, ctrl_flags))
-+ goto out;
-+
- if (ieee80211_lookup_ra_sta(sdata, skb, &sta))
- goto out_free;
-
-@@ -4263,8 +4280,6 @@ void __ieee80211_subif_start_xmit(struct
- skb_set_queue_mapping(skb, ieee80211_select_queue(sdata, sta, skb));
- ieee80211_aggr_check(sdata, sta, skb);
-
-- sk_pacing_shift_update(skb->sk, sdata->local->hw.tx_sk_pacing_shift);
--
- if (sta) {
- struct ieee80211_fast_tx *fast_tx;
-
diff --git a/package/kernel/mac80211/patches/subsys/320-wifi-mac80211-use-mesh-header-cache-to-speed-up-mesh.patch b/package/kernel/mac80211/patches/subsys/320-wifi-mac80211-use-mesh-header-cache-to-speed-up-mesh.patch
deleted file mode 100644
index 28b1ff1106..0000000000
--- a/package/kernel/mac80211/patches/subsys/320-wifi-mac80211-use-mesh-header-cache-to-speed-up-mesh.patch
+++ /dev/null
@@ -1,132 +0,0 @@
-From: Felix Fietkau <nbd@nbd.name>
-Date: Thu, 16 Feb 2023 11:07:30 +0100
-Subject: [PATCH] wifi: mac80211: use mesh header cache to speed up mesh
- forwarding
-
-Significantly reduces mesh forwarding path CPU usage and enables the
-direct use of iTXQ.
-
-Signed-off-by: Felix Fietkau <nbd@nbd.name>
----
-
---- a/net/mac80211/rx.c
-+++ b/net/mac80211/rx.c
-@@ -2720,6 +2720,65 @@ ieee80211_deliver_skb(struct ieee80211_r
- }
- }
-
-+#ifdef CPTCFG_MAC80211_MESH
-+static bool
-+ieee80211_rx_mesh_fast_forward(struct ieee80211_sub_if_data *sdata,
-+ struct sk_buff *skb, int hdrlen)
-+{
-+ struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
-+ struct ieee80211_mesh_fast_tx *entry = NULL;
-+ struct ieee80211s_hdr *mesh_hdr;
-+ struct tid_ampdu_tx *tid_tx;
-+ struct sta_info *sta;
-+ struct ethhdr eth;
-+ u8 tid;
-+
-+ mesh_hdr = (struct ieee80211s_hdr *)(skb->data + sizeof(eth));
-+ if ((mesh_hdr->flags & MESH_FLAGS_AE) == MESH_FLAGS_AE_A5_A6)
-+ entry = mesh_fast_tx_get(sdata, mesh_hdr->eaddr1);
-+ else if (!(mesh_hdr->flags & MESH_FLAGS_AE))
-+ entry = mesh_fast_tx_get(sdata, skb->data);
-+ if (!entry)
-+ return false;
-+
-+ sta = rcu_dereference(entry->mpath->next_hop);
-+ if (!sta)
-+ return false;
-+
-+ if (skb_linearize(skb))
-+ return false;
-+
-+ tid = skb->priority & IEEE80211_QOS_CTL_TAG1D_MASK;
-+ tid_tx = rcu_dereference(sta->ampdu_mlme.tid_tx[tid]);
-+ if (tid_tx) {
-+ if (!test_bit(HT_AGG_STATE_OPERATIONAL, &tid_tx->state))
-+ return false;
-+
-+ if (tid_tx->timeout)
-+ tid_tx->last_tx = jiffies;
-+ }
-+
-+ ieee80211_aggr_check(sdata, sta, skb);
-+
-+ if (ieee80211_get_8023_tunnel_proto(skb->data + hdrlen,
-+ &skb->protocol))
-+ hdrlen += ETH_ALEN;
-+ else
-+ skb->protocol = htons(skb->len - hdrlen);
-+ skb_set_network_header(skb, hdrlen + 2);
-+
-+ skb->dev = sdata->dev;
-+ memcpy(&eth, skb->data, ETH_HLEN - 2);
-+ skb_pull(skb, 2);
-+ __ieee80211_xmit_fast(sdata, sta, &entry->fast_tx, skb, tid_tx,
-+ eth.h_dest, eth.h_source);
-+ IEEE80211_IFSTA_MESH_CTR_INC(ifmsh, fwded_unicast);
-+ IEEE80211_IFSTA_MESH_CTR_INC(ifmsh, fwded_frames);
-+
-+ return true;
-+}
-+#endif
-+
- static ieee80211_rx_result
- ieee80211_rx_mesh_data(struct ieee80211_sub_if_data *sdata, struct sta_info *sta,
- struct sk_buff *skb)
-@@ -2824,6 +2883,10 @@ ieee80211_rx_mesh_data(struct ieee80211_
-
- skb_set_queue_mapping(skb, ieee802_1d_to_ac[skb->priority]);
-
-+ if (!multicast &&
-+ ieee80211_rx_mesh_fast_forward(sdata, skb, mesh_hdrlen))
-+ return RX_QUEUED;
-+
- ieee80211_fill_mesh_addresses(&hdr, &hdr.frame_control,
- eth->h_dest, eth->h_source);
- hdrlen = ieee80211_hdrlen(hdr.frame_control);
-@@ -2862,6 +2925,7 @@ ieee80211_rx_mesh_data(struct ieee80211_
- info->control.flags |= IEEE80211_TX_INTCFL_NEED_TXPROCESSING;
- info->control.vif = &sdata->vif;
- info->control.jiffies = jiffies;
-+ fwd_skb->dev = sdata->dev;
- if (multicast) {
- IEEE80211_IFSTA_MESH_CTR_INC(ifmsh, fwded_mcast);
- memcpy(fwd_hdr->addr2, sdata->vif.addr, ETH_ALEN);
-@@ -2883,7 +2947,6 @@ ieee80211_rx_mesh_data(struct ieee80211_
- }
-
- IEEE80211_IFSTA_MESH_CTR_INC(ifmsh, fwded_frames);
-- fwd_skb->dev = sdata->dev;
- ieee80211_add_pending_skb(local, fwd_skb);
-
- rx_accept:
---- a/net/mac80211/ieee80211_i.h
-+++ b/net/mac80211/ieee80211_i.h
-@@ -2022,6 +2022,8 @@ void __ieee80211_xmit_fast(struct ieee80
- struct ieee80211_fast_tx *fast_tx,
- struct sk_buff *skb, bool ampdu,
- const u8 *da, const u8 *sa);
-+void ieee80211_aggr_check(struct ieee80211_sub_if_data *sdata,
-+ struct sta_info *sta, struct sk_buff *skb);
-
- /* HT */
- void ieee80211_apply_htcap_overrides(struct ieee80211_sub_if_data *sdata,
---- a/net/mac80211/tx.c
-+++ b/net/mac80211/tx.c
-@@ -1191,10 +1191,8 @@ static bool ieee80211_tx_prep_agg(struct
- return queued;
- }
-
--static void
--ieee80211_aggr_check(struct ieee80211_sub_if_data *sdata,
-- struct sta_info *sta,
-- struct sk_buff *skb)
-+void ieee80211_aggr_check(struct ieee80211_sub_if_data *sdata,
-+ struct sta_info *sta, struct sk_buff *skb)
- {
- struct rate_control_ref *ref = sdata->local->rate_ctrl;
- u16 tid;
diff --git a/package/kernel/mac80211/patches/subsys/321-mac80211-fix-mesh-forwarding.patch b/package/kernel/mac80211/patches/subsys/321-mac80211-fix-mesh-forwarding.patch
deleted file mode 100644
index e2b268ae4c..0000000000
--- a/package/kernel/mac80211/patches/subsys/321-mac80211-fix-mesh-forwarding.patch
+++ /dev/null
@@ -1,32 +0,0 @@
-From: Felix Fietkau <nbd@nbd.name>
-Date: Mon, 20 Feb 2023 12:50:50 +0100
-Subject: [PATCH] mac80211: fix mesh forwarding
-
-Linearize packets (needed for forwarding A-MSDU subframes).
-Fix network header offset to fix flow dissector (and fair queueing).
-
-Fixes: 986e43b19ae9 ("wifi: mac80211: fix receiving A-MSDU frames on mesh interfaces")
-Signed-off-by: Felix Fietkau <nbd@nbd.name>
----
-
---- a/net/mac80211/rx.c
-+++ b/net/mac80211/rx.c
-@@ -2904,6 +2904,9 @@ ieee80211_rx_mesh_data(struct ieee80211_
-
- if (skb_cow_head(fwd_skb, hdrlen - sizeof(struct ethhdr)))
- return RX_DROP_UNUSABLE;
-+
-+ if (skb_linearize(fwd_skb))
-+ return RX_DROP_UNUSABLE;
- }
-
- fwd_hdr = skb_push(fwd_skb, hdrlen - sizeof(struct ethhdr));
-@@ -2918,7 +2921,7 @@ ieee80211_rx_mesh_data(struct ieee80211_
- hdrlen += ETH_ALEN;
- else
- fwd_skb->protocol = htons(fwd_skb->len - hdrlen);
-- skb_set_network_header(fwd_skb, hdrlen);
-+ skb_set_network_header(fwd_skb, hdrlen + 2);
-
- info = IEEE80211_SKB_CB(fwd_skb);
- memset(info, 0, sizeof(*info));
diff --git a/package/kernel/mac80211/patches/subsys/322-wifi-mac80211-fix-mesh-path-discovery-based-on-unica.patch b/package/kernel/mac80211/patches/subsys/322-wifi-mac80211-fix-mesh-path-discovery-based-on-unica.patch
deleted file mode 100644
index 292a89ef92..0000000000
--- a/package/kernel/mac80211/patches/subsys/322-wifi-mac80211-fix-mesh-path-discovery-based-on-unica.patch
+++ /dev/null
@@ -1,52 +0,0 @@
-From: Felix Fietkau <nbd@nbd.name>
-Date: Sun, 26 Feb 2023 20:30:20 +0100
-Subject: [PATCH] wifi: mac80211: fix mesh path discovery based on unicast
- packets
-
-If a packet has reached its intended destination, it was bumped to the code
-that accepts it, without first checking if a mesh_path needs to be created
-based on the discovered source.
-Fix this by moving the destination address check further down
-
-Fixes: 986e43b19ae9 ("wifi: mac80211: fix receiving A-MSDU frames on mesh interfaces")
-Signed-off-by: Felix Fietkau <nbd@nbd.name>
----
-
---- a/net/mac80211/rx.c
-+++ b/net/mac80211/rx.c
-@@ -2824,17 +2824,6 @@ ieee80211_rx_mesh_data(struct ieee80211_
- mesh_rmc_check(sdata, eth->h_source, mesh_hdr))
- return RX_DROP_MONITOR;
-
-- /* Frame has reached destination. Don't forward */
-- if (ether_addr_equal(sdata->vif.addr, eth->h_dest))
-- goto rx_accept;
--
-- if (!ifmsh->mshcfg.dot11MeshForwarding) {
-- if (is_multicast_ether_addr(eth->h_dest))
-- goto rx_accept;
--
-- return RX_DROP_MONITOR;
-- }
--
- /* forward packet */
- if (sdata->crypto_tx_tailroom_needed_cnt)
- tailroom = IEEE80211_ENCRYPT_TAILROOM;
-@@ -2881,6 +2870,17 @@ ieee80211_rx_mesh_data(struct ieee80211_
- rcu_read_unlock();
- }
-
-+ /* Frame has reached destination. Don't forward */
-+ if (ether_addr_equal(sdata->vif.addr, eth->h_dest))
-+ goto rx_accept;
-+
-+ if (!ifmsh->mshcfg.dot11MeshForwarding) {
-+ if (is_multicast_ether_addr(eth->h_dest))
-+ goto rx_accept;
-+
-+ return RX_DROP_MONITOR;
-+ }
-+
- skb_set_queue_mapping(skb, ieee802_1d_to_ac[skb->priority]);
-
- if (!multicast &&
diff --git a/package/kernel/mac80211/patches/subsys/323-v6.3-wifi-mac80211-Add-VHT-MU-MIMO-related-flags-in-ieee8.patch b/package/kernel/mac80211/patches/subsys/323-v6.3-wifi-mac80211-Add-VHT-MU-MIMO-related-flags-in-ieee8.patch
deleted file mode 100644
index e23dc4d226..0000000000
--- a/package/kernel/mac80211/patches/subsys/323-v6.3-wifi-mac80211-Add-VHT-MU-MIMO-related-flags-in-ieee8.patch
+++ /dev/null
@@ -1,68 +0,0 @@
-From: Muna Sinada <quic_msinada@quicinc.com>
-Date: Wed, 5 Oct 2022 14:54:45 -0700
-Subject: [PATCH] wifi: mac80211: Add VHT MU-MIMO related flags in
- ieee80211_bss_conf
-
-Adding flags for SU Beamformer, SU Beamformee, MU Beamformer and
-MU Beamformee for VHT. This is utilized to pass MU-MIMO
-configurations from user space to driver in AP mode.
-
-Signed-off-by: Muna Sinada <quic_msinada@quicinc.com>
-Link: https://lore.kernel.org/r/1665006886-23874-1-git-send-email-quic_msinada@quicinc.com
-[fixed indentation, removed redundant !!]
-Signed-off-by: Johannes Berg <johannes.berg@intel.com>
----
-
---- a/include/net/mac80211.h
-+++ b/include/net/mac80211.h
-@@ -653,6 +653,14 @@ struct ieee80211_fils_discovery {
- * write-protected by sdata_lock and local->mtx so holding either is fine
- * for read access.
- * @color_change_color: the bss color that will be used after the change.
-+ * @vht_su_beamformer: in AP mode, does this BSS support operation as an VHT SU
-+ * beamformer
-+ * @vht_su_beamformee: in AP mode, does this BSS support operation as an VHT SU
-+ * beamformee
-+ * @vht_mu_beamformer: in AP mode, does this BSS support operation as an VHT MU
-+ * beamformer
-+ * @vht_mu_beamformee: in AP mode, does this BSS support operation as an VHT MU
-+ * beamformee
- */
- struct ieee80211_bss_conf {
- const u8 *bssid;
-@@ -726,6 +734,11 @@ struct ieee80211_bss_conf {
-
- bool color_change_active;
- u8 color_change_color;
-+
-+ bool vht_su_beamformer;
-+ bool vht_su_beamformee;
-+ bool vht_mu_beamformer;
-+ bool vht_mu_beamformee;
- };
-
- /**
---- a/net/mac80211/cfg.c
-+++ b/net/mac80211/cfg.c
-@@ -1252,6 +1252,21 @@ static int ieee80211_start_ap(struct wip
- prev_beacon_int = link_conf->beacon_int;
- link_conf->beacon_int = params->beacon_interval;
-
-+ if (params->vht_cap) {
-+ link_conf->vht_su_beamformer =
-+ params->vht_cap->vht_cap_info &
-+ cpu_to_le32(IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE);
-+ link_conf->vht_su_beamformee =
-+ params->vht_cap->vht_cap_info &
-+ cpu_to_le32(IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE);
-+ link_conf->vht_mu_beamformer =
-+ params->vht_cap->vht_cap_info &
-+ cpu_to_le32(IEEE80211_VHT_CAP_MU_BEAMFORMER_CAPABLE);
-+ link_conf->vht_mu_beamformee =
-+ params->vht_cap->vht_cap_info &
-+ cpu_to_le32(IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE);
-+ }
-+
- if (params->he_cap && params->he_oper) {
- link_conf->he_support = true;
- link_conf->htc_trig_based_pkt_ext =
diff --git a/package/kernel/mac80211/patches/subsys/324-v6.3-wifi-mac80211-Add-HE-MU-MIMO-related-flags-in-ieee80.patch b/package/kernel/mac80211/patches/subsys/324-v6.3-wifi-mac80211-Add-HE-MU-MIMO-related-flags-in-ieee80.patch
deleted file mode 100644
index f843dba123..0000000000
--- a/package/kernel/mac80211/patches/subsys/324-v6.3-wifi-mac80211-Add-HE-MU-MIMO-related-flags-in-ieee80.patch
+++ /dev/null
@@ -1,68 +0,0 @@
-From: Muna Sinada <quic_msinada@quicinc.com>
-Date: Wed, 5 Oct 2022 14:54:46 -0700
-Subject: [PATCH] wifi: mac80211: Add HE MU-MIMO related flags in
- ieee80211_bss_conf
-
-Adding flags for SU Beamformer, SU Beamformee, MU Beamformer and Full
-Bandwidth UL MU-MIMO for HE. This is utilized to pass MU-MIMO
-configurations from user space to driver in AP mode.
-
-Signed-off-by: Muna Sinada <quic_msinada@quicinc.com>
-Link: https://lore.kernel.org/r/1665006886-23874-2-git-send-email-quic_msinada@quicinc.com
-[fixed indentation, removed redundant !!]
-Signed-off-by: Johannes Berg <johannes.berg@intel.com>
----
-
---- a/include/net/mac80211.h
-+++ b/include/net/mac80211.h
-@@ -661,6 +661,15 @@ struct ieee80211_fils_discovery {
- * beamformer
- * @vht_mu_beamformee: in AP mode, does this BSS support operation as an VHT MU
- * beamformee
-+ * @he_su_beamformer: in AP-mode, does this BSS support operation as an HE SU
-+ * beamformer
-+ * @he_su_beamformee: in AP-mode, does this BSS support operation as an HE SU
-+ * beamformee
-+ * @he_mu_beamformer: in AP-mode, does this BSS support operation as an HE MU
-+ * beamformer
-+ * @he_full_ul_mumimo: does this BSS support the reception (AP) or transmission
-+ * (non-AP STA) of an HE TB PPDU on an RU that spans the entire PPDU
-+ * bandwidth
- */
- struct ieee80211_bss_conf {
- const u8 *bssid;
-@@ -739,6 +748,10 @@ struct ieee80211_bss_conf {
- bool vht_su_beamformee;
- bool vht_mu_beamformer;
- bool vht_mu_beamformee;
-+ bool he_su_beamformer;
-+ bool he_su_beamformee;
-+ bool he_mu_beamformer;
-+ bool he_full_ul_mumimo;
- };
-
- /**
---- a/net/mac80211/cfg.c
-+++ b/net/mac80211/cfg.c
-@@ -1281,6 +1281,21 @@ static int ieee80211_start_ap(struct wip
- changed |= BSS_CHANGED_HE_BSS_COLOR;
- }
-
-+ if (params->he_cap) {
-+ link_conf->he_su_beamformer =
-+ params->he_cap->phy_cap_info[3] &
-+ IEEE80211_HE_PHY_CAP3_SU_BEAMFORMER;
-+ link_conf->he_su_beamformee =
-+ params->he_cap->phy_cap_info[4] &
-+ IEEE80211_HE_PHY_CAP4_SU_BEAMFORMEE;
-+ link_conf->he_mu_beamformer =
-+ params->he_cap->phy_cap_info[4] &
-+ IEEE80211_HE_PHY_CAP4_MU_BEAMFORMER;
-+ link_conf->he_full_ul_mumimo =
-+ params->he_cap->phy_cap_info[2] &
-+ IEEE80211_HE_PHY_CAP2_UL_MU_FULL_MU_MIMO;
-+ }
-+
- if (sdata->vif.type == NL80211_IFTYPE_AP &&
- params->mbssid_config.tx_wdev) {
- err = ieee80211_set_ap_mbssid_options(sdata,
diff --git a/package/kernel/mac80211/patches/subsys/325-wifi-mac80211-introduce-ieee80211_refresh_tx_agg_ses.patch b/package/kernel/mac80211/patches/subsys/325-wifi-mac80211-introduce-ieee80211_refresh_tx_agg_ses.patch
deleted file mode 100644
index 1be5fcfbfa..0000000000
--- a/package/kernel/mac80211/patches/subsys/325-wifi-mac80211-introduce-ieee80211_refresh_tx_agg_ses.patch
+++ /dev/null
@@ -1,60 +0,0 @@
-From: Ryder Lee <ryder.lee@mediatek.com>
-Date: Sat, 18 Feb 2023 01:50:05 +0800
-Subject: [PATCH] wifi: mac80211: introduce
- ieee80211_refresh_tx_agg_session_timer()
-
-This allows low level drivers to refresh the tx agg session timer, based on
-querying stats from the firmware usually. Especially for some mt76 devices
-support .net_fill_forward_path would bypass mac80211, which leads to tx BA
-session timeout for certain clients.
-
-Signed-off-by: Ryder Lee <ryder.lee@mediatek.com>
----
-
---- a/include/net/mac80211.h
-+++ b/include/net/mac80211.h
-@@ -5964,6 +5964,18 @@ void ieee80211_queue_delayed_work(struct
- unsigned long delay);
-
- /**
-+ * ieee80211_refresh_tx_agg_session_timer - Refresh a tx agg session timer.
-+ * @sta: the station for which to start a BA session
-+ * @tid: the TID to BA on.
-+ *
-+ * This function allows low level driver to refresh tx agg session timer
-+ * to maintain BA session, the session level will still be managed by the
-+ * mac80211.
-+ */
-+void ieee80211_refresh_tx_agg_session_timer(struct ieee80211_sta *sta,
-+ u16 tid);
-+
-+/**
- * ieee80211_start_tx_ba_session - Start a tx Block Ack session.
- * @sta: the station for which to start a BA session
- * @tid: the TID to BA on.
---- a/net/mac80211/agg-tx.c
-+++ b/net/mac80211/agg-tx.c
-@@ -554,6 +554,23 @@ void ieee80211_tx_ba_session_handle_star
- ieee80211_send_addba_with_timeout(sta, tid_tx);
- }
-
-+void ieee80211_refresh_tx_agg_session_timer(struct ieee80211_sta *pubsta,
-+ u16 tid)
-+{
-+ struct sta_info *sta = container_of(pubsta, struct sta_info, sta);
-+ struct tid_ampdu_tx *tid_tx;
-+
-+ if (WARN_ON_ONCE(tid >= IEEE80211_NUM_TIDS))
-+ return;
-+
-+ tid_tx = rcu_dereference(sta->ampdu_mlme.tid_tx[tid]);
-+ if (!tid_tx)
-+ return;
-+
-+ tid_tx->last_tx = jiffies;
-+}
-+EXPORT_SYMBOL(ieee80211_refresh_tx_agg_session_timer);
-+
- /*
- * After accepting the AddBA Response we activated a timer,
- * resetting it after each frame that we send.
diff --git a/package/kernel/mac80211/patches/subsys/326-wifi-mac80211-add-mesh-fast-rx-support.patch b/package/kernel/mac80211/patches/subsys/326-wifi-mac80211-add-mesh-fast-rx-support.patch
deleted file mode 100644
index 11f39c2d10..0000000000
--- a/package/kernel/mac80211/patches/subsys/326-wifi-mac80211-add-mesh-fast-rx-support.patch
+++ /dev/null
@@ -1,77 +0,0 @@
-From: Felix Fietkau <nbd@nbd.name>
-Date: Thu, 2 Mar 2023 13:52:29 +0100
-Subject: [PATCH] wifi: mac80211: add mesh fast-rx support
-
-This helps bring down rx CPU usage by avoiding calls to the rx handlers in
-the slow path. Supports forwarding and local rx, including A-MSDU.
-
-Signed-off-by: Felix Fietkau <nbd@nbd.name>
----
-
---- a/net/mac80211/rx.c
-+++ b/net/mac80211/rx.c
-@@ -4564,6 +4564,12 @@ void ieee80211_check_fast_rx(struct sta_
- }
-
- break;
-+ case NL80211_IFTYPE_MESH_POINT:
-+ fastrx.expected_ds_bits = cpu_to_le16(IEEE80211_FCTL_FROMDS |
-+ IEEE80211_FCTL_TODS);
-+ fastrx.da_offs = offsetof(struct ieee80211_hdr, addr3);
-+ fastrx.sa_offs = offsetof(struct ieee80211_hdr, addr4);
-+ break;
- default:
- goto clear;
- }
-@@ -4772,6 +4778,7 @@ static bool ieee80211_invoke_fast_rx(str
- struct sk_buff *skb = rx->skb;
- struct ieee80211_hdr *hdr = (void *)skb->data;
- struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb);
-+ static ieee80211_rx_result res;
- int orig_len = skb->len;
- int hdrlen = ieee80211_hdrlen(hdr->frame_control);
- int snap_offs = hdrlen;
-@@ -4833,7 +4840,8 @@ static bool ieee80211_invoke_fast_rx(str
- snap_offs += IEEE80211_CCMP_HDR_LEN;
- }
-
-- if (!(status->rx_flags & IEEE80211_RX_AMSDU)) {
-+ if (!ieee80211_vif_is_mesh(&rx->sdata->vif) &&
-+ !(status->rx_flags & IEEE80211_RX_AMSDU)) {
- if (!pskb_may_pull(skb, snap_offs + sizeof(*payload)))
- return false;
-
-@@ -4872,13 +4880,29 @@ static bool ieee80211_invoke_fast_rx(str
- /* do the header conversion - first grab the addresses */
- ether_addr_copy(addrs.da, skb->data + fast_rx->da_offs);
- ether_addr_copy(addrs.sa, skb->data + fast_rx->sa_offs);
-- skb_postpull_rcsum(skb, skb->data + snap_offs,
-- sizeof(rfc1042_header) + 2);
-- /* remove the SNAP but leave the ethertype */
-- skb_pull(skb, snap_offs + sizeof(rfc1042_header));
-+ if (ieee80211_vif_is_mesh(&rx->sdata->vif)) {
-+ skb_pull(skb, snap_offs - 2);
-+ put_unaligned_be16(skb->len - 2, skb->data);
-+ } else {
-+ skb_postpull_rcsum(skb, skb->data + snap_offs,
-+ sizeof(rfc1042_header) + 2);
-+
-+ /* remove the SNAP but leave the ethertype */
-+ skb_pull(skb, snap_offs + sizeof(rfc1042_header));
-+ }
- /* push the addresses in front */
- memcpy(skb_push(skb, sizeof(addrs)), &addrs, sizeof(addrs));
-
-+ res = ieee80211_rx_mesh_data(rx->sdata, rx->sta, rx->skb);
-+ switch (res) {
-+ case RX_QUEUED:
-+ return true;
-+ case RX_CONTINUE:
-+ break;
-+ default:
-+ goto drop;
-+ }
-+
- ieee80211_rx_8023(rx, fast_rx, orig_len);
-
- return true;
diff --git a/package/kernel/mac80211/patches/subsys/327-wifi-mac80211-add-support-for-letting-drivers-regist.patch b/package/kernel/mac80211/patches/subsys/327-wifi-mac80211-add-support-for-letting-drivers-regist.patch
deleted file mode 100644
index ac290b5360..0000000000
--- a/package/kernel/mac80211/patches/subsys/327-wifi-mac80211-add-support-for-letting-drivers-regist.patch
+++ /dev/null
@@ -1,149 +0,0 @@
-From: Felix Fietkau <nbd@nbd.name>
-Date: Mon, 20 Mar 2023 14:28:08 +0100
-Subject: [PATCH] wifi: mac80211: add support for letting drivers register tc
- offload support
-
-On newer MediaTek SoCs (e.g. MT7986), WLAN->WLAN or WLAN->Ethernet flows can
-be offloaded by the SoC. In order to support that, the .ndo_setup_tc op is
-needed.
-
-Signed-off-by: Felix Fietkau <nbd@nbd.name>
----
-
---- a/include/net/mac80211.h
-+++ b/include/net/mac80211.h
-@@ -4192,6 +4192,10 @@ struct ieee80211_prep_tx_info {
- * Note that a sta can also be inserted or removed with valid links,
- * i.e. passed to @sta_add/@sta_state with sta->valid_links not zero.
- * In fact, cannot change from having valid_links and not having them.
-+ * @net_setup_tc: Called from .ndo_setup_tc in order to prepare hardware
-+ * flow offloading for flows originating from the vif.
-+ * Note that the driver must not assume that the vif driver_data is valid
-+ * at this point, since the callback can be called during netdev teardown.
- */
- struct ieee80211_ops {
- void (*tx)(struct ieee80211_hw *hw,
-@@ -4547,6 +4551,11 @@ struct ieee80211_ops {
- struct ieee80211_vif *vif,
- struct ieee80211_sta *sta,
- u16 old_links, u16 new_links);
-+ int (*net_setup_tc)(struct ieee80211_hw *hw,
-+ struct ieee80211_vif *vif,
-+ struct net_device *dev,
-+ enum tc_setup_type type,
-+ void *type_data);
- };
-
- /**
---- a/net/mac80211/driver-ops.h
-+++ b/net/mac80211/driver-ops.h
-@@ -1470,6 +1470,23 @@ static inline int drv_net_fill_forward_p
- return ret;
- }
-
-+static inline int drv_net_setup_tc(struct ieee80211_local *local,
-+ struct ieee80211_sub_if_data *sdata,
-+ struct net_device *dev,
-+ enum tc_setup_type type, void *type_data)
-+{
-+ int ret = -EOPNOTSUPP;
-+
-+ sdata = get_bss_sdata(sdata);
-+ trace_drv_net_setup_tc(local, sdata, type);
-+ if (local->ops->net_setup_tc)
-+ ret = local->ops->net_setup_tc(&local->hw, &sdata->vif, dev,
-+ type, type_data);
-+ trace_drv_return_int(local, ret);
-+
-+ return ret;
-+}
-+
- int drv_change_vif_links(struct ieee80211_local *local,
- struct ieee80211_sub_if_data *sdata,
- u16 old_links, u16 new_links,
---- a/net/mac80211/ieee80211_i.h
-+++ b/net/mac80211/ieee80211_i.h
-@@ -1939,7 +1939,8 @@ void ieee80211_color_collision_detection
- /* interface handling */
- #define MAC80211_SUPPORTED_FEATURES_TX (NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | \
- NETIF_F_HW_CSUM | NETIF_F_SG | \
-- NETIF_F_HIGHDMA | NETIF_F_GSO_SOFTWARE)
-+ NETIF_F_HIGHDMA | NETIF_F_GSO_SOFTWARE | \
-+ NETIF_F_HW_TC)
- #define MAC80211_SUPPORTED_FEATURES_RX (NETIF_F_RXCSUM)
- #define MAC80211_SUPPORTED_FEATURES (MAC80211_SUPPORTED_FEATURES_TX | \
- MAC80211_SUPPORTED_FEATURES_RX)
---- a/net/mac80211/iface.c
-+++ b/net/mac80211/iface.c
-@@ -813,6 +813,21 @@ ieee80211_get_stats64(struct net_device
- dev_fetch_sw_netstats(stats, dev->tstats);
- }
-
-+static int ieee80211_netdev_setup_tc(struct net_device *dev,
-+ enum tc_setup_type type, void *type_data)
-+{
-+ struct ieee80211_sub_if_data *sdata;
-+ struct ieee80211_local *local;
-+
-+ sdata = IEEE80211_DEV_TO_SUB_IF(dev);
-+ local = sdata->local;
-+
-+ if (!local->ops->net_setup_tc)
-+ return -EOPNOTSUPP;
-+
-+ return drv_net_setup_tc(local, sdata, dev, type, type_data);
-+}
-+
- static const struct net_device_ops ieee80211_dataif_ops = {
- .ndo_open = ieee80211_open,
- .ndo_stop = ieee80211_stop,
-@@ -821,6 +836,7 @@ static const struct net_device_ops ieee8
- .ndo_set_rx_mode = ieee80211_set_multicast_list,
- .ndo_set_mac_address = ieee80211_change_mac,
- .ndo_get_stats64 = ieee80211_get_stats64,
-+ .ndo_setup_tc = ieee80211_netdev_setup_tc,
- };
-
- static u16 ieee80211_monitor_select_queue(struct net_device *dev,
-@@ -929,6 +945,7 @@ static const struct net_device_ops ieee8
- .ndo_set_mac_address = ieee80211_change_mac,
- .ndo_get_stats64 = ieee80211_get_stats64,
- .ndo_fill_forward_path = ieee80211_netdev_fill_forward_path,
-+ .ndo_setup_tc = ieee80211_netdev_setup_tc,
- };
-
- static bool ieee80211_iftype_supports_hdr_offload(enum nl80211_iftype iftype)
---- a/net/mac80211/trace.h
-+++ b/net/mac80211/trace.h
-@@ -2478,6 +2478,31 @@ DEFINE_EVENT(sta_event, drv_net_fill_for
- TP_ARGS(local, sdata, sta)
- );
-
-+TRACE_EVENT(drv_net_setup_tc,
-+ TP_PROTO(struct ieee80211_local *local,
-+ struct ieee80211_sub_if_data *sdata,
-+ u8 type),
-+
-+ TP_ARGS(local, sdata, type),
-+
-+ TP_STRUCT__entry(
-+ LOCAL_ENTRY
-+ VIF_ENTRY
-+ __field(u8, type)
-+ ),
-+
-+ TP_fast_assign(
-+ LOCAL_ASSIGN;
-+ VIF_ASSIGN;
-+ __entry->type = type;
-+ ),
-+
-+ TP_printk(
-+ LOCAL_PR_FMT VIF_PR_FMT " type:%d\n",
-+ LOCAL_PR_ARG, VIF_PR_ARG, __entry->type
-+ )
-+);
-+
- TRACE_EVENT(drv_change_vif_links,
- TP_PROTO(struct ieee80211_local *local,
- struct ieee80211_sub_if_data *sdata,
diff --git a/package/kernel/mac80211/patches/subsys/329-wifi-mac80211-fix-receiving-mesh-packets-in-forwardi.patch b/package/kernel/mac80211/patches/subsys/329-wifi-mac80211-fix-receiving-mesh-packets-in-forwardi.patch
deleted file mode 100644
index 6882694da8..0000000000
--- a/package/kernel/mac80211/patches/subsys/329-wifi-mac80211-fix-receiving-mesh-packets-in-forwardi.patch
+++ /dev/null
@@ -1,50 +0,0 @@
-From: Felix Fietkau <nbd@nbd.name>
-Date: Sun, 26 Mar 2023 17:11:34 +0200
-Subject: [PATCH] wifi: mac80211: fix receiving mesh packets in forwarding=0
- networks
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-When forwarding is set to 0, frames are typically sent with ttl=1.
-Move the ttl decrement check below the check for local receive in order to
-fix packet drops.
-
-Reported-by: Thomas Hühn <thomas.huehn@hs-nordhausen.de>
-Reported-by: Nick Hainke <vincent@systemli.org>
-Fixes: 986e43b19ae9 ("wifi: mac80211: fix receiving A-MSDU frames on mesh interfaces")
-Signed-off-by: Felix Fietkau <nbd@nbd.name>
----
-
---- a/net/mac80211/rx.c
-+++ b/net/mac80211/rx.c
-@@ -2828,14 +2828,6 @@ ieee80211_rx_mesh_data(struct ieee80211_
- if (sdata->crypto_tx_tailroom_needed_cnt)
- tailroom = IEEE80211_ENCRYPT_TAILROOM;
-
-- if (!--mesh_hdr->ttl) {
-- if (multicast)
-- goto rx_accept;
--
-- IEEE80211_IFSTA_MESH_CTR_INC(ifmsh, dropped_frames_ttl);
-- return RX_DROP_MONITOR;
-- }
--
- if (mesh_hdr->flags & MESH_FLAGS_AE) {
- struct mesh_path *mppath;
- char *proxied_addr;
-@@ -2874,6 +2866,14 @@ ieee80211_rx_mesh_data(struct ieee80211_
- if (ether_addr_equal(sdata->vif.addr, eth->h_dest))
- goto rx_accept;
-
-+ if (!--mesh_hdr->ttl) {
-+ if (multicast)
-+ goto rx_accept;
-+
-+ IEEE80211_IFSTA_MESH_CTR_INC(ifmsh, dropped_frames_ttl);
-+ return RX_DROP_MONITOR;
-+ }
-+
- if (!ifmsh->mshcfg.dot11MeshForwarding) {
- if (is_multicast_ether_addr(eth->h_dest))
- goto rx_accept;
diff --git a/package/kernel/mac80211/patches/subsys/330-wifi-ieee80211-correctly-mark-FTM-frames-non-buffera.patch b/package/kernel/mac80211/patches/subsys/330-wifi-ieee80211-correctly-mark-FTM-frames-non-buffera.patch
deleted file mode 100644
index 079dd2a868..0000000000
--- a/package/kernel/mac80211/patches/subsys/330-wifi-ieee80211-correctly-mark-FTM-frames-non-buffera.patch
+++ /dev/null
@@ -1,134 +0,0 @@
-From: Johannes Berg <johannes.berg@intel.com>
-Date: Wed, 29 Mar 2023 16:46:26 +0200
-Subject: [PATCH] wifi: ieee80211: correctly mark FTM frames non-bufferable
-
-The checks of whether or not a frame is bufferable were not
-taking into account that some action frames aren't, such as
-FTM. Check this, which requires some changes to the function
-ieee80211_is_bufferable_mmpdu() since we need the whole skb
-for the checks now.
-
-Signed-off-by: Johannes Berg <johannes.berg@intel.com>
-Reviewed-by: Greenman, Gregory <gregory.greenman@intel.com>
-Reviewed-by: Peer, Ilan <ilan.peer@intel.com>
----
-
---- a/drivers/net/wireless/intel/iwlwifi/mvm/tx.c
-+++ b/drivers/net/wireless/intel/iwlwifi/mvm/tx.c
-@@ -601,8 +601,9 @@ static void iwl_mvm_skb_prepare_status(s
-
- static int iwl_mvm_get_ctrl_vif_queue(struct iwl_mvm *mvm,
- struct ieee80211_tx_info *info,
-- struct ieee80211_hdr *hdr)
-+ struct sk_buff *skb)
- {
-+ struct ieee80211_hdr *hdr = (void *)skb->data;
- struct iwl_mvm_vif *mvmvif =
- iwl_mvm_vif_from_mac80211(info->control.vif);
- __le16 fc = hdr->frame_control;
-@@ -621,7 +622,7 @@ static int iwl_mvm_get_ctrl_vif_queue(st
- * reason 7 ("Class 3 frame received from nonassociated STA").
- */
- if (ieee80211_is_mgmt(fc) &&
-- (!ieee80211_is_bufferable_mmpdu(fc) ||
-+ (!ieee80211_is_bufferable_mmpdu(skb) ||
- ieee80211_is_deauth(fc) || ieee80211_is_disassoc(fc)))
- return mvm->probe_queue;
-
-@@ -740,7 +741,7 @@ int iwl_mvm_tx_skb_non_sta(struct iwl_mv
- else
- sta_id = mvmvif->mcast_sta.sta_id;
-
-- queue = iwl_mvm_get_ctrl_vif_queue(mvm, &info, hdr);
-+ queue = iwl_mvm_get_ctrl_vif_queue(mvm, &info, skb);
- } else if (info.control.vif->type == NL80211_IFTYPE_MONITOR) {
- queue = mvm->snif_queue;
- sta_id = mvm->snif_sta.sta_id;
---- a/include/linux/ieee80211.h
-+++ b/include/linux/ieee80211.h
-@@ -772,20 +772,6 @@ static inline bool ieee80211_is_any_null
- }
-
- /**
-- * ieee80211_is_bufferable_mmpdu - check if frame is bufferable MMPDU
-- * @fc: frame control field in little-endian byteorder
-- */
--static inline bool ieee80211_is_bufferable_mmpdu(__le16 fc)
--{
-- /* IEEE 802.11-2012, definition of "bufferable management frame";
-- * note that this ignores the IBSS special case. */
-- return ieee80211_is_mgmt(fc) &&
-- (ieee80211_is_action(fc) ||
-- ieee80211_is_disassoc(fc) ||
-- ieee80211_is_deauth(fc));
--}
--
--/**
- * ieee80211_is_first_frag - check if IEEE80211_SCTL_FRAG is not set
- * @seq_ctrl: frame sequence control bytes in little-endian byteorder
- */
-@@ -4121,6 +4107,44 @@ static inline u8 *ieee80211_get_DA(struc
- }
-
- /**
-+ * ieee80211_is_bufferable_mmpdu - check if frame is bufferable MMPDU
-+ * @skb: the skb to check, starting with the 802.11 header
-+ */
-+static inline bool ieee80211_is_bufferable_mmpdu(struct sk_buff *skb)
-+{
-+ struct ieee80211_mgmt *mgmt = (void *)skb->data;
-+ __le16 fc = mgmt->frame_control;
-+
-+ /*
-+ * IEEE 802.11 REVme D2.0 definition of bufferable MMPDU;
-+ * note that this ignores the IBSS special case.
-+ */
-+ if (!ieee80211_is_mgmt(fc))
-+ return false;
-+
-+ if (ieee80211_is_disassoc(fc) || ieee80211_is_deauth(fc))
-+ return true;
-+
-+ if (!ieee80211_is_action(fc))
-+ return false;
-+
-+ if (skb->len < offsetofend(typeof(*mgmt), u.action.u.ftm.action_code))
-+ return true;
-+
-+ /* action frame - additionally check for non-bufferable FTM */
-+
-+ if (mgmt->u.action.category != WLAN_CATEGORY_PUBLIC &&
-+ mgmt->u.action.category != WLAN_CATEGORY_PROTECTED_DUAL_OF_ACTION)
-+ return true;
-+
-+ if (mgmt->u.action.u.ftm.action_code == WLAN_PUB_ACTION_FTM_REQUEST ||
-+ mgmt->u.action.u.ftm.action_code == WLAN_PUBLIC_ACTION_FTM_RESPONSE)
-+ return false;
-+
-+ return true;
-+}
-+
-+/**
- * _ieee80211_is_robust_mgmt_frame - check if frame is a robust management frame
- * @hdr: the frame (buffer must include at least the first octet of payload)
- */
---- a/net/mac80211/tx.c
-+++ b/net/mac80211/tx.c
-@@ -488,7 +488,7 @@ ieee80211_tx_h_unicast_ps_buf(struct iee
- int ac = skb_get_queue_mapping(tx->skb);
-
- if (ieee80211_is_mgmt(hdr->frame_control) &&
-- !ieee80211_is_bufferable_mmpdu(hdr->frame_control)) {
-+ !ieee80211_is_bufferable_mmpdu(tx->skb)) {
- info->flags |= IEEE80211_TX_CTL_NO_PS_BUFFER;
- return TX_CONTINUE;
- }
-@@ -1326,7 +1326,7 @@ static struct txq_info *ieee80211_get_tx
- if (!(info->flags & IEEE80211_TX_CTL_HW_80211_ENCAP) &&
- unlikely(!ieee80211_is_data_present(hdr->frame_control))) {
- if ((!ieee80211_is_mgmt(hdr->frame_control) ||
-- ieee80211_is_bufferable_mmpdu(hdr->frame_control) ||
-+ ieee80211_is_bufferable_mmpdu(skb) ||
- vif->type == NL80211_IFTYPE_STATION) &&
- sta && sta->uploaded) {
- /*
diff --git a/package/kernel/mac80211/patches/subsys/331-wifi-mac80211-flush-queues-on-STA-removal.patch b/package/kernel/mac80211/patches/subsys/331-wifi-mac80211-flush-queues-on-STA-removal.patch
deleted file mode 100644
index 00232ec1b9..0000000000
--- a/package/kernel/mac80211/patches/subsys/331-wifi-mac80211-flush-queues-on-STA-removal.patch
+++ /dev/null
@@ -1,36 +0,0 @@
-From: Johannes Berg <johannes.berg@intel.com>
-Date: Mon, 13 Mar 2023 11:42:12 +0100
-Subject: [PATCH] wifi: mac80211: flush queues on STA removal
-
-When we remove a station, we first make it unreachable,
-then we (must) remove its keys, and then remove the
-station itself. Depending on the hardware design, if
-we have hardware crypto at all, frames still sitting
-on hardware queues may then be transmitted without a
-valid key, possibly unencrypted or with a fixed key.
-
-Fix this by flushing the queues when removing stations
-so this cannot happen.
-
-Cc: stable@vger.kernel.org
-Signed-off-by: Johannes Berg <johannes.berg@intel.com>
-Reviewed-by: Greenman, Gregory <gregory.greenman@intel.com>
----
-
---- a/net/mac80211/sta_info.c
-+++ b/net/mac80211/sta_info.c
-@@ -1271,6 +1271,14 @@ static void __sta_info_destroy_part2(str
- WARN_ON_ONCE(ret);
- }
-
-+ /* Flush queues before removing keys, as that might remove them
-+ * from hardware, and then depending on the offload method, any
-+ * frames sitting on hardware queues might be sent out without
-+ * any encryption at all.
-+ */
-+ if (local->ops->set_key)
-+ ieee80211_flush_queues(local, sta->sdata, false);
-+
- /* now keys can no longer be reached */
- ieee80211_free_sta_keys(local, sta);
-
diff --git a/package/kernel/mac80211/patches/subsys/332-wifi-iwlwifi-mvm-support-flush-on-AP-interfaces.patch b/package/kernel/mac80211/patches/subsys/332-wifi-iwlwifi-mvm-support-flush-on-AP-interfaces.patch
deleted file mode 100644
index 3c31dfeddc..0000000000
--- a/package/kernel/mac80211/patches/subsys/332-wifi-iwlwifi-mvm-support-flush-on-AP-interfaces.patch
+++ /dev/null
@@ -1,34 +0,0 @@
-From: Johannes Berg <johannes.berg@intel.com>
-Date: Mon, 13 Mar 2023 12:02:58 +0100
-Subject: [PATCH] wifi: iwlwifi: mvm: support flush on AP interfaces
-
-Support TX flush on AP interfaces so that we will do a
-proper flush for frames on the queue before keys are
-removed.
-
-Signed-off-by: Johannes Berg <johannes.berg@intel.com>
-Reviewed-by: Greenman, Gregory <gregory.greenman@intel.com>
----
-
---- a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
-+++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
-@@ -4854,9 +4854,6 @@ static void iwl_mvm_mac_flush(struct iee
- return;
- }
-
-- if (vif->type != NL80211_IFTYPE_STATION)
-- return;
--
- /* Make sure we're done with the deferred traffic before flushing */
- flush_work(&mvm->add_stream_wk);
-
-@@ -4874,9 +4871,6 @@ static void iwl_mvm_mac_flush(struct iee
- if (mvmsta->vif != vif)
- continue;
-
-- /* make sure only TDLS peers or the AP are flushed */
-- WARN_ON(i != mvmvif->ap_sta_id && !sta->tdls);
--
- if (drop) {
- if (iwl_mvm_flush_sta(mvm, mvmsta, false))
- IWL_ERR(mvm, "flush request fail\n");
diff --git a/package/kernel/mac80211/patches/subsys/333-wifi-mac80211-add-flush_sta-method.patch b/package/kernel/mac80211/patches/subsys/333-wifi-mac80211-add-flush_sta-method.patch
deleted file mode 100644
index 3bba0b7e66..0000000000
--- a/package/kernel/mac80211/patches/subsys/333-wifi-mac80211-add-flush_sta-method.patch
+++ /dev/null
@@ -1,91 +0,0 @@
-From: Johannes Berg <johannes.berg@intel.com>
-Date: Mon, 13 Mar 2023 11:53:51 +0100
-Subject: [PATCH] wifi: mac80211: add flush_sta method
-
-Some drivers like iwlwifi might have per-STA queues, so we
-may want to flush/drop just those queues rather than all
-when removing a station. Add a separate method for that.
-
-Signed-off-by: Johannes Berg <johannes.berg@intel.com>
-Reviewed-by: Greenman, Gregory <gregory.greenman@intel.com>
----
-
---- a/include/net/mac80211.h
-+++ b/include/net/mac80211.h
-@@ -3918,6 +3918,10 @@ struct ieee80211_prep_tx_info {
- * Note that vif can be NULL.
- * The callback can sleep.
- *
-+ * @flush_sta: Flush or drop all pending frames from the hardware queue(s) for
-+ * the given station, as it's about to be removed.
-+ * The callback can sleep.
-+ *
- * @channel_switch: Drivers that need (or want) to offload the channel
- * switch operation for CSAs received from the AP may implement this
- * callback. They must then call ieee80211_chswitch_done() to indicate
-@@ -4372,6 +4376,8 @@ struct ieee80211_ops {
- #endif
- void (*flush)(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
- u32 queues, bool drop);
-+ void (*flush_sta)(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
-+ struct ieee80211_sta *sta);
- void (*channel_switch)(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif,
- struct ieee80211_channel_switch *ch_switch);
---- a/net/mac80211/driver-ops.h
-+++ b/net/mac80211/driver-ops.h
-@@ -617,6 +617,21 @@ static inline void drv_flush(struct ieee
- trace_drv_return_void(local);
- }
-
-+static inline void drv_flush_sta(struct ieee80211_local *local,
-+ struct ieee80211_sub_if_data *sdata,
-+ struct sta_info *sta)
-+{
-+ might_sleep();
-+
-+ if (sdata && !check_sdata_in_driver(sdata))
-+ return;
-+
-+ trace_drv_flush_sta(local, sdata, &sta->sta);
-+ if (local->ops->flush_sta)
-+ local->ops->flush_sta(&local->hw, &sdata->vif, &sta->sta);
-+ trace_drv_return_void(local);
-+}
-+
- static inline void drv_channel_switch(struct ieee80211_local *local,
- struct ieee80211_sub_if_data *sdata,
- struct ieee80211_channel_switch *ch_switch)
---- a/net/mac80211/sta_info.c
-+++ b/net/mac80211/sta_info.c
-@@ -1276,8 +1276,12 @@ static void __sta_info_destroy_part2(str
- * frames sitting on hardware queues might be sent out without
- * any encryption at all.
- */
-- if (local->ops->set_key)
-- ieee80211_flush_queues(local, sta->sdata, false);
-+ if (local->ops->set_key) {
-+ if (local->ops->flush_sta)
-+ drv_flush_sta(local, sta->sdata, sta);
-+ else
-+ ieee80211_flush_queues(local, sta->sdata, false);
-+ }
-
- /* now keys can no longer be reached */
- ieee80211_free_sta_keys(local, sta);
---- a/net/mac80211/trace.h
-+++ b/net/mac80211/trace.h
-@@ -1177,6 +1177,13 @@ TRACE_EVENT(drv_flush,
- )
- );
-
-+DEFINE_EVENT(sta_event, drv_flush_sta,
-+ TP_PROTO(struct ieee80211_local *local,
-+ struct ieee80211_sub_if_data *sdata,
-+ struct ieee80211_sta *sta),
-+ TP_ARGS(local, sdata, sta)
-+);
-+
- TRACE_EVENT(drv_channel_switch,
- TP_PROTO(struct ieee80211_local *local,
- struct ieee80211_sub_if_data *sdata,
diff --git a/package/kernel/mac80211/patches/subsys/334-wifi-iwlwifi-mvm-support-new-flush_sta-method.patch b/package/kernel/mac80211/patches/subsys/334-wifi-iwlwifi-mvm-support-new-flush_sta-method.patch
deleted file mode 100644
index 18f39d505f..0000000000
--- a/package/kernel/mac80211/patches/subsys/334-wifi-iwlwifi-mvm-support-new-flush_sta-method.patch
+++ /dev/null
@@ -1,53 +0,0 @@
-From: Johannes Berg <johannes.berg@intel.com>
-Date: Mon, 13 Mar 2023 12:05:35 +0100
-Subject: [PATCH] wifi: iwlwifi: mvm: support new flush_sta method
-
-For iwlwifi this is simple to implement, and on newer hardware
-it's an improvement since we have per-station queues.
-
-Signed-off-by: Johannes Berg <johannes.berg@intel.com>
-Reviewed-by: Greenman, Gregory <gregory.greenman@intel.com>
----
-
---- a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
-+++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
-@@ -4890,6 +4890,31 @@ static void iwl_mvm_mac_flush(struct iee
- iwl_trans_wait_tx_queues_empty(mvm->trans, msk);
- }
-
-+static void iwl_mvm_mac_flush_sta(struct ieee80211_hw *hw,
-+ struct ieee80211_vif *vif,
-+ struct ieee80211_sta *sta)
-+{
-+ struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
-+ int i;
-+
-+ mutex_lock(&mvm->mutex);
-+ for (i = 0; i < mvm->fw->ucode_capa.num_stations; i++) {
-+ struct iwl_mvm_sta *mvmsta;
-+ struct ieee80211_sta *tmp;
-+
-+ tmp = rcu_dereference_protected(mvm->fw_id_to_mac_id[i],
-+ lockdep_is_held(&mvm->mutex));
-+ if (tmp != sta)
-+ continue;
-+
-+ mvmsta = iwl_mvm_sta_from_mac80211(sta);
-+
-+ if (iwl_mvm_flush_sta(mvm, mvmsta, false))
-+ IWL_ERR(mvm, "flush request fail\n");
-+ }
-+ mutex_unlock(&mvm->mutex);
-+}
-+
- static int iwl_mvm_mac_get_survey(struct ieee80211_hw *hw, int idx,
- struct survey_info *survey)
- {
-@@ -5417,6 +5442,7 @@ const struct ieee80211_ops iwl_mvm_hw_op
- .mgd_complete_tx = iwl_mvm_mac_mgd_complete_tx,
- .mgd_protect_tdls_discover = iwl_mvm_mac_mgd_protect_tdls_discover,
- .flush = iwl_mvm_mac_flush,
-+ .flush_sta = iwl_mvm_mac_flush_sta,
- .sched_scan_start = iwl_mvm_mac_sched_scan_start,
- .sched_scan_stop = iwl_mvm_mac_sched_scan_stop,
- .set_key = iwl_mvm_mac_set_key,
diff --git a/package/kernel/mac80211/patches/subsys/335-wifi-mac80211-add-LDPC-related-flags-in-ieee80211_bs.patch b/package/kernel/mac80211/patches/subsys/335-wifi-mac80211-add-LDPC-related-flags-in-ieee80211_bs.patch
deleted file mode 100644
index 1b379b76ae..0000000000
--- a/package/kernel/mac80211/patches/subsys/335-wifi-mac80211-add-LDPC-related-flags-in-ieee80211_bs.patch
+++ /dev/null
@@ -1,62 +0,0 @@
-From: Ryder Lee <ryder.lee@mediatek.com>
-Date: Sat, 18 Feb 2023 01:49:25 +0800
-Subject: [PATCH] wifi: mac80211: add LDPC related flags in ieee80211_bss_conf
-
-This is utilized to pass LDPC configurations from user space
-(i.e. hostapd) to driver.
-
-Signed-off-by: Ryder Lee <ryder.lee@mediatek.com>
-Link: https://lore.kernel.org/r/1de696aaa34efd77a926eb657b8c0fda05aaa177.1676628065.git.ryder.lee@mediatek.com
-Signed-off-by: Johannes Berg <johannes.berg@intel.com>
----
-
---- a/include/net/mac80211.h
-+++ b/include/net/mac80211.h
-@@ -653,6 +653,9 @@ struct ieee80211_fils_discovery {
- * write-protected by sdata_lock and local->mtx so holding either is fine
- * for read access.
- * @color_change_color: the bss color that will be used after the change.
-+ * @ht_ldpc: in AP mode, indicates interface has HT LDPC capability.
-+ * @vht_ldpc: in AP mode, indicates interface has VHT LDPC capability.
-+ * @he_ldpc: in AP mode, indicates interface has HE LDPC capability.
- * @vht_su_beamformer: in AP mode, does this BSS support operation as an VHT SU
- * beamformer
- * @vht_su_beamformee: in AP mode, does this BSS support operation as an VHT SU
-@@ -744,6 +747,9 @@ struct ieee80211_bss_conf {
- bool color_change_active;
- u8 color_change_color;
-
-+ bool ht_ldpc;
-+ bool vht_ldpc;
-+ bool he_ldpc;
- bool vht_su_beamformer;
- bool vht_su_beamformee;
- bool vht_mu_beamformer;
---- a/net/mac80211/cfg.c
-+++ b/net/mac80211/cfg.c
-@@ -1252,7 +1252,15 @@ static int ieee80211_start_ap(struct wip
- prev_beacon_int = link_conf->beacon_int;
- link_conf->beacon_int = params->beacon_interval;
-
-+ if (params->ht_cap)
-+ link_conf->ht_ldpc =
-+ params->ht_cap->cap_info &
-+ cpu_to_le16(IEEE80211_HT_CAP_LDPC_CODING);
-+
- if (params->vht_cap) {
-+ link_conf->vht_ldpc =
-+ params->vht_cap->vht_cap_info &
-+ cpu_to_le32(IEEE80211_VHT_CAP_RXLDPC);
- link_conf->vht_su_beamformer =
- params->vht_cap->vht_cap_info &
- cpu_to_le32(IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE);
-@@ -1282,6 +1290,9 @@ static int ieee80211_start_ap(struct wip
- }
-
- if (params->he_cap) {
-+ link_conf->he_ldpc =
-+ params->he_cap->phy_cap_info[1] &
-+ IEEE80211_HE_PHY_CAP1_LDPC_CODING_IN_PAYLOAD;
- link_conf->he_su_beamformer =
- params->he_cap->phy_cap_info[3] &
- IEEE80211_HE_PHY_CAP3_SU_BEAMFORMER;
diff --git a/package/kernel/mac80211/patches/subsys/336-v6.4-wifi-mac80211-generate-EMA-beacons-in-AP-mode.patch b/package/kernel/mac80211/patches/subsys/336-v6.4-wifi-mac80211-generate-EMA-beacons-in-AP-mode.patch
deleted file mode 100644
index 088f468e37..0000000000
--- a/package/kernel/mac80211/patches/subsys/336-v6.4-wifi-mac80211-generate-EMA-beacons-in-AP-mode.patch
+++ /dev/null
@@ -1,372 +0,0 @@
-From bd54f3c29077f23dad92ef82a78061b40be30c65 Mon Sep 17 00:00:00 2001
-From: Aloka Dixit <quic_alokad@quicinc.com>
-Date: Mon, 5 Dec 2022 16:50:37 -0800
-Subject: [PATCH] wifi: mac80211: generate EMA beacons in AP mode
-
-Add APIs to generate an array of beacons for an EMA AP (enhanced
-multiple BSSID advertisements), each including a single MBSSID element.
-EMA profile periodicity equals the count of elements.
-
-- ieee80211_beacon_get_template_ema_list() - Generate and return all
-EMA beacon templates. Drivers must call ieee80211_beacon_free_ema_list()
-to free the memory. No change in the prototype for the existing API,
-ieee80211_beacon_get_template(), which should be used for non-EMA AP.
-
-- ieee80211_beacon_get_template_ema_index() - Generate a beacon which
-includes the multiple BSSID element at the given index. Drivers can use
-this function in a loop until NULL is returned which indicates end of
-available MBSSID elements.
-
-- ieee80211_beacon_free_ema_list() - free the memory allocated for the
-list of EMA beacon templates.
-
-Modify existing functions ieee80211_beacon_get_ap(),
-ieee80211_get_mbssid_beacon_len() and ieee80211_beacon_add_mbssid()
-to accept a new parameter for EMA index.
-
-Signed-off-by: Aloka Dixit <quic_alokad@quicinc.com>
-Co-developed-by: John Crispin <john@phrozen.org>
-Signed-off-by: John Crispin <john@phrozen.org>
-Link: https://lore.kernel.org/r/20221206005040.3177-2-quic_alokad@quicinc.com
-Signed-off-by: Johannes Berg <johannes.berg@intel.com>
----
- include/net/mac80211.h | 68 +++++++++++++++++++
- net/mac80211/cfg.c | 11 +--
- net/mac80211/ieee80211_i.h | 10 ++-
- net/mac80211/tx.c | 134 ++++++++++++++++++++++++++++++++++---
- 4 files changed, 205 insertions(+), 18 deletions(-)
-
---- a/include/net/mac80211.h
-+++ b/include/net/mac80211.h
-@@ -5252,6 +5252,74 @@ ieee80211_beacon_get_template(struct iee
- unsigned int link_id);
-
- /**
-+ * ieee80211_beacon_get_template_ema_index - EMA beacon template generation
-+ * @hw: pointer obtained from ieee80211_alloc_hw().
-+ * @vif: &struct ieee80211_vif pointer from the add_interface callback.
-+ * @offs: &struct ieee80211_mutable_offsets pointer to struct that will
-+ * receive the offsets that may be updated by the driver.
-+ * @link_id: the link id to which the beacon belongs (or 0 for a non-MLD AP).
-+ * @ema_index: index of the beacon in the EMA set.
-+ *
-+ * This function follows the same rules as ieee80211_beacon_get_template()
-+ * but returns a beacon template which includes multiple BSSID element at the
-+ * requested index.
-+ *
-+ * Return: The beacon template. %NULL indicates the end of EMA templates.
-+ */
-+struct sk_buff *
-+ieee80211_beacon_get_template_ema_index(struct ieee80211_hw *hw,
-+ struct ieee80211_vif *vif,
-+ struct ieee80211_mutable_offsets *offs,
-+ unsigned int link_id, u8 ema_index);
-+
-+/**
-+ * struct ieee80211_ema_beacons - List of EMA beacons
-+ * @cnt: count of EMA beacons.
-+ *
-+ * @bcn: array of EMA beacons.
-+ * @bcn.skb: the skb containing this specific beacon
-+ * @bcn.offs: &struct ieee80211_mutable_offsets pointer to struct that will
-+ * receive the offsets that may be updated by the driver.
-+ */
-+struct ieee80211_ema_beacons {
-+ u8 cnt;
-+ struct {
-+ struct sk_buff *skb;
-+ struct ieee80211_mutable_offsets offs;
-+ } bcn[];
-+};
-+
-+/**
-+ * ieee80211_beacon_get_template_ema_list - EMA beacon template generation
-+ * @hw: pointer obtained from ieee80211_alloc_hw().
-+ * @vif: &struct ieee80211_vif pointer from the add_interface callback.
-+ * @link_id: the link id to which the beacon belongs (or 0 for a non-MLD AP)
-+ *
-+ * This function follows the same rules as ieee80211_beacon_get_template()
-+ * but allocates and returns a pointer to list of all beacon templates required
-+ * to cover all profiles in the multiple BSSID set. Each template includes only
-+ * one multiple BSSID element.
-+ *
-+ * Driver must call ieee80211_beacon_free_ema_list() to free the memory.
-+ *
-+ * Return: EMA beacon templates of type struct ieee80211_ema_beacons *.
-+ * %NULL on error.
-+ */
-+struct ieee80211_ema_beacons *
-+ieee80211_beacon_get_template_ema_list(struct ieee80211_hw *hw,
-+ struct ieee80211_vif *vif,
-+ unsigned int link_id);
-+
-+/**
-+ * ieee80211_beacon_free_ema_list - free an EMA beacon template list
-+ * @ema_beacons: list of EMA beacons of type &struct ieee80211_ema_beacons pointers.
-+ *
-+ * This function will free a list previously acquired by calling
-+ * ieee80211_beacon_get_template_ema_list()
-+ */
-+void ieee80211_beacon_free_ema_list(struct ieee80211_ema_beacons *ema_beacons);
-+
-+/**
- * ieee80211_beacon_get_tim - beacon generation function
- * @hw: pointer obtained from ieee80211_alloc_hw().
- * @vif: &struct ieee80211_vif pointer from the add_interface callback.
---- a/net/mac80211/cfg.c
-+++ b/net/mac80211/cfg.c
-@@ -1122,11 +1122,11 @@ static int ieee80211_assign_beacon(struc
- if (params->mbssid_ies) {
- mbssid = params->mbssid_ies;
- size += struct_size(new->mbssid_ies, elem, mbssid->cnt);
-- size += ieee80211_get_mbssid_beacon_len(mbssid);
-+ size += ieee80211_get_mbssid_beacon_len(mbssid, mbssid->cnt);
- } else if (old && old->mbssid_ies) {
- mbssid = old->mbssid_ies;
- size += struct_size(new->mbssid_ies, elem, mbssid->cnt);
-- size += ieee80211_get_mbssid_beacon_len(mbssid);
-+ size += ieee80211_get_mbssid_beacon_len(mbssid, mbssid->cnt);
- }
-
- new = kzalloc(size, GFP_KERNEL);
-@@ -3384,8 +3384,11 @@ cfg80211_beacon_dup(struct cfg80211_beac
-
- len = beacon->head_len + beacon->tail_len + beacon->beacon_ies_len +
- beacon->proberesp_ies_len + beacon->assocresp_ies_len +
-- beacon->probe_resp_len + beacon->lci_len + beacon->civicloc_len +
-- ieee80211_get_mbssid_beacon_len(beacon->mbssid_ies);
-+ beacon->probe_resp_len + beacon->lci_len + beacon->civicloc_len;
-+
-+ if (beacon->mbssid_ies)
-+ len += ieee80211_get_mbssid_beacon_len(beacon->mbssid_ies,
-+ beacon->mbssid_ies->cnt);
-
- new_beacon = kzalloc(sizeof(*new_beacon) + len, GFP_KERNEL);
- if (!new_beacon)
---- a/net/mac80211/ieee80211_i.h
-+++ b/net/mac80211/ieee80211_i.h
-@@ -1182,13 +1182,17 @@ ieee80211_vif_get_shift(struct ieee80211
- }
-
- static inline int
--ieee80211_get_mbssid_beacon_len(struct cfg80211_mbssid_elems *elems)
-+ieee80211_get_mbssid_beacon_len(struct cfg80211_mbssid_elems *elems, u8 i)
- {
-- int i, len = 0;
-+ int len = 0;
-
-- if (!elems)
-+ if (!elems || !elems->cnt || i > elems->cnt)
- return 0;
-
-+ if (i < elems->cnt)
-+ return elems->elem[i].len;
-+
-+ /* i == elems->cnt, calculate total length of all MBSSID elements */
- for (i = 0; i < elems->cnt; i++)
- len += elems->elem[i].len;
-
---- a/net/mac80211/tx.c
-+++ b/net/mac80211/tx.c
-@@ -5205,13 +5205,20 @@ ieee80211_beacon_get_finish(struct ieee8
- }
-
- static void
--ieee80211_beacon_add_mbssid(struct sk_buff *skb, struct beacon_data *beacon)
-+ieee80211_beacon_add_mbssid(struct sk_buff *skb, struct beacon_data *beacon,
-+ u8 i)
- {
-- int i;
-+ if (!beacon->mbssid_ies || !beacon->mbssid_ies->cnt ||
-+ i > beacon->mbssid_ies->cnt)
-+ return;
-
-- if (!beacon->mbssid_ies)
-+ if (i < beacon->mbssid_ies->cnt) {
-+ skb_put_data(skb, beacon->mbssid_ies->elem[i].data,
-+ beacon->mbssid_ies->elem[i].len);
- return;
-+ }
-
-+ /* i == beacon->mbssid_ies->cnt, include all MBSSID elements */
- for (i = 0; i < beacon->mbssid_ies->cnt; i++)
- skb_put_data(skb, beacon->mbssid_ies->elem[i].data,
- beacon->mbssid_ies->elem[i].len);
-@@ -5224,7 +5231,8 @@ ieee80211_beacon_get_ap(struct ieee80211
- struct ieee80211_mutable_offsets *offs,
- bool is_template,
- struct beacon_data *beacon,
-- struct ieee80211_chanctx_conf *chanctx_conf)
-+ struct ieee80211_chanctx_conf *chanctx_conf,
-+ u8 ema_index)
- {
- struct ieee80211_local *local = hw_to_local(hw);
- struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
-@@ -5243,7 +5251,9 @@ ieee80211_beacon_get_ap(struct ieee80211
- /* headroom, head length,
- * tail length, maximum TIM length and multiple BSSID length
- */
-- mbssid_len = ieee80211_get_mbssid_beacon_len(beacon->mbssid_ies);
-+ mbssid_len = ieee80211_get_mbssid_beacon_len(beacon->mbssid_ies,
-+ ema_index);
-+
- skb = dev_alloc_skb(local->tx_headroom + beacon->head_len +
- beacon->tail_len + 256 +
- local->hw.extra_beacon_tailroom + mbssid_len);
-@@ -5261,7 +5271,7 @@ ieee80211_beacon_get_ap(struct ieee80211
- offs->cntdwn_counter_offs[0] = beacon->cntdwn_counter_offsets[0];
-
- if (mbssid_len) {
-- ieee80211_beacon_add_mbssid(skb, beacon);
-+ ieee80211_beacon_add_mbssid(skb, beacon, ema_index);
- offs->mbssid_off = skb->len - mbssid_len;
- }
-
-@@ -5280,12 +5290,51 @@ ieee80211_beacon_get_ap(struct ieee80211
- return skb;
- }
-
-+static struct ieee80211_ema_beacons *
-+ieee80211_beacon_get_ap_ema_list(struct ieee80211_hw *hw,
-+ struct ieee80211_vif *vif,
-+ struct ieee80211_link_data *link,
-+ struct ieee80211_mutable_offsets *offs,
-+ bool is_template, struct beacon_data *beacon,
-+ struct ieee80211_chanctx_conf *chanctx_conf)
-+{
-+ struct ieee80211_ema_beacons *ema = NULL;
-+
-+ if (!beacon->mbssid_ies || !beacon->mbssid_ies->cnt)
-+ return NULL;
-+
-+ ema = kzalloc(struct_size(ema, bcn, beacon->mbssid_ies->cnt),
-+ GFP_ATOMIC);
-+ if (!ema)
-+ return NULL;
-+
-+ for (ema->cnt = 0; ema->cnt < beacon->mbssid_ies->cnt; ema->cnt++) {
-+ ema->bcn[ema->cnt].skb =
-+ ieee80211_beacon_get_ap(hw, vif, link,
-+ &ema->bcn[ema->cnt].offs,
-+ is_template, beacon,
-+ chanctx_conf, ema->cnt);
-+ if (!ema->bcn[ema->cnt].skb)
-+ break;
-+ }
-+
-+ if (ema->cnt == beacon->mbssid_ies->cnt)
-+ return ema;
-+
-+ ieee80211_beacon_free_ema_list(ema);
-+ return NULL;
-+}
-+
-+#define IEEE80211_INCLUDE_ALL_MBSSID_ELEMS -1
-+
- static struct sk_buff *
- __ieee80211_beacon_get(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif,
- struct ieee80211_mutable_offsets *offs,
- bool is_template,
-- unsigned int link_id)
-+ unsigned int link_id,
-+ int ema_index,
-+ struct ieee80211_ema_beacons **ema_beacons)
- {
- struct ieee80211_local *local = hw_to_local(hw);
- struct beacon_data *beacon = NULL;
-@@ -5314,8 +5363,29 @@ __ieee80211_beacon_get(struct ieee80211_
- if (!beacon)
- goto out;
-
-- skb = ieee80211_beacon_get_ap(hw, vif, link, offs, is_template,
-- beacon, chanctx_conf);
-+ if (ema_beacons) {
-+ *ema_beacons =
-+ ieee80211_beacon_get_ap_ema_list(hw, vif, link,
-+ offs,
-+ is_template,
-+ beacon,
-+ chanctx_conf);
-+ } else {
-+ if (beacon->mbssid_ies && beacon->mbssid_ies->cnt) {
-+ if (ema_index >= beacon->mbssid_ies->cnt)
-+ goto out; /* End of MBSSID elements */
-+
-+ if (ema_index <= IEEE80211_INCLUDE_ALL_MBSSID_ELEMS)
-+ ema_index = beacon->mbssid_ies->cnt;
-+ } else {
-+ ema_index = 0;
-+ }
-+
-+ skb = ieee80211_beacon_get_ap(hw, vif, link, offs,
-+ is_template, beacon,
-+ chanctx_conf,
-+ ema_index);
-+ }
- } else if (sdata->vif.type == NL80211_IFTYPE_ADHOC) {
- struct ieee80211_if_ibss *ifibss = &sdata->u.ibss;
- struct ieee80211_hdr *hdr;
-@@ -5403,10 +5473,50 @@ ieee80211_beacon_get_template(struct iee
- struct ieee80211_mutable_offsets *offs,
- unsigned int link_id)
- {
-- return __ieee80211_beacon_get(hw, vif, offs, true, link_id);
-+ return __ieee80211_beacon_get(hw, vif, offs, true, link_id,
-+ IEEE80211_INCLUDE_ALL_MBSSID_ELEMS, NULL);
- }
- EXPORT_SYMBOL(ieee80211_beacon_get_template);
-
-+struct sk_buff *
-+ieee80211_beacon_get_template_ema_index(struct ieee80211_hw *hw,
-+ struct ieee80211_vif *vif,
-+ struct ieee80211_mutable_offsets *offs,
-+ unsigned int link_id, u8 ema_index)
-+{
-+ return __ieee80211_beacon_get(hw, vif, offs, true, link_id, ema_index,
-+ NULL);
-+}
-+EXPORT_SYMBOL(ieee80211_beacon_get_template_ema_index);
-+
-+void ieee80211_beacon_free_ema_list(struct ieee80211_ema_beacons *ema_beacons)
-+{
-+ u8 i;
-+
-+ if (!ema_beacons)
-+ return;
-+
-+ for (i = 0; i < ema_beacons->cnt; i++)
-+ kfree_skb(ema_beacons->bcn[i].skb);
-+
-+ kfree(ema_beacons);
-+}
-+EXPORT_SYMBOL(ieee80211_beacon_free_ema_list);
-+
-+struct ieee80211_ema_beacons *
-+ieee80211_beacon_get_template_ema_list(struct ieee80211_hw *hw,
-+ struct ieee80211_vif *vif,
-+ unsigned int link_id)
-+{
-+ struct ieee80211_ema_beacons *ema_beacons = NULL;
-+
-+ WARN_ON(__ieee80211_beacon_get(hw, vif, NULL, false, link_id, 0,
-+ &ema_beacons));
-+
-+ return ema_beacons;
-+}
-+EXPORT_SYMBOL(ieee80211_beacon_get_template_ema_list);
-+
- struct sk_buff *ieee80211_beacon_get_tim(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif,
- u16 *tim_offset, u16 *tim_length,
-@@ -5414,7 +5524,9 @@ struct sk_buff *ieee80211_beacon_get_tim
- {
- struct ieee80211_mutable_offsets offs = {};
- struct sk_buff *bcn = __ieee80211_beacon_get(hw, vif, &offs, false,
-- link_id);
-+ link_id,
-+ IEEE80211_INCLUDE_ALL_MBSSID_ELEMS,
-+ NULL);
- struct sk_buff *copy;
- int shift;
-
diff --git a/package/kernel/mac80211/patches/subsys/337-mac80211-fix-sband-iftype-data-lookup-for-AP_VLAN.patch b/package/kernel/mac80211/patches/subsys/337-mac80211-fix-sband-iftype-data-lookup-for-AP_VLAN.patch
deleted file mode 100644
index 67b4284949..0000000000
--- a/package/kernel/mac80211/patches/subsys/337-mac80211-fix-sband-iftype-data-lookup-for-AP_VLAN.patch
+++ /dev/null
@@ -1,23 +0,0 @@
-From: Felix Fietkau <nbd@nbd.name>
-Date: Thu, 22 Jun 2023 18:02:25 +0200
-Subject: [PATCH] mac80211: fix sband iftype data lookup for AP_VLAN
-
-AP_VLAN interfaces are virtual, so doesn't really exist as a type for
-capabilities. When passed in as a type, AP is the one that's really intended.
-
-Fixes: c4cbaf7973a7 ("cfg80211: Add support for HE")
-Signed-off-by: Felix Fietkau <nbd@nbd.name>
----
-
---- a/include/net/cfg80211.h
-+++ b/include/net/cfg80211.h
-@@ -567,6 +567,9 @@ ieee80211_get_sband_iftype_data(const st
- if (WARN_ON(iftype >= NL80211_IFTYPE_MAX))
- return NULL;
-
-+ if (iftype == NL80211_IFTYPE_AP_VLAN)
-+ iftype = NL80211_IFTYPE_AP;
-+
- for (i = 0; i < sband->n_iftype_data; i++) {
- const struct ieee80211_sband_iftype_data *data =
- &sband->iftype_data[i];
diff --git a/package/kernel/mac80211/patches/subsys/339-wifi-cfg80211-fix-receving-mesh-packets-without-RFC1.patch b/package/kernel/mac80211/patches/subsys/339-wifi-cfg80211-fix-receving-mesh-packets-without-RFC1.patch
deleted file mode 100644
index e32c6ae1f3..0000000000
--- a/package/kernel/mac80211/patches/subsys/339-wifi-cfg80211-fix-receving-mesh-packets-without-RFC1.patch
+++ /dev/null
@@ -1,25 +0,0 @@
-From: Felix Fietkau <nbd@nbd.name>
-Date: Tue, 11 Jul 2023 13:30:12 +0200
-Subject: [PATCH] wifi: cfg80211: fix receving mesh packets without RFC1042
- header
-
-Fix ethernet header length field after stripping the mesh header
-
-Cc: stable@vger.kernel.org
-Link: https://lore.kernel.org/all/CT5GNZSK28AI.2K6M69OXM9RW5@syracuse/
-Fixes: 986e43b19ae9 ("wifi: mac80211: fix receiving A-MSDU frames on mesh interfaces")
-Reported-by: Nicolas Escande <nico.escande@gmail.com>
-Signed-off-by: Felix Fietkau <nbd@nbd.name>
----
-
---- a/net/wireless/util.c
-+++ b/net/wireless/util.c
-@@ -580,6 +580,8 @@ int ieee80211_strip_8023_mesh_hdr(struct
- hdrlen += ETH_ALEN + 2;
- else if (!pskb_may_pull(skb, hdrlen))
- return -EINVAL;
-+ else
-+ payload.eth.h_proto = htons(skb->len - hdrlen);
-
- mesh_addr = skb->data + sizeof(payload.eth) + ETH_ALEN;
- switch (payload.flags & MESH_FLAGS_AE) {
diff --git a/package/kernel/mac80211/patches/subsys/400-allow-ibss-mixed.patch b/package/kernel/mac80211/patches/subsys/400-allow-ibss-mixed.patch
index c38fa13f03..ad24dfda5a 100644
--- a/package/kernel/mac80211/patches/subsys/400-allow-ibss-mixed.patch
+++ b/package/kernel/mac80211/patches/subsys/400-allow-ibss-mixed.patch
@@ -16,7 +16,7 @@ and we should ignore this.
--- a/net/wireless/core.c
+++ b/net/wireless/core.c
-@@ -614,21 +614,6 @@ static int wiphy_verify_combinations(str
+@@ -649,21 +649,6 @@ static int wiphy_verify_combinations(str
c->limits[j].max > 1))
return -EINVAL;