diff --git a/package/kernel/mac80211/Makefile b/package/kernel/mac80211/Makefile
index 901c08b0de62..aedaac4d32dd 100644
--- a/package/kernel/mac80211/Makefile
+++ b/package/kernel/mac80211/Makefile
@@ -10,10 +10,10 @@ include $(INCLUDE_DIR)/kernel.mk
 
 PKG_NAME:=mac80211
 
-PKG_VERSION:=5.4.36-1
+PKG_VERSION:=5.5.19-1
 PKG_RELEASE:=1
-PKG_SOURCE_URL:=@KERNEL/linux/kernel/projects/backports/stable/v5.4.36/
-PKG_HASH:=5b39734986fba3b9c24c521d0499a2dc9cb17267bb58c02d9a520205add2d16b
+PKG_SOURCE_URL:=@KERNEL/linux/kernel/projects/backports/stable/v5.5.19/
+PKG_HASH:=9dd9153df6082eaa079144193a3fab79d200942e1a2a1a80e032c9667b7b92a6
 
 PKG_SOURCE:=backports-$(PKG_VERSION).tar.xz
 PKG_BUILD_DIR:=$(KERNEL_BUILD_DIR)/backports-$(PKG_VERSION)
diff --git a/package/kernel/mac80211/patches/ath/120-owl-loader-compat.patch b/package/kernel/mac80211/patches/ath/120-owl-loader-compat.patch
index 155f4fc36567..d1d6c9e2e3eb 100644
--- a/package/kernel/mac80211/patches/ath/120-owl-loader-compat.patch
+++ b/package/kernel/mac80211/patches/ath/120-owl-loader-compat.patch
@@ -11,7 +11,7 @@ Signed-off-by: Christian Lamparter <chunkeey@gmail.com>
 
 --- a/drivers/net/wireless/ath/ath9k/ath9k_pci_owl_loader.c
 +++ b/drivers/net/wireless/ath/ath9k/ath9k_pci_owl_loader.c
-@@ -104,6 +104,7 @@ static void owl_fw_cb(const struct firmw
+@@ -103,6 +103,7 @@ static void owl_fw_cb(const struct firmw
  {
  	struct pci_dev *pdev = (struct pci_dev *)context;
  	struct owl_ctx *ctx = (struct owl_ctx *)pci_get_drvdata(pdev);
@@ -19,7 +19,7 @@ Signed-off-by: Christian Lamparter <chunkeey@gmail.com>
  	struct pci_bus *bus;
  
  	complete(&ctx->eeprom_load);
-@@ -119,6 +120,16 @@ static void owl_fw_cb(const struct firmw
+@@ -118,6 +119,16 @@ static void owl_fw_cb(const struct firmw
  		goto release;
  	}
  
@@ -36,7 +36,7 @@ Signed-off-by: Christian Lamparter <chunkeey@gmail.com>
  	if (ath9k_pci_fixup(pdev, (const u16 *)fw->data, fw->size))
  		goto release;
  
-@@ -138,8 +149,14 @@ release:
+@@ -137,8 +148,14 @@ release:
  static const char *owl_get_eeprom_name(struct pci_dev *pdev)
  {
  	struct device *dev = &pdev->dev;
diff --git a/package/kernel/mac80211/patches/ath/403-world_regd_fixup.patch b/package/kernel/mac80211/patches/ath/403-world_regd_fixup.patch
index 2043083158f7..ed616b753259 100644
--- a/package/kernel/mac80211/patches/ath/403-world_regd_fixup.patch
+++ b/package/kernel/mac80211/patches/ath/403-world_regd_fixup.patch
@@ -4,15 +4,15 @@
  					 NL80211_RRF_NO_OFDM)
  
  /* We allow IBSS on these on a case by case basis by regulatory domain */
--#define ATH9K_5GHZ_5150_5350	REG_RULE(5150-10, 5350+10, 80, 0, 30,\
-+#define ATH9K_5GHZ_5150_5350	REG_RULE(5150-10, 5240+10, 80, 0, 30, 0),\
+-#define ATH_5GHZ_5150_5350	REG_RULE(5150-10, 5350+10, 80, 0, 30,\
++#define ATH_5GHZ_5150_5350	REG_RULE(5150-10, 5240+10, 80, 0, 30, 0),\
 +				REG_RULE(5260-10, 5350+10, 80, 0, 30,\
  					 NL80211_RRF_NO_IR)
- #define ATH9K_5GHZ_5470_5850	REG_RULE(5470-10, 5850+10, 80, 0, 30,\
+ #define ATH_5GHZ_5470_5850	REG_RULE(5470-10, 5850+10, 80, 0, 30,\
  					 NL80211_RRF_NO_IR)
 @@ -62,57 +63,56 @@ static struct reg_dmn_pair_mapping *ath_
- #define ATH9K_5GHZ_NO_MIDBAND	ATH9K_5GHZ_5150_5350, \
- 				ATH9K_5GHZ_5725_5850
+ #define ATH_5GHZ_NO_MIDBAND	ATH_5GHZ_5150_5350, \
+ 				ATH_5GHZ_5725_5850
  
 +#define REGD_RULES(...) \
 +	.reg_rules = { __VA_ARGS__ }, \
@@ -25,8 +25,8 @@
  	.alpha2 =  "99",
 -	.reg_rules = {
 +	REGD_RULES(
- 		ATH9K_2GHZ_ALL,
- 		ATH9K_5GHZ_ALL,
+ 		ATH_2GHZ_ALL,
+ 		ATH_5GHZ_ALL,
 -	}
 +	)
  };
@@ -37,9 +37,9 @@
  	.alpha2 =  "99",
 -	.reg_rules = {
 +	REGD_RULES(
- 		ATH9K_2GHZ_CH01_11,
- 		ATH9K_2GHZ_CH12_13,
- 		ATH9K_5GHZ_NO_MIDBAND,
+ 		ATH_2GHZ_CH01_11,
+ 		ATH_2GHZ_CH12_13,
+ 		ATH_5GHZ_NO_MIDBAND,
 -	}
 +	)
  };
@@ -50,8 +50,8 @@
  	.alpha2 =  "99",
 -	.reg_rules = {
 +	REGD_RULES(
- 		ATH9K_2GHZ_CH01_11,
- 		ATH9K_5GHZ_NO_MIDBAND,
+ 		ATH_2GHZ_CH01_11,
+ 		ATH_5GHZ_NO_MIDBAND,
 -	}
 +	)
  };
@@ -62,8 +62,8 @@
  	.alpha2 =  "99",
 -	.reg_rules = {
 +	REGD_RULES(
- 		ATH9K_2GHZ_CH01_11,
- 		ATH9K_5GHZ_ALL,
+ 		ATH_2GHZ_CH01_11,
+ 		ATH_5GHZ_ALL,
 -	}
 +	)
  };
@@ -74,9 +74,9 @@
  	.alpha2 =  "99",
 -	.reg_rules = {
 +	REGD_RULES(
- 		ATH9K_2GHZ_CH01_11,
- 		ATH9K_2GHZ_CH12_13,
- 		ATH9K_5GHZ_ALL,
+ 		ATH_2GHZ_CH01_11,
+ 		ATH_2GHZ_CH12_13,
+ 		ATH_5GHZ_ALL,
 -	}
 +	)
  };
diff --git a/package/kernel/mac80211/patches/ath/921-ath10k_init_devices_synchronously.patch b/package/kernel/mac80211/patches/ath/921-ath10k_init_devices_synchronously.patch
index 69c29f15eea9..728c86effbb4 100644
--- a/package/kernel/mac80211/patches/ath/921-ath10k_init_devices_synchronously.patch
+++ b/package/kernel/mac80211/patches/ath/921-ath10k_init_devices_synchronously.patch
@@ -14,7 +14,7 @@ Signed-off-by: Sven Eckelmann <sven@open-mesh.com>
 
 --- a/drivers/net/wireless/ath/ath10k/core.c
 +++ b/drivers/net/wireless/ath/ath10k/core.c
-@@ -3074,6 +3074,16 @@ int ath10k_core_register(struct ath10k *
+@@ -3105,6 +3105,16 @@ int ath10k_core_register(struct ath10k *
  
  	queue_work(ar->workqueue, &ar->register_work);
  
diff --git a/package/kernel/mac80211/patches/ath/930-ath10k_add_tpt_led_trigger.patch b/package/kernel/mac80211/patches/ath/930-ath10k_add_tpt_led_trigger.patch
index 5a79c3370204..6fe551f9d539 100644
--- a/package/kernel/mac80211/patches/ath/930-ath10k_add_tpt_led_trigger.patch
+++ b/package/kernel/mac80211/patches/ath/930-ath10k_add_tpt_led_trigger.patch
@@ -1,6 +1,6 @@
 --- a/drivers/net/wireless/ath/ath10k/mac.c
 +++ b/drivers/net/wireless/ath/ath10k/mac.c
-@@ -8673,6 +8673,21 @@ static int ath10k_mac_init_rd(struct ath
+@@ -8761,6 +8761,21 @@ static int ath10k_mac_init_rd(struct ath
  	return 0;
  }
  
@@ -22,7 +22,7 @@
  int ath10k_mac_register(struct ath10k *ar)
  {
  	static const u32 cipher_suites[] = {
-@@ -9000,6 +9015,12 @@ int ath10k_mac_register(struct ath10k *a
+@@ -9088,6 +9103,12 @@ int ath10k_mac_register(struct ath10k *a
  
  	ar->hw->weight_multiplier = ATH10K_AIRTIME_WEIGHT_MULTIPLIER;
  
diff --git a/package/kernel/mac80211/patches/ath/972-ath10k_fix-crash-due-to-wrong-handling-of-peer_bw_rxnss_override-parameter.patch b/package/kernel/mac80211/patches/ath/972-ath10k_fix-crash-due-to-wrong-handling-of-peer_bw_rxnss_override-parameter.patch
index c99ba5595585..4d51205b5ed5 100644
--- a/package/kernel/mac80211/patches/ath/972-ath10k_fix-crash-due-to-wrong-handling-of-peer_bw_rxnss_override-parameter.patch
+++ b/package/kernel/mac80211/patches/ath/972-ath10k_fix-crash-due-to-wrong-handling-of-peer_bw_rxnss_override-parameter.patch
@@ -23,7 +23,7 @@ v9: use SM/MS macros from code.h to simplify shift/mask handling
  3 files changed, 52 insertions(+), 23 deletions(-)
 --- a/drivers/net/wireless/ath/ath10k/mac.c
 +++ b/drivers/net/wireless/ath/ath10k/mac.c
-@@ -2515,7 +2515,7 @@ static void ath10k_peer_assoc_h_vht(stru
+@@ -2516,7 +2516,7 @@ static void ath10k_peer_assoc_h_vht(stru
  	const u16 *vht_mcs_mask;
  	u8 ampdu_factor;
  	u8 max_nss, vht_mcs;
@@ -32,7 +32,7 @@ v9: use SM/MS macros from code.h to simplify shift/mask handling
  
  	if (WARN_ON(ath10k_mac_vif_chan(vif, &def)))
  		return;
-@@ -2575,23 +2575,45 @@ static void ath10k_peer_assoc_h_vht(stru
+@@ -2576,23 +2576,45 @@ static void ath10k_peer_assoc_h_vht(stru
  		__le16_to_cpu(vht_cap->vht_mcs.tx_highest);
  	arg->peer_vht_rates.tx_mcs_set = ath10k_peer_assoc_h_vht_limit(
  		__le16_to_cpu(vht_cap->vht_mcs.tx_mcs_map), vht_mcs_mask);
@@ -92,7 +92,7 @@ v9: use SM/MS macros from code.h to simplify shift/mask handling
  }
  
  static void ath10k_peer_assoc_h_qos(struct ath10k *ar,
-@@ -2743,9 +2765,9 @@ static int ath10k_peer_assoc_prepare(str
+@@ -2744,9 +2766,9 @@ static int ath10k_peer_assoc_prepare(str
  	ath10k_peer_assoc_h_crypto(ar, vif, sta, arg);
  	ath10k_peer_assoc_h_rates(ar, vif, sta, arg);
  	ath10k_peer_assoc_h_ht(ar, vif, sta, arg);
@@ -105,7 +105,7 @@ v9: use SM/MS macros from code.h to simplify shift/mask handling
  }
 --- a/drivers/net/wireless/ath/ath10k/wmi.c
 +++ b/drivers/net/wireless/ath/ath10k/wmi.c
-@@ -7552,12 +7552,7 @@ ath10k_wmi_peer_assoc_fill_10_4(struct a
+@@ -7601,12 +7601,7 @@ ath10k_wmi_peer_assoc_fill_10_4(struct a
  	struct wmi_10_4_peer_assoc_complete_cmd *cmd = buf;
  
  	ath10k_wmi_peer_assoc_fill_10_2(ar, buf, arg);
@@ -121,7 +121,7 @@ v9: use SM/MS macros from code.h to simplify shift/mask handling
  static int
 --- a/drivers/net/wireless/ath/ath10k/wmi.h
 +++ b/drivers/net/wireless/ath/ath10k/wmi.h
-@@ -6478,7 +6478,19 @@ struct wmi_10_2_peer_assoc_complete_cmd
+@@ -6501,7 +6501,19 @@ struct wmi_10_2_peer_assoc_complete_cmd
  	__le32 info0; /* WMI_PEER_ASSOC_INFO0_ */
  } __packed;
  
diff --git a/package/kernel/mac80211/patches/ath/973-ath10k_fix-band_center_freq-handling-for-VHT160-in-recent-firmwares.patch b/package/kernel/mac80211/patches/ath/973-ath10k_fix-band_center_freq-handling-for-VHT160-in-recent-firmwares.patch
index d0e293c6dd4c..d6a1ef084989 100644
--- a/package/kernel/mac80211/patches/ath/973-ath10k_fix-band_center_freq-handling-for-VHT160-in-recent-firmwares.patch
+++ b/package/kernel/mac80211/patches/ath/973-ath10k_fix-band_center_freq-handling-for-VHT160-in-recent-firmwares.patch
@@ -13,7 +13,7 @@ v2: fix trailing whitespace issue and fix some typos within the commit note
  2 files changed, 8 insertions(+), 10 deletions(-)
 --- a/drivers/net/wireless/ath/ath10k/mac.c
 +++ b/drivers/net/wireless/ath/ath10k/mac.c
-@@ -4575,13 +4575,6 @@ static struct ieee80211_sta_vht_cap ath1
+@@ -4576,13 +4576,6 @@ static struct ieee80211_sta_vht_cap ath1
  		vht_cap.cap |= val;
  	}
  
@@ -29,7 +29,7 @@ v2: fix trailing whitespace issue and fix some typos within the commit note
  		if ((i < ar->num_rf_chains) && (ar->cfg_tx_chainmask & BIT(i)))
 --- a/drivers/net/wireless/ath/ath10k/wmi.c
 +++ b/drivers/net/wireless/ath/ath10k/wmi.c
-@@ -1700,13 +1700,18 @@ void ath10k_wmi_put_wmi_channel(struct w
+@@ -1713,13 +1713,18 @@ void ath10k_wmi_put_wmi_channel(struct w
  		flags |= WMI_CHAN_FLAG_HT40_PLUS;
  	if (arg->chan_radar)
  		flags |= WMI_CHAN_FLAG_DFS;
diff --git a/package/kernel/mac80211/patches/ath/974-ath10k_add-LED-and-GPIO-controlling-support-for-various-chipsets.patch b/package/kernel/mac80211/patches/ath/974-ath10k_add-LED-and-GPIO-controlling-support-for-various-chipsets.patch
index 70af3892d728..d72d515ad3c0 100644
--- a/package/kernel/mac80211/patches/ath/974-ath10k_add-LED-and-GPIO-controlling-support-for-various-chipsets.patch
+++ b/package/kernel/mac80211/patches/ath/974-ath10k_add-LED-and-GPIO-controlling-support-for-various-chipsets.patch
@@ -124,7 +124,7 @@ v13:
  WCN36XX=
 --- a/drivers/net/wireless/ath/ath10k/core.c
 +++ b/drivers/net/wireless/ath/ath10k/core.c
-@@ -24,6 +24,7 @@
+@@ -25,6 +25,7 @@
  #include "testmode.h"
  #include "wmi-ops.h"
  #include "coredump.h"
@@ -132,7 +132,7 @@ v13:
  
  unsigned int ath10k_debug_mask;
  EXPORT_SYMBOL(ath10k_debug_mask);
-@@ -60,6 +61,7 @@ static const struct ath10k_hw_params ath
+@@ -61,6 +62,7 @@ static const struct ath10k_hw_params ath
  		.dev_id = QCA988X_2_0_DEVICE_ID,
  		.bus = ATH10K_BUS_PCI,
  		.name = "qca988x hw2.0",
@@ -140,7 +140,7 @@ v13:
  		.patch_load_addr = QCA988X_HW_2_0_PATCH_LOAD_ADDR,
  		.uart_pin = 7,
  		.cc_wraparound_type = ATH10K_HW_CC_WRAP_SHIFTED_ALL,
-@@ -130,6 +132,7 @@ static const struct ath10k_hw_params ath
+@@ -131,6 +133,7 @@ static const struct ath10k_hw_params ath
  		.dev_id = QCA9887_1_0_DEVICE_ID,
  		.bus = ATH10K_BUS_PCI,
  		.name = "qca9887 hw1.0",
@@ -148,7 +148,7 @@ v13:
  		.patch_load_addr = QCA9887_HW_1_0_PATCH_LOAD_ADDR,
  		.uart_pin = 7,
  		.cc_wraparound_type = ATH10K_HW_CC_WRAP_SHIFTED_ALL,
-@@ -337,6 +340,7 @@ static const struct ath10k_hw_params ath
+@@ -338,6 +341,7 @@ static const struct ath10k_hw_params ath
  		.dev_id = QCA99X0_2_0_DEVICE_ID,
  		.bus = ATH10K_BUS_PCI,
  		.name = "qca99x0 hw2.0",
@@ -156,7 +156,7 @@ v13:
  		.patch_load_addr = QCA99X0_HW_2_0_PATCH_LOAD_ADDR,
  		.uart_pin = 7,
  		.otp_exe_param = 0x00000700,
-@@ -378,6 +382,7 @@ static const struct ath10k_hw_params ath
+@@ -379,6 +383,7 @@ static const struct ath10k_hw_params ath
  		.dev_id = QCA9984_1_0_DEVICE_ID,
  		.bus = ATH10K_BUS_PCI,
  		.name = "qca9984/qca9994 hw1.0",
@@ -164,7 +164,7 @@ v13:
  		.patch_load_addr = QCA9984_HW_1_0_PATCH_LOAD_ADDR,
  		.uart_pin = 7,
  		.cc_wraparound_type = ATH10K_HW_CC_WRAP_SHIFTED_EACH,
-@@ -426,6 +431,7 @@ static const struct ath10k_hw_params ath
+@@ -427,6 +432,7 @@ static const struct ath10k_hw_params ath
  		.dev_id = QCA9888_2_0_DEVICE_ID,
  		.bus = ATH10K_BUS_PCI,
  		.name = "qca9888 hw2.0",
@@ -172,7 +172,7 @@ v13:
  		.patch_load_addr = QCA9888_HW_2_0_PATCH_LOAD_ADDR,
  		.uart_pin = 7,
  		.cc_wraparound_type = ATH10K_HW_CC_WRAP_SHIFTED_EACH,
-@@ -2791,6 +2797,10 @@ int ath10k_core_start(struct ath10k *ar,
+@@ -2822,6 +2828,10 @@ int ath10k_core_start(struct ath10k *ar,
  		goto err_hif_stop;
  	}
  
@@ -183,7 +183,7 @@ v13:
  	return 0;
  
  err_hif_stop:
-@@ -3047,9 +3057,18 @@ static void ath10k_core_register_work(st
+@@ -3078,9 +3088,18 @@ static void ath10k_core_register_work(st
  		goto err_spectral_destroy;
  	}
  
@@ -202,7 +202,7 @@ v13:
  err_spectral_destroy:
  	ath10k_spectral_destroy(ar);
  err_debug_destroy:
-@@ -3095,6 +3114,8 @@ void ath10k_core_unregister(struct ath10
+@@ -3126,6 +3145,8 @@ void ath10k_core_unregister(struct ath10
  	if (!test_bit(ATH10K_FLAG_CORE_REGISTERED, &ar->dev_flags))
  		return;
  
@@ -221,7 +221,7 @@ v13:
  
  #include "htt.h"
  #include "htc.h"
-@@ -1170,6 +1171,13 @@ struct ath10k {
+@@ -1179,6 +1180,13 @@ struct ath10k {
  	} testmode;
  
  	struct {
@@ -237,7 +237,7 @@ v13:
  		u32 fw_warm_reset_counter;
 --- a/drivers/net/wireless/ath/ath10k/hw.h
 +++ b/drivers/net/wireless/ath/ath10k/hw.h
-@@ -514,6 +514,7 @@ struct ath10k_hw_params {
+@@ -517,6 +517,7 @@ struct ath10k_hw_params {
  	const char *name;
  	u32 patch_load_addr;
  	int uart_pin;
@@ -397,7 +397,7 @@ v13:
 +#endif /* _LEDS_H_ */
 --- a/drivers/net/wireless/ath/ath10k/mac.c
 +++ b/drivers/net/wireless/ath/ath10k/mac.c
-@@ -23,6 +23,7 @@
+@@ -24,6 +24,7 @@
  #include "wmi-tlv.h"
  #include "wmi-ops.h"
  #include "wow.h"
@@ -456,7 +456,7 @@ v13:
  {
 --- a/drivers/net/wireless/ath/ath10k/wmi-tlv.c
 +++ b/drivers/net/wireless/ath/ath10k/wmi-tlv.c
-@@ -4367,6 +4367,8 @@ static const struct wmi_ops wmi_tlv_ops
+@@ -4444,6 +4444,8 @@ static const struct wmi_ops wmi_tlv_ops
  	.gen_echo = ath10k_wmi_tlv_op_gen_echo,
  	.gen_vdev_spectral_conf = ath10k_wmi_tlv_op_gen_vdev_spectral_conf,
  	.gen_vdev_spectral_enable = ath10k_wmi_tlv_op_gen_vdev_spectral_enable,
@@ -467,7 +467,7 @@ v13:
  static const struct wmi_peer_flags_map wmi_tlv_peer_flags_map = {
 --- a/drivers/net/wireless/ath/ath10k/wmi.c
 +++ b/drivers/net/wireless/ath/ath10k/wmi.c
-@@ -7372,6 +7372,49 @@ ath10k_wmi_op_gen_peer_set_param(struct
+@@ -7421,6 +7421,49 @@ ath10k_wmi_op_gen_peer_set_param(struct
  	return skb;
  }
  
@@ -517,7 +517,7 @@ v13:
  static struct sk_buff *
  ath10k_wmi_op_gen_set_psmode(struct ath10k *ar, u32 vdev_id,
  			     enum wmi_sta_ps_mode psmode)
-@@ -9029,6 +9072,9 @@ static const struct wmi_ops wmi_ops = {
+@@ -9078,6 +9121,9 @@ static const struct wmi_ops wmi_ops = {
  	.fw_stats_fill = ath10k_wmi_main_op_fw_stats_fill,
  	.get_vdev_subtype = ath10k_wmi_op_get_vdev_subtype,
  	.gen_echo = ath10k_wmi_op_gen_echo,
@@ -527,7 +527,7 @@ v13:
  	/* .gen_bcn_tmpl not implemented */
  	/* .gen_prb_tmpl not implemented */
  	/* .gen_p2p_go_bcn_ie not implemented */
-@@ -9099,6 +9145,8 @@ static const struct wmi_ops wmi_10_1_ops
+@@ -9148,6 +9194,8 @@ static const struct wmi_ops wmi_10_1_ops
  	.fw_stats_fill = ath10k_wmi_10x_op_fw_stats_fill,
  	.get_vdev_subtype = ath10k_wmi_op_get_vdev_subtype,
  	.gen_echo = ath10k_wmi_op_gen_echo,
@@ -536,7 +536,7 @@ v13:
  	/* .gen_bcn_tmpl not implemented */
  	/* .gen_prb_tmpl not implemented */
  	/* .gen_p2p_go_bcn_ie not implemented */
-@@ -9171,6 +9219,8 @@ static const struct wmi_ops wmi_10_2_ops
+@@ -9220,6 +9268,8 @@ static const struct wmi_ops wmi_10_2_ops
  	.gen_delba_send = ath10k_wmi_op_gen_delba_send,
  	.fw_stats_fill = ath10k_wmi_10x_op_fw_stats_fill,
  	.get_vdev_subtype = ath10k_wmi_op_get_vdev_subtype,
@@ -545,7 +545,7 @@ v13:
  	/* .gen_pdev_enable_adaptive_cca not implemented */
  };
  
-@@ -9242,6 +9292,8 @@ static const struct wmi_ops wmi_10_2_4_o
+@@ -9291,6 +9341,8 @@ static const struct wmi_ops wmi_10_2_4_o
  		ath10k_wmi_op_gen_pdev_enable_adaptive_cca,
  	.get_vdev_subtype = ath10k_wmi_10_2_4_op_get_vdev_subtype,
  	.gen_bb_timing = ath10k_wmi_10_2_4_op_gen_bb_timing,
@@ -554,7 +554,7 @@ v13:
  	/* .gen_bcn_tmpl not implemented */
  	/* .gen_prb_tmpl not implemented */
  	/* .gen_p2p_go_bcn_ie not implemented */
-@@ -9322,6 +9374,8 @@ static const struct wmi_ops wmi_10_4_ops
+@@ -9371,6 +9423,8 @@ static const struct wmi_ops wmi_10_4_ops
  	.gen_pdev_bss_chan_info_req = ath10k_wmi_10_2_op_gen_pdev_bss_chan_info,
  	.gen_echo = ath10k_wmi_op_gen_echo,
  	.gen_pdev_get_tpc_config = ath10k_wmi_10_2_4_op_gen_pdev_get_tpc_config,
@@ -565,7 +565,7 @@ v13:
  int ath10k_wmi_attach(struct ath10k *ar)
 --- a/drivers/net/wireless/ath/ath10k/wmi.h
 +++ b/drivers/net/wireless/ath/ath10k/wmi.h
-@@ -3005,6 +3005,41 @@ enum wmi_10_4_feature_mask {
+@@ -3007,6 +3007,41 @@ enum wmi_10_4_feature_mask {
  
  };
  
diff --git a/package/kernel/mac80211/patches/ath/975-ath10k-use-tpt-trigger-by-default.patch b/package/kernel/mac80211/patches/ath/975-ath10k-use-tpt-trigger-by-default.patch
index 0763d159e646..3973dc8cb31b 100644
--- a/package/kernel/mac80211/patches/ath/975-ath10k-use-tpt-trigger-by-default.patch
+++ b/package/kernel/mac80211/patches/ath/975-ath10k-use-tpt-trigger-by-default.patch
@@ -16,7 +16,7 @@ Signed-off-by: Mathias Kresin <dev@kresin.me>
 
 --- a/drivers/net/wireless/ath/ath10k/core.h
 +++ b/drivers/net/wireless/ath/ath10k/core.h
-@@ -1219,6 +1219,10 @@ struct ath10k {
+@@ -1228,6 +1228,10 @@ struct ath10k {
  	struct ath10k_bus_params bus_param;
  	struct completion peer_delete_done;
  
@@ -42,7 +42,7 @@ Signed-off-by: Mathias Kresin <dev@kresin.me>
  	if (ret)
 --- a/drivers/net/wireless/ath/ath10k/mac.c
 +++ b/drivers/net/wireless/ath/ath10k/mac.c
-@@ -9032,7 +9032,7 @@ int ath10k_mac_register(struct ath10k *a
+@@ -9120,7 +9120,7 @@ int ath10k_mac_register(struct ath10k *a
  	ar->hw->weight_multiplier = ATH10K_AIRTIME_WEIGHT_MULTIPLIER;
  
  #ifdef CPTCFG_MAC80211_LEDS
diff --git a/package/kernel/mac80211/patches/ath/980-ath10k-fix-max-antenna-gain-unit.patch b/package/kernel/mac80211/patches/ath/980-ath10k-fix-max-antenna-gain-unit.patch
index f60163f941ec..149585b050aa 100644
--- a/package/kernel/mac80211/patches/ath/980-ath10k-fix-max-antenna-gain-unit.patch
+++ b/package/kernel/mac80211/patches/ath/980-ath10k-fix-max-antenna-gain-unit.patch
@@ -20,7 +20,7 @@ Forwarded: https://patchwork.kernel.org/patch/10986723/
 
 --- a/drivers/net/wireless/ath/ath10k/mac.c
 +++ b/drivers/net/wireless/ath/ath10k/mac.c
-@@ -1041,7 +1041,7 @@ static int ath10k_monitor_vdev_start(str
+@@ -1042,7 +1042,7 @@ static int ath10k_monitor_vdev_start(str
  	arg.channel.min_power = 0;
  	arg.channel.max_power = channel->max_power * 2;
  	arg.channel.max_reg_power = channel->max_reg_power * 2;
@@ -29,7 +29,7 @@ Forwarded: https://patchwork.kernel.org/patch/10986723/
  
  	reinit_completion(&ar->vdev_setup_done);
  	reinit_completion(&ar->vdev_delete_done);
-@@ -1487,7 +1487,7 @@ static int ath10k_vdev_start_restart(str
+@@ -1488,7 +1488,7 @@ static int ath10k_vdev_start_restart(str
  	arg.channel.min_power = 0;
  	arg.channel.max_power = chandef->chan->max_power * 2;
  	arg.channel.max_reg_power = chandef->chan->max_reg_power * 2;
@@ -38,7 +38,7 @@ Forwarded: https://patchwork.kernel.org/patch/10986723/
  
  	if (arvif->vdev_type == WMI_VDEV_TYPE_AP) {
  		arg.ssid = arvif->u.ap.ssid;
-@@ -3168,7 +3168,7 @@ static int ath10k_update_channel_list(st
+@@ -3169,7 +3169,7 @@ static int ath10k_update_channel_list(st
  			ch->min_power = 0;
  			ch->max_power = channel->max_power * 2;
  			ch->max_reg_power = channel->max_reg_power * 2;
diff --git a/package/kernel/mac80211/patches/ath/981-ath10k-adjust-tx-power-reduction-for-US-regulatory-d.patch b/package/kernel/mac80211/patches/ath/981-ath10k-adjust-tx-power-reduction-for-US-regulatory-d.patch
index 9fbb254127e2..36948e546f4c 100644
--- a/package/kernel/mac80211/patches/ath/981-ath10k-adjust-tx-power-reduction-for-US-regulatory-d.patch
+++ b/package/kernel/mac80211/patches/ath/981-ath10k-adjust-tx-power-reduction-for-US-regulatory-d.patch
@@ -28,7 +28,7 @@ Forwarded: no
 
 --- a/drivers/net/wireless/ath/ath10k/mac.c
 +++ b/drivers/net/wireless/ath/ath10k/mac.c
-@@ -1009,6 +1009,40 @@ static inline int ath10k_vdev_setup_sync
+@@ -1010,6 +1010,40 @@ static inline int ath10k_vdev_setup_sync
  	return ar->last_wmi_vdev_start_status;
  }
  
@@ -69,7 +69,7 @@ Forwarded: no
  static int ath10k_monitor_vdev_start(struct ath10k *ar, int vdev_id)
  {
  	struct cfg80211_chan_def *chandef = NULL;
-@@ -1041,7 +1075,8 @@ static int ath10k_monitor_vdev_start(str
+@@ -1042,7 +1076,8 @@ static int ath10k_monitor_vdev_start(str
  	arg.channel.min_power = 0;
  	arg.channel.max_power = channel->max_power * 2;
  	arg.channel.max_reg_power = channel->max_reg_power * 2;
@@ -79,7 +79,7 @@ Forwarded: no
  
  	reinit_completion(&ar->vdev_setup_done);
  	reinit_completion(&ar->vdev_delete_done);
-@@ -1487,7 +1522,8 @@ static int ath10k_vdev_start_restart(str
+@@ -1488,7 +1523,8 @@ static int ath10k_vdev_start_restart(str
  	arg.channel.min_power = 0;
  	arg.channel.max_power = chandef->chan->max_power * 2;
  	arg.channel.max_reg_power = chandef->chan->max_reg_power * 2;
@@ -89,7 +89,7 @@ Forwarded: no
  
  	if (arvif->vdev_type == WMI_VDEV_TYPE_AP) {
  		arg.ssid = arvif->u.ap.ssid;
-@@ -3168,7 +3204,8 @@ static int ath10k_update_channel_list(st
+@@ -3169,7 +3205,8 @@ static int ath10k_update_channel_list(st
  			ch->min_power = 0;
  			ch->max_power = channel->max_power * 2;
  			ch->max_reg_power = channel->max_reg_power * 2;
diff --git a/package/kernel/mac80211/patches/brcm/101-v5.5-0001-brcmfmac-don-t-WARN-when-there-are-no-requests.patch b/package/kernel/mac80211/patches/brcm/101-v5.5-0001-brcmfmac-don-t-WARN-when-there-are-no-requests.patch
deleted file mode 100644
index a1311e0a49a7..000000000000
--- a/package/kernel/mac80211/patches/brcm/101-v5.5-0001-brcmfmac-don-t-WARN-when-there-are-no-requests.patch
+++ /dev/null
@@ -1,28 +0,0 @@
-From 1524cbf3621576c639405e7aabeac415f9617c8d Mon Sep 17 00:00:00 2001
-From: Adrian Ratiu <adrian.ratiu@collabora.com>
-Date: Wed, 25 Sep 2019 16:44:57 +0300
-Subject: [PATCH] brcmfmac: don't WARN when there are no requests
-
-When n_reqs == 0 there is nothing to do so it doesn't make sense to
-search for requests and issue a warning because none is found.
-
-Signed-off-by: Martyn Welch <martyn.welch@collabora.com>
-Signed-off-by: Adrian Ratiu <adrian.ratiu@collabora.com>
-Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
----
- drivers/net/wireless/broadcom/brcm80211/brcmfmac/pno.c | 4 ++++
- 1 file changed, 4 insertions(+)
-
---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pno.c
-+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pno.c
-@@ -57,6 +57,10 @@ static int brcmf_pno_remove_request(stru
- 
- 	mutex_lock(&pi->req_lock);
- 
-+	/* Nothing to do if we have no requests */
-+	if (pi->n_reqs == 0)
-+		goto done;
-+
- 	/* find request */
- 	for (i = 0; i < pi->n_reqs; i++) {
- 		if (pi->reqs[i]->reqid == reqid)
diff --git a/package/kernel/mac80211/patches/brcm/101-v5.5-0002-brcmfmac-fix-suspend-resume-when-power-is-cut-off.patch b/package/kernel/mac80211/patches/brcm/101-v5.5-0002-brcmfmac-fix-suspend-resume-when-power-is-cut-off.patch
deleted file mode 100644
index eafc96b9015d..000000000000
--- a/package/kernel/mac80211/patches/brcm/101-v5.5-0002-brcmfmac-fix-suspend-resume-when-power-is-cut-off.patch
+++ /dev/null
@@ -1,109 +0,0 @@
-From e0ae4bac22effbd644add326f658a3aeeb8d45ee Mon Sep 17 00:00:00 2001
-From: Adrian Ratiu <adrian.ratiu@collabora.com>
-Date: Wed, 25 Sep 2019 16:44:58 +0300
-Subject: [PATCH] brcmfmac: fix suspend/resume when power is cut off
-
-brcmfmac assumed the wifi device always remains powered on and thus
-hardcoded the MMC_PM_KEEP_POWER flag expecting the wifi device to
-remain on even during suspend/resume cycles.
-
-This is not always the case, some appliances cut power to everything
-connected via SDIO for efficiency reasons and this leads to wifi not
-being usable after coming out of suspend because the device was not
-correctly reinitialized.
-
-So we check for the keep_power capability and if it's not present then
-we remove the device and probe it again during resume to mirror what's
-happening in hardware and ensure correct reinitialization in the case
-when MMC_PM_KEEP_POWER is not supported.
-
-Suggested-by: Gustavo Padovan <gustavo.padovan@collabora.com>
-Signed-off-by: Adrian Ratiu <adrian.ratiu@collabora.com>
-Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
----
- .../broadcom/brcm80211/brcmfmac/bcmsdh.c      | 53 ++++++++++++++-----
- 1 file changed, 39 insertions(+), 14 deletions(-)
-
---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
-+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
-@@ -1108,7 +1108,8 @@ static int brcmf_ops_sdio_suspend(struct
- 	struct sdio_func *func;
- 	struct brcmf_bus *bus_if;
- 	struct brcmf_sdio_dev *sdiodev;
--	mmc_pm_flag_t sdio_flags;
-+	mmc_pm_flag_t pm_caps, sdio_flags;
-+	int ret = 0;
- 
- 	func = container_of(dev, struct sdio_func, dev);
- 	brcmf_dbg(SDIO, "Enter: F%d\n", func->num);
-@@ -1119,19 +1120,33 @@ static int brcmf_ops_sdio_suspend(struct
- 	bus_if = dev_get_drvdata(dev);
- 	sdiodev = bus_if->bus_priv.sdio;
- 
--	brcmf_sdiod_freezer_on(sdiodev);
--	brcmf_sdio_wd_timer(sdiodev->bus, 0);
-+	pm_caps = sdio_get_host_pm_caps(func);
- 
--	sdio_flags = MMC_PM_KEEP_POWER;
--	if (sdiodev->wowl_enabled) {
--		if (sdiodev->settings->bus.sdio.oob_irq_supported)
--			enable_irq_wake(sdiodev->settings->bus.sdio.oob_irq_nr);
--		else
--			sdio_flags |= MMC_PM_WAKE_SDIO_IRQ;
-+	if (pm_caps & MMC_PM_KEEP_POWER) {
-+		/* preserve card power during suspend */
-+		brcmf_sdiod_freezer_on(sdiodev);
-+		brcmf_sdio_wd_timer(sdiodev->bus, 0);
-+
-+		sdio_flags = MMC_PM_KEEP_POWER;
-+		if (sdiodev->wowl_enabled) {
-+			if (sdiodev->settings->bus.sdio.oob_irq_supported)
-+				enable_irq_wake(sdiodev->settings->bus.sdio.oob_irq_nr);
-+			else
-+				sdio_flags |= MMC_PM_WAKE_SDIO_IRQ;
-+		}
-+
-+		if (sdio_set_host_pm_flags(sdiodev->func1, sdio_flags))
-+			brcmf_err("Failed to set pm_flags %x\n", sdio_flags);
-+
-+	} else {
-+		/* power will be cut so remove device, probe again in resume */
-+		brcmf_sdiod_intr_unregister(sdiodev);
-+		ret = brcmf_sdiod_remove(sdiodev);
-+		if (ret)
-+			brcmf_err("Failed to remove device on suspend\n");
- 	}
--	if (sdio_set_host_pm_flags(sdiodev->func1, sdio_flags))
--		brcmf_err("Failed to set pm_flags %x\n", sdio_flags);
--	return 0;
-+
-+	return ret;
- }
- 
- static int brcmf_ops_sdio_resume(struct device *dev)
-@@ -1139,13 +1154,23 @@ static int brcmf_ops_sdio_resume(struct
- 	struct brcmf_bus *bus_if = dev_get_drvdata(dev);
- 	struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv.sdio;
- 	struct sdio_func *func = container_of(dev, struct sdio_func, dev);
-+	mmc_pm_flag_t pm_caps = sdio_get_host_pm_caps(func);
-+	int ret = 0;
- 
- 	brcmf_dbg(SDIO, "Enter: F%d\n", func->num);
- 	if (func->num != 2)
- 		return 0;
- 
--	brcmf_sdiod_freezer_off(sdiodev);
--	return 0;
-+	if (!(pm_caps & MMC_PM_KEEP_POWER)) {
-+		/* bus was powered off and device removed, probe again */
-+		ret = brcmf_sdiod_probe(sdiodev);
-+		if (ret)
-+			brcmf_err("Failed to probe device on resume\n");
-+	} else {
-+		brcmf_sdiod_freezer_off(sdiodev);
-+	}
-+
-+	return ret;
- }
- 
- static const struct dev_pm_ops brcmf_sdio_pm_ops = {
diff --git a/package/kernel/mac80211/patches/brcm/103-v5.5-brcmfmac-remove-set-but-not-used-variable-mpnum-nsp-.patch b/package/kernel/mac80211/patches/brcm/103-v5.5-brcmfmac-remove-set-but-not-used-variable-mpnum-nsp-.patch
deleted file mode 100644
index 25b3ceb95921..000000000000
--- a/package/kernel/mac80211/patches/brcm/103-v5.5-brcmfmac-remove-set-but-not-used-variable-mpnum-nsp-.patch
+++ /dev/null
@@ -1,58 +0,0 @@
-From 7af496b9eb0433bc4cb478c9a46f85509cdb5541 Mon Sep 17 00:00:00 2001
-From: zhengbin <zhengbin13@huawei.com>
-Date: Sat, 16 Nov 2019 15:22:47 +0800
-Subject: [PATCH] brcmfmac: remove set but not used variable
- 'mpnum','nsp','nmp'
-
-Fixes gcc '-Wunused-but-set-variable' warning:
-
-drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c: In function brcmf_chip_dmp_get_regaddr:
-drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c:790:5: warning: variable mpnum set but not used [-Wunused-but-set-variable]
-drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c: In function brcmf_chip_dmp_erom_scan:
-drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c:866:10: warning: variable nsp set but not used [-Wunused-but-set-variable]
-drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c: In function brcmf_chip_dmp_erom_scan:
-drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c:866:5: warning: variable nmp set but not used [-Wunused-but-set-variable]
-
-Reported-by: Hulk Robot <hulkci@huawei.com>
-Signed-off-by: zhengbin <zhengbin13@huawei.com>
-Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
----
- drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c | 6 +-----
- 1 file changed, 1 insertion(+), 5 deletions(-)
-
---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c
-+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c
-@@ -778,7 +778,6 @@ static int brcmf_chip_dmp_get_regaddr(st
- {
- 	u8 desc;
- 	u32 val, szdesc;
--	u8 mpnum = 0;
- 	u8 stype, sztype, wraptype;
- 
- 	*regbase = 0;
-@@ -786,7 +785,6 @@ static int brcmf_chip_dmp_get_regaddr(st
- 
- 	val = brcmf_chip_dmp_get_desc(ci, eromaddr, &desc);
- 	if (desc == DMP_DESC_MASTER_PORT) {
--		mpnum = (val & DMP_MASTER_PORT_NUM) >> DMP_MASTER_PORT_NUM_S;
- 		wraptype = DMP_SLAVE_TYPE_MWRAP;
- 	} else if (desc == DMP_DESC_ADDRESS) {
- 		/* revert erom address */
-@@ -854,7 +852,7 @@ int brcmf_chip_dmp_erom_scan(struct brcm
- 	u8 desc_type = 0;
- 	u32 val;
- 	u16 id;
--	u8 nmp, nsp, nmw, nsw, rev;
-+	u8 nmw, nsw, rev;
- 	u32 base, wrap;
- 	int err;
- 
-@@ -880,8 +878,6 @@ int brcmf_chip_dmp_erom_scan(struct brcm
- 			return -EFAULT;
- 
- 		/* only look at cores with master port(s) */
--		nmp = (val & DMP_COMP_NUM_MPORT) >> DMP_COMP_NUM_MPORT_S;
--		nsp = (val & DMP_COMP_NUM_SPORT) >> DMP_COMP_NUM_SPORT_S;
- 		nmw = (val & DMP_COMP_NUM_MWRAP) >> DMP_COMP_NUM_MWRAP_S;
- 		nsw = (val & DMP_COMP_NUM_SWRAP) >> DMP_COMP_NUM_SWRAP_S;
- 		rev = (val & DMP_COMP_REVISION) >> DMP_COMP_REVISION_S;
diff --git a/package/kernel/mac80211/patches/brcm/114-v5.6-0004-brcmfmac-make-errors-when-setting-roaming-parameters.patch b/package/kernel/mac80211/patches/brcm/114-v5.6-0004-brcmfmac-make-errors-when-setting-roaming-parameters.patch
index cd7ccb0439c8..76138fbc684d 100644
--- a/package/kernel/mac80211/patches/brcm/114-v5.6-0004-brcmfmac-make-errors-when-setting-roaming-parameters.patch
+++ b/package/kernel/mac80211/patches/brcm/114-v5.6-0004-brcmfmac-make-errors-when-setting-roaming-parameters.patch
@@ -16,7 +16,7 @@ Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
 
 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
 +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
-@@ -5944,19 +5944,17 @@ static s32 brcmf_dongle_roam(struct brcm
+@@ -6012,19 +6012,17 @@ static s32 brcmf_dongle_roam(struct brcm
  	roamtrigger[1] = cpu_to_le32(BRCM_BAND_ALL);
  	err = brcmf_fil_cmd_data_set(ifp, BRCMF_C_SET_ROAM_TRIGGER,
  				     (void *)roamtrigger, sizeof(roamtrigger));
diff --git a/package/kernel/mac80211/patches/brcm/114-v5.6-0006-brcmfmac-add-RSDB-condition-when-setting-interface-c.patch b/package/kernel/mac80211/patches/brcm/114-v5.6-0006-brcmfmac-add-RSDB-condition-when-setting-interface-c.patch
index d00c59c07c32..09059defe57c 100644
--- a/package/kernel/mac80211/patches/brcm/114-v5.6-0006-brcmfmac-add-RSDB-condition-when-setting-interface-c.patch
+++ b/package/kernel/mac80211/patches/brcm/114-v5.6-0006-brcmfmac-add-RSDB-condition-when-setting-interface-c.patch
@@ -20,7 +20,7 @@ Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
 
 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
 +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
-@@ -6452,6 +6452,9 @@ brcmf_txrx_stypes[NUM_NL80211_IFTYPES] =
+@@ -6520,6 +6520,9 @@ brcmf_txrx_stypes[NUM_NL80211_IFTYPES] =
   *	#STA <= 1, #AP <= 1, channels = 1, 2 total
   *	#AP <= 4, matching BI, channels = 1, 4 total
   *
@@ -30,7 +30,7 @@ Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
   * p2p, no mchan, and mbss:
   *
   *	#STA <= 1, #P2P-DEV <= 1, #{P2P-CL, P2P-GO} <= 1, channels = 1, 3 total
-@@ -6463,6 +6466,10 @@ brcmf_txrx_stypes[NUM_NL80211_IFTYPES] =
+@@ -6531,6 +6534,10 @@ brcmf_txrx_stypes[NUM_NL80211_IFTYPES] =
   *	#STA <= 1, #P2P-DEV <= 1, #{P2P-CL, P2P-GO} <= 1, channels = 2, 3 total
   *	#STA <= 1, #P2P-DEV <= 1, #AP <= 1, #P2P-CL <= 1, channels = 1, 4 total
   *	#AP <= 4, matching BI, channels = 1, 4 total
@@ -41,7 +41,7 @@ Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
   */
  static int brcmf_setup_ifmodes(struct wiphy *wiphy, struct brcmf_if *ifp)
  {
-@@ -6470,13 +6477,14 @@ static int brcmf_setup_ifmodes(struct wi
+@@ -6538,13 +6545,14 @@ static int brcmf_setup_ifmodes(struct wi
  	struct ieee80211_iface_limit *c0_limits = NULL;
  	struct ieee80211_iface_limit *p2p_limits = NULL;
  	struct ieee80211_iface_limit *mbss_limits = NULL;
@@ -58,7 +58,7 @@ Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
  	combo = kcalloc(n_combos, sizeof(*combo), GFP_KERNEL);
  	if (!combo)
  		goto err;
-@@ -6487,16 +6495,36 @@ static int brcmf_setup_ifmodes(struct wi
+@@ -6555,16 +6563,36 @@ static int brcmf_setup_ifmodes(struct wi
  
  	c = 0;
  	i = 0;
@@ -99,7 +99,7 @@ Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
  		wiphy->interface_modes |= BIT(NL80211_IFTYPE_P2P_CLIENT) |
  					  BIT(NL80211_IFTYPE_P2P_GO) |
  					  BIT(NL80211_IFTYPE_P2P_DEVICE);
-@@ -6505,16 +6533,26 @@ static int brcmf_setup_ifmodes(struct wi
+@@ -6573,16 +6601,26 @@ static int brcmf_setup_ifmodes(struct wi
  		c0_limits[i].max = 1;
  		c0_limits[i++].types = BIT(NL80211_IFTYPE_P2P_CLIENT) |
  				       BIT(NL80211_IFTYPE_P2P_GO);
diff --git a/package/kernel/mac80211/patches/brcm/114-v5.6-0007-brcmfmac-not-set-mbss-in-vif-if-firmware-does-not-su.patch b/package/kernel/mac80211/patches/brcm/114-v5.6-0007-brcmfmac-not-set-mbss-in-vif-if-firmware-does-not-su.patch
index 9c211a68d061..1870088bf64e 100644
--- a/package/kernel/mac80211/patches/brcm/114-v5.6-0007-brcmfmac-not-set-mbss-in-vif-if-firmware-does-not-su.patch
+++ b/package/kernel/mac80211/patches/brcm/114-v5.6-0007-brcmfmac-not-set-mbss-in-vif-if-firmware-does-not-su.patch
@@ -18,7 +18,7 @@ Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
 
 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
 +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
-@@ -5301,6 +5301,7 @@ struct brcmf_cfg80211_vif *brcmf_alloc_v
+@@ -5363,6 +5363,7 @@ struct brcmf_cfg80211_vif *brcmf_alloc_v
  	struct brcmf_cfg80211_vif *vif_walk;
  	struct brcmf_cfg80211_vif *vif;
  	bool mbss;
@@ -26,7 +26,7 @@ Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
  
  	brcmf_dbg(TRACE, "allocating virtual interface (size=%zu)\n",
  		  sizeof(*vif));
-@@ -5313,7 +5314,8 @@ struct brcmf_cfg80211_vif *brcmf_alloc_v
+@@ -5375,7 +5376,8 @@ struct brcmf_cfg80211_vif *brcmf_alloc_v
  
  	brcmf_init_prof(&vif->profile);
  
diff --git a/package/kernel/mac80211/patches/brcm/119-v5.6-0001-brcmfmac-simplify-building-interface-combinations.patch b/package/kernel/mac80211/patches/brcm/119-v5.6-0001-brcmfmac-simplify-building-interface-combinations.patch
index d52a7a1cc082..73fc17aa5a70 100644
--- a/package/kernel/mac80211/patches/brcm/119-v5.6-0001-brcmfmac-simplify-building-interface-combinations.patch
+++ b/package/kernel/mac80211/patches/brcm/119-v5.6-0001-brcmfmac-simplify-building-interface-combinations.patch
@@ -18,7 +18,7 @@ Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
 
 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
 +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
-@@ -6479,12 +6479,13 @@ static int brcmf_setup_ifmodes(struct wi
+@@ -6547,12 +6547,13 @@ static int brcmf_setup_ifmodes(struct wi
  	struct ieee80211_iface_limit *c0_limits = NULL;
  	struct ieee80211_iface_limit *p2p_limits = NULL;
  	struct ieee80211_iface_limit *mbss_limits = NULL;
@@ -33,7 +33,7 @@ Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
  
  	n_combos = 1 + !!(p2p && !rsdb) + !!mbss;
  	combo = kcalloc(n_combos, sizeof(*combo), GFP_KERNEL);
-@@ -6494,6 +6495,10 @@ static int brcmf_setup_ifmodes(struct wi
+@@ -6562,6 +6563,10 @@ static int brcmf_setup_ifmodes(struct wi
  	wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) |
  				 BIT(NL80211_IFTYPE_ADHOC) |
  				 BIT(NL80211_IFTYPE_AP);
@@ -44,7 +44,7 @@ Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
  
  	c = 0;
  	i = 0;
-@@ -6505,48 +6510,28 @@ static int brcmf_setup_ifmodes(struct wi
+@@ -6573,48 +6578,28 @@ static int brcmf_setup_ifmodes(struct wi
  		c0_limits = kcalloc(2, sizeof(*c0_limits), GFP_KERNEL);
  	if (!c0_limits)
  		goto err;
diff --git a/package/kernel/mac80211/patches/brcm/119-v5.6-0002-brcmfmac-add-initial-support-for-monitor-mode.patch b/package/kernel/mac80211/patches/brcm/119-v5.6-0002-brcmfmac-add-initial-support-for-monitor-mode.patch
index 08fa1544eca8..0682c0b0ea7e 100644
--- a/package/kernel/mac80211/patches/brcm/119-v5.6-0002-brcmfmac-add-initial-support-for-monitor-mode.patch
+++ b/package/kernel/mac80211/patches/brcm/119-v5.6-0002-brcmfmac-add-initial-support-for-monitor-mode.patch
@@ -139,7 +139,7 @@ Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
  	case NL80211_IFTYPE_AP:
  		return brcmf_cfg80211_del_ap_iface(wiphy, wdev);
  	case NL80211_IFTYPE_P2P_CLIENT:
-@@ -6479,9 +6558,10 @@ static int brcmf_setup_ifmodes(struct wi
+@@ -6547,9 +6626,10 @@ static int brcmf_setup_ifmodes(struct wi
  	struct ieee80211_iface_limit *c0_limits = NULL;
  	struct ieee80211_iface_limit *p2p_limits = NULL;
  	struct ieee80211_iface_limit *mbss_limits = NULL;
@@ -152,7 +152,7 @@ Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
  	mbss = brcmf_feat_is_enabled(ifp, BRCMF_FEAT_MBSS);
  	p2p = brcmf_feat_is_enabled(ifp, BRCMF_FEAT_P2P);
  	rsdb = brcmf_feat_is_enabled(ifp, BRCMF_FEAT_RSDB);
-@@ -6495,6 +6575,8 @@ static int brcmf_setup_ifmodes(struct wi
+@@ -6563,6 +6643,8 @@ static int brcmf_setup_ifmodes(struct wi
  	wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) |
  				 BIT(NL80211_IFTYPE_ADHOC) |
  				 BIT(NL80211_IFTYPE_AP);
@@ -161,7 +161,7 @@ Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
  	if (p2p)
  		wiphy->interface_modes |= BIT(NL80211_IFTYPE_P2P_CLIENT) |
  					  BIT(NL80211_IFTYPE_P2P_GO) |
-@@ -6502,18 +6584,18 @@ static int brcmf_setup_ifmodes(struct wi
+@@ -6570,18 +6652,18 @@ static int brcmf_setup_ifmodes(struct wi
  
  	c = 0;
  	i = 0;
@@ -186,7 +186,7 @@ Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
  	if (p2p) {
  		c0_limits[i].max = 1;
  		c0_limits[i++].types = BIT(NL80211_IFTYPE_P2P_DEVICE);
-@@ -6562,14 +6644,20 @@ static int brcmf_setup_ifmodes(struct wi
+@@ -6630,14 +6712,20 @@ static int brcmf_setup_ifmodes(struct wi
  	if (mbss) {
  		c++;
  		i = 0;
@@ -312,8 +312,8 @@ Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
  	{ BRCMF_FEAT_MONITOR, "monitor" },
 +	{ BRCMF_FEAT_MONITOR_FLAG, "rtap" },
  	{ BRCMF_FEAT_MONITOR_FMT_RADIOTAP, "rtap" },
- 	{ BRCMF_FEAT_DOT11H, "802.11h" }
- };
+ 	{ BRCMF_FEAT_DOT11H, "802.11h" },
+ 	{ BRCMF_FEAT_SAE, "sae" },
 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.h
 +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.h
 @@ -23,6 +23,7 @@
@@ -324,14 +324,14 @@ Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
   * MONITOR_FMT_RADIOTAP: firmware provides monitor packets with radiotap header
   * MONITOR_FMT_HW_RX_HDR: firmware provides monitor packets with hw/ucode header
   * DOT11H: firmware supports 802.11h
-@@ -43,6 +44,7 @@
+@@ -44,6 +45,7 @@
  	BRCMF_FEAT_DEF(GSCAN) \
  	BRCMF_FEAT_DEF(FWSUP) \
  	BRCMF_FEAT_DEF(MONITOR) \
 +	BRCMF_FEAT_DEF(MONITOR_FLAG) \
  	BRCMF_FEAT_DEF(MONITOR_FMT_RADIOTAP) \
  	BRCMF_FEAT_DEF(MONITOR_FMT_HW_RX_HDR) \
- 	BRCMF_FEAT_DEF(DOT11H)
+ 	BRCMF_FEAT_DEF(DOT11H) \
 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil.h
 +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil.h
 @@ -49,6 +49,8 @@
diff --git a/package/kernel/mac80211/patches/brcm/862-brcmfmac-Disable-power-management.patch b/package/kernel/mac80211/patches/brcm/862-brcmfmac-Disable-power-management.patch
index 988ece1f5f18..905fd4b56e84 100644
--- a/package/kernel/mac80211/patches/brcm/862-brcmfmac-Disable-power-management.patch
+++ b/package/kernel/mac80211/patches/brcm/862-brcmfmac-Disable-power-management.patch
@@ -14,7 +14,7 @@ Signed-off-by: Phil Elwell <phil@raspberrypi.org>
 
 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
 +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
-@@ -2874,6 +2874,10 @@ brcmf_cfg80211_set_power_mgmt(struct wip
+@@ -2936,6 +2936,10 @@ brcmf_cfg80211_set_power_mgmt(struct wip
  	 * preference in cfg struct to apply this to
  	 * FW later while initializing the dongle
  	 */
diff --git a/package/kernel/mac80211/patches/brcm/998-survey.patch b/package/kernel/mac80211/patches/brcm/998-survey.patch
index 3c52cec0b915..b98cb0632c46 100644
--- a/package/kernel/mac80211/patches/brcm/998-survey.patch
+++ b/package/kernel/mac80211/patches/brcm/998-survey.patch
@@ -1,6 +1,6 @@
 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
 +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
-@@ -2826,6 +2826,63 @@ done:
+@@ -2888,6 +2888,63 @@ done:
  }
  
  static int
@@ -64,7 +64,7 @@
  brcmf_cfg80211_dump_station(struct wiphy *wiphy, struct net_device *ndev,
  			    int idx, u8 *mac, struct station_info *sinfo)
  {
-@@ -2915,6 +2972,7 @@ static s32 brcmf_inform_single_bss(struc
+@@ -2977,6 +3034,7 @@ static s32 brcmf_inform_single_bss(struc
  	struct brcmu_chan ch;
  	u16 channel;
  	u32 freq;
@@ -72,7 +72,7 @@
  	u16 notify_capability;
  	u16 notify_interval;
  	u8 *notify_ie;
-@@ -2939,6 +2997,17 @@ static s32 brcmf_inform_single_bss(struc
+@@ -3001,6 +3059,17 @@ static s32 brcmf_inform_single_bss(struc
  		band = NL80211_BAND_5GHZ;
  
  	freq = ieee80211_channel_to_frequency(channel, band);
@@ -90,7 +90,7 @@
  	bss_data.chan = ieee80211_get_channel(wiphy, freq);
  	bss_data.scan_width = NL80211_BSS_CHAN_WIDTH_20;
  	bss_data.boottime_ns = ktime_to_ns(ktime_get_boottime());
-@@ -5356,6 +5425,7 @@ static struct cfg80211_ops brcmf_cfg8021
+@@ -5418,6 +5487,7 @@ static struct cfg80211_ops brcmf_cfg8021
  	.leave_ibss = brcmf_cfg80211_leave_ibss,
  	.get_station = brcmf_cfg80211_get_station,
  	.dump_station = brcmf_cfg80211_dump_station,
diff --git a/package/kernel/mac80211/patches/build/015-ipw200-mtu.patch b/package/kernel/mac80211/patches/build/015-ipw200-mtu.patch
index 0e51b0ffbc06..59d3b62f9dcf 100644
--- a/package/kernel/mac80211/patches/build/015-ipw200-mtu.patch
+++ b/package/kernel/mac80211/patches/build/015-ipw200-mtu.patch
@@ -1,6 +1,6 @@
 --- a/drivers/net/wireless/intel/ipw2x00/ipw2200.c
 +++ b/drivers/net/wireless/intel/ipw2x00/ipw2200.c
-@@ -11482,6 +11482,15 @@ static const struct attribute_group ipw_
+@@ -11479,6 +11479,15 @@ static const struct attribute_group ipw_
  	.attrs = ipw_sysfs_entries,
  };
  
@@ -16,7 +16,7 @@
  #ifdef CPTCFG_IPW2200_PROMISCUOUS
  static int ipw_prom_open(struct net_device *dev)
  {
-@@ -11530,15 +11539,6 @@ static netdev_tx_t ipw_prom_hard_start_x
+@@ -11527,15 +11536,6 @@ static netdev_tx_t ipw_prom_hard_start_x
  	return NETDEV_TX_OK;
  }
  
diff --git a/package/kernel/mac80211/patches/build/050-lib80211_option.patch b/package/kernel/mac80211/patches/build/050-lib80211_option.patch
index 1578286c2bd6..c6174449c662 100644
--- a/package/kernel/mac80211/patches/build/050-lib80211_option.patch
+++ b/package/kernel/mac80211/patches/build/050-lib80211_option.patch
@@ -1,6 +1,6 @@
 --- a/net/wireless/Kconfig
 +++ b/net/wireless/Kconfig
-@@ -186,7 +186,7 @@ config CFG80211_WEXT_EXPORT
+@@ -187,7 +187,7 @@ config CFG80211_WEXT_EXPORT
  endif # CFG80211
  
  config LIB80211
@@ -9,7 +9,7 @@
  	depends on m
  	default n
  	help
-@@ -196,18 +196,18 @@ config LIB80211
+@@ -197,18 +197,18 @@ config LIB80211
  	  Drivers should select this themselves if needed.
  
  config LIB80211_CRYPT_WEP
diff --git a/package/kernel/mac80211/patches/subsys/140-tweak-TSQ-setting.patch b/package/kernel/mac80211/patches/subsys/140-tweak-TSQ-setting.patch
index fa12232f1bac..3b89013d3c3c 100644
--- a/package/kernel/mac80211/patches/subsys/140-tweak-TSQ-setting.patch
+++ b/package/kernel/mac80211/patches/subsys/140-tweak-TSQ-setting.patch
@@ -1,6 +1,6 @@
 --- a/net/mac80211/tx.c
 +++ b/net/mac80211/tx.c
-@@ -4048,6 +4048,12 @@ out:
+@@ -4116,6 +4116,12 @@ out:
  netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb,
  				       struct net_device *dev)
  {
diff --git a/package/kernel/mac80211/patches/subsys/150-disable_addr_notifier.patch b/package/kernel/mac80211/patches/subsys/150-disable_addr_notifier.patch
index 3c5d1d63a860..428c1892d5ab 100644
--- a/package/kernel/mac80211/patches/subsys/150-disable_addr_notifier.patch
+++ b/package/kernel/mac80211/patches/subsys/150-disable_addr_notifier.patch
@@ -18,7 +18,7 @@
  static int ieee80211_ifa6_changed(struct notifier_block *nb,
  				  unsigned long data, void *arg)
  {
-@@ -1267,14 +1267,14 @@ int ieee80211_register_hw(struct ieee802
+@@ -1272,14 +1272,14 @@ int ieee80211_register_hw(struct ieee802
  
  	rtnl_unlock();
  
@@ -35,7 +35,7 @@
  	local->ifa6_notifier.notifier_call = ieee80211_ifa6_changed;
  	result = register_inet6addr_notifier(&local->ifa6_notifier);
  	if (result)
-@@ -1283,13 +1283,13 @@ int ieee80211_register_hw(struct ieee802
+@@ -1288,13 +1288,13 @@ int ieee80211_register_hw(struct ieee802
  
  	return 0;
  
@@ -52,7 +52,7 @@
   fail_ifa:
  #endif
  	wiphy_unregister(local->hw.wiphy);
-@@ -1317,10 +1317,10 @@ void ieee80211_unregister_hw(struct ieee
+@@ -1322,10 +1322,10 @@ void ieee80211_unregister_hw(struct ieee
  	tasklet_kill(&local->tx_pending_tasklet);
  	tasklet_kill(&local->tasklet);
  
diff --git a/package/kernel/mac80211/patches/subsys/250-mac80211-populate-debugfs-only-after-cfg80211-init.patch b/package/kernel/mac80211/patches/subsys/250-mac80211-populate-debugfs-only-after-cfg80211-init.patch
new file mode 100644
index 000000000000..efe216c53092
--- /dev/null
+++ b/package/kernel/mac80211/patches/subsys/250-mac80211-populate-debugfs-only-after-cfg80211-init.patch
@@ -0,0 +1,248 @@
+From 6cb5f3ea4654faf8c28b901266e960b1a4787b26 Mon Sep 17 00:00:00 2001
+From: Johannes Berg <johannes.berg@intel.com>
+Date: Thu, 23 Apr 2020 11:13:49 +0200
+Subject: [PATCH] mac80211: populate debugfs only after cfg80211 init
+
+When fixing the initialization race, we neglected to account for
+the fact that debugfs is initialized in wiphy_register(), and
+some debugfs things went missing (or rather were rerooted to the
+global debugfs root).
+
+Fix this by adding debugfs entries only after wiphy_register().
+This requires some changes in the rate control code since it
+currently adds debugfs at alloc time, which can no longer be
+done after the reordering.
+
+Reported-by: Jouni Malinen <j@w1.fi>
+Reported-by: kernel test robot <rong.a.chen@intel.com>
+Reported-by: Hauke Mehrtens <hauke@hauke-m.de>
+Reported-by: Felix Fietkau <nbd@nbd.name>
+Cc: stable@vger.kernel.org
+Fixes: 52e04b4ce5d0 ("mac80211: fix race in ieee80211_register_hw()")
+Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+Acked-by: Sumit Garg <sumit.garg@linaro.org>
+Link: https://lore.kernel.org/r/20200423111344.0e00d3346f12.Iadc76a03a55093d94391fc672e996a458702875d@changeid
+Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+---
+ drivers/net/wireless/intel/iwlegacy/3945-rs.c |  2 +-
+ drivers/net/wireless/intel/iwlegacy/4965-rs.c |  2 +-
+ drivers/net/wireless/intel/iwlwifi/dvm/rs.c   |  2 +-
+ drivers/net/wireless/intel/iwlwifi/mvm/rs.c   |  2 +-
+ drivers/net/wireless/realtek/rtlwifi/rc.c     |  2 +-
+ include/net/mac80211.h                        |  4 +++-
+ net/mac80211/main.c                           |  5 ++--
+ net/mac80211/rate.c                           | 15 ++++--------
+ net/mac80211/rate.h                           | 23 +++++++++++++++++++
+ net/mac80211/rc80211_minstrel_ht.c            | 19 ++++++++++-----
+ 10 files changed, 51 insertions(+), 25 deletions(-)
+
+--- a/drivers/net/wireless/intel/iwlegacy/3945-rs.c
++++ b/drivers/net/wireless/intel/iwlegacy/3945-rs.c
+@@ -374,7 +374,7 @@ out:
+ }
+ 
+ static void *
+-il3945_rs_alloc(struct ieee80211_hw *hw, struct dentry *debugfsdir)
++il3945_rs_alloc(struct ieee80211_hw *hw)
+ {
+ 	return hw->priv;
+ }
+--- a/drivers/net/wireless/intel/iwlegacy/4965-rs.c
++++ b/drivers/net/wireless/intel/iwlegacy/4965-rs.c
+@@ -2474,7 +2474,7 @@ il4965_rs_fill_link_cmd(struct il_priv *
+ }
+ 
+ static void *
+-il4965_rs_alloc(struct ieee80211_hw *hw, struct dentry *debugfsdir)
++il4965_rs_alloc(struct ieee80211_hw *hw)
+ {
+ 	return hw->priv;
+ }
+--- a/drivers/net/wireless/intel/iwlwifi/dvm/rs.c
++++ b/drivers/net/wireless/intel/iwlwifi/dvm/rs.c
+@@ -3019,7 +3019,7 @@ static void rs_fill_link_cmd(struct iwl_
+ 			cpu_to_le16(priv->lib->bt_params->agg_time_limit);
+ }
+ 
+-static void *rs_alloc(struct ieee80211_hw *hw, struct dentry *debugfsdir)
++static void *rs_alloc(struct ieee80211_hw *hw)
+ {
+ 	return hw->priv;
+ }
+--- a/drivers/net/wireless/intel/iwlwifi/mvm/rs.c
++++ b/drivers/net/wireless/intel/iwlwifi/mvm/rs.c
+@@ -3665,7 +3665,7 @@ static void rs_fill_lq_cmd(struct iwl_mv
+ 			cpu_to_le16(iwl_mvm_coex_agg_time_limit(mvm, sta));
+ }
+ 
+-static void *rs_alloc(struct ieee80211_hw *hw, struct dentry *debugfsdir)
++static void *rs_alloc(struct ieee80211_hw *hw)
+ {
+ 	return hw->priv;
+ }
+--- a/drivers/net/wireless/realtek/rtlwifi/rc.c
++++ b/drivers/net/wireless/realtek/rtlwifi/rc.c
+@@ -261,7 +261,7 @@ static void rtl_rate_update(void *ppriv,
+ {
+ }
+ 
+-static void *rtl_rate_alloc(struct ieee80211_hw *hw, struct dentry *debugfsdir)
++static void *rtl_rate_alloc(struct ieee80211_hw *hw)
+ {
+ 	struct rtl_priv *rtlpriv = rtl_priv(hw);
+ 	return rtlpriv;
+--- a/include/net/mac80211.h
++++ b/include/net/mac80211.h
+@@ -5969,7 +5969,9 @@ enum rate_control_capabilities {
+ struct rate_control_ops {
+ 	unsigned long capa;
+ 	const char *name;
+-	void *(*alloc)(struct ieee80211_hw *hw, struct dentry *debugfsdir);
++	void *(*alloc)(struct ieee80211_hw *hw);
++	void (*add_debugfs)(struct ieee80211_hw *hw, void *priv,
++			    struct dentry *debugfsdir);
+ 	void (*free)(void *priv);
+ 
+ 	void *(*alloc_sta)(void *priv, struct ieee80211_sta *sta, gfp_t gfp);
+--- a/net/mac80211/main.c
++++ b/net/mac80211/main.c
+@@ -1163,8 +1163,6 @@ int ieee80211_register_hw(struct ieee802
+ 	local->tx_headroom = max_t(unsigned int , local->hw.extra_tx_headroom,
+ 				   IEEE80211_TX_STATUS_HEADROOM);
+ 
+-	debugfs_hw_add(local);
+-
+ 	/*
+ 	 * if the driver doesn't specify a max listen interval we
+ 	 * use 5 which should be a safe default
+@@ -1256,6 +1254,9 @@ int ieee80211_register_hw(struct ieee802
+ 	if (result < 0)
+ 		goto fail_wiphy_register;
+ 
++	debugfs_hw_add(local);
++	rate_control_add_debugfs(local);
++
+ 	rtnl_lock();
+ 
+ 	/* add one default STA interface if supported */
+--- a/net/mac80211/rate.c
++++ b/net/mac80211/rate.c
+@@ -214,17 +214,16 @@ static ssize_t rcname_read(struct file *
+ 				       ref->ops->name, len);
+ }
+ 
+-static const struct file_operations rcname_ops = {
++const struct file_operations rcname_ops = {
+ 	.read = rcname_read,
+ 	.open = simple_open,
+ 	.llseek = default_llseek,
+ };
+ #endif
+ 
+-static struct rate_control_ref *rate_control_alloc(const char *name,
+-					    struct ieee80211_local *local)
++static struct rate_control_ref *
++rate_control_alloc(const char *name, struct ieee80211_local *local)
+ {
+-	struct dentry *debugfsdir = NULL;
+ 	struct rate_control_ref *ref;
+ 
+ 	ref = kmalloc(sizeof(struct rate_control_ref), GFP_KERNEL);
+@@ -234,13 +233,7 @@ static struct rate_control_ref *rate_con
+ 	if (!ref->ops)
+ 		goto free;
+ 
+-#ifdef CPTCFG_MAC80211_DEBUGFS
+-	debugfsdir = debugfs_create_dir("rc", local->hw.wiphy->debugfsdir);
+-	local->debugfs.rcdir = debugfsdir;
+-	debugfs_create_file("name", 0400, debugfsdir, ref, &rcname_ops);
+-#endif
+-
+-	ref->priv = ref->ops->alloc(&local->hw, debugfsdir);
++	ref->priv = ref->ops->alloc(&local->hw);
+ 	if (!ref->priv)
+ 		goto free;
+ 	return ref;
+--- a/net/mac80211/rate.h
++++ b/net/mac80211/rate.h
+@@ -60,6 +60,29 @@ static inline void rate_control_add_sta_
+ #endif
+ }
+ 
++extern const struct file_operations rcname_ops;
++
++static inline void rate_control_add_debugfs(struct ieee80211_local *local)
++{
++#ifdef CPTCFG_MAC80211_DEBUGFS
++	struct dentry *debugfsdir;
++
++	if (!local->rate_ctrl)
++		return;
++
++	if (!local->rate_ctrl->ops->add_debugfs)
++		return;
++
++	debugfsdir = debugfs_create_dir("rc", local->hw.wiphy->debugfsdir);
++	local->debugfs.rcdir = debugfsdir;
++	debugfs_create_file("name", 0400, debugfsdir,
++			    local->rate_ctrl, &rcname_ops);
++
++	local->rate_ctrl->ops->add_debugfs(&local->hw, local->rate_ctrl->priv,
++					   debugfsdir);
++#endif
++}
++
+ void ieee80211_check_rate_mask(struct ieee80211_sub_if_data *sdata);
+ 
+ /* Get a reference to the rate control algorithm. If `name' is NULL, get the
+--- a/net/mac80211/rc80211_minstrel_ht.c
++++ b/net/mac80211/rc80211_minstrel_ht.c
+@@ -1635,7 +1635,7 @@ minstrel_ht_init_cck_rates(struct minstr
+ }
+ 
+ static void *
+-minstrel_ht_alloc(struct ieee80211_hw *hw, struct dentry *debugfsdir)
++minstrel_ht_alloc(struct ieee80211_hw *hw)
+ {
+ 	struct minstrel_priv *mp;
+ 
+@@ -1673,7 +1673,17 @@ minstrel_ht_alloc(struct ieee80211_hw *h
+ 	mp->update_interval = HZ / 10;
+ 	mp->new_avg = true;
+ 
++	minstrel_ht_init_cck_rates(mp);
++
++	return mp;
++}
++
+ #ifdef CPTCFG_MAC80211_DEBUGFS
++static void minstrel_ht_add_debugfs(struct ieee80211_hw *hw, void *priv,
++				    struct dentry *debugfsdir)
++{
++	struct minstrel_priv *mp = priv;
++
+ 	mp->fixed_rate_idx = (u32) -1;
+ 	debugfs_create_u32("fixed_rate_idx", S_IRUGO | S_IWUGO, debugfsdir,
+ 			   &mp->fixed_rate_idx);
+@@ -1681,12 +1691,8 @@ minstrel_ht_alloc(struct ieee80211_hw *h
+ 			   &mp->sample_switch);
+ 	debugfs_create_bool("new_avg", S_IRUGO | S_IWUSR, debugfsdir,
+ 			   &mp->new_avg);
+-#endif
+-
+-	minstrel_ht_init_cck_rates(mp);
+-
+-	return mp;
+ }
++#endif
+ 
+ static void
+ minstrel_ht_free(void *priv)
+@@ -1725,6 +1731,7 @@ static const struct rate_control_ops mac
+ 	.alloc = minstrel_ht_alloc,
+ 	.free = minstrel_ht_free,
+ #ifdef CPTCFG_MAC80211_DEBUGFS
++	.add_debugfs = minstrel_ht_add_debugfs,
+ 	.add_sta_debugfs = minstrel_ht_add_sta_debugfs,
+ #endif
+ 	.get_expected_throughput = minstrel_ht_get_expected_throughput,
diff --git a/package/kernel/mac80211/patches/subsys/300-mac80211-optimize-skb-resizing.patch b/package/kernel/mac80211/patches/subsys/300-mac80211-optimize-skb-resizing.patch
index dcdb94565d6d..8c019530d173 100644
--- a/package/kernel/mac80211/patches/subsys/300-mac80211-optimize-skb-resizing.patch
+++ b/package/kernel/mac80211/patches/subsys/300-mac80211-optimize-skb-resizing.patch
@@ -24,7 +24,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
 
 --- a/net/mac80211/ieee80211_i.h
 +++ b/net/mac80211/ieee80211_i.h
-@@ -1782,6 +1782,9 @@ int ieee80211_tx_control_port(struct wip
+@@ -1786,6 +1786,9 @@ int ieee80211_tx_control_port(struct wip
  			      const u8 *dest, __be16 proto, bool unencrypted);
  int ieee80211_probe_mesh_link(struct wiphy *wiphy, struct net_device *dev,
  			      const u8 *buf, size_t len);
@@ -36,7 +36,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
  void ieee80211_apply_htcap_overrides(struct ieee80211_sub_if_data *sdata,
 --- a/net/mac80211/status.c
 +++ b/net/mac80211/status.c
-@@ -815,6 +815,11 @@ void ieee80211_tx_monitor(struct ieee802
+@@ -829,6 +829,11 @@ void ieee80211_tx_monitor(struct ieee802
  	struct net_device *prev_dev = NULL;
  	int rtap_len;
  
@@ -50,7 +50,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
  	if (WARN_ON_ONCE(skb_headroom(skb) < rtap_len)) {
 --- a/net/mac80211/tx.c
 +++ b/net/mac80211/tx.c
-@@ -1943,37 +1943,53 @@ static bool ieee80211_tx(struct ieee8021
+@@ -1936,37 +1936,53 @@ static bool ieee80211_tx(struct ieee8021
  }
  
  /* device xmit handlers */
@@ -123,7 +123,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
  		wiphy_debug(local->hw.wiphy,
  			    "failed to reallocate TX buffer\n");
  		return -ENOMEM;
-@@ -1989,18 +2005,8 @@ void ieee80211_xmit(struct ieee80211_sub
+@@ -1982,18 +1998,8 @@ void ieee80211_xmit(struct ieee80211_sub
  	struct ieee80211_local *local = sdata->local;
  	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
  	struct ieee80211_hdr *hdr;
@@ -143,7 +143,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
  		ieee80211_free_txskb(&local->hw, skb);
  		return;
  	}
-@@ -2790,29 +2796,13 @@ static struct sk_buff *ieee80211_build_h
+@@ -2795,29 +2801,13 @@ static struct sk_buff *ieee80211_build_h
  	}
  
  	skb_pull(skb, skip_header_bytes);
@@ -179,7 +179,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
  	}
  
  	if (encaps_data)
-@@ -3427,7 +3417,6 @@ static bool ieee80211_xmit_fast(struct i
+@@ -3432,7 +3422,6 @@ static bool ieee80211_xmit_fast(struct i
  	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);
@@ -187,7 +187,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
  	struct ethhdr eth;
  	struct ieee80211_tx_info *info;
  	struct ieee80211_hdr *hdr = (void *)fast_tx->hdr;
-@@ -3479,10 +3468,7 @@ static bool ieee80211_xmit_fast(struct i
+@@ -3484,10 +3473,7 @@ static bool ieee80211_xmit_fast(struct i
  	 * as the may-encrypt argument for the resize to not account for
  	 * more room than we already have in 'extra_head'
  	 */
diff --git a/package/kernel/mac80211/patches/subsys/301-mac80211-minstrel-remove-divisions-in-tx-status-path.patch b/package/kernel/mac80211/patches/subsys/301-mac80211-minstrel-remove-divisions-in-tx-status-path.patch
deleted file mode 100644
index 91fb92f1b2b7..000000000000
--- a/package/kernel/mac80211/patches/subsys/301-mac80211-minstrel-remove-divisions-in-tx-status-path.patch
+++ /dev/null
@@ -1,61 +0,0 @@
-From: Felix Fietkau <nbd@nbd.name>
-Date: Sat, 28 Sep 2019 15:44:06 +0200
-Subject: [PATCH] mac80211: minstrel: remove divisions in tx status path
-
-Use a slightly different threshold for downgrading spatial streams to
-make it easier to calculate without divisions.
-Slightly reduces CPU overhead.
-
-Signed-off-by: Felix Fietkau <nbd@nbd.name>
----
-
---- a/net/mac80211/rc80211_minstrel.c
-+++ b/net/mac80211/rc80211_minstrel.c
-@@ -289,8 +289,7 @@ minstrel_tx_status(void *priv, struct ie
- 	if (mi->sample_deferred > 0)
- 		mi->sample_deferred--;
- 
--	if (time_after(jiffies, mi->last_stats_update +
--				(mp->update_interval * HZ) / 1000))
-+	if (time_after(jiffies, mi->last_stats_update + mp->update_interval))
- 		minstrel_update_stats(mp, mi);
- }
- 
---- a/net/mac80211/rc80211_minstrel_ht.c
-+++ b/net/mac80211/rc80211_minstrel_ht.c
-@@ -970,23 +970,21 @@ minstrel_ht_tx_status(void *priv, struct
- 		 */
- 		rate = minstrel_get_ratestats(mi, mi->max_tp_rate[0]);
- 		if (rate->attempts > 30 &&
--		    MINSTREL_FRAC(rate->success, rate->attempts) <
--		    MINSTREL_FRAC(20, 100)) {
-+		    rate->success < rate->attempts / 4) {
- 			minstrel_downgrade_rate(mi, &mi->max_tp_rate[0], true);
- 			update = true;
- 		}
- 
- 		rate2 = minstrel_get_ratestats(mi, mi->max_tp_rate[1]);
- 		if (rate2->attempts > 30 &&
--		    MINSTREL_FRAC(rate2->success, rate2->attempts) <
--		    MINSTREL_FRAC(20, 100)) {
-+		    rate2->success < rate2->attempts / 4) {
- 			minstrel_downgrade_rate(mi, &mi->max_tp_rate[1], false);
- 			update = true;
- 		}
- 	}
- 
- 	if (time_after(jiffies, mi->last_stats_update +
--				(mp->update_interval / 2 * HZ) / 1000)) {
-+				mp->update_interval / 2)) {
- 		update = true;
- 		minstrel_ht_update_stats(mp, mi, true);
- 	}
-@@ -1666,7 +1664,7 @@ minstrel_ht_alloc(struct ieee80211_hw *h
- 		mp->has_mrr = true;
- 
- 	mp->hw = hw;
--	mp->update_interval = 100;
-+	mp->update_interval = HZ / 10;
- 
- 	minstrel_ht_init_cck_rates(mp);
- 
diff --git a/package/kernel/mac80211/patches/subsys/302-mac80211-minstrel_ht-replace-rate-stats-ewma-with-a-.patch b/package/kernel/mac80211/patches/subsys/302-mac80211-minstrel_ht-replace-rate-stats-ewma-with-a-.patch
deleted file mode 100644
index 78e8527a5c90..000000000000
--- a/package/kernel/mac80211/patches/subsys/302-mac80211-minstrel_ht-replace-rate-stats-ewma-with-a-.patch
+++ /dev/null
@@ -1,235 +0,0 @@
-From: Felix Fietkau <nbd@nbd.name>
-Date: Sat, 28 Sep 2019 15:46:06 +0200
-Subject: [PATCH] mac80211: minstrel_ht: replace rate stats ewma with a
- better moving average
-
-Rate success probability usually fluctuates a lot under normal conditions.
-With a simple EWMA, noise and fluctuation can be reduced by increasing the
-window length, but that comes at the cost of introducing lag on sudden
-changes.
-
-This change replaces the EWMA implementation with a moving average that's
-designed to significantly reduce lag while keeping a bigger window size
-by being better at filtering out noise.
-
-It is only slightly more expensive than the simple EWMA and still avoids
-divisions in its calculation.
-
-The algorithm is adapted from an implementation intended for a completely
-different field (stock market trading), where the tradeoff of lag vs
-noise filtering is equally important.
-
-The algorithm works in the same way as the "smoothing filter" from
-http://www.stockspotter.com/files/PredictiveIndicators.pdf adapted for
-fixed-point math with some constants, using only addition, bit shifts
-and multiplication
-
-To better make use of the filtering and bigger window size, the update
-interval is cut in half.
-
-For testing, the algorithm can be reverted to the older one via debugfs
-
-Signed-off-by: Felix Fietkau <nbd@nbd.name>
----
-
---- a/net/mac80211/rc80211_minstrel.c
-+++ b/net/mac80211/rc80211_minstrel.c
-@@ -157,14 +157,18 @@ minstrel_update_rates(struct minstrel_pr
- * Recalculate statistics and counters of a given rate
- */
- void
--minstrel_calc_rate_stats(struct minstrel_rate_stats *mrs)
-+minstrel_calc_rate_stats(struct minstrel_priv *mp,
-+			 struct minstrel_rate_stats *mrs)
- {
- 	unsigned int cur_prob;
- 
- 	if (unlikely(mrs->attempts > 0)) {
- 		mrs->sample_skipped = 0;
- 		cur_prob = MINSTREL_FRAC(mrs->success, mrs->attempts);
--		if (unlikely(!mrs->att_hist)) {
-+		if (mp->new_avg) {
-+			mrs->prob_ewma = minstrel_filter_avg_add(&mrs->avg,
-+								 cur_prob);
-+		} else if (unlikely(!mrs->att_hist)) {
- 			mrs->prob_ewma = cur_prob;
- 		} else {
- 			/*update exponential weighted moving avarage */
-@@ -200,7 +204,7 @@ minstrel_update_stats(struct minstrel_pr
- 		struct minstrel_rate_stats *tmp_mrs = &mi->r[tmp_prob_rate].stats;
- 
- 		/* Update statistics of success probability per rate */
--		minstrel_calc_rate_stats(mrs);
-+		minstrel_calc_rate_stats(mp, mrs);
- 
- 		/* Sample less often below the 10% chance of success.
- 		 * Sample less often above the 95% chance of success. */
-@@ -289,7 +293,8 @@ minstrel_tx_status(void *priv, struct ie
- 	if (mi->sample_deferred > 0)
- 		mi->sample_deferred--;
- 
--	if (time_after(jiffies, mi->last_stats_update + mp->update_interval))
-+	if (time_after(jiffies, mi->last_stats_update +
-+				mp->update_interval / (mp->new_avg ? 2 : 1)))
- 		minstrel_update_stats(mp, mi);
- }
- 
---- a/net/mac80211/rc80211_minstrel.h
-+++ b/net/mac80211/rc80211_minstrel.h
-@@ -19,6 +19,21 @@
- #define MAX_THR_RATES 4
- 
- /*
-+ * Coefficients for moving average with noise filter (period=16),
-+ * scaled by 10 bits
-+ *
-+ * a1 = exp(-pi * sqrt(2) / period)
-+ * coeff2 = 2 * a1 * cos(sqrt(2) * 2 * pi / period)
-+ * coeff3 = -sqr(a1)
-+ * coeff1 = 1 - coeff2 - coeff3
-+ */
-+#define MINSTREL_AVG_COEFF1		(MINSTREL_FRAC(1, 1) - \
-+					 MINSTREL_AVG_COEFF2 - \
-+					 MINSTREL_AVG_COEFF3)
-+#define MINSTREL_AVG_COEFF2		0x00001499
-+#define MINSTREL_AVG_COEFF3		-0x0000092e
-+
-+/*
-  * Perform EWMA (Exponentially Weighted Moving Average) calculation
-  */
- static inline int
-@@ -32,6 +47,41 @@ minstrel_ewma(int old, int new, int weig
- 	return old + incr;
- }
- 
-+struct minstrel_avg_ctx {
-+	s32 prev[2];
-+};
-+
-+static inline int minstrel_filter_avg_add(struct minstrel_avg_ctx *ctx, s32 in)
-+{
-+	s32 out_1 = ctx->prev[0];
-+	s32 out_2 = ctx->prev[1];
-+	s32 val;
-+
-+	if (!in)
-+		in += 1;
-+
-+	if (!out_1) {
-+		val = out_1 = in;
-+		goto out;
-+	}
-+
-+	val = MINSTREL_AVG_COEFF1 * in;
-+	val += MINSTREL_AVG_COEFF2 * out_1;
-+	val += MINSTREL_AVG_COEFF3 * out_2;
-+	val >>= MINSTREL_SCALE;
-+
-+	if (val > 1 << MINSTREL_SCALE)
-+		val = 1 << MINSTREL_SCALE;
-+	if (val < 0)
-+		val = 1;
-+
-+out:
-+	ctx->prev[1] = out_1;
-+	ctx->prev[0] = val;
-+
-+	return val;
-+}
-+
- struct minstrel_rate_stats {
- 	/* current / last sampling period attempts/success counters */
- 	u16 attempts, last_attempts;
-@@ -40,6 +90,8 @@ struct minstrel_rate_stats {
- 	/* total attempts/success counters */
- 	u32 att_hist, succ_hist;
- 
-+	struct minstrel_avg_ctx avg;
-+
- 	/* prob_ewma - exponential weighted moving average of prob */
- 	u16 prob_ewma;
- 
-@@ -95,6 +147,7 @@ struct minstrel_sta_info {
- struct minstrel_priv {
- 	struct ieee80211_hw *hw;
- 	bool has_mrr;
-+	bool new_avg;
- 	u32 sample_switch;
- 	unsigned int cw_min;
- 	unsigned int cw_max;
-@@ -126,7 +179,8 @@ extern const struct rate_control_ops mac
- void minstrel_add_sta_debugfs(void *priv, void *priv_sta, struct dentry *dir);
- 
- /* Recalculate success probabilities and counters for a given rate using EWMA */
--void minstrel_calc_rate_stats(struct minstrel_rate_stats *mrs);
-+void minstrel_calc_rate_stats(struct minstrel_priv *mp,
-+			      struct minstrel_rate_stats *mrs);
- int minstrel_get_tp_avg(struct minstrel_rate *mr, int prob_ewma);
- 
- /* debugfs */
---- a/net/mac80211/rc80211_minstrel_ht.c
-+++ b/net/mac80211/rc80211_minstrel_ht.c
-@@ -737,7 +737,7 @@ minstrel_ht_update_stats(struct minstrel
- 
- 			mrs = &mg->rates[i];
- 			mrs->retry_updated = false;
--			minstrel_calc_rate_stats(mrs);
-+			minstrel_calc_rate_stats(mp, mrs);
- 			cur_prob = mrs->prob_ewma;
- 
- 			if (minstrel_ht_get_tp_avg(mi, group, i, cur_prob) == 0)
-@@ -773,6 +773,8 @@ minstrel_ht_update_stats(struct minstrel
- 
- 	/* try to sample all available rates during each interval */
- 	mi->sample_count *= 8;
-+	if (mp->new_avg)
-+		mi->sample_count /= 2;
- 
- 	if (sample)
- 		minstrel_ht_rate_sample_switch(mp, mi);
-@@ -889,6 +891,7 @@ minstrel_ht_tx_status(void *priv, struct
- 	struct ieee80211_tx_rate *ar = info->status.rates;
- 	struct minstrel_rate_stats *rate, *rate2, *rate_sample = NULL;
- 	struct minstrel_priv *mp = priv;
-+	u32 update_interval = mp->update_interval / 2;
- 	bool last, update = false;
- 	bool sample_status = false;
- 	int i;
-@@ -943,6 +946,10 @@ minstrel_ht_tx_status(void *priv, struct
- 
- 	switch (mi->sample_mode) {
- 	case MINSTREL_SAMPLE_IDLE:
-+		if (mp->new_avg &&
-+		    (mp->hw->max_rates > 1 ||
-+		     mi->total_packets_cur < SAMPLE_SWITCH_THR))
-+			update_interval /= 2;
- 		break;
- 
- 	case MINSTREL_SAMPLE_ACTIVE:
-@@ -983,8 +990,7 @@ minstrel_ht_tx_status(void *priv, struct
- 		}
- 	}
- 
--	if (time_after(jiffies, mi->last_stats_update +
--				mp->update_interval / 2)) {
-+	if (time_after(jiffies, mi->last_stats_update + update_interval)) {
- 		update = true;
- 		minstrel_ht_update_stats(mp, mi, true);
- 	}
-@@ -1665,6 +1671,7 @@ minstrel_ht_alloc(struct ieee80211_hw *h
- 
- 	mp->hw = hw;
- 	mp->update_interval = HZ / 10;
-+	mp->new_avg = true;
- 
- 	minstrel_ht_init_cck_rates(mp);
- 
-@@ -1682,6 +1689,8 @@ static void minstrel_ht_add_debugfs(stru
- 			   &mp->fixed_rate_idx);
- 	debugfs_create_u32("sample_switch", S_IRUGO | S_IWUSR, debugfsdir,
- 			   &mp->sample_switch);
-+	debugfs_create_bool("new_avg", S_IRUGO | S_IWUSR, debugfsdir,
-+			   &mp->new_avg);
- }
- #endif
- 
diff --git a/package/kernel/mac80211/patches/subsys/303-mac80211-minstrel_ht-rename-prob_ewma-to-prob_avg-us.patch b/package/kernel/mac80211/patches/subsys/303-mac80211-minstrel_ht-rename-prob_ewma-to-prob_avg-us.patch
deleted file mode 100644
index f4c4bdb94e90..000000000000
--- a/package/kernel/mac80211/patches/subsys/303-mac80211-minstrel_ht-rename-prob_ewma-to-prob_avg-us.patch
+++ /dev/null
@@ -1,424 +0,0 @@
-From: Felix Fietkau <nbd@nbd.name>
-Date: Tue, 8 Oct 2019 18:54:46 +0200
-Subject: [PATCH] mac80211: minstrel_ht: rename prob_ewma to prob_avg, use it
- for the new average
-
-Reduces per-rate data structure size
-
-Signed-off-by: Felix Fietkau <nbd@nbd.name>
----
-
---- a/net/mac80211/rc80211_minstrel.c
-+++ b/net/mac80211/rc80211_minstrel.c
-@@ -70,7 +70,7 @@ rix_to_ndx(struct minstrel_sta_info *mi,
- }
- 
- /* return current EMWA throughput */
--int minstrel_get_tp_avg(struct minstrel_rate *mr, int prob_ewma)
-+int minstrel_get_tp_avg(struct minstrel_rate *mr, int prob_avg)
- {
- 	int usecs;
- 
-@@ -79,13 +79,13 @@ int minstrel_get_tp_avg(struct minstrel_
- 		usecs = 1000000;
- 
- 	/* reset thr. below 10% success */
--	if (mr->stats.prob_ewma < MINSTREL_FRAC(10, 100))
-+	if (mr->stats.prob_avg < MINSTREL_FRAC(10, 100))
- 		return 0;
- 
--	if (prob_ewma > MINSTREL_FRAC(90, 100))
-+	if (prob_avg > MINSTREL_FRAC(90, 100))
- 		return MINSTREL_TRUNC(100000 * (MINSTREL_FRAC(90, 100) / usecs));
- 	else
--		return MINSTREL_TRUNC(100000 * (prob_ewma / usecs));
-+		return MINSTREL_TRUNC(100000 * (prob_avg / usecs));
- }
- 
- /* find & sort topmost throughput rates */
-@@ -98,8 +98,8 @@ minstrel_sort_best_tp_rates(struct minst
- 
- 	for (j = MAX_THR_RATES; j > 0; --j) {
- 		tmp_mrs = &mi->r[tp_list[j - 1]].stats;
--		if (minstrel_get_tp_avg(&mi->r[i], cur_mrs->prob_ewma) <=
--		    minstrel_get_tp_avg(&mi->r[tp_list[j - 1]], tmp_mrs->prob_ewma))
-+		if (minstrel_get_tp_avg(&mi->r[i], cur_mrs->prob_avg) <=
-+		    minstrel_get_tp_avg(&mi->r[tp_list[j - 1]], tmp_mrs->prob_avg))
- 			break;
- 	}
- 
-@@ -166,15 +166,15 @@ minstrel_calc_rate_stats(struct minstrel
- 		mrs->sample_skipped = 0;
- 		cur_prob = MINSTREL_FRAC(mrs->success, mrs->attempts);
- 		if (mp->new_avg) {
--			mrs->prob_ewma = minstrel_filter_avg_add(&mrs->avg,
--								 cur_prob);
-+			minstrel_filter_avg_add(&mrs->prob_avg,
-+						&mrs->prob_avg_1, cur_prob);
- 		} else if (unlikely(!mrs->att_hist)) {
--			mrs->prob_ewma = cur_prob;
-+			mrs->prob_avg = cur_prob;
- 		} else {
- 			/*update exponential weighted moving avarage */
--			mrs->prob_ewma = minstrel_ewma(mrs->prob_ewma,
--						       cur_prob,
--						       EWMA_LEVEL);
-+			mrs->prob_avg = minstrel_ewma(mrs->prob_avg,
-+						      cur_prob,
-+						      EWMA_LEVEL);
- 		}
- 		mrs->att_hist += mrs->attempts;
- 		mrs->succ_hist += mrs->success;
-@@ -208,8 +208,8 @@ minstrel_update_stats(struct minstrel_pr
- 
- 		/* Sample less often below the 10% chance of success.
- 		 * Sample less often above the 95% chance of success. */
--		if (mrs->prob_ewma > MINSTREL_FRAC(95, 100) ||
--		    mrs->prob_ewma < MINSTREL_FRAC(10, 100)) {
-+		if (mrs->prob_avg > MINSTREL_FRAC(95, 100) ||
-+		    mrs->prob_avg < MINSTREL_FRAC(10, 100)) {
- 			mr->adjusted_retry_count = mrs->retry_count >> 1;
- 			if (mr->adjusted_retry_count > 2)
- 				mr->adjusted_retry_count = 2;
-@@ -229,14 +229,14 @@ minstrel_update_stats(struct minstrel_pr
- 		 * choose the maximum throughput rate as max_prob_rate
- 		 * (2) if all success probabilities < 95%, the rate with
- 		 * highest success probability is chosen as max_prob_rate */
--		if (mrs->prob_ewma >= MINSTREL_FRAC(95, 100)) {
--			tmp_cur_tp = minstrel_get_tp_avg(mr, mrs->prob_ewma);
-+		if (mrs->prob_avg >= MINSTREL_FRAC(95, 100)) {
-+			tmp_cur_tp = minstrel_get_tp_avg(mr, mrs->prob_avg);
- 			tmp_prob_tp = minstrel_get_tp_avg(&mi->r[tmp_prob_rate],
--							  tmp_mrs->prob_ewma);
-+							  tmp_mrs->prob_avg);
- 			if (tmp_cur_tp >= tmp_prob_tp)
- 				tmp_prob_rate = i;
- 		} else {
--			if (mrs->prob_ewma >= tmp_mrs->prob_ewma)
-+			if (mrs->prob_avg >= tmp_mrs->prob_avg)
- 				tmp_prob_rate = i;
- 		}
- 	}
-@@ -426,7 +426,7 @@ minstrel_get_rate(void *priv, struct iee
- 	 * has a probability of >95%, we shouldn't be attempting
- 	 * to use it, as this only wastes precious airtime */
- 	if (!mrr_capable &&
--	   (mi->r[ndx].stats.prob_ewma > MINSTREL_FRAC(95, 100)))
-+	   (mi->r[ndx].stats.prob_avg > MINSTREL_FRAC(95, 100)))
- 		return;
- 
- 	mi->prev_sample = true;
-@@ -577,7 +577,7 @@ static u32 minstrel_get_expected_through
- 	 * computing cur_tp
- 	 */
- 	tmp_mrs = &mi->r[idx].stats;
--	tmp_cur_tp = minstrel_get_tp_avg(&mi->r[idx], tmp_mrs->prob_ewma) * 10;
-+	tmp_cur_tp = minstrel_get_tp_avg(&mi->r[idx], tmp_mrs->prob_avg) * 10;
- 	tmp_cur_tp = tmp_cur_tp * 1200 * 8 / 1024;
- 
- 	return tmp_cur_tp;
---- a/net/mac80211/rc80211_minstrel.h
-+++ b/net/mac80211/rc80211_minstrel.h
-@@ -47,14 +47,10 @@ minstrel_ewma(int old, int new, int weig
- 	return old + incr;
- }
- 
--struct minstrel_avg_ctx {
--	s32 prev[2];
--};
--
--static inline int minstrel_filter_avg_add(struct minstrel_avg_ctx *ctx, s32 in)
-+static inline int minstrel_filter_avg_add(u16 *prev_1, u16 *prev_2, s32 in)
- {
--	s32 out_1 = ctx->prev[0];
--	s32 out_2 = ctx->prev[1];
-+	s32 out_1 = *prev_1;
-+	s32 out_2 = *prev_2;
- 	s32 val;
- 
- 	if (!in)
-@@ -76,8 +72,8 @@ static inline int minstrel_filter_avg_ad
- 		val = 1;
- 
- out:
--	ctx->prev[1] = out_1;
--	ctx->prev[0] = val;
-+	*prev_2 = out_1;
-+	*prev_1 = val;
- 
- 	return val;
- }
-@@ -90,10 +86,9 @@ struct minstrel_rate_stats {
- 	/* total attempts/success counters */
- 	u32 att_hist, succ_hist;
- 
--	struct minstrel_avg_ctx avg;
--
--	/* prob_ewma - exponential weighted moving average of prob */
--	u16 prob_ewma;
-+	/* prob_avg - moving average of prob */
-+	u16 prob_avg;
-+	u16 prob_avg_1;
- 
- 	/* maximum retry counts */
- 	u8 retry_count;
-@@ -181,7 +176,7 @@ void minstrel_add_sta_debugfs(void *priv
- /* Recalculate success probabilities and counters for a given rate using EWMA */
- void minstrel_calc_rate_stats(struct minstrel_priv *mp,
- 			      struct minstrel_rate_stats *mrs);
--int minstrel_get_tp_avg(struct minstrel_rate *mr, int prob_ewma);
-+int minstrel_get_tp_avg(struct minstrel_rate *mr, int prob_avg);
- 
- /* debugfs */
- int minstrel_stats_open(struct inode *inode, struct file *file);
---- a/net/mac80211/rc80211_minstrel_debugfs.c
-+++ b/net/mac80211/rc80211_minstrel_debugfs.c
-@@ -90,8 +90,8 @@ minstrel_stats_open(struct inode *inode,
- 		p += sprintf(p, "%6u ", mr->perfect_tx_time);
- 
- 		tp_max = minstrel_get_tp_avg(mr, MINSTREL_FRAC(100,100));
--		tp_avg = minstrel_get_tp_avg(mr, mrs->prob_ewma);
--		eprob = MINSTREL_TRUNC(mrs->prob_ewma * 1000);
-+		tp_avg = minstrel_get_tp_avg(mr, mrs->prob_avg);
-+		eprob = MINSTREL_TRUNC(mrs->prob_avg * 1000);
- 
- 		p += sprintf(p, "%4u.%1u    %4u.%1u     %3u.%1u"
- 				"     %3u   %3u %-3u   "
-@@ -147,8 +147,8 @@ minstrel_stats_csv_open(struct inode *in
- 		p += sprintf(p, "%u,",mr->perfect_tx_time);
- 
- 		tp_max = minstrel_get_tp_avg(mr, MINSTREL_FRAC(100,100));
--		tp_avg = minstrel_get_tp_avg(mr, mrs->prob_ewma);
--		eprob = MINSTREL_TRUNC(mrs->prob_ewma * 1000);
-+		tp_avg = minstrel_get_tp_avg(mr, mrs->prob_avg);
-+		eprob = MINSTREL_TRUNC(mrs->prob_avg * 1000);
- 
- 		p += sprintf(p, "%u.%u,%u.%u,%u.%u,%u,%u,%u,"
- 				"%llu,%llu,%d,%d\n",
---- a/net/mac80211/rc80211_minstrel_ht.c
-+++ b/net/mac80211/rc80211_minstrel_ht.c
-@@ -346,12 +346,12 @@ minstrel_ht_avg_ampdu_len(struct minstre
-  */
- int
- minstrel_ht_get_tp_avg(struct minstrel_ht_sta *mi, int group, int rate,
--		       int prob_ewma)
-+		       int prob_avg)
- {
- 	unsigned int nsecs = 0;
- 
- 	/* do not account throughput if sucess prob is below 10% */
--	if (prob_ewma < MINSTREL_FRAC(10, 100))
-+	if (prob_avg < MINSTREL_FRAC(10, 100))
- 		return 0;
- 
- 	if (group != MINSTREL_CCK_GROUP)
-@@ -365,11 +365,11 @@ minstrel_ht_get_tp_avg(struct minstrel_h
- 	 * account for collision related packet error rate fluctuation
- 	 * (prob is scaled - see MINSTREL_FRAC above)
- 	 */
--	if (prob_ewma > MINSTREL_FRAC(90, 100))
-+	if (prob_avg > MINSTREL_FRAC(90, 100))
- 		return MINSTREL_TRUNC(100000 * ((MINSTREL_FRAC(90, 100) * 1000)
- 								      / nsecs));
- 	else
--		return MINSTREL_TRUNC(100000 * ((prob_ewma * 1000) / nsecs));
-+		return MINSTREL_TRUNC(100000 * ((prob_avg * 1000) / nsecs));
- }
- 
- /*
-@@ -389,13 +389,13 @@ minstrel_ht_sort_best_tp_rates(struct mi
- 
- 	cur_group = index / MCS_GROUP_RATES;
- 	cur_idx = index  % MCS_GROUP_RATES;
--	cur_prob = mi->groups[cur_group].rates[cur_idx].prob_ewma;
-+	cur_prob = mi->groups[cur_group].rates[cur_idx].prob_avg;
- 	cur_tp_avg = minstrel_ht_get_tp_avg(mi, cur_group, cur_idx, cur_prob);
- 
- 	do {
- 		tmp_group = tp_list[j - 1] / MCS_GROUP_RATES;
- 		tmp_idx = tp_list[j - 1] % MCS_GROUP_RATES;
--		tmp_prob = mi->groups[tmp_group].rates[tmp_idx].prob_ewma;
-+		tmp_prob = mi->groups[tmp_group].rates[tmp_idx].prob_avg;
- 		tmp_tp_avg = minstrel_ht_get_tp_avg(mi, tmp_group, tmp_idx,
- 						    tmp_prob);
- 		if (cur_tp_avg < tmp_tp_avg ||
-@@ -432,7 +432,7 @@ minstrel_ht_set_best_prob_rate(struct mi
- 
- 	tmp_group = mi->max_prob_rate / MCS_GROUP_RATES;
- 	tmp_idx = mi->max_prob_rate % MCS_GROUP_RATES;
--	tmp_prob = mi->groups[tmp_group].rates[tmp_idx].prob_ewma;
-+	tmp_prob = mi->groups[tmp_group].rates[tmp_idx].prob_avg;
- 	tmp_tp_avg = minstrel_ht_get_tp_avg(mi, tmp_group, tmp_idx, tmp_prob);
- 
- 	/* if max_tp_rate[0] is from MCS_GROUP max_prob_rate get selected from
-@@ -444,11 +444,11 @@ minstrel_ht_set_best_prob_rate(struct mi
- 
- 	max_gpr_group = mg->max_group_prob_rate / MCS_GROUP_RATES;
- 	max_gpr_idx = mg->max_group_prob_rate % MCS_GROUP_RATES;
--	max_gpr_prob = mi->groups[max_gpr_group].rates[max_gpr_idx].prob_ewma;
-+	max_gpr_prob = mi->groups[max_gpr_group].rates[max_gpr_idx].prob_avg;
- 
--	if (mrs->prob_ewma > MINSTREL_FRAC(75, 100)) {
-+	if (mrs->prob_avg > MINSTREL_FRAC(75, 100)) {
- 		cur_tp_avg = minstrel_ht_get_tp_avg(mi, cur_group, cur_idx,
--						    mrs->prob_ewma);
-+						    mrs->prob_avg);
- 		if (cur_tp_avg > tmp_tp_avg)
- 			mi->max_prob_rate = index;
- 
-@@ -458,9 +458,9 @@ minstrel_ht_set_best_prob_rate(struct mi
- 		if (cur_tp_avg > max_gpr_tp_avg)
- 			mg->max_group_prob_rate = index;
- 	} else {
--		if (mrs->prob_ewma > tmp_prob)
-+		if (mrs->prob_avg > tmp_prob)
- 			mi->max_prob_rate = index;
--		if (mrs->prob_ewma > max_gpr_prob)
-+		if (mrs->prob_avg > max_gpr_prob)
- 			mg->max_group_prob_rate = index;
- 	}
- }
-@@ -482,12 +482,12 @@ minstrel_ht_assign_best_tp_rates(struct
- 
- 	tmp_group = tmp_cck_tp_rate[0] / MCS_GROUP_RATES;
- 	tmp_idx = tmp_cck_tp_rate[0] % MCS_GROUP_RATES;
--	tmp_prob = mi->groups[tmp_group].rates[tmp_idx].prob_ewma;
-+	tmp_prob = mi->groups[tmp_group].rates[tmp_idx].prob_avg;
- 	tmp_cck_tp = minstrel_ht_get_tp_avg(mi, tmp_group, tmp_idx, tmp_prob);
- 
- 	tmp_group = tmp_mcs_tp_rate[0] / MCS_GROUP_RATES;
- 	tmp_idx = tmp_mcs_tp_rate[0] % MCS_GROUP_RATES;
--	tmp_prob = mi->groups[tmp_group].rates[tmp_idx].prob_ewma;
-+	tmp_prob = mi->groups[tmp_group].rates[tmp_idx].prob_avg;
- 	tmp_mcs_tp = minstrel_ht_get_tp_avg(mi, tmp_group, tmp_idx, tmp_prob);
- 
- 	if (tmp_cck_tp_rate && tmp_cck_tp > tmp_mcs_tp) {
-@@ -518,7 +518,7 @@ minstrel_ht_prob_rate_reduce_streams(str
- 			continue;
- 
- 		tmp_idx = mg->max_group_prob_rate % MCS_GROUP_RATES;
--		tmp_prob = mi->groups[group].rates[tmp_idx].prob_ewma;
-+		tmp_prob = mi->groups[group].rates[tmp_idx].prob_avg;
- 
- 		if (tmp_tp < minstrel_ht_get_tp_avg(mi, group, tmp_idx, tmp_prob) &&
- 		   (minstrel_mcs_groups[group].streams < tmp_max_streams)) {
-@@ -623,7 +623,7 @@ minstrel_ht_rate_sample_switch(struct mi
- 	 * If that fails, look again for a rate that is at least as fast
- 	 */
- 	mrs = minstrel_get_ratestats(mi, mi->max_tp_rate[0]);
--	faster_rate = mrs->prob_ewma > MINSTREL_FRAC(75, 100);
-+	faster_rate = mrs->prob_avg > MINSTREL_FRAC(75, 100);
- 	minstrel_ht_find_probe_rates(mi, rates, &n_rates, faster_rate);
- 	if (!n_rates && faster_rate)
- 		minstrel_ht_find_probe_rates(mi, rates, &n_rates, false);
-@@ -738,7 +738,7 @@ minstrel_ht_update_stats(struct minstrel
- 			mrs = &mg->rates[i];
- 			mrs->retry_updated = false;
- 			minstrel_calc_rate_stats(mp, mrs);
--			cur_prob = mrs->prob_ewma;
-+			cur_prob = mrs->prob_avg;
- 
- 			if (minstrel_ht_get_tp_avg(mi, group, i, cur_prob) == 0)
- 				continue;
-@@ -1012,7 +1012,7 @@ minstrel_calc_retransmit(struct minstrel
- 	unsigned int overhead = 0, overhead_rtscts = 0;
- 
- 	mrs = minstrel_get_ratestats(mi, index);
--	if (mrs->prob_ewma < MINSTREL_FRAC(1, 10)) {
-+	if (mrs->prob_avg < MINSTREL_FRAC(1, 10)) {
- 		mrs->retry_count = 1;
- 		mrs->retry_count_rtscts = 1;
- 		return;
-@@ -1069,7 +1069,7 @@ minstrel_ht_set_rate(struct minstrel_pri
- 	if (!mrs->retry_updated)
- 		minstrel_calc_retransmit(mp, mi, index);
- 
--	if (mrs->prob_ewma < MINSTREL_FRAC(20, 100) || !mrs->retry_count) {
-+	if (mrs->prob_avg < MINSTREL_FRAC(20, 100) || !mrs->retry_count) {
- 		ratetbl->rate[offset].count = 2;
- 		ratetbl->rate[offset].count_rts = 2;
- 		ratetbl->rate[offset].count_cts = 2;
-@@ -1103,11 +1103,11 @@ minstrel_ht_set_rate(struct minstrel_pri
- }
- 
- static inline int
--minstrel_ht_get_prob_ewma(struct minstrel_ht_sta *mi, int rate)
-+minstrel_ht_get_prob_avg(struct minstrel_ht_sta *mi, int rate)
- {
- 	int group = rate / MCS_GROUP_RATES;
- 	rate %= MCS_GROUP_RATES;
--	return mi->groups[group].rates[rate].prob_ewma;
-+	return mi->groups[group].rates[rate].prob_avg;
- }
- 
- static int
-@@ -1119,7 +1119,7 @@ minstrel_ht_get_max_amsdu_len(struct min
- 	unsigned int duration;
- 
- 	/* Disable A-MSDU if max_prob_rate is bad */
--	if (mi->groups[group].rates[rate].prob_ewma < MINSTREL_FRAC(50, 100))
-+	if (mi->groups[group].rates[rate].prob_avg < MINSTREL_FRAC(50, 100))
- 		return 1;
- 
- 	duration = g->duration[rate];
-@@ -1142,7 +1142,7 @@ minstrel_ht_get_max_amsdu_len(struct min
- 	 * data packet size
- 	 */
- 	if (duration > MCS_DURATION(1, 0, 260) ||
--	    (minstrel_ht_get_prob_ewma(mi, mi->max_tp_rate[0]) <
-+	    (minstrel_ht_get_prob_avg(mi, mi->max_tp_rate[0]) <
- 	     MINSTREL_FRAC(75, 100)))
- 		return 3200;
- 
-@@ -1247,7 +1247,7 @@ minstrel_get_sample_rate(struct minstrel
- 	 * rate, to avoid wasting airtime.
- 	 */
- 	sample_dur = minstrel_get_duration(sample_idx);
--	if (mrs->prob_ewma > MINSTREL_FRAC(95, 100) ||
-+	if (mrs->prob_avg > MINSTREL_FRAC(95, 100) ||
- 	    minstrel_get_duration(mi->max_prob_rate) * 3 < sample_dur)
- 		return -1;
- 
-@@ -1711,7 +1711,7 @@ static u32 minstrel_ht_get_expected_thro
- 
- 	i = mi->max_tp_rate[0] / MCS_GROUP_RATES;
- 	j = mi->max_tp_rate[0] % MCS_GROUP_RATES;
--	prob = mi->groups[i].rates[j].prob_ewma;
-+	prob = mi->groups[i].rates[j].prob_avg;
- 
- 	/* convert tp_avg from pkt per second in kbps */
- 	tp_avg = minstrel_ht_get_tp_avg(mi, i, j, prob) * 10;
---- a/net/mac80211/rc80211_minstrel_ht.h
-+++ b/net/mac80211/rc80211_minstrel_ht.h
-@@ -119,6 +119,6 @@ struct minstrel_ht_sta_priv {
- 
- void minstrel_ht_add_sta_debugfs(void *priv, void *priv_sta, struct dentry *dir);
- int minstrel_ht_get_tp_avg(struct minstrel_ht_sta *mi, int group, int rate,
--			   int prob_ewma);
-+			   int prob_avg);
- 
- #endif
---- a/net/mac80211/rc80211_minstrel_ht_debugfs.c
-+++ b/net/mac80211/rc80211_minstrel_ht_debugfs.c
-@@ -98,8 +98,8 @@ minstrel_ht_stats_dump(struct minstrel_h
- 		p += sprintf(p, "%6u  ", tx_time);
- 
- 		tp_max = minstrel_ht_get_tp_avg(mi, i, j, MINSTREL_FRAC(100, 100));
--		tp_avg = minstrel_ht_get_tp_avg(mi, i, j, mrs->prob_ewma);
--		eprob = MINSTREL_TRUNC(mrs->prob_ewma * 1000);
-+		tp_avg = minstrel_ht_get_tp_avg(mi, i, j, mrs->prob_avg);
-+		eprob = MINSTREL_TRUNC(mrs->prob_avg * 1000);
- 
- 		p += sprintf(p, "%4u.%1u    %4u.%1u     %3u.%1u"
- 				"     %3u   %3u %-3u   "
-@@ -243,8 +243,8 @@ minstrel_ht_stats_csv_dump(struct minstr
- 		p += sprintf(p, "%u,", tx_time);
- 
- 		tp_max = minstrel_ht_get_tp_avg(mi, i, j, MINSTREL_FRAC(100, 100));
--		tp_avg = minstrel_ht_get_tp_avg(mi, i, j, mrs->prob_ewma);
--		eprob = MINSTREL_TRUNC(mrs->prob_ewma * 1000);
-+		tp_avg = minstrel_ht_get_tp_avg(mi, i, j, mrs->prob_avg);
-+		eprob = MINSTREL_TRUNC(mrs->prob_avg * 1000);
- 
- 		p += sprintf(p, "%u.%u,%u.%u,%u.%u,%u,%u,"
- 				"%u,%llu,%llu,",
diff --git a/package/kernel/mac80211/patches/subsys/304-mac80211-sta-randomize-BA-session-dialog-token-alloc.patch b/package/kernel/mac80211/patches/subsys/304-mac80211-sta-randomize-BA-session-dialog-token-alloc.patch
index dc7cac5ad15a..64ae487be289 100644
--- a/package/kernel/mac80211/patches/subsys/304-mac80211-sta-randomize-BA-session-dialog-token-alloc.patch
+++ b/package/kernel/mac80211/patches/subsys/304-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
-@@ -324,6 +324,7 @@ struct sta_info *sta_info_alloc(struct i
+@@ -338,6 +338,7 @@ struct sta_info *sta_info_alloc(struct i
  	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-fix-tx-status-for-no-ack-cases.patch b/package/kernel/mac80211/patches/subsys/305-mac80211-fix-tx-status-for-no-ack-cases.patch
index ee8f5d0277cf..16108c83f3a3 100644
--- a/package/kernel/mac80211/patches/subsys/305-mac80211-fix-tx-status-for-no-ack-cases.patch
+++ b/package/kernel/mac80211/patches/subsys/305-mac80211-fix-tx-status-for-no-ack-cases.patch
@@ -12,7 +12,7 @@ Signed-off-by: Johannes Berg <johannes.berg@intel.com>
 
 --- a/net/mac80211/status.c
 +++ b/net/mac80211/status.c
-@@ -881,6 +881,7 @@ static void __ieee80211_tx_status(struct
+@@ -895,6 +895,7 @@ static void __ieee80211_tx_status(struct
  	int rates_idx;
  	bool send_to_cooked;
  	bool acked;
@@ -20,7 +20,7 @@ Signed-off-by: Johannes Berg <johannes.berg@intel.com>
  	struct ieee80211_bar *bar;
  	int shift = 0;
  	int tid = IEEE80211_NUM_TIDS;
-@@ -898,6 +899,8 @@ static void __ieee80211_tx_status(struct
+@@ -913,6 +914,8 @@ static void __ieee80211_tx_status(struct
  			clear_sta_flag(sta, WLAN_STA_SP);
  
  		acked = !!(info->flags & IEEE80211_TX_STAT_ACK);
@@ -29,7 +29,7 @@ Signed-off-by: Johannes Berg <johannes.berg@intel.com>
  
  		/* mesh Peer Service Period support */
  		if (ieee80211_vif_is_mesh(&sta->sdata->vif) &&
-@@ -962,12 +965,12 @@ static void __ieee80211_tx_status(struct
+@@ -977,12 +980,12 @@ static void __ieee80211_tx_status(struct
  			ieee80211_handle_filtered_frame(local, sta, skb);
  			return;
  		} else {
@@ -44,8 +44,8 @@ Signed-off-by: Johannes Berg <johannes.berg@intel.com>
  					sta->status_stats.msdu_failed[tid]++;
  
  				sta->status_stats.msdu_retries[tid] +=
-@@ -994,7 +997,7 @@ static void __ieee80211_tx_status(struct
- 						       info->status.tx_time, 0);
+@@ -1020,7 +1023,7 @@ static void __ieee80211_tx_status(struct
+ 		}
  
  		if (ieee80211_hw_check(&local->hw, REPORTS_TX_ACK_STATUS)) {
 -			if (info->flags & IEEE80211_TX_STAT_ACK) {
@@ -53,7 +53,7 @@ Signed-off-by: Johannes Berg <johannes.berg@intel.com>
  				if (sta->status_stats.lost_packets)
  					sta->status_stats.lost_packets = 0;
  
-@@ -1002,6 +1005,8 @@ static void __ieee80211_tx_status(struct
+@@ -1028,6 +1031,8 @@ static void __ieee80211_tx_status(struct
  				if (test_sta_flag(sta, WLAN_STA_TDLS_PEER_AUTH))
  					sta->status_stats.last_tdls_pkt_time =
  						jiffies;
@@ -62,7 +62,7 @@ Signed-off-by: Johannes Berg <johannes.berg@intel.com>
  			} else {
  				ieee80211_lost_packet(sta, info);
  			}
-@@ -1128,7 +1133,7 @@ void ieee80211_tx_status_ext(struct ieee
+@@ -1148,7 +1153,7 @@ void ieee80211_tx_status_ext(struct ieee
  
  		sta = container_of(pubsta, struct sta_info, sta);
  
@@ -71,7 +71,7 @@ Signed-off-by: Johannes Berg <johannes.berg@intel.com>
  			sta->status_stats.retry_failed++;
  		sta->status_stats.retry_count += retry_count;
  
-@@ -1143,6 +1148,8 @@ void ieee80211_tx_status_ext(struct ieee
+@@ -1163,6 +1168,8 @@ void ieee80211_tx_status_ext(struct ieee
  				sta->status_stats.last_tdls_pkt_time = jiffies;
  		} else if (test_sta_flag(sta, WLAN_STA_PS_STA)) {
  			return;
diff --git a/package/kernel/mac80211/patches/subsys/306-mac80211-move-store-skb-ack-code-to-its-own-function.patch b/package/kernel/mac80211/patches/subsys/306-mac80211-move-store-skb-ack-code-to-its-own-function.patch
deleted file mode 100644
index 4f0a699c808d..000000000000
--- a/package/kernel/mac80211/patches/subsys/306-mac80211-move-store-skb-ack-code-to-its-own-function.patch
+++ /dev/null
@@ -1,78 +0,0 @@
-From: John Crispin <john@phrozen.org>
-Date: Tue, 29 Oct 2019 10:13:02 +0100
-Subject: [PATCH] mac80211: move store skb ack code to its own function
-
-This patch moves the code handling SKBTX_WIFI_STATUS inside the TX path
-into an extra function. This allows us to reuse it inside the 802.11 encap
-offloading datapath.
-
-Signed-off-by: John Crispin <john@phrozen.org>
-Link: https://lore.kernel.org/r/20191029091304.7330-2-john@phrozen.org
-Signed-off-by: Johannes Berg <johannes.berg@intel.com>
----
-
---- a/net/mac80211/tx.c
-+++ b/net/mac80211/tx.c
-@@ -2445,6 +2445,33 @@ static int ieee80211_lookup_ra_sta(struc
- 	return 0;
- }
- 
-+static int ieee80211_store_ack_skb(struct ieee80211_local *local,
-+				   struct sk_buff *skb,
-+				   u32 *info_flags)
-+{
-+	struct sk_buff *ack_skb = skb_clone_sk(skb);
-+	u16 info_id = 0;
-+
-+	if (ack_skb) {
-+		unsigned long flags;
-+		int id;
-+
-+		spin_lock_irqsave(&local->ack_status_lock, flags);
-+		id = idr_alloc(&local->ack_status_frames, ack_skb,
-+			       1, 0x10000, GFP_ATOMIC);
-+		spin_unlock_irqrestore(&local->ack_status_lock, flags);
-+
-+		if (id >= 0) {
-+			info_id = id;
-+			*info_flags |= IEEE80211_TX_CTL_REQ_TX_STATUS;
-+		} else {
-+			kfree_skb(ack_skb);
-+		}
-+	}
-+
-+	return info_id;
-+}
-+
- /**
-  * ieee80211_build_hdr - build 802.11 header in the given frame
-  * @sdata: virtual interface to build the header for
-@@ -2738,26 +2765,8 @@ static struct sk_buff *ieee80211_build_h
- 	}
- 
- 	if (unlikely(!multicast && skb->sk &&
--		     skb_shinfo(skb)->tx_flags & SKBTX_WIFI_STATUS)) {
--		struct sk_buff *ack_skb = skb_clone_sk(skb);
--
--		if (ack_skb) {
--			unsigned long flags;
--			int id;
--
--			spin_lock_irqsave(&local->ack_status_lock, flags);
--			id = idr_alloc(&local->ack_status_frames, ack_skb,
--				       1, 0x10000, GFP_ATOMIC);
--			spin_unlock_irqrestore(&local->ack_status_lock, flags);
--
--			if (id >= 0) {
--				info_id = id;
--				info_flags |= IEEE80211_TX_CTL_REQ_TX_STATUS;
--			} else {
--				kfree_skb(ack_skb);
--			}
--		}
--	}
-+		     skb_shinfo(skb)->tx_flags & SKBTX_WIFI_STATUS))
-+		info_id = ieee80211_store_ack_skb(local, skb, &info_flags);
- 
- 	/*
- 	 * If the skb is shared we need to obtain our own copy.
diff --git a/package/kernel/mac80211/patches/subsys/307-mac80211-Shrink-the-size-of-ack_frame_id-to-make-roo.patch b/package/kernel/mac80211/patches/subsys/307-mac80211-Shrink-the-size-of-ack_frame_id-to-make-roo.patch
deleted file mode 100644
index ff25ceff6e18..000000000000
--- a/package/kernel/mac80211/patches/subsys/307-mac80211-Shrink-the-size-of-ack_frame_id-to-make-roo.patch
+++ /dev/null
@@ -1,67 +0,0 @@
-From: =?UTF-8?q?Toke=20H=C3=B8iland-J=C3=B8rgensen?= <toke@redhat.com>
-Date: Wed, 23 Oct 2019 11:59:00 +0200
-Subject: [PATCH] mac80211: Shrink the size of ack_frame_id to make room for
- tx_time_est
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-To implement airtime queue limiting, we need to keep a running account of
-the estimated airtime of all skbs queued into the device. Do to this
-correctly, we need to store the airtime estimate into the skb so we can
-decrease the outstanding balance when the skb is freed. This means that the
-time estimate must be stored somewhere that will survive for the lifetime
-of the skb.
-
-To get this, decrease the size of the ack_frame_id field to 6 bits, and
-lower the size of the ID space accordingly. This leaves 10 bits for use for
-tx_time_est, which is enough to store a maximum of 4096 us, if we shift the
-values so they become units of 4us.
-
-Signed-off-by: Toke Høiland-Jørgensen <toke@redhat.com>
-Link: https://lore.kernel.org/r/157182474063.150713.16132669599100802716.stgit@toke.dk
-Signed-off-by: Johannes Berg <johannes.berg@intel.com>
----
-
---- a/include/net/mac80211.h
-+++ b/include/net/mac80211.h
-@@ -967,6 +967,7 @@ ieee80211_rate_get_vht_nss(const struct
-  * @band: the band to transmit on (use for checking for races)
-  * @hw_queue: HW queue to put the frame on, skb_get_queue_mapping() gives the AC
-  * @ack_frame_id: internal frame ID for TX status, used internally
-+ * @tx_time_est: TX time estimate in units of 4us, used internally
-  * @control: union part for control data
-  * @control.rates: TX rates array to try
-  * @control.rts_cts_rate_idx: rate for RTS or CTS
-@@ -1007,7 +1008,8 @@ struct ieee80211_tx_info {
- 
- 	u8 hw_queue;
- 
--	u16 ack_frame_id;
-+	u16 ack_frame_id:6;
-+	u16 tx_time_est:10;
- 
- 	union {
- 		struct {
---- a/net/mac80211/cfg.c
-+++ b/net/mac80211/cfg.c
-@@ -3449,7 +3449,7 @@ int ieee80211_attach_ack_skb(struct ieee
- 
- 	spin_lock_irqsave(&local->ack_status_lock, spin_flags);
- 	id = idr_alloc(&local->ack_status_frames, ack_skb,
--		       1, 0x10000, GFP_ATOMIC);
-+		       1, 0x40, GFP_ATOMIC);
- 	spin_unlock_irqrestore(&local->ack_status_lock, spin_flags);
- 
- 	if (id < 0) {
---- a/net/mac80211/tx.c
-+++ b/net/mac80211/tx.c
-@@ -2458,7 +2458,7 @@ static int ieee80211_store_ack_skb(struc
- 
- 		spin_lock_irqsave(&local->ack_status_lock, flags);
- 		id = idr_alloc(&local->ack_status_frames, ack_skb,
--			       1, 0x10000, GFP_ATOMIC);
-+			       1, 0x40, GFP_ATOMIC);
- 		spin_unlock_irqrestore(&local->ack_status_lock, flags);
- 
- 		if (id >= 0) {
diff --git a/package/kernel/mac80211/patches/subsys/308-mac80211-Add-new-sta_info-getter-by-sta-vif-addrs.patch b/package/kernel/mac80211/patches/subsys/308-mac80211-Add-new-sta_info-getter-by-sta-vif-addrs.patch
deleted file mode 100644
index a6b05f4b7497..000000000000
--- a/package/kernel/mac80211/patches/subsys/308-mac80211-Add-new-sta_info-getter-by-sta-vif-addrs.patch
+++ /dev/null
@@ -1,78 +0,0 @@
-From: =?UTF-8?q?Toke=20H=C3=B8iland-J=C3=B8rgensen?= <toke@redhat.com>
-Date: Tue, 12 Nov 2019 14:08:35 +0100
-Subject: [PATCH] mac80211: Add new sta_info getter by sta/vif addrs
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-In ieee80211_tx_status() we don't have an sdata struct when looking up the
-destination sta. Instead, we just do a lookup by the vif addr that is the
-source of the packet being completed. Factor this out into a new sta_info
-getter helper, since we need to use it for accounting AQL as well.
-
-Signed-off-by: Toke Høiland-Jørgensen <toke@redhat.com>
-Link: https://lore.kernel.org/r/20191112130835.382062-1-toke@redhat.com
-[remove internal rcu_read_lock(), document instead]
-Signed-off-by: Johannes Berg <johannes.berg@intel.com>
----
-
---- a/net/mac80211/sta_info.c
-+++ b/net/mac80211/sta_info.c
-@@ -210,6 +210,20 @@ struct sta_info *sta_info_get_bss(struct
- 	return NULL;
- }
- 
-+struct sta_info *sta_info_get_by_addrs(struct ieee80211_local *local,
-+				       const u8 *sta_addr, const u8 *vif_addr)
-+{
-+	struct rhlist_head *tmp;
-+	struct sta_info *sta;
-+
-+	for_each_sta_info(local, sta_addr, sta, tmp) {
-+		if (ether_addr_equal(vif_addr, sta->sdata->vif.addr))
-+			return sta;
-+	}
-+
-+	return NULL;
-+}
-+
- struct sta_info *sta_info_get_by_idx(struct ieee80211_sub_if_data *sdata,
- 				     int idx)
- {
---- a/net/mac80211/sta_info.h
-+++ b/net/mac80211/sta_info.h
-@@ -726,6 +726,10 @@ struct sta_info *sta_info_get(struct iee
- struct sta_info *sta_info_get_bss(struct ieee80211_sub_if_data *sdata,
- 				  const u8 *addr);
- 
-+/* user must hold sta_mtx or be in RCU critical section */
-+struct sta_info *sta_info_get_by_addrs(struct ieee80211_local *local,
-+				       const u8 *sta_addr, const u8 *vif_addr);
-+
- #define for_each_sta_info(local, _addr, _sta, _tmp)			\
- 	rhl_for_each_entry_rcu(_sta, _tmp,				\
- 			       sta_info_hash_lookup(local, _addr), hash_node)
---- a/net/mac80211/status.c
-+++ b/net/mac80211/status.c
-@@ -1086,19 +1086,13 @@ void ieee80211_tx_status(struct ieee8021
- 		.skb = skb,
- 		.info = IEEE80211_SKB_CB(skb),
- 	};
--	struct rhlist_head *tmp;
- 	struct sta_info *sta;
- 
- 	rcu_read_lock();
- 
--	for_each_sta_info(local, hdr->addr1, sta, tmp) {
--		/* skip wrong virtual interface */
--		if (!ether_addr_equal(hdr->addr2, sta->sdata->vif.addr))
--			continue;
--
-+	sta = sta_info_get_by_addrs(local, hdr->addr1, hdr->addr2);
-+	if (sta)
- 		status.sta = &sta->sta;
--		break;
--	}
- 
- 	__ieee80211_tx_status(hw, &status);
- 	rcu_read_unlock();
diff --git a/package/kernel/mac80211/patches/subsys/309-mac80211-Import-airtime-calculation-code-from-mt76.patch b/package/kernel/mac80211/patches/subsys/309-mac80211-Import-airtime-calculation-code-from-mt76.patch
deleted file mode 100644
index 7f049b8d0cc9..000000000000
--- a/package/kernel/mac80211/patches/subsys/309-mac80211-Import-airtime-calculation-code-from-mt76.patch
+++ /dev/null
@@ -1,690 +0,0 @@
-From: =?UTF-8?q?Toke=20H=C3=B8iland-J=C3=B8rgensen?= <toke@redhat.com>
-Date: Mon, 18 Nov 2019 22:06:08 -0800
-Subject: [PATCH] mac80211: Import airtime calculation code from mt76
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-Felix recently added code to calculate airtime of packets to the mt76
-driver. Import this into mac80211 so we can use it for airtime queue limit
-calculations.
-
-The airtime.c file is copied verbatim from the mt76 driver, and adjusted to
-be usable in mac80211. This involves:
-
-- Switching to mac80211 data structures.
-- Adding support for 160 MHz channels and HE mode.
-- Moving the symbol and duration calculations around a bit to avoid
-  rounding with the higher rates and longer symbol times used for HE rates.
-
-The per-rate TX rate calculation is also split out to its own function so
-it can be used directly for the AQL calculations later.
-
-Signed-off-by: Toke Høiland-Jørgensen <toke@redhat.com>
-Link: https://lore.kernel.org/r/20191119060610.76681-3-kyan@google.com
-[fix HE_GROUP_IDX() to use 3 * bw, since there are 3 _gi values]
-Signed-off-by: Johannes Berg <johannes.berg@intel.com>
----
- create mode 100644 net/mac80211/airtime.c
-
---- a/include/net/mac80211.h
-+++ b/include/net/mac80211.h
-@@ -6419,4 +6419,33 @@ void ieee80211_nan_func_match(struct iee
- 			      struct cfg80211_nan_match_params *match,
- 			      gfp_t gfp);
- 
-+/**
-+ * ieee80211_calc_rx_airtime - calculate estimated transmission airtime for RX.
-+ *
-+ * This function calculates the estimated airtime usage of a frame based on the
-+ * rate information in the RX status struct and the frame length.
-+ *
-+ * @hw: pointer as obtained from ieee80211_alloc_hw()
-+ * @status: &struct ieee80211_rx_status containing the transmission rate
-+ *          information.
-+ * @len: frame length in bytes
-+ */
-+u32 ieee80211_calc_rx_airtime(struct ieee80211_hw *hw,
-+			      struct ieee80211_rx_status *status,
-+			      int len);
-+
-+/**
-+ * ieee80211_calc_tx_airtime - calculate estimated transmission airtime for TX.
-+ *
-+ * This function calculates the estimated airtime usage of a frame based on the
-+ * rate information in the TX info struct and the frame length.
-+ *
-+ * @hw: pointer as obtained from ieee80211_alloc_hw()
-+ * @info: &struct ieee80211_tx_info of the frame.
-+ * @len: frame length in bytes
-+ */
-+u32 ieee80211_calc_tx_airtime(struct ieee80211_hw *hw,
-+			      struct ieee80211_tx_info *info,
-+			      int len);
-+
- #endif /* MAC80211_H */
---- a/net/mac80211/Makefile
-+++ b/net/mac80211/Makefile
-@@ -31,7 +31,8 @@ mac80211-y := \
- 	chan.o \
- 	trace.o mlme.o \
- 	tdls.o \
--	ocb.o
-+	ocb.o \
-+	airtime.o
- 
- mac80211-$(CPTCFG_MAC80211_LEDS) += led.o
- mac80211-$(CPTCFG_MAC80211_DEBUGFS) += \
---- /dev/null
-+++ b/net/mac80211/airtime.c
-@@ -0,0 +1,597 @@
-+// SPDX-License-Identifier: ISC
-+/*
-+ * Copyright (C) 2019 Felix Fietkau <nbd@nbd.name>
-+ */
-+
-+#include <net/mac80211.h>
-+#include "ieee80211_i.h"
-+#include "sta_info.h"
-+
-+#define AVG_PKT_SIZE	1024
-+
-+/* Number of bits for an average sized packet */
-+#define MCS_NBITS (AVG_PKT_SIZE << 3)
-+
-+/* Number of kilo-symbols (symbols * 1024) for a packet with (bps) bits per
-+ * symbol. We use k-symbols to avoid rounding in the _TIME macros below.
-+ */
-+#define MCS_N_KSYMS(bps) DIV_ROUND_UP(MCS_NBITS << 10, (bps))
-+
-+/* Transmission time (in 1024 * usec) for a packet containing (ksyms) * 1024
-+ * symbols.
-+ */
-+#define MCS_SYMBOL_TIME(sgi, ksyms)					\
-+	(sgi ?								\
-+	  ((ksyms) * 4 * 18) / 20 :		/* 3.6 us per sym */	\
-+	  ((ksyms) * 4)			/* 4.0 us per sym */	\
-+	)
-+
-+/* Transmit duration for the raw data part of an average sized packet */
-+#define MCS_DURATION(streams, sgi, bps) \
-+	((u32)MCS_SYMBOL_TIME(sgi, MCS_N_KSYMS((streams) * (bps))))
-+
-+#define MCS_DURATION_S(shift, streams, sgi, bps)		\
-+	((u16)((MCS_DURATION(streams, sgi, bps) >> shift)))
-+
-+/* These should match the values in enum nl80211_he_gi */
-+#define HE_GI_08 0
-+#define HE_GI_16 1
-+#define HE_GI_32 2
-+
-+/* Transmission time (1024 usec) for a packet containing (ksyms) * k-symbols */
-+#define HE_SYMBOL_TIME(gi, ksyms)					\
-+	(gi == HE_GI_08 ?						\
-+	 ((ksyms) * 16 * 17) / 20 :		/* 13.6 us per sym */	\
-+	 (gi == HE_GI_16 ?						\
-+	  ((ksyms) * 16 * 18) / 20 :		/* 14.4 us per sym */	\
-+	  ((ksyms) * 16)			/* 16.0 us per sym */	\
-+	 ))
-+
-+/* Transmit duration for the raw data part of an average sized packet */
-+#define HE_DURATION(streams, gi, bps) \
-+	((u32)HE_SYMBOL_TIME(gi, MCS_N_KSYMS((streams) * (bps))))
-+
-+#define HE_DURATION_S(shift, streams, gi, bps)		\
-+	(HE_DURATION(streams, gi, bps) >> shift)
-+
-+#define BW_20			0
-+#define BW_40			1
-+#define BW_80			2
-+#define BW_160			3
-+
-+/*
-+ * Define group sort order: HT40 -> SGI -> #streams
-+ */
-+#define IEEE80211_MAX_STREAMS		4
-+#define IEEE80211_HT_STREAM_GROUPS	4 /* BW(=2) * SGI(=2) */
-+#define IEEE80211_VHT_STREAM_GROUPS	8 /* BW(=4) * SGI(=2) */
-+
-+#define IEEE80211_HE_MAX_STREAMS	8
-+#define IEEE80211_HE_STREAM_GROUPS	12 /* BW(=4) * GI(=3) */
-+
-+#define IEEE80211_HT_GROUPS_NB	(IEEE80211_MAX_STREAMS *	\
-+				 IEEE80211_HT_STREAM_GROUPS)
-+#define IEEE80211_VHT_GROUPS_NB	(IEEE80211_MAX_STREAMS *	\
-+					 IEEE80211_VHT_STREAM_GROUPS)
-+#define IEEE80211_HE_GROUPS_NB	(IEEE80211_HE_MAX_STREAMS *	\
-+				 IEEE80211_HE_STREAM_GROUPS)
-+#define IEEE80211_GROUPS_NB	(IEEE80211_HT_GROUPS_NB +	\
-+				 IEEE80211_VHT_GROUPS_NB +	\
-+				 IEEE80211_HE_GROUPS_NB)
-+
-+#define IEEE80211_HT_GROUP_0	0
-+#define IEEE80211_VHT_GROUP_0	(IEEE80211_HT_GROUP_0 + IEEE80211_HT_GROUPS_NB)
-+#define IEEE80211_HE_GROUP_0	(IEEE80211_VHT_GROUP_0 + IEEE80211_VHT_GROUPS_NB)
-+
-+#define MCS_GROUP_RATES		12
-+
-+#define HT_GROUP_IDX(_streams, _sgi, _ht40)	\
-+	IEEE80211_HT_GROUP_0 +			\
-+	IEEE80211_MAX_STREAMS * 2 * _ht40 +	\
-+	IEEE80211_MAX_STREAMS * _sgi +		\
-+	_streams - 1
-+
-+#define _MAX(a, b) (((a)>(b))?(a):(b))
-+
-+#define GROUP_SHIFT(duration)						\
-+	_MAX(0, 16 - __builtin_clz(duration))
-+
-+/* MCS rate information for an MCS group */
-+#define __MCS_GROUP(_streams, _sgi, _ht40, _s)				\
-+	[HT_GROUP_IDX(_streams, _sgi, _ht40)] = {			\
-+	.shift = _s,							\
-+	.duration = {							\
-+		MCS_DURATION_S(_s, _streams, _sgi, _ht40 ? 54 : 26),	\
-+		MCS_DURATION_S(_s, _streams, _sgi, _ht40 ? 108 : 52),	\
-+		MCS_DURATION_S(_s, _streams, _sgi, _ht40 ? 162 : 78),	\
-+		MCS_DURATION_S(_s, _streams, _sgi, _ht40 ? 216 : 104),	\
-+		MCS_DURATION_S(_s, _streams, _sgi, _ht40 ? 324 : 156),	\
-+		MCS_DURATION_S(_s, _streams, _sgi, _ht40 ? 432 : 208),	\
-+		MCS_DURATION_S(_s, _streams, _sgi, _ht40 ? 486 : 234),	\
-+		MCS_DURATION_S(_s, _streams, _sgi, _ht40 ? 540 : 260)	\
-+	}								\
-+}
-+
-+#define MCS_GROUP_SHIFT(_streams, _sgi, _ht40)				\
-+	GROUP_SHIFT(MCS_DURATION(_streams, _sgi, _ht40 ? 54 : 26))
-+
-+#define MCS_GROUP(_streams, _sgi, _ht40)				\
-+	__MCS_GROUP(_streams, _sgi, _ht40,				\
-+		    MCS_GROUP_SHIFT(_streams, _sgi, _ht40))
-+
-+#define VHT_GROUP_IDX(_streams, _sgi, _bw)				\
-+	(IEEE80211_VHT_GROUP_0 +					\
-+	 IEEE80211_MAX_STREAMS * 2 * (_bw) +				\
-+	 IEEE80211_MAX_STREAMS * (_sgi) +				\
-+	 (_streams) - 1)
-+
-+#define BW2VBPS(_bw, r4, r3, r2, r1)					\
-+	(_bw == BW_160 ? r4 : _bw == BW_80 ? r3 : _bw == BW_40 ? r2 : r1)
-+
-+#define __VHT_GROUP(_streams, _sgi, _bw, _s)				\
-+	[VHT_GROUP_IDX(_streams, _sgi, _bw)] = {			\
-+	.shift = _s,							\
-+	.duration = {							\
-+		MCS_DURATION_S(_s, _streams, _sgi,			\
-+			       BW2VBPS(_bw,  234,  117,  54,  26)),	\
-+		MCS_DURATION_S(_s, _streams, _sgi,			\
-+			       BW2VBPS(_bw,  468,  234, 108,  52)),	\
-+		MCS_DURATION_S(_s, _streams, _sgi,			\
-+			       BW2VBPS(_bw,  702,  351, 162,  78)),	\
-+		MCS_DURATION_S(_s, _streams, _sgi,			\
-+			       BW2VBPS(_bw,  936,  468, 216, 104)),	\
-+		MCS_DURATION_S(_s, _streams, _sgi,			\
-+			       BW2VBPS(_bw, 1404,  702, 324, 156)),	\
-+		MCS_DURATION_S(_s, _streams, _sgi,			\
-+			       BW2VBPS(_bw, 1872,  936, 432, 208)),	\
-+		MCS_DURATION_S(_s, _streams, _sgi,			\
-+			       BW2VBPS(_bw, 2106, 1053, 486, 234)),	\
-+		MCS_DURATION_S(_s, _streams, _sgi,			\
-+			       BW2VBPS(_bw, 2340, 1170, 540, 260)),	\
-+		MCS_DURATION_S(_s, _streams, _sgi,			\
-+			       BW2VBPS(_bw, 2808, 1404, 648, 312)),	\
-+		MCS_DURATION_S(_s, _streams, _sgi,			\
-+			       BW2VBPS(_bw, 3120, 1560, 720, 346))	\
-+        }								\
-+}
-+
-+#define VHT_GROUP_SHIFT(_streams, _sgi, _bw)				\
-+	GROUP_SHIFT(MCS_DURATION(_streams, _sgi,			\
-+				 BW2VBPS(_bw, 243, 117,  54,  26)))
-+
-+#define VHT_GROUP(_streams, _sgi, _bw)					\
-+	__VHT_GROUP(_streams, _sgi, _bw,				\
-+		    VHT_GROUP_SHIFT(_streams, _sgi, _bw))
-+
-+
-+#define HE_GROUP_IDX(_streams, _gi, _bw)				\
-+	(IEEE80211_HE_GROUP_0 +					\
-+	 IEEE80211_HE_MAX_STREAMS * 3 * (_bw) +			\
-+	 IEEE80211_HE_MAX_STREAMS * (_gi) +				\
-+	 (_streams) - 1)
-+
-+#define __HE_GROUP(_streams, _gi, _bw, _s)				\
-+	[HE_GROUP_IDX(_streams, _gi, _bw)] = {			\
-+	.shift = _s,							\
-+	.duration = {							\
-+		HE_DURATION_S(_s, _streams, _gi,			\
-+			      BW2VBPS(_bw,   979,  489,  230,  115)),	\
-+		HE_DURATION_S(_s, _streams, _gi,			\
-+			      BW2VBPS(_bw,  1958,  979,  475,  230)),	\
-+		HE_DURATION_S(_s, _streams, _gi,			\
-+			      BW2VBPS(_bw,  2937, 1468,  705,  345)),	\
-+		HE_DURATION_S(_s, _streams, _gi,			\
-+			      BW2VBPS(_bw,  3916, 1958,  936,  475)),	\
-+		HE_DURATION_S(_s, _streams, _gi,			\
-+			      BW2VBPS(_bw,  5875, 2937, 1411,  705)),	\
-+		HE_DURATION_S(_s, _streams, _gi,			\
-+			      BW2VBPS(_bw,  7833, 3916, 1872,  936)),	\
-+		HE_DURATION_S(_s, _streams, _gi,			\
-+			      BW2VBPS(_bw,  8827, 4406, 2102, 1051)),	\
-+		HE_DURATION_S(_s, _streams, _gi,			\
-+			      BW2VBPS(_bw,  9806, 4896, 2347, 1166)),	\
-+		HE_DURATION_S(_s, _streams, _gi,			\
-+			      BW2VBPS(_bw, 11764, 5875, 2808, 1411)),	\
-+		HE_DURATION_S(_s, _streams, _gi,			\
-+			      BW2VBPS(_bw, 13060, 6523, 3124, 1555)),	\
-+		HE_DURATION_S(_s, _streams, _gi,			\
-+			      BW2VBPS(_bw, 14702, 7344, 3513, 1756)),	\
-+		HE_DURATION_S(_s, _streams, _gi,			\
-+			      BW2VBPS(_bw, 16329, 8164, 3902, 1944))	\
-+        }								\
-+}
-+
-+#define HE_GROUP_SHIFT(_streams, _gi, _bw)				\
-+	GROUP_SHIFT(HE_DURATION(_streams, _gi,			\
-+				BW2VBPS(_bw,   979,  489,  230,  115)))
-+
-+#define HE_GROUP(_streams, _gi, _bw)					\
-+	__HE_GROUP(_streams, _gi, _bw,				\
-+		   HE_GROUP_SHIFT(_streams, _gi, _bw))
-+struct mcs_group {
-+	u8 shift;
-+	u16 duration[MCS_GROUP_RATES];
-+};
-+
-+static const struct mcs_group airtime_mcs_groups[] = {
-+	MCS_GROUP(1, 0, BW_20),
-+	MCS_GROUP(2, 0, BW_20),
-+	MCS_GROUP(3, 0, BW_20),
-+	MCS_GROUP(4, 0, BW_20),
-+
-+	MCS_GROUP(1, 1, BW_20),
-+	MCS_GROUP(2, 1, BW_20),
-+	MCS_GROUP(3, 1, BW_20),
-+	MCS_GROUP(4, 1, BW_20),
-+
-+	MCS_GROUP(1, 0, BW_40),
-+	MCS_GROUP(2, 0, BW_40),
-+	MCS_GROUP(3, 0, BW_40),
-+	MCS_GROUP(4, 0, BW_40),
-+
-+	MCS_GROUP(1, 1, BW_40),
-+	MCS_GROUP(2, 1, BW_40),
-+	MCS_GROUP(3, 1, BW_40),
-+	MCS_GROUP(4, 1, BW_40),
-+
-+	VHT_GROUP(1, 0, BW_20),
-+	VHT_GROUP(2, 0, BW_20),
-+	VHT_GROUP(3, 0, BW_20),
-+	VHT_GROUP(4, 0, BW_20),
-+
-+	VHT_GROUP(1, 1, BW_20),
-+	VHT_GROUP(2, 1, BW_20),
-+	VHT_GROUP(3, 1, BW_20),
-+	VHT_GROUP(4, 1, BW_20),
-+
-+	VHT_GROUP(1, 0, BW_40),
-+	VHT_GROUP(2, 0, BW_40),
-+	VHT_GROUP(3, 0, BW_40),
-+	VHT_GROUP(4, 0, BW_40),
-+
-+	VHT_GROUP(1, 1, BW_40),
-+	VHT_GROUP(2, 1, BW_40),
-+	VHT_GROUP(3, 1, BW_40),
-+	VHT_GROUP(4, 1, BW_40),
-+
-+	VHT_GROUP(1, 0, BW_80),
-+	VHT_GROUP(2, 0, BW_80),
-+	VHT_GROUP(3, 0, BW_80),
-+	VHT_GROUP(4, 0, BW_80),
-+
-+	VHT_GROUP(1, 1, BW_80),
-+	VHT_GROUP(2, 1, BW_80),
-+	VHT_GROUP(3, 1, BW_80),
-+	VHT_GROUP(4, 1, BW_80),
-+
-+	VHT_GROUP(1, 0, BW_160),
-+	VHT_GROUP(2, 0, BW_160),
-+	VHT_GROUP(3, 0, BW_160),
-+	VHT_GROUP(4, 0, BW_160),
-+
-+	VHT_GROUP(1, 1, BW_160),
-+	VHT_GROUP(2, 1, BW_160),
-+	VHT_GROUP(3, 1, BW_160),
-+	VHT_GROUP(4, 1, BW_160),
-+
-+	HE_GROUP(1, HE_GI_08, BW_20),
-+	HE_GROUP(2, HE_GI_08, BW_20),
-+	HE_GROUP(3, HE_GI_08, BW_20),
-+	HE_GROUP(4, HE_GI_08, BW_20),
-+	HE_GROUP(5, HE_GI_08, BW_20),
-+	HE_GROUP(6, HE_GI_08, BW_20),
-+	HE_GROUP(7, HE_GI_08, BW_20),
-+	HE_GROUP(8, HE_GI_08, BW_20),
-+
-+	HE_GROUP(1, HE_GI_16, BW_20),
-+	HE_GROUP(2, HE_GI_16, BW_20),
-+	HE_GROUP(3, HE_GI_16, BW_20),
-+	HE_GROUP(4, HE_GI_16, BW_20),
-+	HE_GROUP(5, HE_GI_16, BW_20),
-+	HE_GROUP(6, HE_GI_16, BW_20),
-+	HE_GROUP(7, HE_GI_16, BW_20),
-+	HE_GROUP(8, HE_GI_16, BW_20),
-+
-+	HE_GROUP(1, HE_GI_32, BW_20),
-+	HE_GROUP(2, HE_GI_32, BW_20),
-+	HE_GROUP(3, HE_GI_32, BW_20),
-+	HE_GROUP(4, HE_GI_32, BW_20),
-+	HE_GROUP(5, HE_GI_32, BW_20),
-+	HE_GROUP(6, HE_GI_32, BW_20),
-+	HE_GROUP(7, HE_GI_32, BW_20),
-+	HE_GROUP(8, HE_GI_32, BW_20),
-+
-+	HE_GROUP(1, HE_GI_08, BW_40),
-+	HE_GROUP(2, HE_GI_08, BW_40),
-+	HE_GROUP(3, HE_GI_08, BW_40),
-+	HE_GROUP(4, HE_GI_08, BW_40),
-+	HE_GROUP(5, HE_GI_08, BW_40),
-+	HE_GROUP(6, HE_GI_08, BW_40),
-+	HE_GROUP(7, HE_GI_08, BW_40),
-+	HE_GROUP(8, HE_GI_08, BW_40),
-+
-+	HE_GROUP(1, HE_GI_16, BW_40),
-+	HE_GROUP(2, HE_GI_16, BW_40),
-+	HE_GROUP(3, HE_GI_16, BW_40),
-+	HE_GROUP(4, HE_GI_16, BW_40),
-+	HE_GROUP(5, HE_GI_16, BW_40),
-+	HE_GROUP(6, HE_GI_16, BW_40),
-+	HE_GROUP(7, HE_GI_16, BW_40),
-+	HE_GROUP(8, HE_GI_16, BW_40),
-+
-+	HE_GROUP(1, HE_GI_32, BW_40),
-+	HE_GROUP(2, HE_GI_32, BW_40),
-+	HE_GROUP(3, HE_GI_32, BW_40),
-+	HE_GROUP(4, HE_GI_32, BW_40),
-+	HE_GROUP(5, HE_GI_32, BW_40),
-+	HE_GROUP(6, HE_GI_32, BW_40),
-+	HE_GROUP(7, HE_GI_32, BW_40),
-+	HE_GROUP(8, HE_GI_32, BW_40),
-+
-+	HE_GROUP(1, HE_GI_08, BW_80),
-+	HE_GROUP(2, HE_GI_08, BW_80),
-+	HE_GROUP(3, HE_GI_08, BW_80),
-+	HE_GROUP(4, HE_GI_08, BW_80),
-+	HE_GROUP(5, HE_GI_08, BW_80),
-+	HE_GROUP(6, HE_GI_08, BW_80),
-+	HE_GROUP(7, HE_GI_08, BW_80),
-+	HE_GROUP(8, HE_GI_08, BW_80),
-+
-+	HE_GROUP(1, HE_GI_16, BW_80),
-+	HE_GROUP(2, HE_GI_16, BW_80),
-+	HE_GROUP(3, HE_GI_16, BW_80),
-+	HE_GROUP(4, HE_GI_16, BW_80),
-+	HE_GROUP(5, HE_GI_16, BW_80),
-+	HE_GROUP(6, HE_GI_16, BW_80),
-+	HE_GROUP(7, HE_GI_16, BW_80),
-+	HE_GROUP(8, HE_GI_16, BW_80),
-+
-+	HE_GROUP(1, HE_GI_32, BW_80),
-+	HE_GROUP(2, HE_GI_32, BW_80),
-+	HE_GROUP(3, HE_GI_32, BW_80),
-+	HE_GROUP(4, HE_GI_32, BW_80),
-+	HE_GROUP(5, HE_GI_32, BW_80),
-+	HE_GROUP(6, HE_GI_32, BW_80),
-+	HE_GROUP(7, HE_GI_32, BW_80),
-+	HE_GROUP(8, HE_GI_32, BW_80),
-+
-+	HE_GROUP(1, HE_GI_08, BW_160),
-+	HE_GROUP(2, HE_GI_08, BW_160),
-+	HE_GROUP(3, HE_GI_08, BW_160),
-+	HE_GROUP(4, HE_GI_08, BW_160),
-+	HE_GROUP(5, HE_GI_08, BW_160),
-+	HE_GROUP(6, HE_GI_08, BW_160),
-+	HE_GROUP(7, HE_GI_08, BW_160),
-+	HE_GROUP(8, HE_GI_08, BW_160),
-+
-+	HE_GROUP(1, HE_GI_16, BW_160),
-+	HE_GROUP(2, HE_GI_16, BW_160),
-+	HE_GROUP(3, HE_GI_16, BW_160),
-+	HE_GROUP(4, HE_GI_16, BW_160),
-+	HE_GROUP(5, HE_GI_16, BW_160),
-+	HE_GROUP(6, HE_GI_16, BW_160),
-+	HE_GROUP(7, HE_GI_16, BW_160),
-+	HE_GROUP(8, HE_GI_16, BW_160),
-+
-+	HE_GROUP(1, HE_GI_32, BW_160),
-+	HE_GROUP(2, HE_GI_32, BW_160),
-+	HE_GROUP(3, HE_GI_32, BW_160),
-+	HE_GROUP(4, HE_GI_32, BW_160),
-+	HE_GROUP(5, HE_GI_32, BW_160),
-+	HE_GROUP(6, HE_GI_32, BW_160),
-+	HE_GROUP(7, HE_GI_32, BW_160),
-+	HE_GROUP(8, HE_GI_32, BW_160),
-+};
-+
-+static u32
-+ieee80211_calc_legacy_rate_duration(u16 bitrate, bool short_pre,
-+				    bool cck, int len)
-+{
-+	u32 duration;
-+
-+	if (cck) {
-+		duration = 144 + 48; /* preamble + PLCP */
-+		if (short_pre)
-+			duration >>= 1;
-+
-+		duration += 10; /* SIFS */
-+	} else {
-+		duration = 20 + 16; /* premable + SIFS */
-+	}
-+
-+	len <<= 3;
-+	duration += (len * 10) / bitrate;
-+
-+	return duration;
-+}
-+
-+u32 ieee80211_calc_rx_airtime(struct ieee80211_hw *hw,
-+			      struct ieee80211_rx_status *status,
-+			      int len)
-+{
-+	struct ieee80211_supported_band *sband;
-+	const struct ieee80211_rate *rate;
-+	bool sgi = status->enc_flags & RX_ENC_FLAG_SHORT_GI;
-+	bool sp = status->enc_flags & RX_ENC_FLAG_SHORTPRE;
-+	int bw, streams;
-+	int group, idx;
-+	u32 duration;
-+	bool cck;
-+
-+	switch (status->bw) {
-+	case RATE_INFO_BW_20:
-+		bw = BW_20;
-+		break;
-+	case RATE_INFO_BW_40:
-+		bw = BW_40;
-+		break;
-+	case RATE_INFO_BW_80:
-+		bw = BW_80;
-+		break;
-+	case RATE_INFO_BW_160:
-+		bw = BW_160;
-+		break;
-+	default:
-+		WARN_ON_ONCE(1);
-+		return 0;
-+	}
-+
-+	switch (status->encoding) {
-+	case RX_ENC_LEGACY:
-+		if (WARN_ON_ONCE(status->band > NL80211_BAND_5GHZ))
-+			return 0;
-+
-+		sband = hw->wiphy->bands[status->band];
-+		if (!sband || status->rate_idx > sband->n_bitrates)
-+			return 0;
-+
-+		rate = &sband->bitrates[status->rate_idx];
-+		cck = rate->flags & IEEE80211_RATE_MANDATORY_B;
-+
-+		return ieee80211_calc_legacy_rate_duration(rate->bitrate, sp,
-+							   cck, len);
-+
-+	case RX_ENC_VHT:
-+		streams = status->nss;
-+		idx = status->rate_idx;
-+		group = VHT_GROUP_IDX(streams, sgi, bw);
-+		break;
-+	case RX_ENC_HT:
-+		streams = ((status->rate_idx >> 3) & 3) + 1;
-+		idx = status->rate_idx & 7;
-+		group = HT_GROUP_IDX(streams, sgi, bw);
-+		break;
-+	case RX_ENC_HE:
-+		streams = status->nss;
-+		idx = status->rate_idx;
-+		group = HE_GROUP_IDX(streams, status->he_gi, bw);
-+		break;
-+	default:
-+		WARN_ON_ONCE(1);
-+		return 0;
-+	}
-+
-+	if (WARN_ON_ONCE((status->encoding != RX_ENC_HE && streams > 4) ||
-+			 (status->encoding == RX_ENC_HE && streams > 8)))
-+		return 0;
-+
-+	duration = airtime_mcs_groups[group].duration[idx];
-+	duration <<= airtime_mcs_groups[group].shift;
-+	duration *= len;
-+	duration /= AVG_PKT_SIZE;
-+	duration /= 1024;
-+
-+	duration += 36 + (streams << 2);
-+
-+	return duration;
-+}
-+EXPORT_SYMBOL_GPL(ieee80211_calc_rx_airtime);
-+
-+static u32 ieee80211_calc_tx_airtime_rate(struct ieee80211_hw *hw,
-+					  struct ieee80211_tx_rate *rate,
-+					  u8 band, int len)
-+{
-+	struct ieee80211_rx_status stat = {
-+		.band = band,
-+	};
-+
-+	if (rate->idx < 0 || !rate->count)
-+		return 0;
-+
-+	if (rate->flags & IEEE80211_TX_RC_80_MHZ_WIDTH)
-+		stat.bw = RATE_INFO_BW_80;
-+	else if (rate->flags & IEEE80211_TX_RC_40_MHZ_WIDTH)
-+		stat.bw = RATE_INFO_BW_40;
-+	else
-+		stat.bw = RATE_INFO_BW_20;
-+
-+	stat.enc_flags = 0;
-+	if (rate->flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE)
-+		stat.enc_flags |= RX_ENC_FLAG_SHORTPRE;
-+	if (rate->flags & IEEE80211_TX_RC_SHORT_GI)
-+		stat.enc_flags |= RX_ENC_FLAG_SHORT_GI;
-+
-+	stat.rate_idx = rate->idx;
-+	if (rate->flags & IEEE80211_TX_RC_VHT_MCS) {
-+		stat.encoding = RX_ENC_VHT;
-+		stat.rate_idx = ieee80211_rate_get_vht_mcs(rate);
-+		stat.nss = ieee80211_rate_get_vht_nss(rate);
-+	} else if (rate->flags & IEEE80211_TX_RC_MCS) {
-+		stat.encoding = RX_ENC_HT;
-+	} else {
-+		stat.encoding = RX_ENC_LEGACY;
-+	}
-+
-+	return ieee80211_calc_rx_airtime(hw, &stat, len);
-+}
-+
-+u32 ieee80211_calc_tx_airtime(struct ieee80211_hw *hw,
-+			      struct ieee80211_tx_info *info,
-+			      int len)
-+{
-+	u32 duration = 0;
-+	int i;
-+
-+	for (i = 0; i < ARRAY_SIZE(info->status.rates); i++) {
-+		struct ieee80211_tx_rate *rate = &info->status.rates[i];
-+		u32 cur_duration;
-+
-+		cur_duration = ieee80211_calc_tx_airtime_rate(hw, rate,
-+							      info->band, len);
-+		if (!cur_duration)
-+			break;
-+
-+		duration += cur_duration * rate->count;
-+	}
-+
-+	return duration;
-+}
-+EXPORT_SYMBOL_GPL(ieee80211_calc_tx_airtime);
-+
-+u32 ieee80211_calc_expected_tx_airtime(struct ieee80211_hw *hw,
-+				       struct ieee80211_vif *vif,
-+				       struct ieee80211_sta *pubsta,
-+				       int len)
-+{
-+	struct ieee80211_supported_band *sband;
-+	struct ieee80211_chanctx_conf *conf;
-+	int rateidx, shift = 0;
-+	bool cck, short_pream;
-+	u32 basic_rates;
-+	u8 band = 0;
-+	u16 rate;
-+
-+	len += 38; /* Ethernet header length */
-+
-+	conf = rcu_dereference(vif->chanctx_conf);
-+	if (conf) {
-+		band = conf->def.chan->band;
-+		shift = ieee80211_chandef_get_shift(&conf->def);
-+	}
-+
-+	if (pubsta) {
-+		struct sta_info *sta = container_of(pubsta, struct sta_info,
-+						    sta);
-+
-+		return ieee80211_calc_tx_airtime_rate(hw,
-+						      &sta->tx_stats.last_rate,
-+						      band, len);
-+	}
-+
-+	if (!conf)
-+		return 0;
-+
-+	/* No station to get latest rate from, so calculate the worst-case
-+	 * duration using the lowest configured basic rate.
-+	 */
-+	sband = hw->wiphy->bands[band];
-+
-+	basic_rates = vif->bss_conf.basic_rates;
-+	short_pream = vif->bss_conf.use_short_preamble;
-+
-+	rateidx = basic_rates ? ffs(basic_rates) - 1 : 0;
-+	rate = sband->bitrates[rateidx].bitrate << shift;
-+	cck = sband->bitrates[rateidx].flags & IEEE80211_RATE_MANDATORY_B;
-+
-+	return ieee80211_calc_legacy_rate_duration(rate, short_pream, cck, len);
-+}
---- a/net/mac80211/ieee80211_i.h
-+++ b/net/mac80211/ieee80211_i.h
-@@ -2253,6 +2253,10 @@ const char *ieee80211_get_reason_code_st
- 
- extern const struct ethtool_ops ieee80211_ethtool_ops;
- 
-+u32 ieee80211_calc_expected_tx_airtime(struct ieee80211_hw *hw,
-+				       struct ieee80211_vif *vif,
-+				       struct ieee80211_sta *pubsta,
-+				       int len);
- #ifdef CPTCFG_MAC80211_NOINLINE
- #define debug_noinline noinline
- #else
diff --git a/package/kernel/mac80211/patches/subsys/310-mac80211-Implement-Airtime-based-Queue-Limit-AQL.patch b/package/kernel/mac80211/patches/subsys/310-mac80211-Implement-Airtime-based-Queue-Limit-AQL.patch
deleted file mode 100644
index b76286d15c68..000000000000
--- a/package/kernel/mac80211/patches/subsys/310-mac80211-Implement-Airtime-based-Queue-Limit-AQL.patch
+++ /dev/null
@@ -1,446 +0,0 @@
-From: Kan Yan <kyan@google.com>
-Date: Mon, 18 Nov 2019 22:06:09 -0800
-Subject: [PATCH] mac80211: Implement Airtime-based Queue Limit (AQL)
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-In order for the Fq_CoDel algorithm integrated in mac80211 layer to operate
-effectively to control excessive queueing latency, the CoDel algorithm
-requires an accurate measure of how long packets stays in the queue, AKA
-sojourn time. The sojourn time measured at the mac80211 layer doesn't
-include queueing latency in the lower layer (firmware/hardware) and CoDel
-expects lower layer to have a short queue. However, most 802.11ac chipsets
-offload tasks such TX aggregation to firmware or hardware, thus have a deep
-lower layer queue.
-
-Without a mechanism to control the lower layer queue size, packets only
-stay in mac80211 layer transiently before being sent to firmware queue.
-As a result, the sojourn time measured by CoDel in the mac80211 layer is
-almost always lower than the CoDel latency target, hence CoDel does little
-to control the latency, even when the lower layer queue causes excessive
-latency.
-
-The Byte Queue Limits (BQL) mechanism is commonly used to address the
-similar issue with wired network interface. However, this method cannot be
-applied directly to the wireless network interface. "Bytes" is not a
-suitable measure of queue depth in the wireless network, as the data rate
-can vary dramatically from station to station in the same network, from a
-few Mbps to over Gbps.
-
-This patch implements an Airtime-based Queue Limit (AQL) to make CoDel work
-effectively with wireless drivers that utilized firmware/hardware
-offloading. AQL allows each txq to release just enough packets to the lower
-layer to form 1-2 large aggregations to keep hardware fully utilized and
-retains the rest of the frames in mac80211 layer to be controlled by the
-CoDel algorithm.
-
-Signed-off-by: Kan Yan <kyan@google.com>
-[ Toke: Keep API to set pending airtime internal, fix nits in commit msg ]
-Signed-off-by: Toke Høiland-Jørgensen <toke@redhat.com>
-Link: https://lore.kernel.org/r/20191119060610.76681-4-kyan@google.com
-Signed-off-by: Johannes Berg <johannes.berg@intel.com>
----
-
---- a/include/net/cfg80211.h
-+++ b/include/net/cfg80211.h
-@@ -2603,6 +2603,13 @@ enum wiphy_params_flags {
- 
- #define IEEE80211_DEFAULT_AIRTIME_WEIGHT	256
- 
-+/* The per TXQ device queue limit in airtime */
-+#define IEEE80211_DEFAULT_AQL_TXQ_LIMIT_L	5000
-+#define IEEE80211_DEFAULT_AQL_TXQ_LIMIT_H	12000
-+
-+/* The per interface airtime threshold to switch to lower queue limit */
-+#define IEEE80211_AQL_THRESHOLD			24000
-+
- /**
-  * struct cfg80211_pmksa - PMK Security Association
-  *
---- a/include/net/mac80211.h
-+++ b/include/net/mac80211.h
-@@ -5559,6 +5559,18 @@ void ieee80211_sta_register_airtime(stru
- 				    u32 tx_airtime, u32 rx_airtime);
- 
- /**
-+ * ieee80211_txq_airtime_check - check if a txq can send frame to device
-+ *
-+ * @hw: pointer obtained from ieee80211_alloc_hw()
-+ * @txq: pointer obtained from station or virtual interface
-+ *
-+ * Return true if the AQL's airtime limit has not been reached and the txq can
-+ * continue to send more packets to the device. Otherwise return false.
-+ */
-+bool
-+ieee80211_txq_airtime_check(struct ieee80211_hw *hw, struct ieee80211_txq *txq);
-+
-+/**
-  * ieee80211_iter_keys - iterate keys programmed into the device
-  * @hw: pointer obtained from ieee80211_alloc_hw()
-  * @vif: virtual interface to iterate, may be %NULL for all
---- a/net/mac80211/debugfs.c
-+++ b/net/mac80211/debugfs.c
-@@ -148,6 +148,87 @@ static const struct file_operations aqm_
- 	.llseek = default_llseek,
- };
- 
-+static ssize_t aql_txq_limit_read(struct file *file,
-+				  char __user *user_buf,
-+				  size_t count,
-+				  loff_t *ppos)
-+{
-+	struct ieee80211_local *local = file->private_data;
-+	char buf[400];
-+	int len = 0;
-+
-+	len = scnprintf(buf, sizeof(buf),
-+			"AC	AQL limit low	AQL limit high\n"
-+			"VO	%u		%u\n"
-+			"VI	%u		%u\n"
-+			"BE	%u		%u\n"
-+			"BK	%u		%u\n",
-+			local->aql_txq_limit_low[IEEE80211_AC_VO],
-+			local->aql_txq_limit_high[IEEE80211_AC_VO],
-+			local->aql_txq_limit_low[IEEE80211_AC_VI],
-+			local->aql_txq_limit_high[IEEE80211_AC_VI],
-+			local->aql_txq_limit_low[IEEE80211_AC_BE],
-+			local->aql_txq_limit_high[IEEE80211_AC_BE],
-+			local->aql_txq_limit_low[IEEE80211_AC_BK],
-+			local->aql_txq_limit_high[IEEE80211_AC_BK]);
-+	return simple_read_from_buffer(user_buf, count, ppos,
-+				       buf, len);
-+}
-+
-+static ssize_t aql_txq_limit_write(struct file *file,
-+				   const char __user *user_buf,
-+				   size_t count,
-+				   loff_t *ppos)
-+{
-+	struct ieee80211_local *local = file->private_data;
-+	char buf[100];
-+	size_t len;
-+	u32 ac, q_limit_low, q_limit_high, q_limit_low_old, q_limit_high_old;
-+	struct sta_info *sta;
-+
-+	if (count > sizeof(buf))
-+		return -EINVAL;
-+
-+	if (copy_from_user(buf, user_buf, count))
-+		return -EFAULT;
-+
-+	buf[sizeof(buf) - 1] = 0;
-+	len = strlen(buf);
-+	if (len > 0 && buf[len - 1] == '\n')
-+		buf[len - 1] = 0;
-+
-+	if (sscanf(buf, "%u %u %u", &ac, &q_limit_low, &q_limit_high) != 3)
-+		return -EINVAL;
-+
-+	if (ac >= IEEE80211_NUM_ACS)
-+		return -EINVAL;
-+
-+	q_limit_low_old = local->aql_txq_limit_low[ac];
-+	q_limit_high_old = local->aql_txq_limit_high[ac];
-+
-+	local->aql_txq_limit_low[ac] = q_limit_low;
-+	local->aql_txq_limit_high[ac] = q_limit_high;
-+
-+	mutex_lock(&local->sta_mtx);
-+	list_for_each_entry(sta, &local->sta_list, list) {
-+		/* If a sta has customized queue limits, keep it */
-+		if (sta->airtime[ac].aql_limit_low == q_limit_low_old &&
-+		    sta->airtime[ac].aql_limit_high == q_limit_high_old) {
-+			sta->airtime[ac].aql_limit_low = q_limit_low;
-+			sta->airtime[ac].aql_limit_high = q_limit_high;
-+		}
-+	}
-+	mutex_unlock(&local->sta_mtx);
-+	return count;
-+}
-+
-+static const struct file_operations aql_txq_limit_ops = {
-+	.write = aql_txq_limit_write,
-+	.read = aql_txq_limit_read,
-+	.open = simple_open,
-+	.llseek = default_llseek,
-+};
-+
- static ssize_t force_tx_status_read(struct file *file,
- 				    char __user *user_buf,
- 				    size_t count,
-@@ -441,6 +522,10 @@ void debugfs_hw_add(struct ieee80211_loc
- 	debugfs_create_u16("airtime_flags", 0600,
- 			   phyd, &local->airtime_flags);
- 
-+	DEBUGFS_ADD(aql_txq_limit);
-+	debugfs_create_u32("aql_threshold", 0600,
-+			   phyd, &local->aql_threshold);
-+
- 	statsd = debugfs_create_dir("statistics", phyd);
- 
- 	/* if the dir failed, don't put all the other things into the root! */
---- a/net/mac80211/debugfs_sta.c
-+++ b/net/mac80211/debugfs_sta.c
-@@ -198,10 +198,12 @@ static ssize_t sta_airtime_read(struct f
- {
- 	struct sta_info *sta = file->private_data;
- 	struct ieee80211_local *local = sta->sdata->local;
--	size_t bufsz = 200;
-+	size_t bufsz = 400;
- 	char *buf = kzalloc(bufsz, GFP_KERNEL), *p = buf;
- 	u64 rx_airtime = 0, tx_airtime = 0;
- 	s64 deficit[IEEE80211_NUM_ACS];
-+	u32 q_depth[IEEE80211_NUM_ACS];
-+	u32 q_limit_l[IEEE80211_NUM_ACS], q_limit_h[IEEE80211_NUM_ACS];
- 	ssize_t rv;
- 	int ac;
- 
-@@ -213,19 +215,22 @@ static ssize_t sta_airtime_read(struct f
- 		rx_airtime += sta->airtime[ac].rx_airtime;
- 		tx_airtime += sta->airtime[ac].tx_airtime;
- 		deficit[ac] = sta->airtime[ac].deficit;
-+		q_limit_l[ac] = sta->airtime[ac].aql_limit_low;
-+		q_limit_h[ac] = sta->airtime[ac].aql_limit_high;
- 		spin_unlock_bh(&local->active_txq_lock[ac]);
-+		q_depth[ac] = atomic_read(&sta->airtime[ac].aql_tx_pending);
- 	}
- 
- 	p += scnprintf(p, bufsz + buf - p,
- 		"RX: %llu us\nTX: %llu us\nWeight: %u\n"
--		"Deficit: VO: %lld us VI: %lld us BE: %lld us BK: %lld us\n",
--		rx_airtime,
--		tx_airtime,
--		sta->airtime_weight,
--		deficit[0],
--		deficit[1],
--		deficit[2],
--		deficit[3]);
-+		"Deficit: VO: %lld us VI: %lld us BE: %lld us BK: %lld us\n"
-+		"Q depth: VO: %u us VI: %u us BE: %u us BK: %u us\n"
-+		"Q limit[low/high]: VO: %u/%u VI: %u/%u BE: %u/%u BK: %u/%u\n",
-+		rx_airtime, tx_airtime, sta->airtime_weight,
-+		deficit[0], deficit[1], deficit[2], deficit[3],
-+		q_depth[0], q_depth[1], q_depth[2], q_depth[3],
-+		q_limit_l[0], q_limit_h[0], q_limit_l[1], q_limit_h[1],
-+		q_limit_l[2], q_limit_h[2], q_limit_l[3], q_limit_h[3]),
- 
- 	rv = simple_read_from_buffer(userbuf, count, ppos, buf, p - buf);
- 	kfree(buf);
-@@ -237,7 +242,25 @@ static ssize_t sta_airtime_write(struct
- {
- 	struct sta_info *sta = file->private_data;
- 	struct ieee80211_local *local = sta->sdata->local;
--	int ac;
-+	u32 ac, q_limit_l, q_limit_h;
-+	char _buf[100] = {}, *buf = _buf;
-+
-+	if (count > sizeof(_buf))
-+		return -EINVAL;
-+
-+	if (copy_from_user(buf, userbuf, count))
-+		return -EFAULT;
-+
-+	buf[sizeof(_buf) - 1] = '\0';
-+	if (sscanf(buf, "queue limit %u %u %u", &ac, &q_limit_l, &q_limit_h)
-+	    != 3)
-+		return -EINVAL;
-+
-+	if (ac >= IEEE80211_NUM_ACS)
-+		return -EINVAL;
-+
-+	sta->airtime[ac].aql_limit_low = q_limit_l;
-+	sta->airtime[ac].aql_limit_high = q_limit_h;
- 
- 	for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) {
- 		spin_lock_bh(&local->active_txq_lock[ac]);
---- a/net/mac80211/ieee80211_i.h
-+++ b/net/mac80211/ieee80211_i.h
-@@ -1142,6 +1142,10 @@ struct ieee80211_local {
- 	u16 schedule_round[IEEE80211_NUM_ACS];
- 
- 	u16 airtime_flags;
-+	u32 aql_txq_limit_low[IEEE80211_NUM_ACS];
-+	u32 aql_txq_limit_high[IEEE80211_NUM_ACS];
-+	u32 aql_threshold;
-+	atomic_t aql_total_pending_airtime;
- 
- 	const struct ieee80211_ops *ops;
- 
---- a/net/mac80211/main.c
-+++ b/net/mac80211/main.c
-@@ -669,8 +669,16 @@ struct ieee80211_hw *ieee80211_alloc_hw_
- 	for (i = 0; i < IEEE80211_NUM_ACS; i++) {
- 		INIT_LIST_HEAD(&local->active_txqs[i]);
- 		spin_lock_init(&local->active_txq_lock[i]);
-+		local->aql_txq_limit_low[i] = IEEE80211_DEFAULT_AQL_TXQ_LIMIT_L;
-+		local->aql_txq_limit_high[i] =
-+			IEEE80211_DEFAULT_AQL_TXQ_LIMIT_H;
- 	}
--	local->airtime_flags = AIRTIME_USE_TX | AIRTIME_USE_RX;
-+
-+	local->airtime_flags = AIRTIME_USE_TX |
-+			       AIRTIME_USE_RX |
-+			       AIRTIME_USE_AQL;
-+	local->aql_threshold = IEEE80211_AQL_THRESHOLD;
-+	atomic_set(&local->aql_total_pending_airtime, 0);
- 
- 	INIT_LIST_HEAD(&local->chanctx_list);
- 	mutex_init(&local->chanctx_mtx);
---- a/net/mac80211/sta_info.c
-+++ b/net/mac80211/sta_info.c
-@@ -411,6 +411,9 @@ struct sta_info *sta_info_alloc(struct i
- 		skb_queue_head_init(&sta->ps_tx_buf[i]);
- 		skb_queue_head_init(&sta->tx_filtered[i]);
- 		sta->airtime[i].deficit = sta->airtime_weight;
-+		atomic_set(&sta->airtime[i].aql_tx_pending, 0);
-+		sta->airtime[i].aql_limit_low = local->aql_txq_limit_low[i];
-+		sta->airtime[i].aql_limit_high = local->aql_txq_limit_high[i];
- 	}
- 
- 	for (i = 0; i < IEEE80211_NUM_TIDS; i++)
-@@ -1913,6 +1916,41 @@ void ieee80211_sta_register_airtime(stru
- }
- EXPORT_SYMBOL(ieee80211_sta_register_airtime);
- 
-+void ieee80211_sta_update_pending_airtime(struct ieee80211_local *local,
-+					  struct sta_info *sta, u8 ac,
-+					  u16 tx_airtime, bool tx_completed)
-+{
-+	int tx_pending;
-+
-+	if (!tx_completed) {
-+		if (sta)
-+			atomic_add(tx_airtime,
-+				   &sta->airtime[ac].aql_tx_pending);
-+
-+		atomic_add(tx_airtime, &local->aql_total_pending_airtime);
-+		return;
-+	}
-+
-+	if (sta) {
-+		tx_pending = atomic_sub_return(tx_airtime,
-+					       &sta->airtime[ac].aql_tx_pending);
-+		if (WARN_ONCE(tx_pending < 0,
-+			      "STA %pM AC %d txq pending airtime underflow: %u, %u",
-+			      sta->addr, ac, tx_pending, tx_airtime))
-+			atomic_cmpxchg(&sta->airtime[ac].aql_tx_pending,
-+				       tx_pending, 0);
-+	}
-+
-+	tx_pending = atomic_sub_return(tx_airtime,
-+				       &local->aql_total_pending_airtime);
-+	if (WARN_ONCE(tx_pending < 0,
-+		      "Device %s AC %d pending airtime underflow: %u, %u",
-+		      wiphy_name(local->hw.wiphy), ac, tx_pending,
-+		      tx_airtime))
-+		atomic_cmpxchg(&local->aql_total_pending_airtime,
-+			       tx_pending, 0);
-+}
-+
- int sta_info_move_state(struct sta_info *sta,
- 			enum ieee80211_sta_state new_state)
- {
---- a/net/mac80211/sta_info.h
-+++ b/net/mac80211/sta_info.h
-@@ -128,13 +128,21 @@ enum ieee80211_agg_stop_reason {
- /* Debugfs flags to enable/disable use of RX/TX airtime in scheduler */
- #define AIRTIME_USE_TX		BIT(0)
- #define AIRTIME_USE_RX		BIT(1)
-+#define AIRTIME_USE_AQL		BIT(2)
- 
- struct airtime_info {
- 	u64 rx_airtime;
- 	u64 tx_airtime;
- 	s64 deficit;
-+	atomic_t aql_tx_pending; /* Estimated airtime for frames pending */
-+	u32 aql_limit_low;
-+	u32 aql_limit_high;
- };
- 
-+void ieee80211_sta_update_pending_airtime(struct ieee80211_local *local,
-+					  struct sta_info *sta, u8 ac,
-+					  u16 tx_airtime, bool tx_completed);
-+
- struct sta_info;
- 
- /**
---- a/net/mac80211/tx.c
-+++ b/net/mac80211/tx.c
-@@ -3700,7 +3700,8 @@ struct ieee80211_txq *ieee80211_next_txq
- {
- 	struct ieee80211_local *local = hw_to_local(hw);
- 	struct ieee80211_txq *ret = NULL;
--	struct txq_info *txqi = NULL;
-+	struct txq_info *txqi = NULL, *head = NULL;
-+	bool found_eligible_txq = false;
- 
- 	spin_lock_bh(&local->active_txq_lock[ac]);
- 
-@@ -3711,13 +3712,30 @@ struct ieee80211_txq *ieee80211_next_txq
- 	if (!txqi)
- 		goto out;
- 
-+	if (txqi == head) {
-+		if (!found_eligible_txq)
-+			goto out;
-+		else
-+			found_eligible_txq = false;
-+	}
-+
-+	if (!head)
-+		head = txqi;
-+
- 	if (txqi->txq.sta) {
- 		struct sta_info *sta = container_of(txqi->txq.sta,
--						struct sta_info, sta);
-+						    struct sta_info, sta);
-+		bool aql_check = ieee80211_txq_airtime_check(hw, &txqi->txq);
-+		s64 deficit = sta->airtime[txqi->txq.ac].deficit;
- 
--		if (sta->airtime[txqi->txq.ac].deficit < 0) {
-+		if (aql_check)
-+			found_eligible_txq = true;
-+
-+		if (deficit < 0)
- 			sta->airtime[txqi->txq.ac].deficit +=
- 				sta->airtime_weight;
-+
-+		if (deficit < 0 || !aql_check) {
- 			list_move_tail(&txqi->schedule_order,
- 				       &local->active_txqs[txqi->txq.ac]);
- 			goto begin;
-@@ -3771,6 +3789,33 @@ void __ieee80211_schedule_txq(struct iee
- }
- EXPORT_SYMBOL(__ieee80211_schedule_txq);
- 
-+bool ieee80211_txq_airtime_check(struct ieee80211_hw *hw,
-+				 struct ieee80211_txq *txq)
-+{
-+	struct sta_info *sta;
-+	struct ieee80211_local *local = hw_to_local(hw);
-+
-+	if (!(local->airtime_flags & AIRTIME_USE_AQL))
-+		return true;
-+
-+	if (!txq->sta)
-+		return true;
-+
-+	sta = container_of(txq->sta, struct sta_info, sta);
-+	if (atomic_read(&sta->airtime[txq->ac].aql_tx_pending) <
-+	    sta->airtime[txq->ac].aql_limit_low)
-+		return true;
-+
-+	if (atomic_read(&local->aql_total_pending_airtime) <
-+	    local->aql_threshold &&
-+	    atomic_read(&sta->airtime[txq->ac].aql_tx_pending) <
-+	    sta->airtime[txq->ac].aql_limit_high)
-+		return true;
-+
-+	return false;
-+}
-+EXPORT_SYMBOL(ieee80211_txq_airtime_check);
-+
- bool ieee80211_txq_may_transmit(struct ieee80211_hw *hw,
- 				struct ieee80211_txq *txq)
- {
diff --git a/package/kernel/mac80211/patches/subsys/311-mac80211-Use-Airtime-based-Queue-Limits-AQL-on-packe.patch b/package/kernel/mac80211/patches/subsys/311-mac80211-Use-Airtime-based-Queue-Limits-AQL-on-packe.patch
deleted file mode 100644
index a0548d9d057a..000000000000
--- a/package/kernel/mac80211/patches/subsys/311-mac80211-Use-Airtime-based-Queue-Limits-AQL-on-packe.patch
+++ /dev/null
@@ -1,146 +0,0 @@
-From: =?UTF-8?q?Toke=20H=C3=B8iland-J=C3=B8rgensen?= <toke@redhat.com>
-Date: Mon, 18 Nov 2019 22:06:10 -0800
-Subject: [PATCH] mac80211: Use Airtime-based Queue Limits (AQL) on packet
- dequeue
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-The previous commit added the ability to throttle stations when they queue
-too much airtime in the hardware. This commit enables the functionality by
-calculating the expected airtime usage of each packet that is dequeued from
-the TXQs in mac80211, and accounting that as pending airtime.
-
-The estimated airtime for each skb is stored in the tx_info, so we can
-subtract the same amount from the running total when the skb is freed or
-recycled. The throttling mechanism relies on this accounting to be
-accurate (i.e., that we are not freeing skbs without subtracting any
-airtime they were accounted for), so we put the subtraction into
-ieee80211_report_used_skb(). As an optimisation, we also subtract the
-airtime on regular TX completion, zeroing out the value stored in the
-packet afterwards, to avoid having to do an expensive lookup of the station
-from the packet data on every packet.
-
-This patch does *not* include any mechanism to wake a throttled TXQ again,
-on the assumption that this will happen anyway as a side effect of whatever
-freed the skb (most commonly a TX completion).
-
-Signed-off-by: Toke Høiland-Jørgensen <toke@redhat.com>
-Link: https://lore.kernel.org/r/20191119060610.76681-5-kyan@google.com
-Signed-off-by: Johannes Berg <johannes.berg@intel.com>
----
-
---- a/include/net/mac80211.h
-+++ b/include/net/mac80211.h
-@@ -1060,6 +1060,22 @@ struct ieee80211_tx_info {
- 	};
- };
- 
-+static inline u16
-+ieee80211_info_set_tx_time_est(struct ieee80211_tx_info *info, u16 tx_time_est)
-+{
-+	/* We only have 10 bits in tx_time_est, so store airtime
-+	 * in increments of 4us and clamp the maximum to 2**12-1
-+	 */
-+	info->tx_time_est = min_t(u16, tx_time_est, 4095) >> 2;
-+	return info->tx_time_est << 2;
-+}
-+
-+static inline u16
-+ieee80211_info_get_tx_time_est(struct ieee80211_tx_info *info)
-+{
-+	return info->tx_time_est << 2;
-+}
-+
- /**
-  * struct ieee80211_tx_status - extended tx staus info for rate control
-  *
---- a/net/mac80211/status.c
-+++ b/net/mac80211/status.c
-@@ -670,12 +670,26 @@ static void ieee80211_report_used_skb(st
- 				      struct sk_buff *skb, bool dropped)
- {
- 	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
-+	u16 tx_time_est = ieee80211_info_get_tx_time_est(info);
- 	struct ieee80211_hdr *hdr = (void *)skb->data;
- 	bool acked = info->flags & IEEE80211_TX_STAT_ACK;
- 
- 	if (dropped)
- 		acked = false;
- 
-+	if (tx_time_est) {
-+		struct sta_info *sta;
-+
-+		rcu_read_lock();
-+
-+		sta = sta_info_get_by_addrs(local, hdr->addr1, hdr->addr2);
-+		ieee80211_sta_update_pending_airtime(local, sta,
-+						     skb_get_queue_mapping(skb),
-+						     tx_time_est,
-+						     true);
-+		rcu_read_unlock();
-+	}
-+
- 	if (info->flags & IEEE80211_TX_INTFL_MLME_CONN_TX) {
- 		struct ieee80211_sub_if_data *sdata;
- 
-@@ -885,6 +899,7 @@ static void __ieee80211_tx_status(struct
- 	struct ieee80211_bar *bar;
- 	int shift = 0;
- 	int tid = IEEE80211_NUM_TIDS;
-+	u16 tx_time_est;
- 
- 	rates_idx = ieee80211_tx_get_rates(hw, info, &retry_count);
- 
-@@ -996,6 +1011,17 @@ static void __ieee80211_tx_status(struct
- 			ieee80211_sta_register_airtime(&sta->sta, tid,
- 						       info->status.tx_time, 0);
- 
-+		if ((tx_time_est = ieee80211_info_get_tx_time_est(info)) > 0) {
-+			/* Do this here to avoid the expensive lookup of the sta
-+			 * in ieee80211_report_used_skb().
-+			 */
-+			ieee80211_sta_update_pending_airtime(local, sta,
-+							     skb_get_queue_mapping(skb),
-+							     tx_time_est,
-+							     true);
-+			ieee80211_info_set_tx_time_est(info, 0);
-+		}
-+
- 		if (ieee80211_hw_check(&local->hw, REPORTS_TX_ACK_STATUS)) {
- 			if (acked) {
- 				if (sta->status_stats.lost_packets)
---- a/net/mac80211/tx.c
-+++ b/net/mac80211/tx.c
-@@ -3559,6 +3559,9 @@ struct sk_buff *ieee80211_tx_dequeue(str
- 
- 	WARN_ON_ONCE(softirq_count() == 0);
- 
-+	if (!ieee80211_txq_airtime_check(hw, txq))
-+		return NULL;
-+
- begin:
- 	spin_lock_bh(&fq->lock);
- 
-@@ -3687,6 +3690,21 @@ begin:
- 	}
- 
- 	IEEE80211_SKB_CB(skb)->control.vif = vif;
-+
-+	if (local->airtime_flags & AIRTIME_USE_AQL) {
-+		u32 airtime;
-+
-+		airtime = ieee80211_calc_expected_tx_airtime(hw, vif, txq->sta,
-+							     skb->len);
-+		if (airtime) {
-+			airtime = ieee80211_info_set_tx_time_est(info, airtime);
-+			ieee80211_sta_update_pending_airtime(local, tx.sta,
-+							     txq->ac,
-+							     airtime,
-+							     false);
-+		}
-+	}
-+
- 	return skb;
- 
- out:
diff --git a/package/kernel/mac80211/patches/subsys/312-mac80211-airtime-Fix-an-off-by-one-in-ieee80211_calc.patch b/package/kernel/mac80211/patches/subsys/312-mac80211-airtime-Fix-an-off-by-one-in-ieee80211_calc.patch
deleted file mode 100644
index 4ff496c12e6d..000000000000
--- a/package/kernel/mac80211/patches/subsys/312-mac80211-airtime-Fix-an-off-by-one-in-ieee80211_calc.patch
+++ /dev/null
@@ -1,31 +0,0 @@
-From: Dan Carpenter <dan.carpenter@oracle.com>
-Date: Tue, 26 Nov 2019 15:09:39 +0300
-Subject: [PATCH] mac80211: airtime: Fix an off by one in
- ieee80211_calc_rx_airtime()
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-This code was copied from mt76 and inherited an off by one bug from
-there.  The > should be >= so that we don't read one element beyond
-the end of the array.
-
-Fixes: db3e1c40cf2f ("mac80211: Import airtime calculation code from mt76")
-Reported-by: Toke Høiland-Jørgensen <toke@redhat.com>
-Signed-off-by: Dan Carpenter <dan.carpenter@oracle.com>
-Acked-by: Toke Høiland-Jørgensen <toke@redhat.com>
-Link: https://lore.kernel.org/r/20191126120910.ftr4t7me3by32aiz@kili.mountain
-Signed-off-by: Johannes Berg <johannes.berg@intel.com>
----
-
---- a/net/mac80211/airtime.c
-+++ b/net/mac80211/airtime.c
-@@ -442,7 +442,7 @@ u32 ieee80211_calc_rx_airtime(struct iee
- 			return 0;
- 
- 		sband = hw->wiphy->bands[status->band];
--		if (!sband || status->rate_idx > sband->n_bitrates)
-+		if (!sband || status->rate_idx >= sband->n_bitrates)
- 			return 0;
- 
- 		rate = &sband->bitrates[status->rate_idx];
diff --git a/package/kernel/mac80211/patches/subsys/313-mac80211-Turn-AQL-into-an-NL80211_EXT_FEATURE.patch b/package/kernel/mac80211/patches/subsys/313-mac80211-Turn-AQL-into-an-NL80211_EXT_FEATURE.patch
deleted file mode 100644
index 389f2ae225eb..000000000000
--- a/package/kernel/mac80211/patches/subsys/313-mac80211-Turn-AQL-into-an-NL80211_EXT_FEATURE.patch
+++ /dev/null
@@ -1,253 +0,0 @@
-From: =?UTF-8?q?Toke=20H=C3=B8iland-J=C3=B8rgensen?= <toke@redhat.com>
-Date: Thu, 12 Dec 2019 12:14:37 +0100
-Subject: [PATCH] mac80211: Turn AQL into an NL80211_EXT_FEATURE
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-Instead of just having an airtime flag in debugfs, turn AQL into a proper
-NL80211_EXT_FEATURE, so drivers can turn it on when they are ready, and so
-we also expose the presence of the feature to userspace.
-
-This also has the effect of flipping the default, so drivers have to opt in
-to using AQL instead of getting it by default with TXQs. To keep
-functionality the same as pre-patch, we set this feature for ath10k (which
-is where it is needed the most).
-
-While we're at it, split out the debugfs interface so AQL gets its own
-per-station debugfs file instead of using the 'airtime' file.
-
-[Johannes:]
-This effectively disables AQL for iwlwifi, where it fixes a number of
-issues:
- * TSO in iwlwifi is causing underflows and associated warnings in AQL
- * HE (802.11ax) rates aren't reported properly so at HE rates, AQL could
-   never have a valid estimate (it'd use 6 Mbps instead of up to 2400!)
-
-Signed-off-by: Toke Høiland-Jørgensen <toke@redhat.com>
-Link: https://lore.kernel.org/r/20191212111437.224294-1-toke@redhat.com
-Fixes: 3ace10f5b5ad ("mac80211: Implement Airtime-based Queue Limit (AQL)")
-Signed-off-by: Johannes Berg <johannes.berg@intel.com>
----
-
---- a/drivers/net/wireless/ath/ath10k/mac.c
-+++ b/drivers/net/wireless/ath/ath10k/mac.c
-@@ -8870,6 +8870,7 @@ int ath10k_mac_register(struct ath10k *a
- 	wiphy_ext_feature_set(ar->hw->wiphy, NL80211_EXT_FEATURE_VHT_IBSS);
- 	wiphy_ext_feature_set(ar->hw->wiphy,
- 			      NL80211_EXT_FEATURE_SET_SCAN_DWELL);
-+	wiphy_ext_feature_set(ar->hw->wiphy, NL80211_EXT_FEATURE_AQL);
- 
- 	if (test_bit(WMI_SERVICE_TX_DATA_ACK_RSSI, ar->wmi.svc_map) ||
- 	    test_bit(WMI_SERVICE_HTT_MGMT_TX_COMP_VALID_FLAGS, ar->wmi.svc_map))
---- a/include/uapi/linux/nl80211.h
-+++ b/include/uapi/linux/nl80211.h
-@@ -5484,6 +5484,10 @@ enum nl80211_feature_flags {
-  * @NL80211_EXT_FEATURE_SAE_OFFLOAD: Device wants to do SAE authentication in
-  *	station mode (SAE password is passed as part of the connect command).
-  *
-+ * @NL80211_EXT_FEATURE_AQL: The driver supports the Airtime Queue Limit (AQL)
-+ *	feature, which prevents bufferbloat by using the expected transmission
-+ *	time to limit the amount of data buffered in the hardware.
-+ *
-  * @NUM_NL80211_EXT_FEATURES: number of extended features.
-  * @MAX_NL80211_EXT_FEATURES: highest extended feature index.
-  */
-@@ -5529,6 +5533,8 @@ enum nl80211_ext_feature_index {
- 	NL80211_EXT_FEATURE_EXT_KEY_ID,
- 	NL80211_EXT_FEATURE_STA_TX_PWR,
- 	NL80211_EXT_FEATURE_SAE_OFFLOAD,
-+	NL80211_EXT_FEATURE_VLAN_OFFLOAD,
-+	NL80211_EXT_FEATURE_AQL,
- 
- 	/* add new features before the definition below */
- 	NUM_NL80211_EXT_FEATURES,
---- a/net/mac80211/debugfs_sta.c
-+++ b/net/mac80211/debugfs_sta.c
-@@ -202,8 +202,6 @@ static ssize_t sta_airtime_read(struct f
- 	char *buf = kzalloc(bufsz, GFP_KERNEL), *p = buf;
- 	u64 rx_airtime = 0, tx_airtime = 0;
- 	s64 deficit[IEEE80211_NUM_ACS];
--	u32 q_depth[IEEE80211_NUM_ACS];
--	u32 q_limit_l[IEEE80211_NUM_ACS], q_limit_h[IEEE80211_NUM_ACS];
- 	ssize_t rv;
- 	int ac;
- 
-@@ -215,6 +213,56 @@ static ssize_t sta_airtime_read(struct f
- 		rx_airtime += sta->airtime[ac].rx_airtime;
- 		tx_airtime += sta->airtime[ac].tx_airtime;
- 		deficit[ac] = sta->airtime[ac].deficit;
-+		spin_unlock_bh(&local->active_txq_lock[ac]);
-+	}
-+
-+	p += scnprintf(p, bufsz + buf - p,
-+		"RX: %llu us\nTX: %llu us\nWeight: %u\n"
-+		"Deficit: VO: %lld us VI: %lld us BE: %lld us BK: %lld us\n",
-+		rx_airtime, tx_airtime, sta->airtime_weight,
-+		deficit[0], deficit[1], deficit[2], deficit[3]);
-+
-+	rv = simple_read_from_buffer(userbuf, count, ppos, buf, p - buf);
-+	kfree(buf);
-+	return rv;
-+}
-+
-+static ssize_t sta_airtime_write(struct file *file, const char __user *userbuf,
-+				 size_t count, loff_t *ppos)
-+{
-+	struct sta_info *sta = file->private_data;
-+	struct ieee80211_local *local = sta->sdata->local;
-+	int ac;
-+
-+	for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) {
-+		spin_lock_bh(&local->active_txq_lock[ac]);
-+		sta->airtime[ac].rx_airtime = 0;
-+		sta->airtime[ac].tx_airtime = 0;
-+		sta->airtime[ac].deficit = sta->airtime_weight;
-+		spin_unlock_bh(&local->active_txq_lock[ac]);
-+	}
-+
-+	return count;
-+}
-+STA_OPS_RW(airtime);
-+
-+static ssize_t sta_aql_read(struct file *file, char __user *userbuf,
-+				size_t count, loff_t *ppos)
-+{
-+	struct sta_info *sta = file->private_data;
-+	struct ieee80211_local *local = sta->sdata->local;
-+	size_t bufsz = 400;
-+	char *buf = kzalloc(bufsz, GFP_KERNEL), *p = buf;
-+	u32 q_depth[IEEE80211_NUM_ACS];
-+	u32 q_limit_l[IEEE80211_NUM_ACS], q_limit_h[IEEE80211_NUM_ACS];
-+	ssize_t rv;
-+	int ac;
-+
-+	if (!buf)
-+		return -ENOMEM;
-+
-+	for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) {
-+		spin_lock_bh(&local->active_txq_lock[ac]);
- 		q_limit_l[ac] = sta->airtime[ac].aql_limit_low;
- 		q_limit_h[ac] = sta->airtime[ac].aql_limit_high;
- 		spin_unlock_bh(&local->active_txq_lock[ac]);
-@@ -222,12 +270,8 @@ static ssize_t sta_airtime_read(struct f
- 	}
- 
- 	p += scnprintf(p, bufsz + buf - p,
--		"RX: %llu us\nTX: %llu us\nWeight: %u\n"
--		"Deficit: VO: %lld us VI: %lld us BE: %lld us BK: %lld us\n"
- 		"Q depth: VO: %u us VI: %u us BE: %u us BK: %u us\n"
- 		"Q limit[low/high]: VO: %u/%u VI: %u/%u BE: %u/%u BK: %u/%u\n",
--		rx_airtime, tx_airtime, sta->airtime_weight,
--		deficit[0], deficit[1], deficit[2], deficit[3],
- 		q_depth[0], q_depth[1], q_depth[2], q_depth[3],
- 		q_limit_l[0], q_limit_h[0], q_limit_l[1], q_limit_h[1],
- 		q_limit_l[2], q_limit_h[2], q_limit_l[3], q_limit_h[3]),
-@@ -237,11 +281,10 @@ static ssize_t sta_airtime_read(struct f
- 	return rv;
- }
- 
--static ssize_t sta_airtime_write(struct file *file, const char __user *userbuf,
-+static ssize_t sta_aql_write(struct file *file, const char __user *userbuf,
- 				 size_t count, loff_t *ppos)
- {
- 	struct sta_info *sta = file->private_data;
--	struct ieee80211_local *local = sta->sdata->local;
- 	u32 ac, q_limit_l, q_limit_h;
- 	char _buf[100] = {}, *buf = _buf;
- 
-@@ -252,7 +295,7 @@ static ssize_t sta_airtime_write(struct
- 		return -EFAULT;
- 
- 	buf[sizeof(_buf) - 1] = '\0';
--	if (sscanf(buf, "queue limit %u %u %u", &ac, &q_limit_l, &q_limit_h)
-+	if (sscanf(buf, "limit %u %u %u", &ac, &q_limit_l, &q_limit_h)
- 	    != 3)
- 		return -EINVAL;
- 
-@@ -262,17 +305,10 @@ static ssize_t sta_airtime_write(struct
- 	sta->airtime[ac].aql_limit_low = q_limit_l;
- 	sta->airtime[ac].aql_limit_high = q_limit_h;
- 
--	for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) {
--		spin_lock_bh(&local->active_txq_lock[ac]);
--		sta->airtime[ac].rx_airtime = 0;
--		sta->airtime[ac].tx_airtime = 0;
--		sta->airtime[ac].deficit = sta->airtime_weight;
--		spin_unlock_bh(&local->active_txq_lock[ac]);
--	}
--
- 	return count;
- }
--STA_OPS_RW(airtime);
-+STA_OPS_RW(aql);
-+
- 
- static ssize_t sta_agg_status_read(struct file *file, char __user *userbuf,
- 					size_t count, loff_t *ppos)
-@@ -1002,6 +1038,10 @@ void ieee80211_sta_debugfs_add(struct st
- 				    NL80211_EXT_FEATURE_AIRTIME_FAIRNESS))
- 		DEBUGFS_ADD(airtime);
- 
-+	if (wiphy_ext_feature_isset(local->hw.wiphy,
-+				    NL80211_EXT_FEATURE_AQL))
-+		DEBUGFS_ADD(aql);
-+
- 	if (sizeof(sta->driver_buffered_tids) == sizeof(u32))
- 		debugfs_create_x32("driver_buffered_tids", 0400,
- 				   sta->debugfs_dir,
---- a/net/mac80211/main.c
-+++ b/net/mac80211/main.c
-@@ -674,9 +674,7 @@ struct ieee80211_hw *ieee80211_alloc_hw_
- 			IEEE80211_DEFAULT_AQL_TXQ_LIMIT_H;
- 	}
- 
--	local->airtime_flags = AIRTIME_USE_TX |
--			       AIRTIME_USE_RX |
--			       AIRTIME_USE_AQL;
-+	local->airtime_flags = AIRTIME_USE_TX | AIRTIME_USE_RX;
- 	local->aql_threshold = IEEE80211_AQL_THRESHOLD;
- 	atomic_set(&local->aql_total_pending_airtime, 0);
- 
---- a/net/mac80211/sta_info.c
-+++ b/net/mac80211/sta_info.c
-@@ -1922,6 +1922,9 @@ void ieee80211_sta_update_pending_airtim
- {
- 	int tx_pending;
- 
-+	if (!wiphy_ext_feature_isset(local->hw.wiphy, NL80211_EXT_FEATURE_AQL))
-+		return;
-+
- 	if (!tx_completed) {
- 		if (sta)
- 			atomic_add(tx_airtime,
---- a/net/mac80211/sta_info.h
-+++ b/net/mac80211/sta_info.h
-@@ -128,7 +128,6 @@ enum ieee80211_agg_stop_reason {
- /* Debugfs flags to enable/disable use of RX/TX airtime in scheduler */
- #define AIRTIME_USE_TX		BIT(0)
- #define AIRTIME_USE_RX		BIT(1)
--#define AIRTIME_USE_AQL		BIT(2)
- 
- struct airtime_info {
- 	u64 rx_airtime;
---- a/net/mac80211/tx.c
-+++ b/net/mac80211/tx.c
-@@ -3691,7 +3691,7 @@ begin:
- 
- 	IEEE80211_SKB_CB(skb)->control.vif = vif;
- 
--	if (local->airtime_flags & AIRTIME_USE_AQL) {
-+	if (wiphy_ext_feature_isset(local->hw.wiphy, NL80211_EXT_FEATURE_AQL)) {
- 		u32 airtime;
- 
- 		airtime = ieee80211_calc_expected_tx_airtime(hw, vif, txq->sta,
-@@ -3813,7 +3813,7 @@ bool ieee80211_txq_airtime_check(struct
- 	struct sta_info *sta;
- 	struct ieee80211_local *local = hw_to_local(hw);
- 
--	if (!(local->airtime_flags & AIRTIME_USE_AQL))
-+	if (!wiphy_ext_feature_isset(local->hw.wiphy, NL80211_EXT_FEATURE_AQL))
- 		return true;
- 
- 	if (!txq->sta)
diff --git a/package/kernel/mac80211/patches/subsys/353-mac80211-use-more-bits-for-ack_frame_id.patch b/package/kernel/mac80211/patches/subsys/353-mac80211-use-more-bits-for-ack_frame_id.patch
deleted file mode 100644
index a2fb9d4b10bd..000000000000
--- a/package/kernel/mac80211/patches/subsys/353-mac80211-use-more-bits-for-ack_frame_id.patch
+++ /dev/null
@@ -1,70 +0,0 @@
-From: Johannes Berg <johannes.berg@intel.com>
-Date: Wed, 15 Jan 2020 12:25:50 +0100
-Subject: [PATCH] mac80211: use more bits for ack_frame_id
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-It turns out that this wasn't a good idea, I hit a test failure in
-hwsim due to this. That particular failure was easily worked around,
-but it raised questions: if an AP needs to, for example, send action
-frames to each connected station, the current limit is nowhere near
-enough (especially if those stations are sleeping and the frames are
-queued for a while.)
-
-Shuffle around some bits to make more room for ack_frame_id to allow
-up to 8192 queued up frames, that's enough for queueing 4 frames to
-each connected station, even at the maximum of 2007 stations on a
-single AP.
-
-We take the bits from band (which currently only 2 but I leave 3 in
-case we add another band) and from the hw_queue, which can only need
-4 since it has a limit of 16 queues.
-
-Fixes: 6912daed05e1 ("mac80211: Shrink the size of ack_frame_id to make room for tx_time_est")
-Signed-off-by: Johannes Berg <johannes.berg@intel.com>
-Acked-by: Toke Høiland-Jørgensen <toke@redhat.com>
----
-
---- a/include/net/mac80211.h
-+++ b/include/net/mac80211.h
-@@ -1004,12 +1004,11 @@ ieee80211_rate_get_vht_nss(const struct
- struct ieee80211_tx_info {
- 	/* common information */
- 	u32 flags;
--	u8 band;
--
--	u8 hw_queue;
--
--	u16 ack_frame_id:6;
--	u16 tx_time_est:10;
-+	u32 band:3,
-+	    ack_frame_id:13,
-+	    hw_queue:4,
-+	    tx_time_est:10;
-+	/* 2 free bits */
- 
- 	union {
- 		struct {
---- a/net/mac80211/cfg.c
-+++ b/net/mac80211/cfg.c
-@@ -3449,7 +3449,7 @@ int ieee80211_attach_ack_skb(struct ieee
- 
- 	spin_lock_irqsave(&local->ack_status_lock, spin_flags);
- 	id = idr_alloc(&local->ack_status_frames, ack_skb,
--		       1, 0x40, GFP_ATOMIC);
-+		       1, 0x2000, GFP_ATOMIC);
- 	spin_unlock_irqrestore(&local->ack_status_lock, spin_flags);
- 
- 	if (id < 0) {
---- a/net/mac80211/tx.c
-+++ b/net/mac80211/tx.c
-@@ -2458,7 +2458,7 @@ static int ieee80211_store_ack_skb(struc
- 
- 		spin_lock_irqsave(&local->ack_status_lock, flags);
- 		id = idr_alloc(&local->ack_status_frames, ack_skb,
--			       1, 0x40, GFP_ATOMIC);
-+			       1, 0x2000, GFP_ATOMIC);
- 		spin_unlock_irqrestore(&local->ack_status_lock, flags);
- 
- 		if (id >= 0) {
diff --git a/package/kernel/mac80211/patches/subsys/500-mac80211_configure_antenna_gain.patch b/package/kernel/mac80211/patches/subsys/500-mac80211_configure_antenna_gain.patch
index ca028dd833a7..151ca25d18cd 100644
--- a/package/kernel/mac80211/patches/subsys/500-mac80211_configure_antenna_gain.patch
+++ b/package/kernel/mac80211/patches/subsys/500-mac80211_configure_antenna_gain.patch
@@ -1,6 +1,6 @@
 --- a/include/net/cfg80211.h
 +++ b/include/net/cfg80211.h
-@@ -3454,6 +3454,7 @@ struct cfg80211_update_owe_info {
+@@ -3458,6 +3458,7 @@ struct cfg80211_update_owe_info {
   *	(as advertised by the nl80211 feature flag.)
   * @get_tx_power: store the current TX power into the dbm variable;
   *	return 0 if successful
@@ -8,7 +8,7 @@
   *
   * @set_wds_peer: set the WDS peer for a WDS interface
   *
-@@ -3769,6 +3770,7 @@ struct cfg80211_ops {
+@@ -3773,6 +3774,7 @@ struct cfg80211_ops {
  				enum nl80211_tx_power_setting type, int mbm);
  	int	(*get_tx_power)(struct wiphy *wiphy, struct wireless_dev *wdev,
  				int *dbm);
@@ -36,9 +36,9 @@
  	u8 ps_dtim_period;
 --- a/include/uapi/linux/nl80211.h
 +++ b/include/uapi/linux/nl80211.h
-@@ -2373,6 +2373,9 @@ enum nl80211_commands {
-  *	the allowed channel bandwidth configurations. (u8 attribute)
-  *	Defined by IEEE P802.11ay/D4.0 section 9.4.2.251, Table 13.
+@@ -2400,6 +2400,9 @@ enum nl80211_commands {
+  * @NL80211_ATTR_VLAN_ID: VLAN ID (1..4094) for the station and VLAN group key
+  *	(u16).
   *
 + * @NL80211_ATTR_WIPHY_ANTENNA_GAIN: Configured antenna gain. Used to reduce
 + *	transmit power to stay within regulatory limits. u32, dBi.
@@ -46,9 +46,9 @@
   * @NUM_NL80211_ATTR: total number of nl80211_attrs available
   * @NL80211_ATTR_MAX: highest attribute number currently defined
   * @__NL80211_ATTR_AFTER_LAST: internal use
-@@ -2835,6 +2838,8 @@ enum nl80211_attrs {
- 	NL80211_ATTR_WIPHY_EDMG_CHANNELS,
- 	NL80211_ATTR_WIPHY_EDMG_BW_CONFIG,
+@@ -2864,6 +2867,8 @@ enum nl80211_attrs {
+ 
+ 	NL80211_ATTR_VLAN_ID,
  
 +	NL80211_ATTR_WIPHY_ANTENNA_GAIN,
 +
@@ -129,15 +129,15 @@
  	local->hw.max_mtu = IEEE80211_MAX_DATA_LEN;
 --- a/net/wireless/nl80211.c
 +++ b/net/wireless/nl80211.c
-@@ -628,6 +628,7 @@ const struct nla_policy nl80211_policy[N
- 					.len = SAE_PASSWORD_MAX_LEN },
+@@ -630,6 +630,7 @@ const struct nla_policy nl80211_policy[N
  	[NL80211_ATTR_TWT_RESPONDER] = { .type = NLA_FLAG },
  	[NL80211_ATTR_HE_OBSS_PD] = NLA_POLICY_NESTED(he_obss_pd_policy),
+ 	[NL80211_ATTR_VLAN_ID] = NLA_POLICY_RANGE(NLA_U16, 1, VLAN_N_VID - 2),
 +	[NL80211_ATTR_WIPHY_ANTENNA_GAIN] = { .type = NLA_U32 },
  };
  
  /* policy for the key attributes */
-@@ -2992,6 +2993,20 @@ static int nl80211_set_wiphy(struct sk_b
+@@ -2994,6 +2995,20 @@ static int nl80211_set_wiphy(struct sk_b
  		if (result)
  			return result;
  	}
diff --git a/package/network/utils/iw/patches/001-nl80211_h_sync.patch b/package/network/utils/iw/patches/001-nl80211_h_sync.patch
index 6b65f61846af..57f05b711adf 100644
--- a/package/network/utils/iw/patches/001-nl80211_h_sync.patch
+++ b/package/network/utils/iw/patches/001-nl80211_h_sync.patch
@@ -1,28 +1,75 @@
 --- a/nl80211.h
 +++ b/nl80211.h
-@@ -2373,6 +2373,9 @@ enum nl80211_commands {
+@@ -249,6 +249,22 @@
+  */
+ 
+ /**
++ * DOC: VLAN offload support for setting group keys and binding STAs to VLANs
++ *
++ * By setting @NL80211_EXT_FEATURE_VLAN_OFFLOAD flag drivers can indicate they
++ * support offloading VLAN functionality in a manner where the driver exposes a
++ * single netdev that uses VLAN tagged frames and separate VLAN-specific netdevs
++ * can then be added using RTM_NEWLINK/IFLA_VLAN_ID similarly to the Ethernet
++ * case. Frames received from stations that are not assigned to any VLAN are
++ * delivered on the main netdev and frames to such stations can be sent through
++ * that main netdev.
++ *
++ * %NL80211_CMD_NEW_KEY (for group keys), %NL80211_CMD_NEW_STATION, and
++ * %NL80211_CMD_SET_STATION will optionally specify vlan_id using
++ * %NL80211_ATTR_VLAN_ID.
++ */
++
++/**
+  * enum nl80211_commands - supported nl80211 commands
+  *
+  * @NL80211_CMD_UNSPEC: unspecified command to catch errors
+@@ -571,6 +587,14 @@
+  *	set of BSSID,frequency parameters is used (i.e., either the enforcing
+  *	%NL80211_ATTR_MAC,%NL80211_ATTR_WIPHY_FREQ or the less strict
+  *	%NL80211_ATTR_MAC_HINT and %NL80211_ATTR_WIPHY_FREQ_HINT).
++ *	Driver shall not modify the IEs specified through %NL80211_ATTR_IE if
++ *	%NL80211_ATTR_MAC is included. However, if %NL80211_ATTR_MAC_HINT is
++ *	included, these IEs through %NL80211_ATTR_IE are specified by the user
++ *	space based on the best possible BSS selected. Thus, if the driver ends
++ *	up selecting a different BSS, it can modify these IEs accordingly (e.g.
++ *	userspace asks the driver to perform PMKSA caching with BSS1 and the
++ *	driver ends up selecting BSS2 with different PMKSA cache entry; RSNIE
++ *	has to get updated with the apt PMKID).
+  *	%NL80211_ATTR_PREV_BSSID can be used to request a reassociation within
+  *	the ESS in case the device is already associated and an association with
+  *	a different BSS is desired.
+@@ -2373,6 +2397,12 @@ enum nl80211_commands {
   *	the allowed channel bandwidth configurations. (u8 attribute)
   *	Defined by IEEE P802.11ay/D4.0 section 9.4.2.251, Table 13.
   *
++ * @NL80211_ATTR_VLAN_ID: VLAN ID (1..4094) for the station and VLAN group key
++ *	(u16).
++ *
 + * @NL80211_ATTR_WIPHY_ANTENNA_GAIN: Configured antenna gain. Used to reduce
 + *	transmit power to stay within regulatory limits. u32, dBi.
 + *
   * @NUM_NL80211_ATTR: total number of nl80211_attrs available
   * @NL80211_ATTR_MAX: highest attribute number currently defined
   * @__NL80211_ATTR_AFTER_LAST: internal use
-@@ -2835,6 +2838,8 @@ enum nl80211_attrs {
+@@ -2835,6 +2865,10 @@ enum nl80211_attrs {
  	NL80211_ATTR_WIPHY_EDMG_CHANNELS,
  	NL80211_ATTR_WIPHY_EDMG_BW_CONFIG,
  
++	NL80211_ATTR_VLAN_ID,
++
 +	NL80211_ATTR_WIPHY_ANTENNA_GAIN,
 +
  	/* add attributes here, update the policy in nl80211.c */
  
  	__NL80211_ATTR_AFTER_LAST,
-@@ -5484,6 +5489,10 @@ enum nl80211_feature_flags {
+@@ -5484,6 +5518,14 @@ enum nl80211_feature_flags {
   * @NL80211_EXT_FEATURE_SAE_OFFLOAD: Device wants to do SAE authentication in
   *	station mode (SAE password is passed as part of the connect command).
   *
++ * @NL80211_EXT_FEATURE_VLAN_OFFLOAD: The driver supports a single netdev
++ *	with VLAN tagged frames and separate VLAN-specific netdevs added using
++ *	vconfig similarly to the Ethernet case.
++ *
 + * @NL80211_EXT_FEATURE_AQL: The driver supports the Airtime Queue Limit (AQL)
 + *	feature, which prevents bufferbloat by using the expected transmission
 + *	time to limit the amount of data buffered in the hardware.
@@ -30,7 +77,7 @@
   * @NUM_NL80211_EXT_FEATURES: number of extended features.
   * @MAX_NL80211_EXT_FEATURES: highest extended feature index.
   */
-@@ -5529,6 +5538,8 @@ enum nl80211_ext_feature_index {
+@@ -5529,6 +5571,8 @@ enum nl80211_ext_feature_index {
  	NL80211_EXT_FEATURE_EXT_KEY_ID,
  	NL80211_EXT_FEATURE_STA_TX_PWR,
  	NL80211_EXT_FEATURE_SAE_OFFLOAD,
