[rdkb][common][bsp][Refactor and sync wifi from openwrt]
[Description]
ac60b1ff [MAC80211][misc][Add Filogic 880/860/830/820/630 Release Information]
7eb946a0 [MAC80211][WiFi7][hostapd][sync hostapd patches]
91638fc9 [MAC80211][WiFi7][mac80211][sync backports code]
8e45746b [MAC80211][WiFi7][mt76][sync mt76 patches]
1c564afa [MAC80211][WiFi7][mt76][Add Eagle BE19000 ifem default bin]
[Release-log]
Change-Id: I1d4218d3b1211700acb5937fe310cbd0bf219968
diff --git a/recipes-wifi/linux-mac80211/files/backports-2024-04-03.tar.xz b/recipes-wifi/linux-mac80211/files/backports-2024-04-03.tar.xz
new file mode 100644
index 0000000..a6715ac
--- /dev/null
+++ b/recipes-wifi/linux-mac80211/files/backports-2024-04-03.tar.xz
Binary files differ
diff --git a/recipes-wifi/linux-mac80211/files/patches-6.x/build/000-fix_kconfig.patch b/recipes-wifi/linux-mac80211/files/patches-6.x/build/000-fix_kconfig.patch
deleted file mode 100644
index 3987aae..0000000
--- a/recipes-wifi/linux-mac80211/files/patches-6.x/build/000-fix_kconfig.patch
+++ /dev/null
@@ -1,14 +0,0 @@
---- a/kconf/Makefile
-+++ b/kconf/Makefile
-@@ -1,9 +1,9 @@
--CFLAGS=-Wall -Wmissing-prototypes -Wstrict-prototypes -O2 -fomit-frame-pointer
-+CFLAGS=-Wall -Wmissing-prototypes -Wstrict-prototypes -O2 -fomit-frame-pointer -DKBUILD_NO_NLS
-
- LXDIALOG := lxdialog/checklist.o lxdialog/inputbox.o lxdialog/menubox.o lxdialog/textbox.o lxdialog/util.o lxdialog/yesno.o
-
- conf: conf.o zconf.tab.o
--mconf_CFLAGS := $(shell ./lxdialog/check-lxdialog.sh -ccflags) -DLOCALE
-+mconf_CFLAGS := $(shell ./lxdialog/check-lxdialog.sh -ccflags)
- mconf_LDFLAGS := $(shell ./lxdialog/check-lxdialog.sh -ldflags $(CC))
- mconf: CFLAGS += $(mconf_CFLAGS)
-
diff --git a/recipes-wifi/linux-mac80211/files/patches-6.x/build/001-fix_build.patch b/recipes-wifi/linux-mac80211/files/patches-6.x/build/001-fix_build.patch
deleted file mode 100644
index 8f63d36..0000000
--- a/recipes-wifi/linux-mac80211/files/patches-6.x/build/001-fix_build.patch
+++ /dev/null
@@ -1,169 +0,0 @@
---- a/Makefile
-+++ b/Makefile
-@@ -5,7 +5,7 @@
- ifeq ($(KERNELRELEASE),)
-
- MAKEFLAGS += --no-print-directory
--SHELL := /bin/bash
-+SHELL := /usr/bin/env bash
- BACKPORT_DIR := $(shell pwd)
-
- KMODDIR ?= updates
-@@ -19,6 +19,7 @@ KLIB_BUILD ?= $(KLIB)/build/
- KERNEL_CONFIG := $(KLIB_BUILD)/.config
- KERNEL_MAKEFILE := $(KLIB_BUILD)/Makefile
- CONFIG_MD5 := $(shell md5sum $(KERNEL_CONFIG) 2>/dev/null | sed 's/\s.*//')
-+STAMP_KERNEL_CONFIG := .kernel_config_md5_$(CONFIG_MD5)
-
- export KLIB KLIB_BUILD BACKPORT_DIR KMODDIR KMODPATH_ARG
-
-@@ -36,7 +37,8 @@ mrproper:
- @rm -f .kernel_config_md5 Kconfig.versions Kconfig.kernel
- @rm -f backport-include/backport/autoconf.h
-
--.DEFAULT:
-+.SILENT: $(STAMP_KERNEL_CONFIG)
-+$(STAMP_KERNEL_CONFIG):
- @set -e ; test -f local-symbols || ( \
- echo "/--------------" ;\
- echo "| You shouldn't run make in the backports tree, but only in" ;\
-@@ -60,58 +62,62 @@ mrproper:
- echo "| (that isn't currently running.)" ;\
- echo "\\--" ;\
- false)
-- @set -e ; if [ "$$(cat .kernel_config_md5 2>/dev/null)" != "$(CONFIG_MD5)" ] ;\
-- then \
-- echo -n "Generating local configuration database from kernel ..." ;\
-- grep -v -f local-symbols $(KERNEL_CONFIG) | grep = | ( \
-- while read l ; do \
-- if [ "$${l:0:7}" != "CONFIG_" ] ; then \
-- continue ;\
-- fi ;\
-- l=$${l:7} ;\
-- n=$${l%%=*} ;\
-- v=$${l#*=} ;\
-- if [ "$$v" = "m" ] ; then \
-- echo config $$n ;\
-- echo ' tristate' ;\
-- elif [ "$$v" = "y" ] ; then \
-- echo config $$n ;\
-- echo ' bool' ;\
-- else \
-- continue ;\
-- fi ;\
-- echo " default $$v" ;\
-- echo "" ;\
-- done \
-- ) > Kconfig.kernel ;\
-- kver=$$($(MAKE) --no-print-directory -C $(KLIB_BUILD) M=$(BACKPORT_DIR) \
-- kernelversion | sed 's/^\(\([3-5]\|2\.6\)\.[0-9]\+\).*/\1/;t;d');\
-- test "$$kver" != "" || echo "Kernel version parse failed!" ;\
-- test "$$kver" != "" ;\
-- kvers="$$(seq 14 39 | sed 's/^/2.6./')" ;\
-- kvers="$$kvers $$(seq 0 19 | sed 's/^/3./')" ;\
-- kvers="$$kvers $$(seq 0 20 | sed 's/^/4./')" ;\
-- kvers="$$kvers $$(seq 0 99 | sed 's/^/5./')" ;\
-- print=0 ;\
-- for v in $$kvers ; do \
-- if [ "$$print" = "1" ] ; then \
-- echo config KERNEL_$$(echo $$v | tr . _) ;\
-- echo " def_bool y" ;\
-- fi ;\
-- if [ "$$v" = "$$kver" ] ; then print=1 ; fi ;\
-- done > Kconfig.versions ;\
-- # RHEL as well, sadly we need to grep for it ;\
-- RHEL_MAJOR=$$(grep '^RHEL_MAJOR' $(KERNEL_MAKEFILE) | \
-- sed 's/.*=\s*\([0-9]*\)/\1/;t;d') ;\
-- RHEL_MINOR=$$(grep '^RHEL_MINOR' $(KERNEL_MAKEFILE) | \
-- sed 's/.*=\s*\([0-9]*\)/\1/;t;d') ;\
-- for v in $$(seq 0 $$RHEL_MINOR) ; do \
-- echo config BACKPORT_RHEL_KERNEL_$${RHEL_MAJOR}_$$v ;\
-- echo " def_bool y" ;\
-- done >> Kconfig.versions ;\
-- echo " done." ;\
-- fi ;\
-- echo "$(CONFIG_MD5)" > .kernel_config_md5
-+ @rm -f .kernel_config_md5_*
-+ @touch $@
-+
-+Kconfig.kernel: $(STAMP_KERNEL_CONFIG) local-symbols
-+ @printf "Generating local configuration database from kernel ..."
-+ @grep -v -f local-symbols $(KERNEL_CONFIG) | grep = | ( \
-+ while read l ; do \
-+ if [ "$${l:0:7}" != "CONFIG_" ] ; then \
-+ continue ;\
-+ fi ;\
-+ l=$${l:7} ;\
-+ n=$${l%%=*} ;\
-+ v=$${l#*=} ;\
-+ if [ "$$v" = "m" ] ; then \
-+ echo config $$n ;\
-+ echo ' tristate' ;\
-+ elif [ "$$v" = "y" ] ; then \
-+ echo config $$n ;\
-+ echo ' bool' ;\
-+ else \
-+ continue ;\
-+ fi ;\
-+ echo " default $$v" ;\
-+ echo "" ;\
-+ done \
-+ ) > $@
-+ @echo " done."
-+
-+Kconfig.versions: Kconfig.kernel
-+ @kver=$$($(MAKE) --no-print-directory -C $(KLIB_BUILD) M=$(BACKPORT_DIR) \
-+ kernelversion | sed 's/^\(\([3-5]\|2\.6\)\.[0-9]\+\).*/\1/;t;d');\
-+ test "$$kver" != "" || echo "Kernel version parse failed!" ;\
-+ test "$$kver" != "" ;\
-+ kvers="$$(seq 14 39 | sed 's/^/2.6./')" ;\
-+ kvers="$$kvers $$(seq 0 19 | sed 's/^/3./')" ;\
-+ kvers="$$kvers $$(seq 0 20 | sed 's/^/4./')" ;\
-+ kvers="$$kvers $$(seq 0 99 | sed 's/^/5./')" ;\
-+ print=0 ;\
-+ for v in $$kvers ; do \
-+ if [ "$$print" = "1" ] ; then \
-+ echo config KERNEL_$$(echo $$v | tr . _) ;\
-+ echo " def_bool y" ;\
-+ fi ;\
-+ if [ "$$v" = "$$kver" ] ; then print=1 ; fi ;\
-+ done > $@
-+ @RHEL_MAJOR=$$(grep '^RHEL_MAJOR' $(KERNEL_MAKEFILE) | \
-+ sed 's/.*=\s*\([0-9]*\)/\1/;t;d') ;\
-+ RHEL_MINOR=$$(grep '^RHEL_MINOR' $(KERNEL_MAKEFILE) | \
-+ sed 's/.*=\s*\([0-9]*\)/\1/;t;d') ;\
-+ for v in $$(seq 0 $$RHEL_MINOR) ; do \
-+ echo config BACKPORT_RHEL_KERNEL_$${RHEL_MAJOR}_$$v ;\
-+ echo " def_bool y" ;\
-+ done >> $@
-+
-+.DEFAULT:
-+ @$(MAKE) Kconfig.versions
- @$(MAKE) -f Makefile.real "$@"
-
- .PHONY: defconfig-help
---- a/Makefile.real
-+++ b/Makefile.real
-@@ -59,7 +59,7 @@ defconfig-%::
-
- backport-include/backport/autoconf.h: .config Kconfig.versions Kconfig.kernel
- @$(MAKE) oldconfig
-- @echo -n "Building backport-include/backport/autoconf.h ..."
-+ @printf "Building backport-include/backport/autoconf.h ..."
- @grep -f local-symbols .config | ( \
- echo "#ifndef COMPAT_AUTOCONF_INCLUDED" ;\
- echo "#define COMPAT_AUTOCONF_INCLUDED" ;\
-@@ -80,7 +80,12 @@ backport-include/backport/autoconf.h: .c
- esac ;\
- done ;\
- echo "#endif /* COMPAT_AUTOCONF_INCLUDED */" ;\
-- ) > backport-include/backport/autoconf.h
-+ ) > $@.new
-+ @if cmp -s $@ $@.new; then \
-+ rm -f $@.new; \
-+ else \
-+ mv $@.new $@; \
-+ fi
- @echo " done."
-
- .PHONY: modules
diff --git a/recipes-wifi/linux-mac80211/files/patches-6.x/build/002-change_allconfig.patch b/recipes-wifi/linux-mac80211/files/patches-6.x/build/002-change_allconfig.patch
deleted file mode 100644
index 368725d..0000000
--- a/recipes-wifi/linux-mac80211/files/patches-6.x/build/002-change_allconfig.patch
+++ /dev/null
@@ -1,64 +0,0 @@
---- a/kconf/conf.c
-+++ b/kconf/conf.c
-@@ -598,40 +598,12 @@ int main(int ac, char **av)
- case oldconfig:
- case listnewconfig:
- case olddefconfig:
-- conf_read(NULL);
-- break;
- case allnoconfig:
- case allyesconfig:
- case allmodconfig:
- case alldefconfig:
- case randconfig:
-- name = getenv("KCONFIG_ALLCONFIG");
-- if (!name)
-- break;
-- if ((strcmp(name, "") != 0) && (strcmp(name, "1") != 0)) {
-- if (conf_read_simple(name, S_DEF_USER)) {
-- fprintf(stderr,
-- _("*** Can't read seed configuration \"%s\"!\n"),
-- name);
-- exit(1);
-- }
-- break;
-- }
-- switch (input_mode) {
-- case allnoconfig: name = "allno.config"; break;
-- case allyesconfig: name = "allyes.config"; break;
-- case allmodconfig: name = "allmod.config"; break;
-- case alldefconfig: name = "alldef.config"; break;
-- case randconfig: name = "allrandom.config"; break;
-- default: break;
-- }
-- if (conf_read_simple(name, S_DEF_USER) &&
-- conf_read_simple("all.config", S_DEF_USER)) {
-- fprintf(stderr,
-- _("*** KCONFIG_ALLCONFIG set, but no \"%s\" or \"all.config\" file found\n"),
-- name);
-- exit(1);
-- }
-+ conf_read(NULL);
- break;
- default:
- break;
---- a/kconf/confdata.c
-+++ b/kconf/confdata.c
-@@ -1170,6 +1170,8 @@ bool conf_set_all_new_symbols(enum conf_
- }
- bool has_changed = false;
-
-+ sym_clear_all_valid();
-+
- for_all_symbols(i, sym) {
- if (sym_has_value(sym) || (sym->flags & SYMBOL_VALID))
- continue;
-@@ -1213,8 +1215,6 @@ bool conf_set_all_new_symbols(enum conf_
-
- }
-
-- sym_clear_all_valid();
--
- /*
- * We have different type of choice blocks.
- * If curr.tri equals to mod then we can select several
diff --git a/recipes-wifi/linux-mac80211/files/patches-6.x/build/003-remove_bogus_modparams.patch b/recipes-wifi/linux-mac80211/files/patches-6.x/build/003-remove_bogus_modparams.patch
deleted file mode 100644
index aa26c8c..0000000
--- a/recipes-wifi/linux-mac80211/files/patches-6.x/build/003-remove_bogus_modparams.patch
+++ /dev/null
@@ -1,34 +0,0 @@
---- a/compat/main.c
-+++ b/compat/main.c
-@@ -19,31 +19,6 @@ MODULE_LICENSE("GPL");
- #error "You need a CPTCFG_VERSION"
- #endif
-
--static char *backported_kernel_name = CPTCFG_KERNEL_NAME;
--
--module_param(backported_kernel_name, charp, 0400);
--MODULE_PARM_DESC(backported_kernel_name,
-- "The kernel tree name that was used for this backport (" CPTCFG_KERNEL_NAME ")");
--
--#ifdef BACKPORTS_GIT_TRACKED
--static char *backports_tracker_id = BACKPORTS_GIT_TRACKED;
--module_param(backports_tracker_id, charp, 0400);
--MODULE_PARM_DESC(backports_tracker_id,
-- "The version of the tree containing this backport (" BACKPORTS_GIT_TRACKED ")");
--#else
--static char *backported_kernel_version = CPTCFG_KERNEL_VERSION;
--static char *backports_version = CPTCFG_VERSION;
--
--module_param(backported_kernel_version, charp, 0400);
--MODULE_PARM_DESC(backported_kernel_version,
-- "The kernel version that was used for this backport (" CPTCFG_KERNEL_VERSION ")");
--
--module_param(backports_version, charp, 0400);
--MODULE_PARM_DESC(backports_version,
-- "The git version of the backports tree used to generate this backport (" CPTCFG_VERSION ")");
--
--#endif
--
- void backport_dependency_symbol(void)
- {
- }
diff --git a/recipes-wifi/linux-mac80211/files/patches-6.x/build/004-fix-kconf-compiling.patch b/recipes-wifi/linux-mac80211/files/patches-6.x/build/004-fix-kconf-compiling.patch
deleted file mode 100644
index 8bae836..0000000
--- a/recipes-wifi/linux-mac80211/files/patches-6.x/build/004-fix-kconf-compiling.patch
+++ /dev/null
@@ -1,47 +0,0 @@
---- a/Makefile.real
-+++ b/Makefile.real
-@@ -6,6 +6,18 @@ else
- export BACKPORTS_GIT_TRACKER_DEF=
- endif
-
-+ifneq ($(LLVM),)
-+ifneq ($(filter %/,$(LLVM)),)
-+LLVM_PREFIX := $(LLVM)
-+else ifneq ($(filter -%,$(LLVM)),)
-+LLVM_SUFFIX := $(LLVM)
-+endif
-+
-+HOSTCC = $(LLVM_PREFIX)clang$(LLVM_SUFFIX)
-+else
-+HOSTCC = gcc
-+endif
-+
- # disable built-in rules for this file
- .SUFFIXES:
-
-@@ -24,21 +36,21 @@ listnewconfig oldaskconfig oldconfig \
- silentoldconfig olddefconfig oldnoconfig \
- allnoconfig allyesconfig allmodconfig \
- alldefconfig randconfig:
-- @$(MAKE) -C kconf conf
-+ @$(MAKE) -C kconf CC=$(HOSTCC) conf
- @./kconf/conf --$@ Kconfig
-
- .PHONY: usedefconfig
- usedefconfig:
-- @$(MAKE) -C kconf conf
-+ @$(MAKE) -C kconf CC=$(HOSTCC) conf
- @./kconf/conf --defconfig=defconfig Kconfig
-
- .PHONY: savedefconfig
- savedefconfig:
-- @$(MAKE) -C kconf conf
-+ @$(MAKE) -C kconf CC=$(HOSTCC) conf
- @./kconf/conf --savedefconfig=defconfig Kconfig
-
- defconfig-%::
-- @$(MAKE) -C kconf conf
-+ @$(MAKE) -C kconf CC=$(HOSTCC) conf
- @./kconf/conf --defconfig=defconfigs/$(@:defconfig-%=%) Kconfig
-
- .config:
diff --git a/recipes-wifi/linux-mac80211/files/patches-6.x/build/012-kernel_build_check.patch b/recipes-wifi/linux-mac80211/files/patches-6.x/build/012-kernel_build_check.patch
deleted file mode 100644
index d225ba1..0000000
--- a/recipes-wifi/linux-mac80211/files/patches-6.x/build/012-kernel_build_check.patch
+++ /dev/null
@@ -1,11 +0,0 @@
---- a/Makefile
-+++ b/Makefile
-@@ -2,7 +2,7 @@
- # Makefile for the output source package
- #
-
--ifeq ($(KERNELRELEASE),)
-+ifeq ($(KERNELVERSION),)
-
- MAKEFLAGS += --no-print-directory
- SHELL := /usr/bin/env bash
diff --git a/recipes-wifi/linux-mac80211/files/patches-6.x/build/060-no_local_ssb_bcma.patch b/recipes-wifi/linux-mac80211/files/patches-6.x/build/060-no_local_ssb_bcma.patch
deleted file mode 100644
index 2a0f9ed..0000000
--- a/recipes-wifi/linux-mac80211/files/patches-6.x/build/060-no_local_ssb_bcma.patch
+++ /dev/null
@@ -1,314 +0,0 @@
---- a/local-symbols
-+++ b/local-symbols
-@@ -493,43 +493,6 @@ USB_VL600=
- USB_NET_CH9200=
- USB_NET_AQC111=
- USB_RTL8153_ECM=
--SSB_POSSIBLE=
--SSB=
--SSB_SPROM=
--SSB_BLOCKIO=
--SSB_PCIHOST_POSSIBLE=
--SSB_PCIHOST=
--SSB_B43_PCI_BRIDGE=
--SSB_PCMCIAHOST_POSSIBLE=
--SSB_PCMCIAHOST=
--SSB_SDIOHOST_POSSIBLE=
--SSB_SDIOHOST=
--SSB_HOST_SOC=
--SSB_SERIAL=
--SSB_DRIVER_PCICORE_POSSIBLE=
--SSB_DRIVER_PCICORE=
--SSB_PCICORE_HOSTMODE=
--SSB_DRIVER_MIPS=
--SSB_SFLASH=
--SSB_EMBEDDED=
--SSB_DRIVER_EXTIF=
--SSB_DRIVER_GIGE=
--SSB_DRIVER_GPIO=
--BCMA_POSSIBLE=
--BCMA=
--BCMA_BLOCKIO=
--BCMA_HOST_PCI_POSSIBLE=
--BCMA_HOST_PCI=
--BCMA_HOST_SOC=
--BCMA_DRIVER_PCI=
--BCMA_DRIVER_PCI_HOSTMODE=
--BCMA_DRIVER_MIPS=
--BCMA_PFLASH=
--BCMA_SFLASH=
--BCMA_NFLASH=
--BCMA_DRIVER_GMAC_CMN=
--BCMA_DRIVER_GPIO=
--BCMA_DEBUG=
- USB_ACM=
- USB_PRINTER=
- USB_WDM=
---- a/drivers/net/wireless/broadcom/b43/Kconfig
-+++ b/drivers/net/wireless/broadcom/b43/Kconfig
-@@ -63,21 +63,21 @@ endchoice
- config B43_PCI_AUTOSELECT
- bool
- depends on B43 && SSB_PCIHOST_POSSIBLE
-- select SSB_PCIHOST
-- select SSB_B43_PCI_BRIDGE
-+ depends on SSB_PCIHOST
-+ depends on SSB_B43_PCI_BRIDGE
- default y
-
- # Auto-select SSB PCICORE driver, if possible
- config B43_PCICORE_AUTOSELECT
- bool
- depends on B43 && SSB_DRIVER_PCICORE_POSSIBLE
-- select SSB_DRIVER_PCICORE
-+ depends on SSB_DRIVER_PCICORE
- default y
-
- config B43_SDIO
- bool "Broadcom 43xx SDIO device support"
- depends on B43 && B43_SSB && SSB_SDIOHOST_POSSIBLE
-- select SSB_SDIOHOST
-+ depends on SSB_SDIOHOST
- help
- Broadcom 43xx device support for Soft-MAC SDIO devices.
-
-@@ -96,13 +96,13 @@ config B43_SDIO
- config B43_BCMA_PIO
- bool
- depends on B43 && B43_BCMA
-- select BCMA_BLOCKIO
-+ depends on BCMA_BLOCKIO
- default y
-
- config B43_PIO
- bool
- depends on B43 && B43_SSB
-- select SSB_BLOCKIO
-+ depends on SSB_BLOCKIO
- default y
-
- config B43_PHY_G
---- a/drivers/net/wireless/broadcom/b43/main.c
-+++ b/drivers/net/wireless/broadcom/b43/main.c
-@@ -2853,7 +2853,7 @@ static struct ssb_device *b43_ssb_gpio_d
- {
- struct ssb_bus *bus = dev->dev->sdev->bus;
-
--#ifdef CPTCFG_SSB_DRIVER_PCICORE
-+#ifdef CONFIG_SSB_DRIVER_PCICORE
- return (bus->chipco.dev ? bus->chipco.dev : bus->pcicore.dev);
- #else
- return bus->chipco.dev;
-@@ -4871,7 +4871,7 @@ static int b43_wireless_core_init(struct
- }
- if (sprom->boardflags_lo & B43_BFL_XTAL_NOSLOW)
- hf |= B43_HF_DSCRQ; /* Disable slowclock requests from ucode. */
--#if defined(CPTCFG_B43_SSB) && defined(CPTCFG_SSB_DRIVER_PCICORE)
-+#if defined(CPTCFG_B43_SSB) && defined(CONFIG_SSB_DRIVER_PCICORE)
- if (dev->dev->bus_type == B43_BUS_SSB &&
- dev->dev->sdev->bus->bustype == SSB_BUSTYPE_PCI &&
- dev->dev->sdev->bus->pcicore.dev->id.revision <= 10)
---- a/drivers/net/wireless/broadcom/b43legacy/Kconfig
-+++ b/drivers/net/wireless/broadcom/b43legacy/Kconfig
-@@ -3,7 +3,7 @@ config B43LEGACY
- tristate "Broadcom 43xx-legacy wireless support (mac80211 stack)"
- depends on m
- depends on SSB_POSSIBLE && MAC80211 && HAS_DMA
-- select SSB
-+ depends on SSB
- depends on FW_LOADER
- help
- b43legacy is a driver for 802.11b devices from Broadcom (BCM4301 and
-@@ -25,15 +25,15 @@ config B43LEGACY
- config B43LEGACY_PCI_AUTOSELECT
- bool
- depends on B43LEGACY && SSB_PCIHOST_POSSIBLE
-- select SSB_PCIHOST
-- select SSB_B43_PCI_BRIDGE
-+ depends on SSB_PCIHOST
-+ depends on SSB_B43_PCI_BRIDGE
- default y
-
- # Auto-select SSB PCICORE driver, if possible
- config B43LEGACY_PCICORE_AUTOSELECT
- bool
- depends on B43LEGACY && SSB_DRIVER_PCICORE_POSSIBLE
-- select SSB_DRIVER_PCICORE
-+ depends on SSB_DRIVER_PCICORE
- default y
-
- # LED support
---- a/drivers/net/wireless/broadcom/b43legacy/main.c
-+++ b/drivers/net/wireless/broadcom/b43legacy/main.c
-@@ -1907,7 +1907,7 @@ static int b43legacy_gpio_init(struct b4
- if (dev->dev->id.revision >= 2)
- mask |= 0x0010; /* FIXME: This is redundant. */
-
--#ifdef CPTCFG_SSB_DRIVER_PCICORE
-+#ifdef CONFIG_SSB_DRIVER_PCICORE
- pcidev = bus->pcicore.dev;
- #endif
- gpiodev = bus->chipco.dev ? : pcidev;
-@@ -1926,7 +1926,7 @@ static void b43legacy_gpio_cleanup(struc
- struct ssb_bus *bus = dev->dev->bus;
- struct ssb_device *gpiodev, *pcidev = NULL;
-
--#ifdef CPTCFG_SSB_DRIVER_PCICORE
-+#ifdef CONFIG_SSB_DRIVER_PCICORE
- pcidev = bus->pcicore.dev;
- #endif
- gpiodev = bus->chipco.dev ? : pcidev;
---- a/drivers/net/wireless/broadcom/brcm80211/Kconfig
-+++ b/drivers/net/wireless/broadcom/brcm80211/Kconfig
-@@ -8,7 +8,7 @@ config BRCMSMAC
- depends on m
- depends on MAC80211
- depends on BCMA_POSSIBLE
-- select BCMA
-+ depends on BCMA
- select BRCMUTIL
- depends on FW_LOADER
- depends on CORDIC
---- a/Kconfig.local
-+++ b/Kconfig.local
-@@ -1483,117 +1483,6 @@ config BACKPORTED_USB_NET_AQC111
- config BACKPORTED_USB_RTL8153_ECM
- tristate
- default USB_RTL8153_ECM
--config BACKPORTED_SSB_POSSIBLE
-- tristate
-- default SSB_POSSIBLE
--config BACKPORTED_SSB
-- tristate
-- default SSB
--config BACKPORTED_SSB_SPROM
-- tristate
-- default SSB_SPROM
--config BACKPORTED_SSB_BLOCKIO
-- tristate
-- default SSB_BLOCKIO
--config BACKPORTED_SSB_PCIHOST_POSSIBLE
-- tristate
-- default SSB_PCIHOST_POSSIBLE
--config BACKPORTED_SSB_PCIHOST
-- tristate
-- default SSB_PCIHOST
--config BACKPORTED_SSB_B43_PCI_BRIDGE
-- tristate
-- default SSB_B43_PCI_BRIDGE
--config BACKPORTED_SSB_PCMCIAHOST_POSSIBLE
-- tristate
-- default SSB_PCMCIAHOST_POSSIBLE
--config BACKPORTED_SSB_PCMCIAHOST
-- tristate
-- default SSB_PCMCIAHOST
--config BACKPORTED_SSB_SDIOHOST_POSSIBLE
-- tristate
-- default SSB_SDIOHOST_POSSIBLE
--config BACKPORTED_SSB_SDIOHOST
-- tristate
-- default SSB_SDIOHOST
--config BACKPORTED_SSB_HOST_SOC
-- tristate
-- default SSB_HOST_SOC
--config BACKPORTED_SSB_SERIAL
-- tristate
-- default SSB_SERIAL
--config BACKPORTED_SSB_DRIVER_PCICORE_POSSIBLE
-- tristate
-- default SSB_DRIVER_PCICORE_POSSIBLE
--config BACKPORTED_SSB_DRIVER_PCICORE
-- tristate
-- default SSB_DRIVER_PCICORE
--config BACKPORTED_SSB_PCICORE_HOSTMODE
-- tristate
-- default SSB_PCICORE_HOSTMODE
--config BACKPORTED_SSB_DRIVER_MIPS
-- tristate
-- default SSB_DRIVER_MIPS
--config BACKPORTED_SSB_SFLASH
-- tristate
-- default SSB_SFLASH
--config BACKPORTED_SSB_EMBEDDED
-- tristate
-- default SSB_EMBEDDED
--config BACKPORTED_SSB_DRIVER_EXTIF
-- tristate
-- default SSB_DRIVER_EXTIF
--config BACKPORTED_SSB_DRIVER_GIGE
-- tristate
-- default SSB_DRIVER_GIGE
--config BACKPORTED_SSB_DRIVER_GPIO
-- tristate
-- default SSB_DRIVER_GPIO
--config BACKPORTED_BCMA_POSSIBLE
-- tristate
-- default BCMA_POSSIBLE
--config BACKPORTED_BCMA
-- tristate
-- default BCMA
--config BACKPORTED_BCMA_BLOCKIO
-- tristate
-- default BCMA_BLOCKIO
--config BACKPORTED_BCMA_HOST_PCI_POSSIBLE
-- tristate
-- default BCMA_HOST_PCI_POSSIBLE
--config BACKPORTED_BCMA_HOST_PCI
-- tristate
-- default BCMA_HOST_PCI
--config BACKPORTED_BCMA_HOST_SOC
-- tristate
-- default BCMA_HOST_SOC
--config BACKPORTED_BCMA_DRIVER_PCI
-- tristate
-- default BCMA_DRIVER_PCI
--config BACKPORTED_BCMA_DRIVER_PCI_HOSTMODE
-- tristate
-- default BCMA_DRIVER_PCI_HOSTMODE
--config BACKPORTED_BCMA_DRIVER_MIPS
-- tristate
-- default BCMA_DRIVER_MIPS
--config BACKPORTED_BCMA_PFLASH
-- tristate
-- default BCMA_PFLASH
--config BACKPORTED_BCMA_SFLASH
-- tristate
-- default BCMA_SFLASH
--config BACKPORTED_BCMA_NFLASH
-- tristate
-- default BCMA_NFLASH
--config BACKPORTED_BCMA_DRIVER_GMAC_CMN
-- tristate
-- default BCMA_DRIVER_GMAC_CMN
--config BACKPORTED_BCMA_DRIVER_GPIO
-- tristate
-- default BCMA_DRIVER_GPIO
--config BACKPORTED_BCMA_DEBUG
-- tristate
-- default BCMA_DEBUG
- config BACKPORTED_USB_ACM
- tristate
- default USB_ACM
---- a/Kconfig.sources
-+++ b/Kconfig.sources
-@@ -10,9 +10,6 @@ source "$BACKPORT_DIR/drivers/soc/qcom/K
- source "$BACKPORT_DIR/drivers/net/wireless/Kconfig"
- source "$BACKPORT_DIR/drivers/net/usb/Kconfig"
-
--source "$BACKPORT_DIR/drivers/ssb/Kconfig"
--source "$BACKPORT_DIR/drivers/bcma/Kconfig"
--
- source "$BACKPORT_DIR/drivers/usb/class/Kconfig"
-
- source "$BACKPORT_DIR/drivers/staging/Kconfig"
---- a/Makefile.kernel
-+++ b/Makefile.kernel
-@@ -43,8 +43,6 @@ obj-$(CPTCFG_QRTR) += net/qrtr/
- obj-$(CPTCFG_QCOM_QMI_HELPERS) += drivers/soc/qcom/
- obj-$(CPTCFG_MHI_BUS) += drivers/bus/mhi/
- obj-$(CPTCFG_WLAN) += drivers/net/wireless/
--obj-$(CPTCFG_SSB) += drivers/ssb/
--obj-$(CPTCFG_BCMA) += drivers/bcma/
- obj-$(CPTCFG_USB_NET_RNDIS_WLAN) += drivers/net/usb/
-
- obj-$(CPTCFG_USB_WDM) += drivers/usb/class/
diff --git a/recipes-wifi/linux-mac80211/files/patches-6.x/build/070-remove-broken-wext-select.patch b/recipes-wifi/linux-mac80211/files/patches-6.x/build/070-remove-broken-wext-select.patch
deleted file mode 100644
index 121b7fa..0000000
--- a/recipes-wifi/linux-mac80211/files/patches-6.x/build/070-remove-broken-wext-select.patch
+++ /dev/null
@@ -1,10 +0,0 @@
---- a/drivers/staging/rtl8723bs/Kconfig
-+++ b/drivers/staging/rtl8723bs/Kconfig
-@@ -5,7 +5,6 @@ config RTL8723BS
- depends on m
- depends on WLAN && MMC && CFG80211
- depends on m
-- select CFG80211_WEXT
- depends on CRYPTO
- select BPAUTO_CRYPTO_LIB_ARC4
- help
diff --git a/recipes-wifi/linux-mac80211/files/patches-6.x/build/080-resv_start_op.patch b/recipes-wifi/linux-mac80211/files/patches-6.x/build/080-resv_start_op.patch
deleted file mode 100644
index bbd9018..0000000
--- a/recipes-wifi/linux-mac80211/files/patches-6.x/build/080-resv_start_op.patch
+++ /dev/null
@@ -1,24 +0,0 @@
---- a/drivers/net/wireless/virtual/mac80211_hwsim.c
-+++ b/drivers/net/wireless/virtual/mac80211_hwsim.c
-@@ -6179,7 +6179,9 @@ static struct genl_family hwsim_genl_fam
- .module = THIS_MODULE,
- .small_ops = hwsim_ops,
- .n_small_ops = ARRAY_SIZE(hwsim_ops),
-+#if LINUX_VERSION_IS_GEQ(6,1,0)
- .resv_start_op = HWSIM_CMD_REPORT_PMSR + 1, // match with __HWSIM_CMD_MAX
-+#endif
- .mcgrps = hwsim_mcgrps,
- .n_mcgrps = ARRAY_SIZE(hwsim_mcgrps),
- };
---- a/net/wireless/nl80211.c
-+++ b/net/wireless/nl80211.c
-@@ -17551,7 +17551,9 @@ static struct genl_family nl80211_fam __
- .n_ops = ARRAY_SIZE(nl80211_ops),
- .small_ops = nl80211_small_ops,
- .n_small_ops = ARRAY_SIZE(nl80211_small_ops),
-+#if LINUX_VERSION_IS_GEQ(6,1,0)
- .resv_start_op = NL80211_CMD_REMOVE_LINK_STA + 1,
-+#endif
- .mcgrps = nl80211_mcgrps,
- .n_mcgrps = ARRAY_SIZE(nl80211_mcgrps),
- .parallel_ops = true,
diff --git a/recipes-wifi/linux-mac80211/files/patches-6.x/build/090-bcma-otp.patch b/recipes-wifi/linux-mac80211/files/patches-6.x/build/090-bcma-otp.patch
deleted file mode 100644
index 3974776..0000000
--- a/recipes-wifi/linux-mac80211/files/patches-6.x/build/090-bcma-otp.patch
+++ /dev/null
@@ -1,13 +0,0 @@
---- /dev/null
-+++ b/backport-include/linux/bcma/bcma_driver_chipcommon.h
-@@ -0,0 +1,10 @@
-+#ifndef __BACKPORT_BCMA_DRIVER_CHIPCOMMON_H
-+#define __BACKPORT_BCMA_DRIVER_CHIPCOMMON_H
-+
-+#include_next <linux/bcma/bcma_driver_chipcommon.h>
-+
-+#ifndef BCMA_CC_SROM_CONTROL_OTP_PRESENT
-+#define BCMA_CC_SROM_CONTROL_OTP_PRESENT 0x00000020
-+#endif
-+
-+#endif
diff --git a/recipes-wifi/linux-mac80211/files/patches-6.x/build/100-backports-drop-QRTR-and-MHI.patch b/recipes-wifi/linux-mac80211/files/patches-6.x/build/100-backports-drop-QRTR-and-MHI.patch
deleted file mode 100644
index b017a0c..0000000
--- a/recipes-wifi/linux-mac80211/files/patches-6.x/build/100-backports-drop-QRTR-and-MHI.patch
+++ /dev/null
@@ -1,76 +0,0 @@
-From 54e0f9aaf340377fb76acdffee9ec7372c4b70ae Mon Sep 17 00:00:00 2001
-From: Robert Marko <robimarko@gmail.com>
-Date: Mon, 17 Oct 2022 11:35:36 +0200
-Subject: [PATCH] backports: drop QRTR and MHI
-
-Backports currently include QRTR and MHI due to ath11k-pci requiring them,
-however this at the same time prevents us from adding ath11k-ahb as it
-also requires QRTR however its AHB variant from the kernel will conflict
-with the core provided by backports.
-
-Since MHI also conflicts with existing OpenWrt kmods providing MHI drop
-both from backports and use the ones provided by OpenWrt kernel.
-
-Signed-off-by: Robert Marko <robimarko@gmail.com>
----
- Kconfig.sources | 2 --
- Makefile.kernel | 2 --
- drivers/net/wireless/ath/ath11k/Kconfig | 6 +++---
- local-symbols | 8 --------
- 4 files changed, 3 insertions(+), 15 deletions(-)
-
---- a/Kconfig.sources
-+++ b/Kconfig.sources
-@@ -4,8 +4,6 @@ source "$BACKPORT_DIR/compat/Kconfig"
- # these are copied from the kernel
- source "$BACKPORT_DIR/net/wireless/Kconfig"
- source "$BACKPORT_DIR/net/mac80211/Kconfig"
--source "$BACKPORT_DIR/net/qrtr/Kconfig"
--source "$BACKPORT_DIR/drivers/bus/mhi/Kconfig"
- source "$BACKPORT_DIR/drivers/soc/qcom/Kconfig"
- source "$BACKPORT_DIR/drivers/net/wireless/Kconfig"
- source "$BACKPORT_DIR/drivers/net/usb/Kconfig"
---- a/Makefile.kernel
-+++ b/Makefile.kernel
-@@ -39,9 +39,7 @@ obj-y += compat/
-
- obj-$(CPTCFG_CFG80211) += net/wireless/
- obj-$(CPTCFG_MAC80211) += net/mac80211/
--obj-$(CPTCFG_QRTR) += net/qrtr/
- obj-$(CPTCFG_QCOM_QMI_HELPERS) += drivers/soc/qcom/
--obj-$(CPTCFG_MHI_BUS) += drivers/bus/mhi/
- obj-$(CPTCFG_WLAN) += drivers/net/wireless/
- obj-$(CPTCFG_USB_NET_RNDIS_WLAN) += drivers/net/usb/
-
---- a/drivers/net/wireless/ath/ath11k/Kconfig
-+++ b/drivers/net/wireless/ath/ath11k/Kconfig
-@@ -25,9 +25,9 @@ config ATH11K_PCI
- tristate "Atheros ath11k PCI support"
- depends on m
- depends on ATH11K && PCI
-- select MHI_BUS
-- select QRTR
-- select QRTR_MHI
-+ depends on MHI_BUS
-+ depends on QRTR
-+ depends on QRTR_MHI
- help
- This module adds support for PCIE bus
-
---- a/local-symbols
-+++ b/local-symbols
-@@ -65,14 +65,6 @@ MAC80211_MESH_PS_DEBUG=
- MAC80211_TDLS_DEBUG=
- MAC80211_DEBUG_COUNTERS=
- MAC80211_STA_HASH_MAX_SIZE=
--QRTR=
--QRTR_SMD=
--QRTR_TUN=
--QRTR_MHI=
--MHI_BUS=
--MHI_BUS_DEBUG=
--MHI_BUS_PCI_GENERIC=
--MHI_BUS_EP=
- QCOM_AOSS_QMP=
- QCOM_COMMAND_DB=
- QCOM_CPR=
diff --git a/recipes-wifi/linux-mac80211/files/patches-6.x/build/110-backport_namepace_const.patch b/recipes-wifi/linux-mac80211/files/patches-6.x/build/110-backport_namepace_const.patch
deleted file mode 100644
index 6dca708..0000000
--- a/recipes-wifi/linux-mac80211/files/patches-6.x/build/110-backport_namepace_const.patch
+++ /dev/null
@@ -1,14 +0,0 @@
---- a/net/wireless/sysfs.c
-+++ b/net/wireless/sysfs.c
-@@ -154,7 +154,11 @@ static SIMPLE_DEV_PM_OPS(wiphy_pm_ops, w
- #define WIPHY_PM_OPS NULL
- #endif
-
-+#if LINUX_VERSION_IS_GEQ(6,2,0)
- static const void *wiphy_namespace(const struct device *d)
-+#else
-+static const void *wiphy_namespace(struct device *d)
-+#endif
- {
- struct wiphy *wiphy = container_of(d, struct wiphy, dev);
-
diff --git a/recipes-wifi/linux-mac80211/files/patches-6.x/build/120-headers_version_fix.patch b/recipes-wifi/linux-mac80211/files/patches-6.x/build/120-headers_version_fix.patch
deleted file mode 100644
index 9a8c474..0000000
--- a/recipes-wifi/linux-mac80211/files/patches-6.x/build/120-headers_version_fix.patch
+++ /dev/null
@@ -1,25 +0,0 @@
---- a/backport-include/linux/random.h
-+++ b/backport-include/linux/random.h
-@@ -23,7 +23,7 @@ static inline u16 get_random_u16(void)
- }
- #endif
-
--#if LINUX_VERSION_IS_LESS(6,2,0)
-+#if LINUX_VERSION_IS_LESS(6,1,4)
- static inline u32 __get_random_u32_below(u32 ceil)
- {
- /*
---- a/backport-include/net/dropreason.h
-+++ b/backport-include/net/dropreason.h
-@@ -3,10 +3,9 @@
-
- #include <linux/version.h>
-
-+#include <net/dropreason-core.h>
- #if LINUX_VERSION_IS_GEQ(6,0,0)
- #include_next <net/dropreason.h>
--#else
--#include <net/dropreason-core.h>
- #endif
-
- #if LINUX_VERSION_IS_LESS(6,4,0)
diff --git a/recipes-wifi/linux-mac80211/files/patches-6.x/build/130-iommu_backport.patch b/recipes-wifi/linux-mac80211/files/patches-6.x/build/130-iommu_backport.patch
deleted file mode 100644
index 2d3ef88..0000000
--- a/recipes-wifi/linux-mac80211/files/patches-6.x/build/130-iommu_backport.patch
+++ /dev/null
@@ -1,26 +0,0 @@
---- /dev/null
-+++ b/backport-include/linux/iommu.h
-@@ -0,0 +1,23 @@
-+#ifndef __BACKPORT_LINUX_IOMMU_H
-+#define __BACKPORT_LINUX_IOMMU_H
-+
-+#include_next <linux/iommu.h>
-+#include <linux/version.h>
-+
-+#if LINUX_VERSION_IS_LESS(6,3,0)
-+
-+static inline int LINUX_BACKPORT(iommu_map)(struct iommu_domain *domain,
-+ unsigned long iova,
-+ phys_addr_t paddr, size_t size,
-+ int prot, gfp_t gfp)
-+{
-+ if (gfp == GFP_ATOMIC)
-+ return iommu_map_atomic(domain, iova, paddr, size, prot);
-+
-+ return iommu_map(domain, iova, paddr, size, prot);
-+}
-+#define iommu_map LINUX_BACKPORT(iommu_map)
-+
-+#endif /* < 6.3 */
-+
-+#endif
diff --git a/recipes-wifi/linux-mac80211/files/patches-6.x/build/200-Revert-wifi-iwlwifi-Use-generic-thermal_zone_get_tri.patch b/recipes-wifi/linux-mac80211/files/patches-6.x/build/200-Revert-wifi-iwlwifi-Use-generic-thermal_zone_get_tri.patch
deleted file mode 100644
index 3a5285d..0000000
--- a/recipes-wifi/linux-mac80211/files/patches-6.x/build/200-Revert-wifi-iwlwifi-Use-generic-thermal_zone_get_tri.patch
+++ /dev/null
@@ -1,159 +0,0 @@
-From: Felix Fietkau <nbd@nbd.name>
-Date: Mon, 17 Apr 2023 19:42:38 +0200
-Subject: [PATCH] Revert "wifi: iwlwifi: Use generic thermal_zone_get_trip()
- function"
-
-This reverts commit 3d2f20ad46f83b333025f5e8e4afc34be8f13c4c.
----
-
---- a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h
-+++ b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h
-@@ -531,7 +531,7 @@ struct iwl_mvm_tt_mgmt {
- * @tzone: thermal zone device data
- */
- struct iwl_mvm_thermal_device {
-- struct thermal_trip trips[IWL_MAX_DTS_TRIPS];
-+ s16 temp_trips[IWL_MAX_DTS_TRIPS];
- u8 fw_trips_index[IWL_MAX_DTS_TRIPS];
- struct thermal_zone_device *tzone;
- };
---- a/drivers/net/wireless/intel/iwlwifi/mvm/tt.c
-+++ b/drivers/net/wireless/intel/iwlwifi/mvm/tt.c
-@@ -573,11 +573,11 @@ int iwl_mvm_send_temp_report_ths_cmd(str
- * and uncompressed, the FW should get it compressed and sorted
- */
-
-- /* compress trips to cmd array, remove uninitialized values*/
-+ /* compress temp_trips to cmd array, remove uninitialized values*/
- for (i = 0; i < IWL_MAX_DTS_TRIPS; i++) {
-- if (mvm->tz_device.trips[i].temperature != INT_MIN) {
-+ if (mvm->tz_device.temp_trips[i] != S16_MIN) {
- cmd.thresholds[idx++] =
-- cpu_to_le16((s16)(mvm->tz_device.trips[i].temperature / 1000));
-+ cpu_to_le16(mvm->tz_device.temp_trips[i]);
- }
- }
- cmd.num_temps = cpu_to_le32(idx);
-@@ -593,8 +593,8 @@ int iwl_mvm_send_temp_report_ths_cmd(str
- */
- for (i = 0; i < idx; i++) {
- for (j = 0; j < IWL_MAX_DTS_TRIPS; j++) {
-- if ((int)(le16_to_cpu(cmd.thresholds[i]) * 1000) ==
-- mvm->tz_device.trips[j].temperature)
-+ if (le16_to_cpu(cmd.thresholds[i]) ==
-+ mvm->tz_device.temp_trips[j])
- mvm->tz_device.fw_trips_index[i] = j;
- }
- }
-@@ -638,12 +638,37 @@ out:
- return ret;
- }
-
-+static int iwl_mvm_tzone_get_trip_temp(struct thermal_zone_device *device,
-+ int trip, int *temp)
-+{
-+ struct iwl_mvm *mvm = (struct iwl_mvm *)device->devdata;
-+
-+ if (trip < 0 || trip >= IWL_MAX_DTS_TRIPS)
-+ return -EINVAL;
-+
-+ *temp = mvm->tz_device.temp_trips[trip] * 1000;
-+
-+ return 0;
-+}
-+
-+static int iwl_mvm_tzone_get_trip_type(struct thermal_zone_device *device,
-+ int trip, enum thermal_trip_type *type)
-+{
-+ if (trip < 0 || trip >= IWL_MAX_DTS_TRIPS)
-+ return -EINVAL;
-+
-+ *type = THERMAL_TRIP_PASSIVE;
-+
-+ return 0;
-+}
-+
- static int iwl_mvm_tzone_set_trip_temp(struct thermal_zone_device *device,
- int trip, int temp)
- {
- struct iwl_mvm *mvm = thermal_zone_device_priv(device);
- struct iwl_mvm_thermal_device *tzone;
-- int ret;
-+ int i, ret;
-+ s16 temperature;
-
- mutex_lock(&mvm->mutex);
-
-@@ -653,17 +678,40 @@ static int iwl_mvm_tzone_set_trip_temp(s
- goto out;
- }
-
-+ if (trip < 0 || trip >= IWL_MAX_DTS_TRIPS) {
-+ ret = -EINVAL;
-+ goto out;
-+ }
-+
- if ((temp / 1000) > S16_MAX) {
- ret = -EINVAL;
- goto out;
- }
-
-+ temperature = (s16)(temp / 1000);
- tzone = &mvm->tz_device;
-+
- if (!tzone) {
- ret = -EIO;
- goto out;
- }
-
-+ /* no updates*/
-+ if (tzone->temp_trips[trip] == temperature) {
-+ ret = 0;
-+ goto out;
-+ }
-+
-+ /* already existing temperature */
-+ for (i = 0; i < IWL_MAX_DTS_TRIPS; i++) {
-+ if (tzone->temp_trips[i] == temperature) {
-+ ret = -EINVAL;
-+ goto out;
-+ }
-+ }
-+
-+ tzone->temp_trips[trip] = temperature;
-+
- ret = iwl_mvm_send_temp_report_ths_cmd(mvm);
- out:
- mutex_unlock(&mvm->mutex);
-@@ -672,6 +720,8 @@ out:
-
- static struct thermal_zone_device_ops tzone_ops = {
- .get_temp = iwl_mvm_tzone_get_temp,
-+ .get_trip_temp = iwl_mvm_tzone_get_trip_temp,
-+ .get_trip_type = iwl_mvm_tzone_get_trip_type,
- .set_trip_temp = iwl_mvm_tzone_set_trip_temp,
- };
-
-@@ -693,8 +743,7 @@ static void iwl_mvm_thermal_zone_registe
- BUILD_BUG_ON(ARRAY_SIZE(name) >= THERMAL_NAME_LENGTH);
-
- sprintf(name, "iwlwifi_%u", atomic_inc_return(&counter) & 0xFF);
-- mvm->tz_device.tzone = thermal_zone_device_register_with_trips(name,
-- mvm->tz_device.trips,
-+ mvm->tz_device.tzone = thermal_zone_device_register(name,
- IWL_MAX_DTS_TRIPS,
- IWL_WRITABLE_TRIPS_MSK,
- mvm, &tzone_ops,
-@@ -717,10 +766,8 @@ static void iwl_mvm_thermal_zone_registe
- /* 0 is a valid temperature,
- * so initialize the array with S16_MIN which invalid temperature
- */
-- for (i = 0 ; i < IWL_MAX_DTS_TRIPS; i++) {
-- mvm->tz_device.trips[i].temperature = INT_MIN;
-- mvm->tz_device.trips[i].type = THERMAL_TRIP_PASSIVE;
-- }
-+ for (i = 0 ; i < IWL_MAX_DTS_TRIPS; i++)
-+ mvm->tz_device.temp_trips[i] = S16_MIN;
- }
-
- static int iwl_mvm_tcool_get_max_state(struct thermal_cooling_device *cdev,
diff --git a/recipes-wifi/linux-mac80211/files/patches-6.x/build/210-revert-split-op.patch b/recipes-wifi/linux-mac80211/files/patches-6.x/build/210-revert-split-op.patch
deleted file mode 100644
index 4f1f8a7..0000000
--- a/recipes-wifi/linux-mac80211/files/patches-6.x/build/210-revert-split-op.patch
+++ /dev/null
@@ -1,22 +0,0 @@
---- a/net/wireless/nl80211.c
-+++ b/net/wireless/nl80211.c
-@@ -16442,8 +16442,7 @@ static u32 nl80211_internal_flags[] = {
- #undef SELECTOR
- };
-
--static int nl80211_pre_doit(const struct genl_split_ops *ops,
-- struct sk_buff *skb,
-+static int nl80211_pre_doit(const struct genl_ops *ops, struct sk_buff *skb,
- struct genl_info *info)
- {
- struct cfg80211_registered_device *rdev = NULL;
-@@ -16544,8 +16543,7 @@ out_unlock:
- return err;
- }
-
--static void nl80211_post_doit(const struct genl_split_ops *ops,
-- struct sk_buff *skb,
-+static void nl80211_post_doit(const struct genl_ops *ops, struct sk_buff *skb,
- struct genl_info *info)
- {
- u32 internal_flags = nl80211_internal_flags[ops->internal_flags];
diff --git a/recipes-wifi/linux-mac80211/files/patches-6.x/build/220-list-don-t-backport-list_count_nodes.patch b/recipes-wifi/linux-mac80211/files/patches-6.x/build/220-list-don-t-backport-list_count_nodes.patch
deleted file mode 100644
index 6d30002..0000000
--- a/recipes-wifi/linux-mac80211/files/patches-6.x/build/220-list-don-t-backport-list_count_nodes.patch
+++ /dev/null
@@ -1,26 +0,0 @@
-From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <rafal@milecki.pl>
-Date: Fri, 15 Dec 2023 10:17:21 +0100
-Subject: [PATCH] list: don't backport list_count_nodes()
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-It's redundant in OpenWrt as it backports it on its own. This fixes:
-backport-include/linux/list.h:11:22: error: redefinition of 'list_count_nodes'
-
-Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
----
- backport-include/linux/list.h | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
---- a/backport-include/linux/list.h
-+++ b/backport-include/linux/list.h
-@@ -3,7 +3,7 @@
- #include_next <linux/list.h>
- #include <linux/version.h>
-
--#if LINUX_VERSION_IS_LESS(6,3,0)
-+#if 0 /* OpenWrt backports list_count_nodes() on its own */
- /**
- * list_count_nodes - count nodes in the list
- * @head: the head for your list.
diff --git a/recipes-wifi/linux-mac80211/files/patches-6.x/build/230-backport_genl_info_userhdr.patch b/recipes-wifi/linux-mac80211/files/patches-6.x/build/230-backport_genl_info_userhdr.patch
deleted file mode 100644
index 38f86dc..0000000
--- a/recipes-wifi/linux-mac80211/files/patches-6.x/build/230-backport_genl_info_userhdr.patch
+++ /dev/null
@@ -1,32 +0,0 @@
---- a/backport-include/net/genetlink.h
-+++ b/backport-include/net/genetlink.h
-@@ -3,6 +3,7 @@
- #include_next <net/genetlink.h>
- #include <linux/version.h>
-
-+#if LINUX_VERSION_IS_LESS(4,12,0)
- static inline void __bp_genl_info_userhdr_set(struct genl_info *info,
- void *userhdr)
- {
-@@ -14,7 +15,6 @@ static inline void *__bp_genl_info_userh
- return info->userhdr;
- }
-
--#if LINUX_VERSION_IS_LESS(4,12,0)
- #define GENL_SET_ERR_MSG(info, msg) NL_SET_ERR_MSG(genl_info_extack(info), msg)
-
- static inline int genl_err_attr(struct genl_info *info, int err,
-@@ -44,11 +44,13 @@ static inline struct netlink_ext_ack *ge
- #endif
- }
-
-+#if LINUX_VERSION_IS_LESS(6,6,0)
- /* this gets put in place of info->userhdr, since we use that above */
- static inline void *genl_info_userhdr(struct genl_info *info)
- {
- return (u8 *)info->genlhdr + GENL_HDRLEN;
- }
-+#endif
-
- #if LINUX_VERSION_IS_LESS(4,10,0)
- #define __genl_ro_after_init
diff --git a/recipes-wifi/linux-mac80211/files/patches-6.x/build/240-backport_genl_split_ops.patch b/recipes-wifi/linux-mac80211/files/patches-6.x/build/240-backport_genl_split_ops.patch
deleted file mode 100644
index b22804c..0000000
--- a/recipes-wifi/linux-mac80211/files/patches-6.x/build/240-backport_genl_split_ops.patch
+++ /dev/null
@@ -1,32 +0,0 @@
---- a/net/wireless/nl80211.c
-+++ b/net/wireless/nl80211.c
-@@ -16442,8 +16442,14 @@ static u32 nl80211_internal_flags[] = {
- #undef SELECTOR
- };
-
-+#if LINUX_VERSION_IS_LESS(6,2,0)
- static int nl80211_pre_doit(const struct genl_ops *ops, struct sk_buff *skb,
- struct genl_info *info)
-+#else
-+static int nl80211_pre_doit(const struct genl_split_ops *ops,
-+ struct sk_buff *skb,
-+ struct genl_info *info)
-+#endif
- {
- struct cfg80211_registered_device *rdev = NULL;
- struct wireless_dev *wdev = NULL;
-@@ -16543,8 +16549,14 @@ out_unlock:
- return err;
- }
-
-+#if LINUX_VERSION_IS_LESS(6,2,0)
- static void nl80211_post_doit(const struct genl_ops *ops, struct sk_buff *skb,
- struct genl_info *info)
-+#else
-+static void nl80211_post_doit(const struct genl_split_ops *ops,
-+ struct sk_buff *skb,
-+ struct genl_info *info)
-+#endif
- {
- u32 internal_flags = nl80211_internal_flags[ops->internal_flags];
-
diff --git a/recipes-wifi/linux-mac80211/files/patches-6.x/build/250-backport_iwlwifi_thermal.patch b/recipes-wifi/linux-mac80211/files/patches-6.x/build/250-backport_iwlwifi_thermal.patch
deleted file mode 100644
index 631fdd7..0000000
--- a/recipes-wifi/linux-mac80211/files/patches-6.x/build/250-backport_iwlwifi_thermal.patch
+++ /dev/null
@@ -1,160 +0,0 @@
---- a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h
-+++ b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h
-@@ -531,7 +531,11 @@ struct iwl_mvm_tt_mgmt {
- * @tzone: thermal zone device data
- */
- struct iwl_mvm_thermal_device {
-+#if LINUX_VERSION_IS_LESS(6,6,0)
- s16 temp_trips[IWL_MAX_DTS_TRIPS];
-+#else
-+ struct thermal_trip trips[IWL_MAX_DTS_TRIPS];
-+#endif
- u8 fw_trips_index[IWL_MAX_DTS_TRIPS];
- struct thermal_zone_device *tzone;
- };
---- a/drivers/net/wireless/intel/iwlwifi/mvm/tt.c
-+++ b/drivers/net/wireless/intel/iwlwifi/mvm/tt.c
-@@ -573,6 +573,7 @@ int iwl_mvm_send_temp_report_ths_cmd(str
- * and uncompressed, the FW should get it compressed and sorted
- */
-
-+#if LINUX_VERSION_IS_LESS(6,6,0)
- /* compress temp_trips to cmd array, remove uninitialized values*/
- for (i = 0; i < IWL_MAX_DTS_TRIPS; i++) {
- if (mvm->tz_device.temp_trips[i] != S16_MIN) {
-@@ -580,6 +581,15 @@ int iwl_mvm_send_temp_report_ths_cmd(str
- cpu_to_le16(mvm->tz_device.temp_trips[i]);
- }
- }
-+#else
-+ /* compress trips to cmd array, remove uninitialized values*/
-+ for (i = 0; i < IWL_MAX_DTS_TRIPS; i++) {
-+ if (mvm->tz_device.trips[i].temperature != INT_MIN) {
-+ cmd.thresholds[idx++] =
-+ cpu_to_le16((s16)(mvm->tz_device.trips[i].temperature / 1000));
-+ }
-+ }
-+#endif
- cmd.num_temps = cpu_to_le32(idx);
-
- if (!idx)
-@@ -593,8 +603,13 @@ int iwl_mvm_send_temp_report_ths_cmd(str
- */
- for (i = 0; i < idx; i++) {
- for (j = 0; j < IWL_MAX_DTS_TRIPS; j++) {
-+#if LINUX_VERSION_IS_LESS(6,6,0)
- if (le16_to_cpu(cmd.thresholds[i]) ==
- mvm->tz_device.temp_trips[j])
-+#else
-+ if ((int)(le16_to_cpu(cmd.thresholds[i]) * 1000) ==
-+ mvm->tz_device.trips[j].temperature)
-+#endif
- mvm->tz_device.fw_trips_index[i] = j;
- }
- }
-@@ -638,6 +653,7 @@ out:
- return ret;
- }
-
-+#if LINUX_VERSION_IS_LESS(6,6,0)
- static int iwl_mvm_tzone_get_trip_temp(struct thermal_zone_device *device,
- int trip, int *temp)
- {
-@@ -661,14 +677,19 @@ static int iwl_mvm_tzone_get_trip_type(s
-
- return 0;
- }
-+#endif
-
- static int iwl_mvm_tzone_set_trip_temp(struct thermal_zone_device *device,
- int trip, int temp)
- {
- struct iwl_mvm *mvm = thermal_zone_device_priv(device);
- struct iwl_mvm_thermal_device *tzone;
-+#if LINUX_VERSION_IS_LESS(6,6,0)
- int i, ret;
- s16 temperature;
-+#else
-+ int ret;
-+#endif
-
- mutex_lock(&mvm->mutex);
-
-@@ -678,17 +699,21 @@ static int iwl_mvm_tzone_set_trip_temp(s
- goto out;
- }
-
-+#if LINUX_VERSION_IS_LESS(6,6,0)
- if (trip < 0 || trip >= IWL_MAX_DTS_TRIPS) {
- ret = -EINVAL;
- goto out;
- }
-+#endif
-
- if ((temp / 1000) > S16_MAX) {
- ret = -EINVAL;
- goto out;
- }
-
-+#if LINUX_VERSION_IS_LESS(6,6,0)
- temperature = (s16)(temp / 1000);
-+#endif
- tzone = &mvm->tz_device;
-
- if (!tzone) {
-@@ -696,6 +721,7 @@ static int iwl_mvm_tzone_set_trip_temp(s
- goto out;
- }
-
-+#if LINUX_VERSION_IS_LESS(6,6,0)
- /* no updates*/
- if (tzone->temp_trips[trip] == temperature) {
- ret = 0;
-@@ -711,6 +737,7 @@ static int iwl_mvm_tzone_set_trip_temp(s
- }
-
- tzone->temp_trips[trip] = temperature;
-+#endif
-
- ret = iwl_mvm_send_temp_report_ths_cmd(mvm);
- out:
-@@ -720,8 +747,10 @@ out:
-
- static struct thermal_zone_device_ops tzone_ops = {
- .get_temp = iwl_mvm_tzone_get_temp,
-+#if LINUX_VERSION_IS_LESS(6,6,0)
- .get_trip_temp = iwl_mvm_tzone_get_trip_temp,
- .get_trip_type = iwl_mvm_tzone_get_trip_type,
-+#endif
- .set_trip_temp = iwl_mvm_tzone_set_trip_temp,
- };
-
-@@ -743,7 +772,12 @@ static void iwl_mvm_thermal_zone_registe
- BUILD_BUG_ON(ARRAY_SIZE(name) >= THERMAL_NAME_LENGTH);
-
- sprintf(name, "iwlwifi_%u", atomic_inc_return(&counter) & 0xFF);
-+#if LINUX_VERSION_IS_LESS(6,6,0)
- mvm->tz_device.tzone = thermal_zone_device_register(name,
-+#else
-+ mvm->tz_device.tzone = thermal_zone_device_register_with_trips(name,
-+ mvm->tz_device.trips,
-+#endif
- IWL_MAX_DTS_TRIPS,
- IWL_WRITABLE_TRIPS_MSK,
- mvm, &tzone_ops,
-@@ -766,8 +800,15 @@ static void iwl_mvm_thermal_zone_registe
- /* 0 is a valid temperature,
- * so initialize the array with S16_MIN which invalid temperature
- */
-+#if LINUX_VERSION_IS_LESS(6,6,0)
- for (i = 0 ; i < IWL_MAX_DTS_TRIPS; i++)
- mvm->tz_device.temp_trips[i] = S16_MIN;
-+#else
-+ for (i = 0 ; i < IWL_MAX_DTS_TRIPS; i++) {
-+ mvm->tz_device.trips[i].temperature = INT_MIN;
-+ mvm->tz_device.trips[i].type = THERMAL_TRIP_PASSIVE;
-+ }
-+#endif
- }
-
- static int iwl_mvm_tcool_get_max_state(struct thermal_cooling_device *cdev,
diff --git a/recipes-wifi/linux-mac80211/files/patches-6.x/build/build.inc b/recipes-wifi/linux-mac80211/files/patches-6.x/build/build.inc
deleted file mode 100644
index 40fef68..0000000
--- a/recipes-wifi/linux-mac80211/files/patches-6.x/build/build.inc
+++ /dev/null
@@ -1,23 +0,0 @@
-#patch build (come from openwrt/lede/target/linux/mediatek)
-SRC_URI_append = " \
- file://000-fix_kconfig.patch \
- file://001-fix_build.patch \
- file://002-change_allconfig.patch \
- file://003-remove_bogus_modparams.patch \
- file://004-fix-kconf-compiling.patch \
- file://012-kernel_build_check.patch \
- file://060-no_local_ssb_bcma.patch \
- file://070-remove-broken-wext-select.patch \
- file://080-resv_start_op.patch \
- file://090-bcma-otp.patch \
- file://100-backports-drop-QRTR-and-MHI.patch \
- file://110-backport_namepace_const.patch \
- file://120-headers_version_fix.patch \
- file://130-iommu_backport.patch \
- file://200-Revert-wifi-iwlwifi-Use-generic-thermal_zone_get_tri.patch \
- file://210-revert-split-op.patch \
- file://220-list-don-t-backport-list_count_nodes.patch \
- file://230-backport_genl_info_userhdr.patch \
- file://240-backport_genl_split_ops.patch \
- file://250-backport_iwlwifi_thermal.patch \
- "
diff --git a/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/0001-sync-backports-patches-build.patch b/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/0001-sync-backports-patches-build.patch
new file mode 100644
index 0000000..e926f0b
--- /dev/null
+++ b/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/0001-sync-backports-patches-build.patch
@@ -0,0 +1,815 @@
+From 45a2c927c790c9f71a81983f6d59b15cfb6b05ac Mon Sep 17 00:00:00 2001
+From: Shayne Chen <shayne.chen@mediatek.com>
+Date: Tue, 12 Mar 2024 11:25:41 +0800
+Subject: [PATCH 01/61] sync backports patches/build
+
+---
+ Kconfig.local | 111 -----------------
+ Kconfig.sources | 5 -
+ Makefile | 116 +++++++++---------
+ Makefile.real | 29 ++++-
+ compat/main.c | 25 ----
+ drivers/net/wireless/ath/ath11k/Kconfig | 6 +-
+ drivers/net/wireless/broadcom/b43/Kconfig | 12 +-
+ drivers/net/wireless/broadcom/b43/main.c | 4 +-
+ .../net/wireless/broadcom/b43legacy/Kconfig | 8 +-
+ .../net/wireless/broadcom/b43legacy/main.c | 4 +-
+ .../net/wireless/broadcom/brcm80211/Kconfig | 2 +-
+ drivers/net/wireless/intel/iwlwifi/mvm/mvm.h | 2 +-
+ drivers/net/wireless/intel/iwlwifi/mvm/tt.c | 21 ++--
+ drivers/staging/rtl8723bs/Kconfig | 1 -
+ kconf/Makefile | 4 +-
+ kconf/conf.c | 30 +----
+ kconf/confdata.c | 4 +-
+ local-symbols | 45 -------
+ 18 files changed, 118 insertions(+), 311 deletions(-)
+
+diff --git a/Kconfig.local b/Kconfig.local
+index d9495b1..547f8ad 100644
+--- a/Kconfig.local
++++ b/Kconfig.local
+@@ -1420,117 +1420,6 @@ config BACKPORTED_USB_NET_AQC111
+ config BACKPORTED_USB_RTL8153_ECM
+ tristate
+ default USB_RTL8153_ECM
+-config BACKPORTED_SSB_POSSIBLE
+- tristate
+- default SSB_POSSIBLE
+-config BACKPORTED_SSB
+- tristate
+- default SSB
+-config BACKPORTED_SSB_SPROM
+- tristate
+- default SSB_SPROM
+-config BACKPORTED_SSB_BLOCKIO
+- tristate
+- default SSB_BLOCKIO
+-config BACKPORTED_SSB_PCIHOST_POSSIBLE
+- tristate
+- default SSB_PCIHOST_POSSIBLE
+-config BACKPORTED_SSB_PCIHOST
+- tristate
+- default SSB_PCIHOST
+-config BACKPORTED_SSB_B43_PCI_BRIDGE
+- tristate
+- default SSB_B43_PCI_BRIDGE
+-config BACKPORTED_SSB_PCMCIAHOST_POSSIBLE
+- tristate
+- default SSB_PCMCIAHOST_POSSIBLE
+-config BACKPORTED_SSB_PCMCIAHOST
+- tristate
+- default SSB_PCMCIAHOST
+-config BACKPORTED_SSB_SDIOHOST_POSSIBLE
+- tristate
+- default SSB_SDIOHOST_POSSIBLE
+-config BACKPORTED_SSB_SDIOHOST
+- tristate
+- default SSB_SDIOHOST
+-config BACKPORTED_SSB_HOST_SOC
+- tristate
+- default SSB_HOST_SOC
+-config BACKPORTED_SSB_SERIAL
+- tristate
+- default SSB_SERIAL
+-config BACKPORTED_SSB_DRIVER_PCICORE_POSSIBLE
+- tristate
+- default SSB_DRIVER_PCICORE_POSSIBLE
+-config BACKPORTED_SSB_DRIVER_PCICORE
+- tristate
+- default SSB_DRIVER_PCICORE
+-config BACKPORTED_SSB_PCICORE_HOSTMODE
+- tristate
+- default SSB_PCICORE_HOSTMODE
+-config BACKPORTED_SSB_DRIVER_MIPS
+- tristate
+- default SSB_DRIVER_MIPS
+-config BACKPORTED_SSB_SFLASH
+- tristate
+- default SSB_SFLASH
+-config BACKPORTED_SSB_EMBEDDED
+- tristate
+- default SSB_EMBEDDED
+-config BACKPORTED_SSB_DRIVER_EXTIF
+- tristate
+- default SSB_DRIVER_EXTIF
+-config BACKPORTED_SSB_DRIVER_GIGE
+- tristate
+- default SSB_DRIVER_GIGE
+-config BACKPORTED_SSB_DRIVER_GPIO
+- tristate
+- default SSB_DRIVER_GPIO
+-config BACKPORTED_BCMA_POSSIBLE
+- tristate
+- default BCMA_POSSIBLE
+-config BACKPORTED_BCMA
+- tristate
+- default BCMA
+-config BACKPORTED_BCMA_BLOCKIO
+- tristate
+- default BCMA_BLOCKIO
+-config BACKPORTED_BCMA_HOST_PCI_POSSIBLE
+- tristate
+- default BCMA_HOST_PCI_POSSIBLE
+-config BACKPORTED_BCMA_HOST_PCI
+- tristate
+- default BCMA_HOST_PCI
+-config BACKPORTED_BCMA_HOST_SOC
+- tristate
+- default BCMA_HOST_SOC
+-config BACKPORTED_BCMA_DRIVER_PCI
+- tristate
+- default BCMA_DRIVER_PCI
+-config BACKPORTED_BCMA_DRIVER_PCI_HOSTMODE
+- tristate
+- default BCMA_DRIVER_PCI_HOSTMODE
+-config BACKPORTED_BCMA_DRIVER_MIPS
+- tristate
+- default BCMA_DRIVER_MIPS
+-config BACKPORTED_BCMA_PFLASH
+- tristate
+- default BCMA_PFLASH
+-config BACKPORTED_BCMA_SFLASH
+- tristate
+- default BCMA_SFLASH
+-config BACKPORTED_BCMA_NFLASH
+- tristate
+- default BCMA_NFLASH
+-config BACKPORTED_BCMA_DRIVER_GMAC_CMN
+- tristate
+- default BCMA_DRIVER_GMAC_CMN
+-config BACKPORTED_BCMA_DRIVER_GPIO
+- tristate
+- default BCMA_DRIVER_GPIO
+-config BACKPORTED_BCMA_DEBUG
+- tristate
+- default BCMA_DEBUG
+ config BACKPORTED_USB_ACM
+ tristate
+ default USB_ACM
+diff --git a/Kconfig.sources b/Kconfig.sources
+index 2ea4d8a..d74affd 100644
+--- a/Kconfig.sources
++++ b/Kconfig.sources
+@@ -4,15 +4,10 @@ source "$BACKPORT_DIR/compat/Kconfig"
+ # these are copied from the kernel
+ source "$BACKPORT_DIR/net/wireless/Kconfig"
+ source "$BACKPORT_DIR/net/mac80211/Kconfig"
+-source "$BACKPORT_DIR/net/qrtr/Kconfig"
+-source "$BACKPORT_DIR/drivers/bus/mhi/Kconfig"
+ source "$BACKPORT_DIR/drivers/soc/qcom/Kconfig"
+ source "$BACKPORT_DIR/drivers/net/wireless/Kconfig"
+ source "$BACKPORT_DIR/drivers/net/usb/Kconfig"
+
+-source "$BACKPORT_DIR/drivers/ssb/Kconfig"
+-source "$BACKPORT_DIR/drivers/bcma/Kconfig"
+-
+ source "$BACKPORT_DIR/drivers/usb/class/Kconfig"
+
+ source "$BACKPORT_DIR/drivers/staging/Kconfig"
+diff --git a/Makefile b/Makefile
+index 77c2670..c431b71 100644
+--- a/Makefile
++++ b/Makefile
+@@ -2,10 +2,10 @@
+ # Makefile for the output source package
+ #
+
+-ifeq ($(KERNELRELEASE),)
++ifeq ($(KERNELVERSION),)
+
+ MAKEFLAGS += --no-print-directory
+-SHELL := /bin/bash
++SHELL := /usr/bin/env bash
+ BACKPORT_DIR := $(shell pwd)
+
+ KMODDIR ?= updates
+@@ -19,6 +19,7 @@ KLIB_BUILD ?= $(KLIB)/build/
+ KERNEL_CONFIG := $(KLIB_BUILD)/.config
+ KERNEL_MAKEFILE := $(KLIB_BUILD)/Makefile
+ CONFIG_MD5 := $(shell md5sum $(KERNEL_CONFIG) 2>/dev/null | sed 's/\s.*//')
++STAMP_KERNEL_CONFIG := .kernel_config_md5_$(CONFIG_MD5)
+
+ export KLIB KLIB_BUILD BACKPORT_DIR KMODDIR KMODPATH_ARG
+
+@@ -36,7 +37,8 @@ mrproper:
+ @rm -f .kernel_config_md5 Kconfig.versions Kconfig.kernel
+ @rm -f backport-include/backport/autoconf.h
+
+-.DEFAULT:
++.SILENT: $(STAMP_KERNEL_CONFIG)
++$(STAMP_KERNEL_CONFIG):
+ @set -e ; test -f local-symbols || ( \
+ echo "/--------------" ;\
+ echo "| You shouldn't run make in the backports tree, but only in" ;\
+@@ -60,58 +62,62 @@ mrproper:
+ echo "| (that isn't currently running.)" ;\
+ echo "\\--" ;\
+ false)
+- @set -e ; if [ "$$(cat .kernel_config_md5 2>/dev/null)" != "$(CONFIG_MD5)" ] ;\
+- then \
+- echo -n "Generating local configuration database from kernel ..." ;\
+- grep -v -f local-symbols $(KERNEL_CONFIG) | grep = | ( \
+- while read l ; do \
+- if [ "$${l:0:7}" != "CONFIG_" ] ; then \
+- continue ;\
+- fi ;\
+- l=$${l:7} ;\
+- n=$${l%%=*} ;\
+- v=$${l#*=} ;\
+- if [ "$$v" = "m" ] ; then \
+- echo config $$n ;\
+- echo ' tristate' ;\
+- elif [ "$$v" = "y" ] ; then \
+- echo config $$n ;\
+- echo ' bool' ;\
+- else \
+- continue ;\
+- fi ;\
+- echo " default $$v" ;\
+- echo "" ;\
+- done \
+- ) > Kconfig.kernel ;\
+- kver=$$($(MAKE) --no-print-directory -C $(KLIB_BUILD) M=$(BACKPORT_DIR) \
+- kernelversion | sed 's/^\(\([3-5]\|2\.6\)\.[0-9]\+\).*/\1/;t;d');\
+- test "$$kver" != "" || echo "Kernel version parse failed!" ;\
+- test "$$kver" != "" ;\
+- kvers="$$(seq 14 39 | sed 's/^/2.6./')" ;\
+- kvers="$$kvers $$(seq 0 19 | sed 's/^/3./')" ;\
+- kvers="$$kvers $$(seq 0 20 | sed 's/^/4./')" ;\
+- kvers="$$kvers $$(seq 0 99 | sed 's/^/5./')" ;\
+- print=0 ;\
+- for v in $$kvers ; do \
+- if [ "$$print" = "1" ] ; then \
+- echo config KERNEL_$$(echo $$v | tr . _) ;\
+- echo " def_bool y" ;\
+- fi ;\
+- if [ "$$v" = "$$kver" ] ; then print=1 ; fi ;\
+- done > Kconfig.versions ;\
+- # RHEL as well, sadly we need to grep for it ;\
+- RHEL_MAJOR=$$(grep '^RHEL_MAJOR' $(KERNEL_MAKEFILE) | \
+- sed 's/.*=\s*\([0-9]*\)/\1/;t;d') ;\
+- RHEL_MINOR=$$(grep '^RHEL_MINOR' $(KERNEL_MAKEFILE) | \
+- sed 's/.*=\s*\([0-9]*\)/\1/;t;d') ;\
+- for v in $$(seq 0 $$RHEL_MINOR) ; do \
+- echo config BACKPORT_RHEL_KERNEL_$${RHEL_MAJOR}_$$v ;\
+- echo " def_bool y" ;\
+- done >> Kconfig.versions ;\
+- echo " done." ;\
+- fi ;\
+- echo "$(CONFIG_MD5)" > .kernel_config_md5
++ @rm -f .kernel_config_md5_*
++ @touch $@
++
++Kconfig.kernel: $(STAMP_KERNEL_CONFIG) local-symbols
++ @printf "Generating local configuration database from kernel ..."
++ @grep -v -f local-symbols $(KERNEL_CONFIG) | grep = | ( \
++ while read l ; do \
++ if [ "$${l:0:7}" != "CONFIG_" ] ; then \
++ continue ;\
++ fi ;\
++ l=$${l:7} ;\
++ n=$${l%%=*} ;\
++ v=$${l#*=} ;\
++ if [ "$$v" = "m" ] ; then \
++ echo config $$n ;\
++ echo ' tristate' ;\
++ elif [ "$$v" = "y" ] ; then \
++ echo config $$n ;\
++ echo ' bool' ;\
++ else \
++ continue ;\
++ fi ;\
++ echo " default $$v" ;\
++ echo "" ;\
++ done \
++ ) > $@
++ @echo " done."
++
++Kconfig.versions: Kconfig.kernel
++ @kver=$$($(MAKE) --no-print-directory -C $(KLIB_BUILD) M=$(BACKPORT_DIR) \
++ kernelversion | sed 's/^\(\([3-5]\|2\.6\)\.[0-9]\+\).*/\1/;t;d');\
++ test "$$kver" != "" || echo "Kernel version parse failed!" ;\
++ test "$$kver" != "" ;\
++ kvers="$$(seq 14 39 | sed 's/^/2.6./')" ;\
++ kvers="$$kvers $$(seq 0 19 | sed 's/^/3./')" ;\
++ kvers="$$kvers $$(seq 0 20 | sed 's/^/4./')" ;\
++ kvers="$$kvers $$(seq 0 99 | sed 's/^/5./')" ;\
++ print=0 ;\
++ for v in $$kvers ; do \
++ if [ "$$print" = "1" ] ; then \
++ echo config KERNEL_$$(echo $$v | tr . _) ;\
++ echo " def_bool y" ;\
++ fi ;\
++ if [ "$$v" = "$$kver" ] ; then print=1 ; fi ;\
++ done > $@
++ @RHEL_MAJOR=$$(grep '^RHEL_MAJOR' $(KERNEL_MAKEFILE) | \
++ sed 's/.*=\s*\([0-9]*\)/\1/;t;d') ;\
++ RHEL_MINOR=$$(grep '^RHEL_MINOR' $(KERNEL_MAKEFILE) | \
++ sed 's/.*=\s*\([0-9]*\)/\1/;t;d') ;\
++ for v in $$(seq 0 $$RHEL_MINOR) ; do \
++ echo config BACKPORT_RHEL_KERNEL_$${RHEL_MAJOR}_$$v ;\
++ echo " def_bool y" ;\
++ done >> $@
++
++.DEFAULT:
++ @$(MAKE) Kconfig.versions
+ @$(MAKE) -f Makefile.real "$@"
+
+ .PHONY: defconfig-help
+diff --git a/Makefile.real b/Makefile.real
+index 6550802..971a543 100644
+--- a/Makefile.real
++++ b/Makefile.real
+@@ -6,6 +6,18 @@ else
+ export BACKPORTS_GIT_TRACKER_DEF=
+ endif
+
++ifneq ($(LLVM),)
++ifneq ($(filter %/,$(LLVM)),)
++LLVM_PREFIX := $(LLVM)
++else ifneq ($(filter -%,$(LLVM)),)
++LLVM_SUFFIX := $(LLVM)
++endif
++
++HOSTCC = $(LLVM_PREFIX)clang$(LLVM_SUFFIX)
++else
++HOSTCC = gcc
++endif
++
+ # disable built-in rules for this file
+ .SUFFIXES:
+
+@@ -24,21 +36,21 @@ listnewconfig oldaskconfig oldconfig \
+ silentoldconfig olddefconfig oldnoconfig \
+ allnoconfig allyesconfig allmodconfig \
+ alldefconfig randconfig:
+- @$(MAKE) -C kconf conf
++ @$(MAKE) -C kconf CC=$(HOSTCC) conf
+ @./kconf/conf --$@ Kconfig
+
+ .PHONY: usedefconfig
+ usedefconfig:
+- @$(MAKE) -C kconf conf
++ @$(MAKE) -C kconf CC=$(HOSTCC) conf
+ @./kconf/conf --defconfig=defconfig Kconfig
+
+ .PHONY: savedefconfig
+ savedefconfig:
+- @$(MAKE) -C kconf conf
++ @$(MAKE) -C kconf CC=$(HOSTCC) conf
+ @./kconf/conf --savedefconfig=defconfig Kconfig
+
+ defconfig-%::
+- @$(MAKE) -C kconf conf
++ @$(MAKE) -C kconf CC=$(HOSTCC) conf
+ @./kconf/conf --defconfig=defconfigs/$(@:defconfig-%=%) Kconfig
+
+ .config:
+@@ -59,7 +71,7 @@ defconfig-%::
+
+ backport-include/backport/autoconf.h: .config Kconfig.versions Kconfig.kernel
+ @$(MAKE) oldconfig
+- @echo -n "Building backport-include/backport/autoconf.h ..."
++ @printf "Building backport-include/backport/autoconf.h ..."
+ @grep -f local-symbols .config | ( \
+ echo "#ifndef COMPAT_AUTOCONF_INCLUDED" ;\
+ echo "#define COMPAT_AUTOCONF_INCLUDED" ;\
+@@ -80,7 +92,12 @@ backport-include/backport/autoconf.h: .config Kconfig.versions Kconfig.kernel
+ esac ;\
+ done ;\
+ echo "#endif /* COMPAT_AUTOCONF_INCLUDED */" ;\
+- ) > backport-include/backport/autoconf.h
++ ) > $@.new
++ @if cmp -s $@ $@.new; then \
++ rm -f $@.new; \
++ else \
++ mv $@.new $@; \
++ fi
+ @echo " done."
+
+ .PHONY: modules
+diff --git a/compat/main.c b/compat/main.c
+index d4f3340..651ab63 100644
+--- a/compat/main.c
++++ b/compat/main.c
+@@ -19,31 +19,6 @@ MODULE_LICENSE("GPL");
+ #error "You need a CPTCFG_VERSION"
+ #endif
+
+-static char *backported_kernel_name = CPTCFG_KERNEL_NAME;
+-
+-module_param(backported_kernel_name, charp, 0400);
+-MODULE_PARM_DESC(backported_kernel_name,
+- "The kernel tree name that was used for this backport (" CPTCFG_KERNEL_NAME ")");
+-
+-#ifdef BACKPORTS_GIT_TRACKED
+-static char *backports_tracker_id = BACKPORTS_GIT_TRACKED;
+-module_param(backports_tracker_id, charp, 0400);
+-MODULE_PARM_DESC(backports_tracker_id,
+- "The version of the tree containing this backport (" BACKPORTS_GIT_TRACKED ")");
+-#else
+-static char *backported_kernel_version = CPTCFG_KERNEL_VERSION;
+-static char *backports_version = CPTCFG_VERSION;
+-
+-module_param(backported_kernel_version, charp, 0400);
+-MODULE_PARM_DESC(backported_kernel_version,
+- "The kernel version that was used for this backport (" CPTCFG_KERNEL_VERSION ")");
+-
+-module_param(backports_version, charp, 0400);
+-MODULE_PARM_DESC(backports_version,
+- "The git version of the backports tree used to generate this backport (" CPTCFG_VERSION ")");
+-
+-#endif
+-
+ void backport_dependency_symbol(void)
+ {
+ }
+diff --git a/drivers/net/wireless/ath/ath11k/Kconfig b/drivers/net/wireless/ath/ath11k/Kconfig
+index 7430aaf..f5f58a5 100644
+--- a/drivers/net/wireless/ath/ath11k/Kconfig
++++ b/drivers/net/wireless/ath/ath11k/Kconfig
+@@ -25,9 +25,9 @@ config ATH11K_PCI
+ tristate "Atheros ath11k PCI support"
+ depends on m
+ depends on ATH11K && PCI
+- select MHI_BUS
+- select QRTR
+- select QRTR_MHI
++ depends on MHI_BUS
++ depends on QRTR
++ depends on QRTR_MHI
+ help
+ This module adds support for PCIE bus
+
+diff --git a/drivers/net/wireless/broadcom/b43/Kconfig b/drivers/net/wireless/broadcom/b43/Kconfig
+index 2e196b5..84cbe38 100644
+--- a/drivers/net/wireless/broadcom/b43/Kconfig
++++ b/drivers/net/wireless/broadcom/b43/Kconfig
+@@ -63,21 +63,21 @@ endchoice
+ config B43_PCI_AUTOSELECT
+ bool
+ depends on B43 && SSB_PCIHOST_POSSIBLE
+- select SSB_PCIHOST
+- select SSB_B43_PCI_BRIDGE
++ depends on SSB_PCIHOST
++ depends on SSB_B43_PCI_BRIDGE
+ default y
+
+ # Auto-select SSB PCICORE driver, if possible
+ config B43_PCICORE_AUTOSELECT
+ bool
+ depends on B43 && SSB_DRIVER_PCICORE_POSSIBLE
+- select SSB_DRIVER_PCICORE
++ depends on SSB_DRIVER_PCICORE
+ default y
+
+ config B43_SDIO
+ bool "Broadcom 43xx SDIO device support"
+ depends on B43 && B43_SSB && SSB_SDIOHOST_POSSIBLE
+- select SSB_SDIOHOST
++ depends on SSB_SDIOHOST
+ help
+ Broadcom 43xx device support for Soft-MAC SDIO devices.
+
+@@ -96,13 +96,13 @@ config B43_SDIO
+ config B43_BCMA_PIO
+ bool
+ depends on B43 && B43_BCMA
+- select BCMA_BLOCKIO
++ depends on BCMA_BLOCKIO
+ default y
+
+ config B43_PIO
+ bool
+ depends on B43 && B43_SSB
+- select SSB_BLOCKIO
++ depends on SSB_BLOCKIO
+ default y
+
+ config B43_PHY_G
+diff --git a/drivers/net/wireless/broadcom/b43/main.c b/drivers/net/wireless/broadcom/b43/main.c
+index c2e0a05..bf2be0a 100644
+--- a/drivers/net/wireless/broadcom/b43/main.c
++++ b/drivers/net/wireless/broadcom/b43/main.c
+@@ -2854,7 +2854,7 @@ static struct ssb_device *b43_ssb_gpio_dev(struct b43_wldev *dev)
+ {
+ struct ssb_bus *bus = dev->dev->sdev->bus;
+
+-#ifdef CPTCFG_SSB_DRIVER_PCICORE
++#ifdef CONFIG_SSB_DRIVER_PCICORE
+ return (bus->chipco.dev ? bus->chipco.dev : bus->pcicore.dev);
+ #else
+ return bus->chipco.dev;
+@@ -4873,7 +4873,7 @@ static int b43_wireless_core_init(struct b43_wldev *dev)
+ }
+ if (sprom->boardflags_lo & B43_BFL_XTAL_NOSLOW)
+ hf |= B43_HF_DSCRQ; /* Disable slowclock requests from ucode. */
+-#if defined(CPTCFG_B43_SSB) && defined(CPTCFG_SSB_DRIVER_PCICORE)
++#if defined(CPTCFG_B43_SSB) && defined(CONFIG_SSB_DRIVER_PCICORE)
+ if (dev->dev->bus_type == B43_BUS_SSB &&
+ dev->dev->sdev->bus->bustype == SSB_BUSTYPE_PCI &&
+ dev->dev->sdev->bus->pcicore.dev->id.revision <= 10)
+diff --git a/drivers/net/wireless/broadcom/b43legacy/Kconfig b/drivers/net/wireless/broadcom/b43legacy/Kconfig
+index 6ba7eb7..b924f63 100644
+--- a/drivers/net/wireless/broadcom/b43legacy/Kconfig
++++ b/drivers/net/wireless/broadcom/b43legacy/Kconfig
+@@ -3,7 +3,7 @@ config B43LEGACY
+ tristate "Broadcom 43xx-legacy wireless support (mac80211 stack)"
+ depends on m
+ depends on SSB_POSSIBLE && MAC80211 && HAS_DMA
+- select SSB
++ depends on SSB
+ depends on FW_LOADER
+ help
+ b43legacy is a driver for 802.11b devices from Broadcom (BCM4301 and
+@@ -25,15 +25,15 @@ config B43LEGACY
+ config B43LEGACY_PCI_AUTOSELECT
+ bool
+ depends on B43LEGACY && SSB_PCIHOST_POSSIBLE
+- select SSB_PCIHOST
+- select SSB_B43_PCI_BRIDGE
++ depends on SSB_PCIHOST
++ depends on SSB_B43_PCI_BRIDGE
+ default y
+
+ # Auto-select SSB PCICORE driver, if possible
+ config B43LEGACY_PCICORE_AUTOSELECT
+ bool
+ depends on B43LEGACY && SSB_DRIVER_PCICORE_POSSIBLE
+- select SSB_DRIVER_PCICORE
++ depends on SSB_DRIVER_PCICORE
+ default y
+
+ # LED support
+diff --git a/drivers/net/wireless/broadcom/b43legacy/main.c b/drivers/net/wireless/broadcom/b43legacy/main.c
+index edd91ff..0222f63 100644
+--- a/drivers/net/wireless/broadcom/b43legacy/main.c
++++ b/drivers/net/wireless/broadcom/b43legacy/main.c
+@@ -1907,7 +1907,7 @@ static int b43legacy_gpio_init(struct b43legacy_wldev *dev)
+ if (dev->dev->id.revision >= 2)
+ mask |= 0x0010; /* FIXME: This is redundant. */
+
+-#ifdef CPTCFG_SSB_DRIVER_PCICORE
++#ifdef CONFIG_SSB_DRIVER_PCICORE
+ pcidev = bus->pcicore.dev;
+ #endif
+ gpiodev = bus->chipco.dev ? : pcidev;
+@@ -1926,7 +1926,7 @@ static void b43legacy_gpio_cleanup(struct b43legacy_wldev *dev)
+ struct ssb_bus *bus = dev->dev->bus;
+ struct ssb_device *gpiodev, *pcidev = NULL;
+
+-#ifdef CPTCFG_SSB_DRIVER_PCICORE
++#ifdef CONFIG_SSB_DRIVER_PCICORE
+ pcidev = bus->pcicore.dev;
+ #endif
+ gpiodev = bus->chipco.dev ? : pcidev;
+diff --git a/drivers/net/wireless/broadcom/brcm80211/Kconfig b/drivers/net/wireless/broadcom/brcm80211/Kconfig
+index 400dc88..b2d97b8 100644
+--- a/drivers/net/wireless/broadcom/brcm80211/Kconfig
++++ b/drivers/net/wireless/broadcom/brcm80211/Kconfig
+@@ -8,7 +8,7 @@ config BRCMSMAC
+ depends on m
+ depends on MAC80211
+ depends on BCMA_POSSIBLE
+- select BCMA
++ depends on BCMA
+ select BRCMUTIL
+ depends on FW_LOADER
+ depends on CORDIC
+diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h
+index b1a1ce5..66f9281 100644
+--- a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h
++++ b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h
+@@ -555,7 +555,7 @@ struct iwl_mvm_tt_mgmt {
+ * @tzone: thermal zone device data
+ */
+ struct iwl_mvm_thermal_device {
+- struct thermal_trip trips[IWL_MAX_DTS_TRIPS];
++ s16 temp_trips[IWL_MAX_DTS_TRIPS];
+ u8 fw_trips_index[IWL_MAX_DTS_TRIPS];
+ struct thermal_zone_device *tzone;
+ };
+diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/tt.c b/drivers/net/wireless/intel/iwlwifi/mvm/tt.c
+index dee9c36..1fb364d 100644
+--- a/drivers/net/wireless/intel/iwlwifi/mvm/tt.c
++++ b/drivers/net/wireless/intel/iwlwifi/mvm/tt.c
+@@ -573,11 +573,11 @@ int iwl_mvm_send_temp_report_ths_cmd(struct iwl_mvm *mvm)
+ * and uncompressed, the FW should get it compressed and sorted
+ */
+
+- /* compress trips to cmd array, remove uninitialized values*/
++ /* compress temp_trips to cmd array, remove uninitialized values*/
+ for (i = 0; i < IWL_MAX_DTS_TRIPS; i++) {
+- if (mvm->tz_device.trips[i].temperature != INT_MIN) {
++ if (mvm->tz_device.temp_trips[i] != S16_MIN) {
+ cmd.thresholds[idx++] =
+- cpu_to_le16((s16)(mvm->tz_device.trips[i].temperature / 1000));
++ cpu_to_le16(mvm->tz_device.temp_trips[i]);
+ }
+ }
+ cmd.num_temps = cpu_to_le32(idx);
+@@ -593,8 +593,8 @@ int iwl_mvm_send_temp_report_ths_cmd(struct iwl_mvm *mvm)
+ */
+ for (i = 0; i < idx; i++) {
+ for (j = 0; j < IWL_MAX_DTS_TRIPS; j++) {
+- if ((int)(le16_to_cpu(cmd.thresholds[i]) * 1000) ==
+- mvm->tz_device.trips[j].temperature)
++ if (le16_to_cpu(cmd.thresholds[i]) ==
++ mvm->tz_device.temp_trips[j])
+ mvm->tz_device.fw_trips_index[i] = j;
+ }
+ }
+@@ -665,6 +665,8 @@ out:
+
+ static struct thermal_zone_device_ops tzone_ops = {
+ .get_temp = iwl_mvm_tzone_get_temp,
++ .get_trip_temp = iwl_mvm_tzone_get_trip_temp,
++ .get_trip_type = iwl_mvm_tzone_get_trip_type,
+ .set_trip_temp = iwl_mvm_tzone_set_trip_temp,
+ };
+
+@@ -686,8 +688,7 @@ static void iwl_mvm_thermal_zone_register(struct iwl_mvm *mvm)
+ BUILD_BUG_ON(ARRAY_SIZE(name) >= THERMAL_NAME_LENGTH);
+
+ sprintf(name, "iwlwifi_%u", atomic_inc_return(&counter) & 0xFF);
+- mvm->tz_device.tzone = thermal_zone_device_register_with_trips(name,
+- mvm->tz_device.trips,
++ mvm->tz_device.tzone = thermal_zone_device_register(name,
+ IWL_MAX_DTS_TRIPS,
+ IWL_WRITABLE_TRIPS_MSK,
+ mvm, &tzone_ops,
+@@ -710,10 +711,8 @@ static void iwl_mvm_thermal_zone_register(struct iwl_mvm *mvm)
+ /* 0 is a valid temperature,
+ * so initialize the array with S16_MIN which invalid temperature
+ */
+- for (i = 0 ; i < IWL_MAX_DTS_TRIPS; i++) {
+- mvm->tz_device.trips[i].temperature = INT_MIN;
+- mvm->tz_device.trips[i].type = THERMAL_TRIP_PASSIVE;
+- }
++ for (i = 0 ; i < IWL_MAX_DTS_TRIPS; i++)
++ mvm->tz_device.temp_trips[i] = S16_MIN;
+ }
+
+ static int iwl_mvm_tcool_get_max_state(struct thermal_cooling_device *cdev,
+diff --git a/drivers/staging/rtl8723bs/Kconfig b/drivers/staging/rtl8723bs/Kconfig
+index b51916c..b46ff98 100644
+--- a/drivers/staging/rtl8723bs/Kconfig
++++ b/drivers/staging/rtl8723bs/Kconfig
+@@ -5,7 +5,6 @@ config RTL8723BS
+ depends on m
+ depends on WLAN && MMC && CFG80211
+ depends on m
+- select CFG80211_WEXT
+ depends on CRYPTO
+ select BPAUTO_CRYPTO_LIB_ARC4
+ help
+diff --git a/kconf/Makefile b/kconf/Makefile
+index 2004c44..a2790b1 100644
+--- a/kconf/Makefile
++++ b/kconf/Makefile
+@@ -1,9 +1,9 @@
+-CFLAGS=-Wall -Wmissing-prototypes -Wstrict-prototypes -O2 -fomit-frame-pointer
++CFLAGS=-Wall -Wmissing-prototypes -Wstrict-prototypes -O2 -fomit-frame-pointer -DKBUILD_NO_NLS
+
+ LXDIALOG := lxdialog/checklist.o lxdialog/inputbox.o lxdialog/menubox.o lxdialog/textbox.o lxdialog/util.o lxdialog/yesno.o
+
+ conf: conf.o zconf.tab.o
+-mconf_CFLAGS := $(shell ./lxdialog/check-lxdialog.sh -ccflags) -DLOCALE
++mconf_CFLAGS := $(shell ./lxdialog/check-lxdialog.sh -ccflags)
+ mconf_LDFLAGS := $(shell ./lxdialog/check-lxdialog.sh -ldflags $(CC))
+ mconf: CFLAGS += $(mconf_CFLAGS)
+
+diff --git a/kconf/conf.c b/kconf/conf.c
+index 283eeed..1707f05 100644
+--- a/kconf/conf.c
++++ b/kconf/conf.c
+@@ -598,40 +598,12 @@ int main(int ac, char **av)
+ case oldconfig:
+ case listnewconfig:
+ case olddefconfig:
+- conf_read(NULL);
+- break;
+ case allnoconfig:
+ case allyesconfig:
+ case allmodconfig:
+ case alldefconfig:
+ case randconfig:
+- name = getenv("KCONFIG_ALLCONFIG");
+- if (!name)
+- break;
+- if ((strcmp(name, "") != 0) && (strcmp(name, "1") != 0)) {
+- if (conf_read_simple(name, S_DEF_USER)) {
+- fprintf(stderr,
+- _("*** Can't read seed configuration \"%s\"!\n"),
+- name);
+- exit(1);
+- }
+- break;
+- }
+- switch (input_mode) {
+- case allnoconfig: name = "allno.config"; break;
+- case allyesconfig: name = "allyes.config"; break;
+- case allmodconfig: name = "allmod.config"; break;
+- case alldefconfig: name = "alldef.config"; break;
+- case randconfig: name = "allrandom.config"; break;
+- default: break;
+- }
+- if (conf_read_simple(name, S_DEF_USER) &&
+- conf_read_simple("all.config", S_DEF_USER)) {
+- fprintf(stderr,
+- _("*** KCONFIG_ALLCONFIG set, but no \"%s\" or \"all.config\" file found\n"),
+- name);
+- exit(1);
+- }
++ conf_read(NULL);
+ break;
+ default:
+ break;
+diff --git a/kconf/confdata.c b/kconf/confdata.c
+index df26c7b..1038c30 100644
+--- a/kconf/confdata.c
++++ b/kconf/confdata.c
+@@ -1170,6 +1170,8 @@ bool conf_set_all_new_symbols(enum conf_def_mode mode)
+ }
+ bool has_changed = false;
+
++ sym_clear_all_valid();
++
+ for_all_symbols(i, sym) {
+ if (sym_has_value(sym) || (sym->flags & SYMBOL_VALID))
+ continue;
+@@ -1213,8 +1215,6 @@ bool conf_set_all_new_symbols(enum conf_def_mode mode)
+
+ }
+
+- sym_clear_all_valid();
+-
+ /*
+ * We have different type of choice blocks.
+ * If curr.tri equals to mod then we can select several
+diff --git a/local-symbols b/local-symbols
+index 078fe8b..0743888 100644
+--- a/local-symbols
++++ b/local-symbols
+@@ -67,14 +67,6 @@ MAC80211_MESH_PS_DEBUG=
+ MAC80211_TDLS_DEBUG=
+ MAC80211_DEBUG_COUNTERS=
+ MAC80211_STA_HASH_MAX_SIZE=
+-QRTR=
+-QRTR_SMD=
+-QRTR_TUN=
+-QRTR_MHI=
+-MHI_BUS=
+-MHI_BUS_DEBUG=
+-MHI_BUS_PCI_GENERIC=
+-MHI_BUS_EP=
+ QCOM_AOSS_QMP=
+ QCOM_COMMAND_DB=
+ QCOM_GENI_SE=
+@@ -472,43 +464,6 @@ USB_VL600=
+ USB_NET_CH9200=
+ USB_NET_AQC111=
+ USB_RTL8153_ECM=
+-SSB_POSSIBLE=
+-SSB=
+-SSB_SPROM=
+-SSB_BLOCKIO=
+-SSB_PCIHOST_POSSIBLE=
+-SSB_PCIHOST=
+-SSB_B43_PCI_BRIDGE=
+-SSB_PCMCIAHOST_POSSIBLE=
+-SSB_PCMCIAHOST=
+-SSB_SDIOHOST_POSSIBLE=
+-SSB_SDIOHOST=
+-SSB_HOST_SOC=
+-SSB_SERIAL=
+-SSB_DRIVER_PCICORE_POSSIBLE=
+-SSB_DRIVER_PCICORE=
+-SSB_PCICORE_HOSTMODE=
+-SSB_DRIVER_MIPS=
+-SSB_SFLASH=
+-SSB_EMBEDDED=
+-SSB_DRIVER_EXTIF=
+-SSB_DRIVER_GIGE=
+-SSB_DRIVER_GPIO=
+-BCMA_POSSIBLE=
+-BCMA=
+-BCMA_BLOCKIO=
+-BCMA_HOST_PCI_POSSIBLE=
+-BCMA_HOST_PCI=
+-BCMA_HOST_SOC=
+-BCMA_DRIVER_PCI=
+-BCMA_DRIVER_PCI_HOSTMODE=
+-BCMA_DRIVER_MIPS=
+-BCMA_PFLASH=
+-BCMA_SFLASH=
+-BCMA_NFLASH=
+-BCMA_DRIVER_GMAC_CMN=
+-BCMA_DRIVER_GPIO=
+-BCMA_DEBUG=
+ USB_ACM=
+ USB_PRINTER=
+ USB_WDM=
+--
+2.39.2
+
diff --git a/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/0002-sync-backports-patches-ath.patch b/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/0002-sync-backports-patches-ath.patch
new file mode 100644
index 0000000..f47e6f5
--- /dev/null
+++ b/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/0002-sync-backports-patches-ath.patch
@@ -0,0 +1,482 @@
+From 429745cbf1435d31a656d4d912b7ea1cdd271be2 Mon Sep 17 00:00:00 2001
+From: Shayne Chen <shayne.chen@mediatek.com>
+Date: Tue, 12 Mar 2024 11:26:07 +0800
+Subject: [PATCH 02/61] sync backports patches/ath
+
+---
+ drivers/net/wireless/ath/Kconfig | 5 +-
+ drivers/net/wireless/ath/Makefile | 2 +-
+ drivers/net/wireless/ath/ath.h | 17 ++---
+ drivers/net/wireless/ath/ath5k/ani.c | 2 +-
+ drivers/net/wireless/ath/ath5k/base.c | 4 +-
+ drivers/net/wireless/ath/ath5k/mac80211-ops.c | 2 +-
+ drivers/net/wireless/ath/ath5k/pci.c | 26 ++++++-
+ drivers/net/wireless/ath/ath9k/link.c | 2 +-
+ drivers/net/wireless/ath/ath9k/main.c | 4 +-
+ drivers/net/wireless/ath/hw.c | 2 +-
+ drivers/net/wireless/ath/regd.c | 72 +++++++++++++------
+ drivers/net/wireless/ath/regd_common.h | 3 +
+ local-symbols | 1 +
+ net/wireless/reg.c | 3 +
+ 14 files changed, 102 insertions(+), 43 deletions(-)
+
+diff --git a/drivers/net/wireless/ath/Kconfig b/drivers/net/wireless/ath/Kconfig
+index 9ef8d46..bd576b4 100644
+--- a/drivers/net/wireless/ath/Kconfig
++++ b/drivers/net/wireless/ath/Kconfig
+@@ -1,6 +1,6 @@
+ # SPDX-License-Identifier: ISC
+ config ATH_COMMON
+- tristate
++ tristate "ath.ko"
+ depends on m
+
+ config WLAN_VENDOR_ATH
+@@ -24,6 +24,9 @@ config WLAN_VENDOR_ATH
+
+ if WLAN_VENDOR_ATH
+
++config ATH_USER_REGD
++ bool "Do not enforce EEPROM regulatory restrictions"
++
+ config ATH_DEBUG
+ bool "Atheros wireless debugging"
+ help
+diff --git a/drivers/net/wireless/ath/Makefile b/drivers/net/wireless/ath/Makefile
+index 7432d87..adea25c 100644
+--- a/drivers/net/wireless/ath/Makefile
++++ b/drivers/net/wireless/ath/Makefile
+@@ -16,10 +16,10 @@ ath-objs := main.o \
+ regd.o \
+ hw.o \
+ key.o \
++ debug.o \
+ dfs_pattern_detector.o \
+ dfs_pri_detector.o
+
+-ath-$(CPTCFG_ATH_DEBUG) += debug.o
+ ath-$(CPTCFG_ATH_TRACEPOINTS) += trace.o
+
+ CFLAGS_trace.o := -I$(src)
+diff --git a/drivers/net/wireless/ath/ath.h b/drivers/net/wireless/ath/ath.h
+index e9d95c7..888c5e2 100644
+--- a/drivers/net/wireless/ath/ath.h
++++ b/drivers/net/wireless/ath/ath.h
+@@ -43,10 +43,12 @@ struct ath_ani {
+ };
+
+ struct ath_cycle_counters {
+- u32 cycles;
+- u32 rx_busy;
+- u32 rx_frame;
+- u32 tx_frame;
++ struct_group(cnts,
++ u32 cycles;
++ u32 rx_busy;
++ u32 rx_frame;
++ u32 tx_frame;
++ );
+ };
+
+ enum ath_device_state {
+@@ -319,14 +321,7 @@ void _ath_dbg(struct ath_common *common, enum ATH_DEBUG dbg_mask,
+ #endif /* CPTCFG_ATH_DEBUG */
+
+ /** Returns string describing opmode, or NULL if unknown mode. */
+-#ifdef CPTCFG_ATH_DEBUG
+ const char *ath_opmode_to_string(enum nl80211_iftype opmode);
+-#else
+-static inline const char *ath_opmode_to_string(enum nl80211_iftype opmode)
+-{
+- return "UNKNOWN";
+-}
+-#endif
+
+ extern const char *ath_bus_type_strings[];
+ static inline const char *ath_bus_type_to_string(enum ath_bus_type bustype)
+diff --git a/drivers/net/wireless/ath/ath5k/ani.c b/drivers/net/wireless/ath/ath5k/ani.c
+index 11fd1ca..897cfd9 100644
+--- a/drivers/net/wireless/ath/ath5k/ani.c
++++ b/drivers/net/wireless/ath/ath5k/ani.c
+@@ -379,7 +379,7 @@ ath5k_hw_ani_get_listen_time(struct ath5k_hw *ah, struct ath5k_ani_state *as)
+ spin_lock_bh(&common->cc_lock);
+
+ ath_hw_cycle_counters_update(common);
+- memcpy(&as->last_cc, &common->cc_ani, sizeof(as->last_cc));
++ memcpy(&as->last_cc.cnts, &common->cc_ani.cnts, sizeof(as->last_cc.cnts));
+
+ /* clears common->cc_ani */
+ listen = ath_hw_get_listen_time(common);
+diff --git a/drivers/net/wireless/ath/ath5k/base.c b/drivers/net/wireless/ath/ath5k/base.c
+index 7ec5d9a..bad83fd 100644
+--- a/drivers/net/wireless/ath/ath5k/base.c
++++ b/drivers/net/wireless/ath/ath5k/base.c
+@@ -2985,8 +2985,8 @@ ath5k_reset(struct ath5k_hw *ah, struct ieee80211_channel *chan,
+ memset(&ah->survey, 0, sizeof(ah->survey));
+ spin_lock_bh(&common->cc_lock);
+ ath_hw_cycle_counters_update(common);
+- memset(&common->cc_survey, 0, sizeof(common->cc_survey));
+- memset(&common->cc_ani, 0, sizeof(common->cc_ani));
++ memset(&common->cc_survey.cnts, 0, sizeof(common->cc_survey.cnts));
++ memset(&common->cc_ani.cnts, 0, sizeof(common->cc_ani.cnts));
+ spin_unlock_bh(&common->cc_lock);
+
+ /*
+diff --git a/drivers/net/wireless/ath/ath5k/mac80211-ops.c b/drivers/net/wireless/ath/ath5k/mac80211-ops.c
+index eea4bda..da9dc62 100644
+--- a/drivers/net/wireless/ath/ath5k/mac80211-ops.c
++++ b/drivers/net/wireless/ath/ath5k/mac80211-ops.c
+@@ -664,7 +664,7 @@ ath5k_get_survey(struct ieee80211_hw *hw, int idx, struct survey_info *survey)
+ ah->survey.time_rx += cc->rx_frame / div;
+ ah->survey.time_tx += cc->tx_frame / div;
+ }
+- memset(cc, 0, sizeof(*cc));
++ memset(&cc->cnts, 0, sizeof(cc->cnts));
+ spin_unlock_bh(&common->cc_lock);
+
+ memcpy(survey, &ah->survey, sizeof(*survey));
+diff --git a/drivers/net/wireless/ath/ath5k/pci.c b/drivers/net/wireless/ath/ath5k/pci.c
+index b51fce5..c4315dd 100644
+--- a/drivers/net/wireless/ath/ath5k/pci.c
++++ b/drivers/net/wireless/ath/ath5k/pci.c
+@@ -20,6 +20,7 @@
+ #include <linux/pci.h>
+ #include <linux/etherdevice.h>
+ #include <linux/module.h>
++#include <linux/ath5k_platform.h>
+ #include "../ath.h"
+ #include "ath5k.h"
+ #include "debug.h"
+@@ -71,7 +72,7 @@ static void ath5k_pci_read_cachesize(struct ath_common *common, int *csz)
+ }
+
+ /*
+- * Read from eeprom
++ * Read from eeprom or platform_data
+ */
+ static bool
+ ath5k_pci_eeprom_read(struct ath_common *common, u32 offset, u16 *data)
+@@ -79,6 +80,19 @@ ath5k_pci_eeprom_read(struct ath_common *common, u32 offset, u16 *data)
+ struct ath5k_hw *ah = common->ah;
+ u32 status, timeout;
+
++ struct ath5k_platform_data *pdata = NULL;
++
++ if (ah->pdev)
++ pdata = ah->pdev->dev.platform_data;
++
++ if (pdata && pdata->eeprom_data && pdata->eeprom_data[61] == AR5K_EEPROM_MAGIC_VALUE) {
++ if (offset >= ATH5K_PLAT_EEP_MAX_WORDS)
++ return false;
++
++ *data = pdata->eeprom_data[offset];
++ return true;
++ }
++
+ /*
+ * Initialize EEPROM access
+ */
+@@ -122,6 +136,16 @@ static int ath5k_pci_eeprom_read_mac(struct ath5k_hw *ah, u8 *mac)
+ u16 data;
+ int octet;
+
++ struct ath5k_platform_data *pdata = NULL;
++
++ if (ah->pdev)
++ pdata = ah->pdev->dev.platform_data;
++
++ if (pdata && pdata->macaddr) {
++ memcpy(mac, pdata->macaddr, ETH_ALEN);
++ return 0;
++ }
++
+ AR5K_EEPROM_READ(0x20, data);
+
+ for (offset = 0x1f, octet = 0, total = 0; offset >= 0x1d; offset--) {
+diff --git a/drivers/net/wireless/ath/ath9k/link.c b/drivers/net/wireless/ath/ath9k/link.c
+index d1e5767..7f18d71 100644
+--- a/drivers/net/wireless/ath/ath9k/link.c
++++ b/drivers/net/wireless/ath/ath9k/link.c
+@@ -536,7 +536,7 @@ int ath_update_survey_stats(struct ath_softc *sc)
+ if (cc->cycles > 0)
+ ret = cc->rx_busy * 100 / cc->cycles;
+
+- memset(cc, 0, sizeof(*cc));
++ memset(&cc->cnts, 0, sizeof(cc->cnts));
+
+ ath_update_survey_nf(sc, pos);
+
+diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c
+index 34d11b0..6d120df 100644
+--- a/drivers/net/wireless/ath/ath9k/main.c
++++ b/drivers/net/wireless/ath/ath9k/main.c
+@@ -135,8 +135,8 @@ void ath9k_ps_wakeup(struct ath_softc *sc)
+ if (power_mode != ATH9K_PM_AWAKE) {
+ spin_lock(&common->cc_lock);
+ ath_hw_cycle_counters_update(common);
+- memset(&common->cc_survey, 0, sizeof(common->cc_survey));
+- memset(&common->cc_ani, 0, sizeof(common->cc_ani));
++ memset(&common->cc_survey.cnts, 0, sizeof(common->cc_survey.cnts));
++ memset(&common->cc_ani.cnts, 0, sizeof(common->cc_ani.cnts));
+ spin_unlock(&common->cc_lock);
+ }
+
+diff --git a/drivers/net/wireless/ath/hw.c b/drivers/net/wireless/ath/hw.c
+index 8595557..be8bfed 100644
+--- a/drivers/net/wireless/ath/hw.c
++++ b/drivers/net/wireless/ath/hw.c
+@@ -183,7 +183,7 @@ int32_t ath_hw_get_listen_time(struct ath_common *common)
+ listen_time = (cc->cycles - cc->rx_frame - cc->tx_frame) /
+ (common->clockrate * 1000);
+
+- memset(cc, 0, sizeof(*cc));
++ memset(&cc->cnts, 0, sizeof(cc->cnts));
+
+ return listen_time;
+ }
+diff --git a/drivers/net/wireless/ath/regd.c b/drivers/net/wireless/ath/regd.c
+index 2afdebf..3ba9fc3 100644
+--- a/drivers/net/wireless/ath/regd.c
++++ b/drivers/net/wireless/ath/regd.c
+@@ -24,6 +24,7 @@
+ #include "regd_common.h"
+
+ static int __ath_regd_init(struct ath_regulatory *reg);
++static struct reg_dmn_pair_mapping *ath_get_regpair(int regdmn);
+
+ /*
+ * This is a set of common rules used by our world regulatory domains.
+@@ -43,7 +44,8 @@ static int __ath_regd_init(struct ath_regulatory *reg);
+ NL80211_RRF_NO_OFDM)
+
+ /* We allow IBSS on these on a case by case basis by regulatory domain */
+-#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 ATH_5GHZ_5470_5850 REG_RULE(5470-10, 5850+10, 80, 0, 30,\
+ NL80211_RRF_NO_IR)
+@@ -61,64 +63,79 @@ static int __ath_regd_init(struct ath_regulatory *reg);
+ #define ATH_5GHZ_NO_MIDBAND ATH_5GHZ_5150_5350, \
+ ATH_5GHZ_5725_5850
+
++#define REGD_RULES(...) \
++ .reg_rules = { __VA_ARGS__ }, \
++ .n_reg_rules = ARRAY_SIZE(((struct ieee80211_reg_rule[]) { __VA_ARGS__ }))
++
+ /* Can be used for:
+ * 0x60, 0x61, 0x62 */
+ static const struct ieee80211_regdomain ath_world_regdom_60_61_62 = {
+- .n_reg_rules = 5,
+ .alpha2 = "99",
+- .reg_rules = {
++ REGD_RULES(
+ ATH_2GHZ_ALL,
+ ATH_5GHZ_ALL,
+- }
++ )
+ };
+
+ /* Can be used by 0x63 and 0x65 */
+ static const struct ieee80211_regdomain ath_world_regdom_63_65 = {
+- .n_reg_rules = 4,
+ .alpha2 = "99",
+- .reg_rules = {
++ REGD_RULES(
+ ATH_2GHZ_CH01_11,
+ ATH_2GHZ_CH12_13,
+ ATH_5GHZ_NO_MIDBAND,
+- }
++ )
+ };
+
+ /* Can be used by 0x64 only */
+ static const struct ieee80211_regdomain ath_world_regdom_64 = {
+- .n_reg_rules = 3,
+ .alpha2 = "99",
+- .reg_rules = {
++ REGD_RULES(
+ ATH_2GHZ_CH01_11,
+ ATH_5GHZ_NO_MIDBAND,
+- }
++ )
+ };
+
+ /* Can be used by 0x66 and 0x69 */
+ static const struct ieee80211_regdomain ath_world_regdom_66_69 = {
+- .n_reg_rules = 3,
+ .alpha2 = "99",
+- .reg_rules = {
++ REGD_RULES(
+ ATH_2GHZ_CH01_11,
+ ATH_5GHZ_ALL,
+- }
++ )
+ };
+
+ /* Can be used by 0x67, 0x68, 0x6A and 0x6C */
+ static const struct ieee80211_regdomain ath_world_regdom_67_68_6A_6C = {
+- .n_reg_rules = 4,
+ .alpha2 = "99",
+- .reg_rules = {
++ REGD_RULES(
+ ATH_2GHZ_CH01_11,
+ ATH_2GHZ_CH12_13,
+ ATH_5GHZ_ALL,
+- }
++ )
+ };
+
++static u16 ath_regd_get_eepromRD(struct ath_regulatory *reg)
++{
++ return reg->current_rd & ~WORLDWIDE_ROAMING_FLAG;
++}
++
++static bool is_default_regd(struct ath_regulatory *reg)
++{
++ return ath_regd_get_eepromRD(reg) == CTRY_DEFAULT;
++}
++
+ static bool dynamic_country_user_possible(struct ath_regulatory *reg)
+ {
++ if (IS_ENABLED(CPTCFG_ATH_USER_REGD))
++ return true;
++
+ if (IS_ENABLED(CPTCFG_ATH_REG_DYNAMIC_USER_CERT_TESTING))
+ return true;
+
++ if (is_default_regd(reg))
++ return true;
++
+ switch (reg->country_code) {
+ case CTRY_UNITED_STATES:
+ case CTRY_JAPAN1:
+@@ -188,6 +205,8 @@ static bool dynamic_country_user_possible(struct ath_regulatory *reg)
+
+ static bool ath_reg_dyn_country_user_allow(struct ath_regulatory *reg)
+ {
++ if (IS_ENABLED(CPTCFG_ATH_USER_REGD))
++ return true;
+ if (!IS_ENABLED(CPTCFG_ATH_REG_DYNAMIC_USER_REG_HINTS))
+ return false;
+ if (!dynamic_country_user_possible(reg))
+@@ -202,11 +221,6 @@ static inline bool is_wwr_sku(u16 regd)
+ (regd == WORLD));
+ }
+
+-static u16 ath_regd_get_eepromRD(struct ath_regulatory *reg)
+-{
+- return reg->current_rd & ~WORLDWIDE_ROAMING_FLAG;
+-}
+-
+ bool ath_is_world_regd(struct ath_regulatory *reg)
+ {
+ return is_wwr_sku(ath_regd_get_eepromRD(reg));
+@@ -345,6 +359,9 @@ ath_reg_apply_beaconing_flags(struct wiphy *wiphy,
+ struct ieee80211_channel *ch;
+ unsigned int i;
+
++ if (IS_ENABLED(CPTCFG_ATH_USER_REGD))
++ return;
++
+ for (band = 0; band < NUM_NL80211_BANDS; band++) {
+ if (!wiphy->bands[band])
+ continue;
+@@ -379,6 +396,9 @@ ath_reg_apply_ir_flags(struct wiphy *wiphy,
+ {
+ struct ieee80211_supported_band *sband;
+
++ if (IS_ENABLED(CPTCFG_ATH_USER_REGD))
++ return;
++
+ sband = wiphy->bands[NL80211_BAND_2GHZ];
+ if (!sband)
+ return;
+@@ -408,6 +428,9 @@ static void ath_reg_apply_radar_flags(struct wiphy *wiphy,
+ struct ieee80211_channel *ch;
+ unsigned int i;
+
++ if (IS_ENABLED(CPTCFG_ATH_USER_REGD))
++ return;
++
+ if (!wiphy->bands[NL80211_BAND_5GHZ])
+ return;
+
+@@ -640,6 +663,13 @@ ath_regd_init_wiphy(struct ath_regulatory *reg,
+ const struct ieee80211_regdomain *regd;
+
+ wiphy->reg_notifier = reg_notifier;
++
++ if (IS_ENABLED(CPTCFG_ATH_USER_REGD))
++ return 0;
++
++ if (is_default_regd(reg))
++ return 0;
++
+ wiphy->regulatory_flags |= REGULATORY_STRICT_REG |
+ REGULATORY_CUSTOM_REG;
+
+diff --git a/drivers/net/wireless/ath/regd_common.h b/drivers/net/wireless/ath/regd_common.h
+index cdb1e9a..2574f80 100644
+--- a/drivers/net/wireless/ath/regd_common.h
++++ b/drivers/net/wireless/ath/regd_common.h
+@@ -32,6 +32,7 @@ enum EnumRd {
+ FCC2_WORLD = 0x21,
+ FCC2_ETSIC = 0x22,
+ FCC6_WORLD = 0x23,
++ FCC3_FCCA_2 = 0x2A,
+ FRANCE_RES = 0x31,
+ FCC3_FCCA = 0x3A,
+ FCC3_WORLD = 0x3B,
+@@ -173,6 +174,7 @@ static struct reg_dmn_pair_mapping regDomainPairs[] = {
+ {FCC2_WORLD, CTL_FCC, CTL_ETSI},
+ {FCC2_ETSIC, CTL_FCC, CTL_ETSI},
+ {FCC3_FCCA, CTL_FCC, CTL_FCC},
++ {FCC3_FCCA_2, CTL_FCC, CTL_FCC},
+ {FCC3_WORLD, CTL_FCC, CTL_ETSI},
+ {FCC3_ETSIC, CTL_FCC, CTL_ETSI},
+ {FCC4_FCCA, CTL_FCC, CTL_FCC},
+@@ -486,6 +488,7 @@ static struct country_code_to_enum_rd allCountries[] = {
+ {CTRY_UAE, NULL1_WORLD, "AE"},
+ {CTRY_UNITED_KINGDOM, ETSI1_WORLD, "GB"},
+ {CTRY_UNITED_STATES, FCC3_FCCA, "US"},
++ {CTRY_UNITED_STATES, FCC3_FCCA_2, "US"},
+ {CTRY_UNITED_STATES2, FCC3_FCCA, "US"},
+ {CTRY_UNITED_STATES3, FCC3_FCCA, "US"},
+ /* This "PS" is for US public safety actually... to support this we
+diff --git a/local-symbols b/local-symbols
+index 0743888..b200b00 100644
+--- a/local-symbols
++++ b/local-symbols
+@@ -101,6 +101,7 @@ ADM8211=
+ ATH_COMMON=
+ WLAN_VENDOR_ATH=
+ ATH_DEBUG=
++ATH_USER_REGD=
+ ATH_TRACEPOINTS=
+ ATH_REG_DYNAMIC_USER_REG_HINTS=
+ ATH_REG_DYNAMIC_USER_CERT_TESTING=
+diff --git a/net/wireless/reg.c b/net/wireless/reg.c
+index 233ebab..2c0c1f1 100644
+--- a/net/wireless/reg.c
++++ b/net/wireless/reg.c
+@@ -3365,6 +3365,8 @@ void regulatory_hint_country_ie(struct wiphy *wiphy, enum nl80211_band band,
+ enum environment_cap env = ENVIRON_ANY;
+ struct regulatory_request *request = NULL, *lr;
+
++ return;
++
+ /* IE len must be evenly divisible by 2 */
+ if (country_ie_len & 0x01)
+ return;
+@@ -3616,6 +3618,7 @@ static bool is_wiphy_all_set_reg_flag(enum ieee80211_regulatory_flags flag)
+
+ void regulatory_hint_disconnect(void)
+ {
++ return;
+ /* Restore of regulatory settings is not required when wiphy(s)
+ * ignore IE from connected access point but clearance of beacon hints
+ * is required when wiphy(s) supports beacon hints.
+--
+2.39.2
+
diff --git a/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/0003-sync-backports-patches-ath5k.patch b/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/0003-sync-backports-patches-ath5k.patch
new file mode 100644
index 0000000..e0051b5
--- /dev/null
+++ b/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/0003-sync-backports-patches-ath5k.patch
@@ -0,0 +1,315 @@
+From 410e3c08cd5f7bd85e3ca3965fcbf79b9eb6d1e4 Mon Sep 17 00:00:00 2001
+From: Shayne Chen <shayne.chen@mediatek.com>
+Date: Tue, 12 Mar 2024 11:26:26 +0800
+Subject: [PATCH 03/61] sync backports patches/ath5k
+
+---
+ drivers/net/wireless/ath/ath5k/ath5k.h | 1 +
+ drivers/net/wireless/ath/ath5k/base.c | 8 +-
+ drivers/net/wireless/ath/ath5k/debug.c | 93 +++++++++++++++++++
+ drivers/net/wireless/ath/ath5k/dma.c | 8 ++
+ drivers/net/wireless/ath/ath5k/initvals.c | 6 ++
+ drivers/net/wireless/ath/ath5k/mac80211-ops.c | 9 +-
+ drivers/net/wireless/ath/ath5k/pci.c | 2 +
+ drivers/net/wireless/ath/ath5k/reset.c | 2 +
+ include/linux/ath5k_platform.h | 30 ++++++
+ 9 files changed, 150 insertions(+), 9 deletions(-)
+ create mode 100644 include/linux/ath5k_platform.h
+
+diff --git a/drivers/net/wireless/ath/ath5k/ath5k.h b/drivers/net/wireless/ath/ath5k/ath5k.h
+index 308a429..0e6d184 100644
+--- a/drivers/net/wireless/ath/ath5k/ath5k.h
++++ b/drivers/net/wireless/ath/ath5k/ath5k.h
+@@ -1372,6 +1372,7 @@ struct ath5k_hw {
+ u8 ah_coverage_class;
+ bool ah_ack_bitrate_high;
+ u8 ah_bwmode;
++ u8 ah_bwmode_debug;
+ bool ah_short_slot;
+
+ /* Antenna Control */
+diff --git a/drivers/net/wireless/ath/ath5k/base.c b/drivers/net/wireless/ath/ath5k/base.c
+index bad83fd..fb0366c 100644
+--- a/drivers/net/wireless/ath/ath5k/base.c
++++ b/drivers/net/wireless/ath/ath5k/base.c
+@@ -465,6 +465,9 @@ ath5k_chan_set(struct ath5k_hw *ah, struct cfg80211_chan_def *chandef)
+ return -EINVAL;
+ }
+
++ if (ah->ah_bwmode_debug != AR5K_BWMODE_DEFAULT)
++ ah->ah_bwmode = ah->ah_bwmode_debug;
++
+ /*
+ * To switch channels clear any pending DMA operations;
+ * wait long enough for the RX fifo to drain, reset the
+@@ -2009,7 +2012,7 @@ ath5k_beacon_send(struct ath5k_hw *ah)
+ }
+
+ if ((ah->opmode == NL80211_IFTYPE_AP && ah->num_ap_vifs +
+- ah->num_mesh_vifs > 1) ||
++ ah->num_adhoc_vifs + ah->num_mesh_vifs > 1) ||
+ ah->opmode == NL80211_IFTYPE_MESH_POINT) {
+ u64 tsf = ath5k_hw_get_tsf64(ah);
+ u32 tsftu = TSF_TO_TU(tsf);
+@@ -2095,7 +2098,7 @@ ath5k_beacon_update_timers(struct ath5k_hw *ah, u64 bc_tsf)
+
+ intval = ah->bintval & AR5K_BEACON_PERIOD;
+ if (ah->opmode == NL80211_IFTYPE_AP && ah->num_ap_vifs
+- + ah->num_mesh_vifs > 1) {
++ + ah->num_adhoc_vifs + ah->num_mesh_vifs > 1) {
+ intval /= ATH_BCBUF; /* staggered multi-bss beacons */
+ if (intval < 15)
+ ATH5K_WARN(ah, "intval %u is too low, min 15\n",
+@@ -2561,6 +2564,7 @@ static const struct ieee80211_iface_limit if_limits[] = {
+ BIT(NL80211_IFTYPE_MESH_POINT) |
+ #endif
+ BIT(NL80211_IFTYPE_AP) },
++ { .max = 1, .types = BIT(NL80211_IFTYPE_ADHOC) },
+ };
+
+ static const struct ieee80211_iface_combination if_comb = {
+diff --git a/drivers/net/wireless/ath/ath5k/debug.c b/drivers/net/wireless/ath/ath5k/debug.c
+index ec13051..239d789 100644
+--- a/drivers/net/wireless/ath/ath5k/debug.c
++++ b/drivers/net/wireless/ath/ath5k/debug.c
+@@ -803,6 +803,97 @@ static const struct file_operations fops_ani = {
+ .llseek = default_llseek,
+ };
+
++/* debugfs: bwmode */
++
++static ssize_t read_file_bwmode(struct file *file, char __user *user_buf,
++ size_t count, loff_t *ppos)
++{
++ struct ath5k_hw *ah = file->private_data;
++ char buf[15];
++ unsigned int len = 0;
++
++ int cur_ah_bwmode = ah->ah_bwmode_debug;
++
++#define print_selected(MODE, LABEL) \
++ if (cur_ah_bwmode == MODE) \
++ len += snprintf(buf+len, sizeof(buf)-len, "[%s]", LABEL); \
++ else \
++ len += snprintf(buf+len, sizeof(buf)-len, "%s", LABEL); \
++ len += snprintf(buf+len, sizeof(buf)-len, " ");
++
++ print_selected(AR5K_BWMODE_5MHZ, "5");
++ print_selected(AR5K_BWMODE_10MHZ, "10");
++ print_selected(AR5K_BWMODE_DEFAULT, "20");
++ print_selected(AR5K_BWMODE_40MHZ, "40");
++#undef print_selected
++
++ len += snprintf(buf+len, sizeof(buf)-len, "\n");
++
++ return simple_read_from_buffer(user_buf, count, ppos, buf, len);
++}
++
++static ssize_t write_file_bwmode(struct file *file,
++ const char __user *userbuf,
++ size_t count, loff_t *ppos)
++{
++ struct ath5k_hw *ah = file->private_data;
++ char buf[3];
++ int bw = 20;
++ int tobwmode = AR5K_BWMODE_DEFAULT;
++
++ if (copy_from_user(buf, userbuf, min(count, sizeof(buf))))
++ return -EFAULT;
++
++ /* TODO: Add check for active interface */
++
++ if(strncmp(buf, "5", 1) == 0 ) {
++ tobwmode = AR5K_BWMODE_5MHZ;
++ bw = 5;
++ } else if ( strncmp(buf, "10", 2) == 0 ) {
++ tobwmode = AR5K_BWMODE_10MHZ;
++ bw = 10;
++ } else if ( strncmp(buf, "20", 2) == 0 ) {
++ tobwmode = AR5K_BWMODE_DEFAULT;
++ bw = 20;
++ } else if ( strncmp(buf, "40", 2) == 0 ) {
++ tobwmode = AR5K_BWMODE_40MHZ;
++ bw = 40;
++ } else
++ return -EINVAL;
++
++ ATH5K_INFO(ah, "Changing to %imhz channel width[%i]\n",
++ bw, tobwmode);
++
++ switch (ah->ah_radio) {
++ /* TODO: only define radios that actually support 5/10mhz channels */
++ case AR5K_RF5413:
++ case AR5K_RF5110:
++ case AR5K_RF5111:
++ case AR5K_RF5112:
++ case AR5K_RF2413:
++ case AR5K_RF2316:
++ case AR5K_RF2317:
++ case AR5K_RF2425:
++ if(ah->ah_bwmode_debug != tobwmode) {
++ mutex_lock(&ah->lock);
++ ah->ah_bwmode = tobwmode;
++ ah->ah_bwmode_debug = tobwmode;
++ mutex_unlock(&ah->lock);
++ }
++ break;
++ default:
++ return -EOPNOTSUPP;
++ }
++ return count;
++}
++
++static const struct file_operations fops_bwmode = {
++ .read = read_file_bwmode,
++ .write = write_file_bwmode,
++ .open = simple_open,
++ .owner = THIS_MODULE,
++ .llseek = default_llseek,
++};
+
+ /* debugfs: queues etc */
+
+@@ -995,6 +1086,8 @@ ath5k_debug_init_device(struct ath5k_hw *ah)
+ debugfs_create_file("queue", 0600, phydir, ah, &fops_queue);
+ debugfs_create_bool("32khz_clock", 0600, phydir,
+ &ah->ah_use_32khz_clock);
++ debugfs_create_file("bwmode", S_IWUSR | S_IRUSR, phydir, ah,
++ &fops_bwmode);
+ }
+
+ /* functions used in other places */
+diff --git a/drivers/net/wireless/ath/ath5k/dma.c b/drivers/net/wireless/ath/ath5k/dma.c
+index d9e376e..db06ff8 100644
+--- a/drivers/net/wireless/ath/ath5k/dma.c
++++ b/drivers/net/wireless/ath/ath5k/dma.c
+@@ -854,10 +854,18 @@ ath5k_hw_dma_init(struct ath5k_hw *ah)
+ * guess we can tweak it and see how it goes ;-)
+ */
+ if (ah->ah_version != AR5K_AR5210) {
++#if !defined(CONFIG_ATHEROS_AR71XX) && !defined(CONFIG_ATH79)
+ AR5K_REG_WRITE_BITS(ah, AR5K_TXCFG,
+ AR5K_TXCFG_SDMAMR, AR5K_DMASIZE_128B);
+ AR5K_REG_WRITE_BITS(ah, AR5K_RXCFG,
+ AR5K_RXCFG_SDMAMW, AR5K_DMASIZE_128B);
++#else
++ /* WAR for AR71xx PCI bug */
++ AR5K_REG_WRITE_BITS(ah, AR5K_TXCFG,
++ AR5K_TXCFG_SDMAMR, AR5K_DMASIZE_128B);
++ AR5K_REG_WRITE_BITS(ah, AR5K_RXCFG,
++ AR5K_RXCFG_SDMAMW, AR5K_DMASIZE_4B);
++#endif
+ }
+
+ /* Pre-enable interrupts on 5211/5212*/
+diff --git a/drivers/net/wireless/ath/ath5k/initvals.c b/drivers/net/wireless/ath/ath5k/initvals.c
+index ee1c2fa..122fe1c 100644
+--- a/drivers/net/wireless/ath/ath5k/initvals.c
++++ b/drivers/net/wireless/ath/ath5k/initvals.c
+@@ -62,8 +62,14 @@ static const struct ath5k_ini ar5210_ini[] = {
+ { AR5K_IMR, 0 },
+ { AR5K_IER, AR5K_IER_DISABLE },
+ { AR5K_BSR, 0, AR5K_INI_READ },
++#if !defined(CONFIG_ATHEROS_AR71XX) && !defined(CONFIG_ATH79)
+ { AR5K_TXCFG, AR5K_DMASIZE_128B },
+ { AR5K_RXCFG, AR5K_DMASIZE_128B },
++#else
++ /* WAR for AR71xx PCI bug */
++ { AR5K_TXCFG, AR5K_DMASIZE_128B },
++ { AR5K_RXCFG, AR5K_DMASIZE_4B },
++#endif
+ { AR5K_CFG, AR5K_INIT_CFG },
+ { AR5K_TOPS, 8 },
+ { AR5K_RXNOFRM, 8 },
+diff --git a/drivers/net/wireless/ath/ath5k/mac80211-ops.c b/drivers/net/wireless/ath/ath5k/mac80211-ops.c
+index da9dc62..2fb37d3 100644
+--- a/drivers/net/wireless/ath/ath5k/mac80211-ops.c
++++ b/drivers/net/wireless/ath/ath5k/mac80211-ops.c
+@@ -86,13 +86,8 @@ ath5k_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
+ goto end;
+ }
+
+- /* Don't allow other interfaces if one ad-hoc is configured.
+- * TODO: Fix the problems with ad-hoc and multiple other interfaces.
+- * We would need to operate the HW in ad-hoc mode to allow TSF updates
+- * for the IBSS, but this breaks with additional AP or STA interfaces
+- * at the moment. */
+- if (ah->num_adhoc_vifs ||
+- (ah->nvifs && vif->type == NL80211_IFTYPE_ADHOC)) {
++ /* Don't allow more than one ad-hoc interface */
++ if (ah->num_adhoc_vifs && vif->type == NL80211_IFTYPE_ADHOC) {
+ ATH5K_ERR(ah, "Only one single ad-hoc interface is allowed.\n");
+ ret = -ELNRNG;
+ goto end;
+diff --git a/drivers/net/wireless/ath/ath5k/pci.c b/drivers/net/wireless/ath/ath5k/pci.c
+index c4315dd..2aae4de 100644
+--- a/drivers/net/wireless/ath/ath5k/pci.c
++++ b/drivers/net/wireless/ath/ath5k/pci.c
+@@ -47,6 +47,8 @@ static const struct pci_device_id ath5k_pci_id_table[] = {
+ { PCI_VDEVICE(ATHEROS, 0x001b) }, /* 5413 Eagle */
+ { PCI_VDEVICE(ATHEROS, 0x001c) }, /* PCI-E cards */
+ { PCI_VDEVICE(ATHEROS, 0x001d) }, /* 2417 Nala */
++ { PCI_VDEVICE(ATHEROS, 0xff16) }, /* 2413,2414 sx76x on lantiq_danube */
++ { PCI_VDEVICE(ATHEROS, 0xff1a) }, /* 2417 arv45xx on lantiq_danube */
+ { PCI_VDEVICE(ATHEROS, 0xff1b) }, /* AR5BXB63 */
+ { 0 }
+ };
+diff --git a/drivers/net/wireless/ath/ath5k/reset.c b/drivers/net/wireless/ath/ath5k/reset.c
+index 9fdb528..eabf225 100644
+--- a/drivers/net/wireless/ath/ath5k/reset.c
++++ b/drivers/net/wireless/ath/ath5k/reset.c
+@@ -1154,6 +1154,7 @@ ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode,
+ tsf_lo = 0;
+ mode = 0;
+
++#if 0
+ /*
+ * Sanity check for fast flag
+ * Fast channel change only available
+@@ -1161,6 +1162,7 @@ ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode,
+ */
+ if (fast && (ah->ah_radio != AR5K_RF2413) &&
+ (ah->ah_radio != AR5K_RF5413))
++#endif
+ fast = false;
+
+ /* Disable sleep clock operation
+diff --git a/include/linux/ath5k_platform.h b/include/linux/ath5k_platform.h
+new file mode 100644
+index 0000000..ec85224
+--- /dev/null
++++ b/include/linux/ath5k_platform.h
+@@ -0,0 +1,30 @@
++/*
++ * Copyright (c) 2008 Atheros Communications Inc.
++ * Copyright (c) 2009 Gabor Juhos <juhosg@openwrt.org>
++ * Copyright (c) 2009 Imre Kaloz <kaloz@openwrt.org>
++ * Copyright (c) 2010 Daniel Golle <daniel.golle@gmail.com>
++ *
++ * Permission to use, copy, modify, and/or distribute this software for any
++ * purpose with or without fee is hereby granted, provided that the above
++ * copyright notice and this permission notice appear in all copies.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
++ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
++ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
++ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
++ */
++
++#ifndef _LINUX_ATH5K_PLATFORM_H
++#define _LINUX_ATH5K_PLATFORM_H
++
++#define ATH5K_PLAT_EEP_MAX_WORDS 2048
++
++struct ath5k_platform_data {
++ u16 *eeprom_data;
++ u8 *macaddr;
++};
++
++#endif /* _LINUX_ATH5K_PLATFORM_H */
+--
+2.39.2
+
diff --git a/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/0004-sync-backports-patches-ath9k.patch b/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/0004-sync-backports-patches-ath9k.patch
new file mode 100644
index 0000000..93b4572
--- /dev/null
+++ b/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/0004-sync-backports-patches-ath9k.patch
@@ -0,0 +1,2508 @@
+From 58736b0bd1ae576889c23c0639aa36f29ab6a74f Mon Sep 17 00:00:00 2001
+From: Shayne Chen <shayne.chen@mediatek.com>
+Date: Tue, 12 Mar 2024 11:26:51 +0800
+Subject: [PATCH 04/61] sync backports patches/ath9k
+
+---
+ drivers/net/wireless/ath/ath.h | 2 +
+ drivers/net/wireless/ath/ath9k/Kconfig | 13 +
+ drivers/net/wireless/ath/ath9k/Makefile | 1 +
+ drivers/net/wireless/ath/ath9k/ahb.c | 260 ++++++++++++-
+ drivers/net/wireless/ath/ath9k/ani.h | 2 +-
+ drivers/net/wireless/ath/ath9k/ar5008_phy.c | 72 ++--
+ drivers/net/wireless/ath/ath9k/ar9002_phy.h | 11 +
+ drivers/net/wireless/ath/ath9k/ar9003_phy.c | 95 +----
+ drivers/net/wireless/ath/ath9k/ath9k.h | 34 +-
+ drivers/net/wireless/ath/ath9k/channel.c | 7 +
+ drivers/net/wireless/ath/ath9k/common-debug.c | 107 +++++
+ drivers/net/wireless/ath/ath9k/common-debug.h | 4 +
+ drivers/net/wireless/ath/ath9k/common.c | 21 +-
+ drivers/net/wireless/ath/ath9k/debug.c | 107 +++++
+ drivers/net/wireless/ath/ath9k/gpio.c | 365 ++++++++++++++++--
+ drivers/net/wireless/ath/ath9k/hsr.c | 247 ++++++++++++
+ drivers/net/wireless/ath/ath9k/hsr.h | 48 +++
+ .../net/wireless/ath/ath9k/htc_drv_debug.c | 2 +
+ drivers/net/wireless/ath/ath9k/htc_drv_init.c | 7 +-
+ drivers/net/wireless/ath/ath9k/hw-ops.h | 6 +
+ drivers/net/wireless/ath/ath9k/hw.c | 154 ++++++--
+ drivers/net/wireless/ath/ath9k/hw.h | 12 +
+ drivers/net/wireless/ath/ath9k/init.c | 48 ++-
+ drivers/net/wireless/ath/ath9k/mac.c | 9 +-
+ drivers/net/wireless/ath/ath9k/main.c | 12 +
+ drivers/net/wireless/ath/ath9k/pci.c | 1 +
+ drivers/net/wireless/ath/ath9k/phy.h | 3 +
+ include/linux/ath9k_platform.h | 7 +
+ local-symbols | 1 +
+ 29 files changed, 1438 insertions(+), 220 deletions(-)
+ create mode 100644 drivers/net/wireless/ath/ath9k/hsr.c
+ create mode 100644 drivers/net/wireless/ath/ath9k/hsr.h
+
+diff --git a/drivers/net/wireless/ath/ath.h b/drivers/net/wireless/ath/ath.h
+index 888c5e2..f7e2e89 100644
+--- a/drivers/net/wireless/ath/ath.h
++++ b/drivers/net/wireless/ath/ath.h
+@@ -153,6 +153,7 @@ struct ath_common {
+ int debug_mask;
+ enum ath_device_state state;
+ unsigned long op_flags;
++ u32 chan_bw;
+
+ struct ath_ani ani;
+
+@@ -181,6 +182,7 @@ struct ath_common {
+ const struct ath_ops *ops;
+ const struct ath_bus_ops *bus_ops;
+ const struct ath_ps_ops *ps_ops;
++ const struct ieee80211_ops *ieee_ops;
+
+ bool btcoex_enabled;
+ bool disable_ani;
+diff --git a/drivers/net/wireless/ath/ath9k/Kconfig b/drivers/net/wireless/ath/ath9k/Kconfig
+index b97598f..d3e72a8 100644
+--- a/drivers/net/wireless/ath/ath9k/Kconfig
++++ b/drivers/net/wireless/ath/ath9k/Kconfig
+@@ -58,6 +58,19 @@ config ATH9K_AHB
+ Say Y, if you have a SoC with a compatible built-in
+ wireless MAC. Say N if unsure.
+
++config ATH9K_UBNTHSR
++ bool "Ubiquiti UniFi Outdoor Plus HSR support"
++ depends on ATH9K
++ ---help---
++ This options enables code to control the HSR RF
++ filter in the receive path of the Ubiquiti UniFi
++ Outdoor Plus access point.
++
++ Say Y if you want to use the access point. The
++ code will only be used if the device is detected,
++ so it does not harm other setup other than occupying
++ a bit of memory.
++
+ config ATH9K_DEBUGFS
+ bool "Atheros ath9k debugging"
+ depends on ATH9K && DEBUG_FS && MAC80211_DEBUGFS
+diff --git a/drivers/net/wireless/ath/ath9k/Makefile b/drivers/net/wireless/ath/ath9k/Makefile
+index 847c8a8..6427bc6 100644
+--- a/drivers/net/wireless/ath/ath9k/Makefile
++++ b/drivers/net/wireless/ath/ath9k/Makefile
+@@ -17,6 +17,7 @@ ath9k-$(CPTCFG_ATH9K_DFS_CERTIFIED) += dfs.o
+ ath9k-$(CPTCFG_ATH9K_TX99) += tx99.o
+ ath9k-$(CPTCFG_ATH9K_WOW) += wow.o
+ ath9k-$(CPTCFG_ATH9K_HWRNG) += rng.o
++ath9k-$(CPTCFG_ATH9K_UBNTHSR) += hsr.o
+
+ ath9k-$(CPTCFG_ATH9K_DEBUGFS) += debug.o
+
+diff --git a/drivers/net/wireless/ath/ath9k/ahb.c b/drivers/net/wireless/ath/ath9k/ahb.c
+index 1a6697b..f9a76e7 100644
+--- a/drivers/net/wireless/ath/ath9k/ahb.c
++++ b/drivers/net/wireless/ath/ath9k/ahb.c
+@@ -20,7 +20,15 @@
+ #include <linux/platform_device.h>
+ #include <linux/module.h>
+ #include <linux/mod_devicetable.h>
++#include <linux/of_device.h>
+ #include "ath9k.h"
++#include <linux/ath9k_platform.h>
++
++#ifdef CONFIG_OF
++#include <asm/mach-ath79/ath79.h>
++#include <asm/mach-ath79/ar71xx_regs.h>
++#include <linux/mtd/mtd.h>
++#endif
+
+ static const struct platform_device_id ath9k_platform_id_table[] = {
+ {
+@@ -69,6 +77,236 @@ static const struct ath_bus_ops ath_ahb_bus_ops = {
+ .eeprom_read = ath_ahb_eeprom_read,
+ };
+
++#ifdef CONFIG_OF
++
++#define QCA955X_DDR_CTL_CONFIG 0x108
++#define QCA955X_DDR_CTL_CONFIG_ACT_WMAC BIT(23)
++
++static int of_get_wifi_cal(struct device_node *np, struct ath9k_platform_data *pdata)
++{
++#ifdef CONFIG_MTD
++ struct device_node *mtd_np = NULL;
++ size_t retlen;
++ int size, ret;
++ struct mtd_info *mtd;
++ const char *part;
++ const __be32 *list;
++ phandle phandle;
++
++ list = of_get_property(np, "mtd-cal-data", &size);
++ if (!list)
++ return 0;
++
++ if (size != (2 * sizeof(*list)))
++ return 1;
++
++ phandle = be32_to_cpup(list++);
++ if (phandle)
++ mtd_np = of_find_node_by_phandle(phandle);
++
++ if (!mtd_np)
++ return 1;
++
++ part = of_get_property(mtd_np, "label", NULL);
++ if (!part)
++ part = mtd_np->name;
++
++ mtd = get_mtd_device_nm(part);
++ if (IS_ERR(mtd))
++ return 1;
++
++ ret = mtd_read(mtd, be32_to_cpup(list), sizeof(pdata->eeprom_data),
++ &retlen, (u8*)pdata->eeprom_data);
++ put_mtd_device(mtd);
++
++#endif
++ return 0;
++}
++
++static int ar913x_wmac_reset(void)
++{
++ ath79_device_reset_set(AR913X_RESET_AMBA2WMAC);
++ mdelay(10);
++
++ ath79_device_reset_clear(AR913X_RESET_AMBA2WMAC);
++ mdelay(10);
++
++ return 0;
++}
++
++static int ar933x_wmac_reset(void)
++{
++ int retries = 20;
++
++ ath79_device_reset_set(AR933X_RESET_WMAC);
++ ath79_device_reset_clear(AR933X_RESET_WMAC);
++
++ while (1) {
++ u32 bootstrap;
++
++ bootstrap = ath79_reset_rr(AR933X_RESET_REG_BOOTSTRAP);
++ if ((bootstrap & AR933X_BOOTSTRAP_EEPBUSY) == 0)
++ return 0;
++
++ if (retries-- == 0)
++ break;
++
++ udelay(10000);
++ }
++
++ pr_err("ar933x: WMAC reset timed out");
++ return -ETIMEDOUT;
++}
++
++static int qca955x_wmac_reset(void)
++{
++ int i;
++
++ /* Try to wait for WMAC DDR activity to stop */
++ for (i = 0; i < 10; i++) {
++ if (!(__raw_readl(ath79_ddr_base + QCA955X_DDR_CTL_CONFIG) &
++ QCA955X_DDR_CTL_CONFIG_ACT_WMAC))
++ break;
++
++ udelay(10);
++ }
++
++ ath79_device_reset_set(QCA955X_RESET_RTC);
++ udelay(10);
++ ath79_device_reset_clear(QCA955X_RESET_RTC);
++ udelay(10);
++
++ return 0;
++}
++
++enum {
++ AR913X_WMAC = 0,
++ AR933X_WMAC,
++ AR934X_WMAC,
++ QCA953X_WMAC,
++ QCA955X_WMAC,
++ QCA956X_WMAC,
++};
++
++static int ar9330_get_soc_revision(void)
++{
++ if (ath79_soc_rev == 1)
++ return ath79_soc_rev;
++
++ return 0;
++}
++
++static int ath79_get_soc_revision(void)
++{
++ return ath79_soc_rev;
++}
++
++static const struct of_ath_ahb_data {
++ u16 dev_id;
++ u32 bootstrap_reg;
++ u32 bootstrap_ref;
++
++ int (*soc_revision)(void);
++ int (*wmac_reset)(void);
++} of_ath_ahb_data[] = {
++ [AR913X_WMAC] = {
++ .dev_id = AR5416_AR9100_DEVID,
++ .wmac_reset = ar913x_wmac_reset,
++
++ },
++ [AR933X_WMAC] = {
++ .dev_id = AR9300_DEVID_AR9330,
++ .bootstrap_reg = AR933X_RESET_REG_BOOTSTRAP,
++ .bootstrap_ref = AR933X_BOOTSTRAP_REF_CLK_40,
++ .soc_revision = ar9330_get_soc_revision,
++ .wmac_reset = ar933x_wmac_reset,
++ },
++ [AR934X_WMAC] = {
++ .dev_id = AR9300_DEVID_AR9340,
++ .bootstrap_reg = AR934X_RESET_REG_BOOTSTRAP,
++ .bootstrap_ref = AR934X_BOOTSTRAP_REF_CLK_40,
++ .soc_revision = ath79_get_soc_revision,
++ },
++ [QCA953X_WMAC] = {
++ .dev_id = AR9300_DEVID_AR953X,
++ .bootstrap_reg = QCA953X_RESET_REG_BOOTSTRAP,
++ .bootstrap_ref = QCA953X_BOOTSTRAP_REF_CLK_40,
++ .soc_revision = ath79_get_soc_revision,
++ },
++ [QCA955X_WMAC] = {
++ .dev_id = AR9300_DEVID_QCA955X,
++ .bootstrap_reg = QCA955X_RESET_REG_BOOTSTRAP,
++ .bootstrap_ref = QCA955X_BOOTSTRAP_REF_CLK_40,
++ .wmac_reset = qca955x_wmac_reset,
++ },
++ [QCA956X_WMAC] = {
++ .dev_id = AR9300_DEVID_QCA956X,
++ .bootstrap_reg = QCA956X_RESET_REG_BOOTSTRAP,
++ .bootstrap_ref = QCA956X_BOOTSTRAP_REF_CLK_40,
++ .soc_revision = ath79_get_soc_revision,
++ },
++};
++
++const struct of_device_id of_ath_ahb_match[] = {
++ { .compatible = "qca,ar9130-wmac", .data = &of_ath_ahb_data[AR913X_WMAC] },
++ { .compatible = "qca,ar9330-wmac", .data = &of_ath_ahb_data[AR933X_WMAC] },
++ { .compatible = "qca,ar9340-wmac", .data = &of_ath_ahb_data[AR934X_WMAC] },
++ { .compatible = "qca,qca9530-wmac", .data = &of_ath_ahb_data[QCA953X_WMAC] },
++ { .compatible = "qca,qca9550-wmac", .data = &of_ath_ahb_data[QCA955X_WMAC] },
++ { .compatible = "qca,qca9560-wmac", .data = &of_ath_ahb_data[QCA956X_WMAC] },
++ {},
++};
++MODULE_DEVICE_TABLE(of, of_ath_ahb_match);
++
++static int of_ath_ahb_probe(struct platform_device *pdev)
++{
++ struct ath9k_platform_data *pdata;
++ const struct of_device_id *match;
++ const struct of_ath_ahb_data *data;
++ u8 led_pin;
++
++ match = of_match_device(of_ath_ahb_match, &pdev->dev);
++ data = (const struct of_ath_ahb_data *)match->data;
++
++ pdata = dev_get_platdata(&pdev->dev);
++
++ if (!of_property_read_u8(pdev->dev.of_node, "qca,led-pin", &led_pin))
++ pdata->led_pin = led_pin;
++ else
++ pdata->led_pin = -1;
++
++ if (of_property_read_bool(pdev->dev.of_node, "qca,tx-gain-buffalo"))
++ pdata->tx_gain_buffalo = true;
++
++ if (data->wmac_reset) {
++ data->wmac_reset();
++ pdata->external_reset = data->wmac_reset;
++ }
++
++ if (data->dev_id == AR9300_DEVID_AR953X) {
++ /*
++ * QCA953x only supports 25MHz refclk.
++ * Some vendors have an invalid bootstrap option
++ * set, which would break the WMAC here.
++ */
++ pdata->is_clk_25mhz = true;
++ } else if (data->bootstrap_reg && data->bootstrap_ref) {
++ u32 t = ath79_reset_rr(data->bootstrap_reg);
++ if (t & data->bootstrap_ref)
++ pdata->is_clk_25mhz = false;
++ else
++ pdata->is_clk_25mhz = true;
++ }
++
++ pdata->get_mac_revision = data->soc_revision;
++
++ if (of_get_wifi_cal(pdev->dev.of_node, pdata))
++ dev_err(&pdev->dev, "failed to load calibration data from mtd device\n");
++
++ return data->dev_id;
++}
++#endif
++
+ static int ath_ahb_probe(struct platform_device *pdev)
+ {
+ void __iomem *mem;
+@@ -80,6 +318,17 @@ static int ath_ahb_probe(struct platform_device *pdev)
+ int ret = 0;
+ struct ath_hw *ah;
+ char hw_name[64];
++ u16 dev_id;
++
++ if (id)
++ dev_id = id->driver_data;
++
++#ifdef CONFIG_OF
++ if (pdev->dev.of_node)
++ pdev->dev.platform_data = devm_kzalloc(&pdev->dev,
++ sizeof(struct ath9k_platform_data),
++ GFP_KERNEL);
++#endif
+
+ if (!dev_get_platdata(&pdev->dev)) {
+ dev_err(&pdev->dev, "no platform data specified\n");
+@@ -118,17 +367,23 @@ static int ath_ahb_probe(struct platform_device *pdev)
+ sc->mem = mem;
+ sc->irq = irq;
+
++#ifdef CONFIG_OF
++ dev_id = of_ath_ahb_probe(pdev);
++#endif
+ ret = request_irq(irq, ath_isr, IRQF_SHARED, "ath9k", sc);
+ if (ret) {
+ dev_err(&pdev->dev, "request_irq failed\n");
+ goto err_free_hw;
+ }
+
+- ret = ath9k_init_device(id->driver_data, sc, &ath_ahb_bus_ops);
++ ret = ath9k_init_device(dev_id, sc, &ath_ahb_bus_ops);
+ if (ret) {
+ dev_err(&pdev->dev, "failed to initialize device\n");
+ goto err_irq;
+ }
++#ifdef CONFIG_OF
++ pdev->dev.platform_data = NULL;
++#endif
+
+ ah = sc->sc_ah;
+ ath9k_hw_name(ah, hw_name, sizeof(hw_name));
+@@ -162,6 +417,9 @@ static struct platform_driver ath_ahb_driver = {
+ .remove_new = ath_ahb_remove,
+ .driver = {
+ .name = "ath9k",
++#ifdef CONFIG_OF
++ .of_match_table = of_ath_ahb_match,
++#endif
+ },
+ .id_table = ath9k_platform_id_table,
+ };
+diff --git a/drivers/net/wireless/ath/ath9k/ani.h b/drivers/net/wireless/ath/ath9k/ani.h
+index c40965b..f66f7ed 100644
+--- a/drivers/net/wireless/ath/ath9k/ani.h
++++ b/drivers/net/wireless/ath/ath9k/ani.h
+@@ -42,7 +42,7 @@
+ #define ATH9K_ANI_PERIOD 300
+
+ /* in ms */
+-#define ATH9K_ANI_POLLINTERVAL 1000
++#define ATH9K_ANI_POLLINTERVAL 300
+
+ #define ATH9K_SIG_FIRSTEP_SETTING_MIN 0
+ #define ATH9K_SIG_FIRSTEP_SETTING_MAX 20
+diff --git a/drivers/net/wireless/ath/ath9k/ar5008_phy.c b/drivers/net/wireless/ath/ath9k/ar5008_phy.c
+index 7a45f5f..3f0ca1d 100644
+--- a/drivers/net/wireless/ath/ath9k/ar5008_phy.c
++++ b/drivers/net/wireless/ath/ath9k/ar5008_phy.c
+@@ -969,55 +969,6 @@ static bool ar5008_hw_ani_control_new(struct ath_hw *ah,
+ * on == 0 means more noise imm
+ */
+ u32 on = param ? 1 : 0;
+- /*
+- * make register setting for default
+- * (weak sig detect ON) come from INI file
+- */
+- int m1ThreshLow = on ?
+- aniState->iniDef.m1ThreshLow : m1ThreshLow_off;
+- int m2ThreshLow = on ?
+- aniState->iniDef.m2ThreshLow : m2ThreshLow_off;
+- int m1Thresh = on ?
+- aniState->iniDef.m1Thresh : m1Thresh_off;
+- int m2Thresh = on ?
+- aniState->iniDef.m2Thresh : m2Thresh_off;
+- int m2CountThr = on ?
+- aniState->iniDef.m2CountThr : m2CountThr_off;
+- int m2CountThrLow = on ?
+- aniState->iniDef.m2CountThrLow : m2CountThrLow_off;
+- int m1ThreshLowExt = on ?
+- aniState->iniDef.m1ThreshLowExt : m1ThreshLowExt_off;
+- int m2ThreshLowExt = on ?
+- aniState->iniDef.m2ThreshLowExt : m2ThreshLowExt_off;
+- int m1ThreshExt = on ?
+- aniState->iniDef.m1ThreshExt : m1ThreshExt_off;
+- int m2ThreshExt = on ?
+- aniState->iniDef.m2ThreshExt : m2ThreshExt_off;
+-
+- REG_RMW_FIELD(ah, AR_PHY_SFCORR_LOW,
+- AR_PHY_SFCORR_LOW_M1_THRESH_LOW,
+- m1ThreshLow);
+- REG_RMW_FIELD(ah, AR_PHY_SFCORR_LOW,
+- AR_PHY_SFCORR_LOW_M2_THRESH_LOW,
+- m2ThreshLow);
+- REG_RMW_FIELD(ah, AR_PHY_SFCORR,
+- AR_PHY_SFCORR_M1_THRESH, m1Thresh);
+- REG_RMW_FIELD(ah, AR_PHY_SFCORR,
+- AR_PHY_SFCORR_M2_THRESH, m2Thresh);
+- REG_RMW_FIELD(ah, AR_PHY_SFCORR,
+- AR_PHY_SFCORR_M2COUNT_THR, m2CountThr);
+- REG_RMW_FIELD(ah, AR_PHY_SFCORR_LOW,
+- AR_PHY_SFCORR_LOW_M2COUNT_THR_LOW,
+- m2CountThrLow);
+-
+- REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT,
+- AR_PHY_SFCORR_EXT_M1_THRESH_LOW, m1ThreshLowExt);
+- REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT,
+- AR_PHY_SFCORR_EXT_M2_THRESH_LOW, m2ThreshLowExt);
+- REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT,
+- AR_PHY_SFCORR_EXT_M1_THRESH, m1ThreshExt);
+- REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT,
+- AR_PHY_SFCORR_EXT_M2_THRESH, m2ThreshExt);
+
+ if (on)
+ REG_SET_BIT(ah, AR_PHY_SFCORR_LOW,
+@@ -1340,9 +1291,30 @@ void ar5008_hw_init_rate_txpower(struct ath_hw *ah, int16_t *rate_array,
+ }
+ }
+
++static void ar5008_hw_get_adc_entropy(struct ath_hw *ah, u8 *buf, size_t len)
++{
++ int i, j;
++
++ REG_RMW_FIELD(ah, AR_PHY_TEST, AR_PHY_TEST_BBB_OBS_SEL, 1);
++ REG_CLR_BIT(ah, AR_PHY_TEST, AR_PHY_TEST_RX_OBS_SEL_BIT5);
++ REG_RMW_FIELD(ah, AR_PHY_TEST2, AR_PHY_TEST2_RX_OBS_SEL, 0);
++
++ memset(buf, 0, len);
++ for (i = 0; i < len; i++) {
++ for (j = 0; j < 4; j++) {
++ u32 regval = REG_READ(ah, AR_PHY_TST_ADC);
++
++ buf[i] <<= 2;
++ buf[i] |= (regval & 1) | ((regval & BIT(9)) >> 8);
++ udelay(1);
++ }
++ }
++}
++
+ int ar5008_hw_attach_phy_ops(struct ath_hw *ah)
+ {
+ struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah);
++ struct ath_hw_ops *ops = ath9k_hw_ops(ah);
+ static const u32 ar5416_cca_regs[6] = {
+ AR_PHY_CCA,
+ AR_PHY_CH1_CCA,
+@@ -1357,6 +1329,8 @@ int ar5008_hw_attach_phy_ops(struct ath_hw *ah)
+ if (ret)
+ return ret;
+
++ ops->get_adc_entropy = ar5008_hw_get_adc_entropy;
++
+ priv_ops->rf_set_freq = ar5008_hw_set_channel;
+ priv_ops->spur_mitigate_freq = ar5008_hw_spur_mitigate;
+
+diff --git a/drivers/net/wireless/ath/ath9k/ar9002_phy.h b/drivers/net/wireless/ath/ath9k/ar9002_phy.h
+index 2b58245..d20a936 100644
+--- a/drivers/net/wireless/ath/ath9k/ar9002_phy.h
++++ b/drivers/net/wireless/ath/ath9k/ar9002_phy.h
+@@ -20,6 +20,12 @@
+ #define PHY_AGC_CLR 0x10000000
+ #define RFSILENT_BB 0x00002000
+
++#define AR_PHY_TEST_BBB_OBS_SEL 0x780000
++#define AR_PHY_TEST_BBB_OBS_SEL_S 19
++
++#define AR_PHY_TEST_RX_OBS_SEL_BIT5_S 23
++#define AR_PHY_TEST_RX_OBS_SEL_BIT5 (1 << AR_PHY_TEST_RX_OBS_SEL_BIT5_S)
++
+ #define AR_PHY_TURBO 0x9804
+ #define AR_PHY_FC_TURBO_MODE 0x00000001
+ #define AR_PHY_FC_TURBO_SHORT 0x00000002
+@@ -36,6 +42,9 @@
+
+ #define AR_PHY_TEST2 0x9808
+
++#define AR_PHY_TEST2_RX_OBS_SEL 0x3C00
++#define AR_PHY_TEST2_RX_OBS_SEL_S 10
++
+ #define AR_PHY_TIMING2 0x9810
+ #define AR_PHY_TIMING3 0x9814
+ #define AR_PHY_TIMING3_DSC_MAN 0xFFFE0000
+@@ -393,6 +402,8 @@
+ #define AR_PHY_RFBUS_GRANT 0x9C20
+ #define AR_PHY_RFBUS_GRANT_EN 0x00000001
+
++#define AR_PHY_TST_ADC 0x9C24
++
+ #define AR_PHY_CHAN_INFO_GAIN_DIFF 0x9CF4
+ #define AR_PHY_CHAN_INFO_GAIN_DIFF_UPPER_LIMIT 320
+
+diff --git a/drivers/net/wireless/ath/ath9k/ar9003_phy.c b/drivers/net/wireless/ath/ath9k/ar9003_phy.c
+index f715149..0246ad0 100644
+--- a/drivers/net/wireless/ath/ath9k/ar9003_phy.c
++++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.c
+@@ -42,20 +42,6 @@ static const int cycpwrThr1_table[] =
+ /* level: 0 1 2 3 4 5 6 7 8 */
+ { -6, -4, -2, 0, 2, 4, 6, 8 }; /* lvl 0-7, default 3 */
+
+-/*
+- * register values to turn OFDM weak signal detection OFF
+- */
+-static const int m1ThreshLow_off = 127;
+-static const int m2ThreshLow_off = 127;
+-static const int m1Thresh_off = 127;
+-static const int m2Thresh_off = 127;
+-static const int m2CountThr_off = 31;
+-static const int m2CountThrLow_off = 63;
+-static const int m1ThreshLowExt_off = 127;
+-static const int m2ThreshLowExt_off = 127;
+-static const int m1ThreshExt_off = 127;
+-static const int m2ThreshExt_off = 127;
+-
+ static const u8 ofdm2pwr[] = {
+ ALL_TARGET_LEGACY_6_24,
+ ALL_TARGET_LEGACY_6_24,
+@@ -1065,11 +1051,6 @@ static bool ar9003_hw_ani_control(struct ath_hw *ah,
+ struct ath_common *common = ath9k_hw_common(ah);
+ struct ath9k_channel *chan = ah->curchan;
+ struct ar5416AniState *aniState = &ah->ani;
+- int m1ThreshLow, m2ThreshLow;
+- int m1Thresh, m2Thresh;
+- int m2CountThr, m2CountThrLow;
+- int m1ThreshLowExt, m2ThreshLowExt;
+- int m1ThreshExt, m2ThreshExt;
+ s32 value, value2;
+
+ switch (cmd & ah->ani_function) {
+@@ -1083,61 +1064,6 @@ static bool ar9003_hw_ani_control(struct ath_hw *ah,
+ */
+ u32 on = param ? 1 : 0;
+
+- if (AR_SREV_9462(ah) || AR_SREV_9565(ah))
+- goto skip_ws_det;
+-
+- m1ThreshLow = on ?
+- aniState->iniDef.m1ThreshLow : m1ThreshLow_off;
+- m2ThreshLow = on ?
+- aniState->iniDef.m2ThreshLow : m2ThreshLow_off;
+- m1Thresh = on ?
+- aniState->iniDef.m1Thresh : m1Thresh_off;
+- m2Thresh = on ?
+- aniState->iniDef.m2Thresh : m2Thresh_off;
+- m2CountThr = on ?
+- aniState->iniDef.m2CountThr : m2CountThr_off;
+- m2CountThrLow = on ?
+- aniState->iniDef.m2CountThrLow : m2CountThrLow_off;
+- m1ThreshLowExt = on ?
+- aniState->iniDef.m1ThreshLowExt : m1ThreshLowExt_off;
+- m2ThreshLowExt = on ?
+- aniState->iniDef.m2ThreshLowExt : m2ThreshLowExt_off;
+- m1ThreshExt = on ?
+- aniState->iniDef.m1ThreshExt : m1ThreshExt_off;
+- m2ThreshExt = on ?
+- aniState->iniDef.m2ThreshExt : m2ThreshExt_off;
+-
+- REG_RMW_FIELD(ah, AR_PHY_SFCORR_LOW,
+- AR_PHY_SFCORR_LOW_M1_THRESH_LOW,
+- m1ThreshLow);
+- REG_RMW_FIELD(ah, AR_PHY_SFCORR_LOW,
+- AR_PHY_SFCORR_LOW_M2_THRESH_LOW,
+- m2ThreshLow);
+- REG_RMW_FIELD(ah, AR_PHY_SFCORR,
+- AR_PHY_SFCORR_M1_THRESH,
+- m1Thresh);
+- REG_RMW_FIELD(ah, AR_PHY_SFCORR,
+- AR_PHY_SFCORR_M2_THRESH,
+- m2Thresh);
+- REG_RMW_FIELD(ah, AR_PHY_SFCORR,
+- AR_PHY_SFCORR_M2COUNT_THR,
+- m2CountThr);
+- REG_RMW_FIELD(ah, AR_PHY_SFCORR_LOW,
+- AR_PHY_SFCORR_LOW_M2COUNT_THR_LOW,
+- m2CountThrLow);
+- REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT,
+- AR_PHY_SFCORR_EXT_M1_THRESH_LOW,
+- m1ThreshLowExt);
+- REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT,
+- AR_PHY_SFCORR_EXT_M2_THRESH_LOW,
+- m2ThreshLowExt);
+- REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT,
+- AR_PHY_SFCORR_EXT_M1_THRESH,
+- m1ThreshExt);
+- REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT,
+- AR_PHY_SFCORR_EXT_M2_THRESH,
+- m2ThreshExt);
+-skip_ws_det:
+ if (on)
+ REG_SET_BIT(ah, AR_PHY_SFCORR_LOW,
+ AR_PHY_SFCORR_LOW_USE_SELF_CORR_LOW);
+@@ -1915,6 +1841,26 @@ void ar9003_hw_init_rate_txpower(struct ath_hw *ah, u8 *rate_array,
+ }
+ }
+
++static void ar9003_hw_get_adc_entropy(struct ath_hw *ah, u8 *buf, size_t len)
++{
++ int i, j;
++
++ REG_RMW_FIELD(ah, AR_PHY_TEST(ah), AR_PHY_TEST_BBB_OBS_SEL, 1);
++ REG_CLR_BIT(ah, AR_PHY_TEST(ah), AR_PHY_TEST_RX_OBS_SEL_BIT5);
++ REG_RMW_FIELD(ah, AR_PHY_TEST_CTL_STATUS(ah), AR_PHY_TEST_CTL_RX_OBS_SEL, 0);
++
++ memset(buf, 0, len);
++ for (i = 0; i < len; i++) {
++ for (j = 0; j < 4; j++) {
++ u32 regval = REG_READ(ah, AR_PHY_TST_ADC);
++
++ buf[i] <<= 2;
++ buf[i] |= (regval & 1) | ((regval & BIT(10)) >> 9);
++ udelay(1);
++ }
++ }
++}
++
+ void ar9003_hw_attach_phy_ops(struct ath_hw *ah)
+ {
+ struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah);
+@@ -1951,6 +1897,7 @@ void ar9003_hw_attach_phy_ops(struct ath_hw *ah)
+ priv_ops->set_radar_params = ar9003_hw_set_radar_params;
+ priv_ops->fast_chan_change = ar9003_hw_fast_chan_change;
+
++ ops->get_adc_entropy = ar9003_hw_get_adc_entropy;
+ ops->antdiv_comb_conf_get = ar9003_hw_antdiv_comb_conf_get;
+ ops->antdiv_comb_conf_set = ar9003_hw_antdiv_comb_conf_set;
+ ops->spectral_scan_config = ar9003_hw_spectral_scan_config;
+diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h
+index 97f4710..94efbdb 100644
+--- a/drivers/net/wireless/ath/ath9k/ath9k.h
++++ b/drivers/net/wireless/ath/ath9k/ath9k.h
+@@ -25,6 +25,8 @@
+ #include <linux/completion.h>
+ #include <linux/time.h>
+ #include <linux/hw_random.h>
++#include <linux/gpio/driver.h>
++#include <linux/reset.h>
+
+ #include "common.h"
+ #include "debug.h"
+@@ -90,7 +92,7 @@ int ath_descdma_setup(struct ath_softc *sc, struct ath_descdma *dd,
+ (_l) &= ((_sz) - 1); \
+ } while (0)
+
+-#define ATH_RXBUF 512
++#define ATH_RXBUF 256
+ #define ATH_TXBUF 512
+ #define ATH_TXBUF_RESERVE 5
+ #define ATH_TXMAXTRY 13
+@@ -845,6 +847,9 @@ static inline int ath9k_dump_btcoex(struct ath_softc *sc, u8 *buf, u32 size)
+ #ifdef CPTCFG_MAC80211_LEDS
+ void ath_init_leds(struct ath_softc *sc);
+ void ath_deinit_leds(struct ath_softc *sc);
++int ath_create_gpio_led(struct ath_softc *sc, int gpio, const char *name,
++ const char *trigger, bool active_low);
++
+ #else
+ static inline void ath_init_leds(struct ath_softc *sc)
+ {
+@@ -981,6 +986,21 @@ void ath_ant_comb_scan(struct ath_softc *sc, struct ath_rx_status *rs);
+
+ #define ATH9K_NUM_CHANCTX 2 /* supports 2 operating channels */
+
++struct ath_led {
++ struct list_head list;
++ struct ath_softc *sc;
++ const struct gpio_led *gpio;
++ struct led_classdev cdev;
++};
++
++#ifdef CONFIG_GPIOLIB
++struct ath9k_gpio_chip {
++ struct ath_softc *sc;
++ char label[32];
++ struct gpio_chip gchip;
++};
++#endif
++
+ struct ath_softc {
+ struct ieee80211_hw *hw;
+ struct device *dev;
+@@ -994,6 +1014,9 @@ struct ath_softc {
+ struct ath_hw *sc_ah;
+ void __iomem *mem;
+ int irq;
++#ifdef CONFIG_OF
++ struct reset_control *reset;
++#endif
+ spinlock_t sc_serial_rw;
+ spinlock_t sc_pm_lock;
+ spinlock_t sc_pcu_lock;
+@@ -1034,9 +1057,12 @@ struct ath_softc {
+ spinlock_t chan_lock;
+
+ #ifdef CPTCFG_MAC80211_LEDS
+- bool led_registered;
+- char led_name[32];
+- struct led_classdev led_cdev;
++ const char *led_default_trigger;
++ struct list_head leds;
++#ifdef CONFIG_GPIOLIB
++ struct ath9k_gpio_chip *gpiochip;
++ struct platform_device *btnpdev; /* gpio-keys-polled */
++#endif
+ #endif
+
+ #ifdef CPTCFG_ATH9K_DEBUGFS
+diff --git a/drivers/net/wireless/ath/ath9k/channel.c b/drivers/net/wireless/ath/ath9k/channel.c
+index 86c59bd..49cf036 100644
+--- a/drivers/net/wireless/ath/ath9k/channel.c
++++ b/drivers/net/wireless/ath/ath9k/channel.c
+@@ -15,6 +15,7 @@
+ */
+
+ #include "ath9k.h"
++#include "hsr.h"
+
+ /* Set/change channels. If the channel is really being changed, it's done
+ * by reseting the chip. To accomplish this we must first cleanup any pending
+@@ -22,6 +23,7 @@
+ */
+ static int ath_set_channel(struct ath_softc *sc)
+ {
++ struct device_node *np = sc->dev->of_node;
+ struct ath_hw *ah = sc->sc_ah;
+ struct ath_common *common = ath9k_hw_common(ah);
+ struct ieee80211_hw *hw = sc->hw;
+@@ -42,6 +44,11 @@ static int ath_set_channel(struct ath_softc *sc)
+ ath_dbg(common, CONFIG, "Set channel: %d MHz width: %d\n",
+ chan->center_freq, chandef->width);
+
++ if (of_property_read_bool(np, "ubnt,hsr")) {
++ ath9k_hsr_enable(ah, chandef->width, chan->center_freq);
++ ath9k_hsr_status(ah);
++ }
++
+ /* update survey stats for the old channel before switching */
+ spin_lock_irqsave(&common->cc_lock, flags);
+ ath_update_survey_stats(sc);
+diff --git a/drivers/net/wireless/ath/ath9k/common-debug.c b/drivers/net/wireless/ath/ath9k/common-debug.c
+index 7aefb79..944bbe0 100644
+--- a/drivers/net/wireless/ath/ath9k/common-debug.c
++++ b/drivers/net/wireless/ath/ath9k/common-debug.c
+@@ -260,3 +260,110 @@ void ath9k_cmn_debug_phy_err(struct dentry *debugfs_phy,
+ &fops_phy_err);
+ }
+ EXPORT_SYMBOL(ath9k_cmn_debug_phy_err);
++
++static ssize_t read_file_eeprom(struct file *file, char __user *user_buf,
++ size_t count, loff_t *ppos)
++{
++ struct ath_hw *ah = file->private_data;
++ struct ath_common *common = ath9k_hw_common(ah);
++ int bytes = 0;
++ int pos = *ppos;
++ int size = 4096;
++ u16 val;
++ int i;
++
++ if (AR_SREV_9300_20_OR_LATER(ah))
++ size = 16384;
++
++ if (*ppos < 0)
++ return -EINVAL;
++
++ if (count > size - *ppos)
++ count = size - *ppos;
++
++ for (i = *ppos / 2; count > 0; count -= bytes, *ppos += bytes, i++) {
++ void *from = &val;
++
++ if (!common->bus_ops->eeprom_read(common, i, &val))
++ val = 0xffff;
++
++ if (*ppos % 2) {
++ from++;
++ bytes = 1;
++ } else if (count == 1) {
++ bytes = 1;
++ } else {
++ bytes = 2;
++ }
++ if (copy_to_user(user_buf, from, bytes))
++ return -EFAULT;
++ user_buf += bytes;
++ }
++ return *ppos - pos;
++}
++
++static const struct file_operations fops_eeprom = {
++ .read = read_file_eeprom,
++ .open = simple_open,
++ .owner = THIS_MODULE
++};
++
++void ath9k_cmn_debug_eeprom(struct dentry *debugfs_phy,
++ struct ath_hw *ah)
++{
++ debugfs_create_file("eeprom", S_IRUSR, debugfs_phy, ah,
++ &fops_eeprom);
++}
++EXPORT_SYMBOL(ath9k_cmn_debug_eeprom);
++
++static ssize_t read_file_chan_bw(struct file *file, char __user *user_buf,
++ size_t count, loff_t *ppos)
++{
++ struct ath_hw *ah = file->private_data;
++ struct ath_common *common = ath9k_hw_common(ah);
++ char buf[32];
++ unsigned int len;
++
++ len = sprintf(buf, "0x%08x\n", common->chan_bw);
++ return simple_read_from_buffer(user_buf, count, ppos, buf, len);
++}
++
++static ssize_t write_file_chan_bw(struct file *file, const char __user *user_buf,
++ size_t count, loff_t *ppos)
++{
++ struct ath_hw *ah = file->private_data;
++ struct ath_common *common = ath9k_hw_common(ah);
++ unsigned long chan_bw;
++ char buf[32];
++ ssize_t len;
++
++ len = min(count, sizeof(buf) - 1);
++ if (copy_from_user(buf, user_buf, len))
++ return -EFAULT;
++
++ buf[len] = '\0';
++ if (kstrtoul(buf, 0, &chan_bw))
++ return -EINVAL;
++
++ common->chan_bw = chan_bw;
++ if (!test_bit(ATH_OP_INVALID, &common->op_flags))
++ common->ieee_ops->config(ah->hw, IEEE80211_CONF_CHANGE_CHANNEL);
++
++ return count;
++}
++
++static const struct file_operations fops_chanbw = {
++ .read = read_file_chan_bw,
++ .write = write_file_chan_bw,
++ .open = simple_open,
++ .owner = THIS_MODULE,
++ .llseek = default_llseek,
++};
++
++void ath9k_cmn_debug_chanbw(struct dentry *debugfs_phy,
++ struct ath_hw *ah)
++{
++ debugfs_create_file("chanbw", S_IRUSR | S_IWUSR, debugfs_phy, ah,
++ &fops_chanbw);
++}
++EXPORT_SYMBOL(ath9k_cmn_debug_chanbw);
+diff --git a/drivers/net/wireless/ath/ath9k/common-debug.h b/drivers/net/wireless/ath/ath9k/common-debug.h
+index 54f4c42..7a8b7ed 100644
+--- a/drivers/net/wireless/ath/ath9k/common-debug.h
++++ b/drivers/net/wireless/ath/ath9k/common-debug.h
+@@ -69,6 +69,10 @@ void ath9k_cmn_debug_modal_eeprom(struct dentry *debugfs_phy,
+ struct ath_hw *ah);
+ void ath9k_cmn_debug_base_eeprom(struct dentry *debugfs_phy,
+ struct ath_hw *ah);
++void ath9k_cmn_debug_eeprom(struct dentry *debugfs_phy,
++ struct ath_hw *ah);
++void ath9k_cmn_debug_chanbw(struct dentry *debugfs_phy,
++ struct ath_hw *ah);
+ void ath9k_cmn_debug_stat_rx(struct ath_rx_stats *rxstats,
+ struct ath_rx_status *rs);
+ void ath9k_cmn_debug_recv(struct dentry *debugfs_phy,
+diff --git a/drivers/net/wireless/ath/ath9k/common.c b/drivers/net/wireless/ath/ath9k/common.c
+index 099f3d4..86d4a50 100644
+--- a/drivers/net/wireless/ath/ath9k/common.c
++++ b/drivers/net/wireless/ath/ath9k/common.c
+@@ -297,11 +297,13 @@ EXPORT_SYMBOL(ath9k_cmn_get_hw_crypto_keytype);
+ /*
+ * Update internal channel flags.
+ */
+-static void ath9k_cmn_update_ichannel(struct ath9k_channel *ichan,
++static void ath9k_cmn_update_ichannel(struct ath_common *common,
++ struct ath9k_channel *ichan,
+ struct cfg80211_chan_def *chandef)
+ {
+ struct ieee80211_channel *chan = chandef->chan;
+ u16 flags = 0;
++ int width;
+
+ ichan->channel = chan->center_freq;
+ ichan->chan = chan;
+@@ -309,7 +311,19 @@ static void ath9k_cmn_update_ichannel(struct ath9k_channel *ichan,
+ if (chan->band == NL80211_BAND_5GHZ)
+ flags |= CHANNEL_5GHZ;
+
+- switch (chandef->width) {
++ switch (common->chan_bw) {
++ case 5:
++ width = NL80211_CHAN_WIDTH_5;
++ break;
++ case 10:
++ width = NL80211_CHAN_WIDTH_10;
++ break;
++ default:
++ width = chandef->width;
++ break;
++ }
++
++ switch (width) {
+ case NL80211_CHAN_WIDTH_5:
+ flags |= CHANNEL_QUARTER;
+ break;
+@@ -342,10 +356,11 @@ struct ath9k_channel *ath9k_cmn_get_channel(struct ieee80211_hw *hw,
+ struct cfg80211_chan_def *chandef)
+ {
+ struct ieee80211_channel *curchan = chandef->chan;
++ struct ath_common *common = ath9k_hw_common(ah);
+ struct ath9k_channel *channel;
+
+ channel = &ah->channels[curchan->hw_value];
+- ath9k_cmn_update_ichannel(channel, chandef);
++ ath9k_cmn_update_ichannel(common, channel, chandef);
+
+ return channel;
+ }
+diff --git a/drivers/net/wireless/ath/ath9k/debug.c b/drivers/net/wireless/ath/ath9k/debug.c
+index 87ffcb4..f081d1d 100644
+--- a/drivers/net/wireless/ath/ath9k/debug.c
++++ b/drivers/net/wireless/ath/ath9k/debug.c
+@@ -123,6 +123,61 @@ static const struct file_operations fops_debug = {
+
+ #define DMA_BUF_LEN 1024
+
++#ifdef CONFIG_MAC80211_LEDS
++
++static ssize_t write_file_gpio_led(struct file *file, const char __user *ubuf,
++ size_t count, loff_t *ppos)
++{
++ struct ath_softc *sc = file->private_data;
++ char buf[32], *str, *name, *c;
++ ssize_t len;
++ unsigned int gpio;
++ bool active_low = false;
++
++ len = min(count, sizeof(buf) - 1);
++ if (copy_from_user(buf, ubuf, len))
++ return -EFAULT;
++
++ buf[len] = '\0';
++ name = strchr(buf, ',');
++ if (!name)
++ return -EINVAL;
++
++ *(name++) = 0;
++ if (!*name)
++ return -EINVAL;
++
++ c = strchr(name, '\n');
++ if (c)
++ *c = 0;
++
++ str = buf;
++ if (*str == '!') {
++ str++;
++ active_low = true;
++ }
++
++ if (kstrtouint(str, 0, &gpio) < 0)
++ return -EINVAL;
++
++ if (gpio >= sc->sc_ah->caps.num_gpio_pins)
++ return -EINVAL;
++
++ if (ath_create_gpio_led(sc, gpio, name, NULL, active_low) < 0)
++ return -EINVAL;
++
++ return count;
++}
++
++static const struct file_operations fops_gpio_led = {
++ .write = write_file_gpio_led,
++ .open = simple_open,
++ .owner = THIS_MODULE,
++ .llseek = default_llseek,
++};
++
++#endif
++
+
+ static ssize_t read_file_ani(struct file *file, char __user *user_buf,
+ size_t count, loff_t *ppos)
+@@ -1373,6 +1428,50 @@ void ath9k_deinit_debug(struct ath_softc *sc)
+ ath9k_cmn_spectral_deinit_debug(&sc->spec_priv);
+ }
+
++static ssize_t read_file_diag(struct file *file, char __user *user_buf,
++ size_t count, loff_t *ppos)
++{
++ struct ath_softc *sc = file->private_data;
++ struct ath_hw *ah = sc->sc_ah;
++ char buf[32];
++ unsigned int len;
++
++ len = sprintf(buf, "0x%08lx\n", ah->diag);
++ return simple_read_from_buffer(user_buf, count, ppos, buf, len);
++}
++
++static ssize_t write_file_diag(struct file *file, const char __user *user_buf,
++ size_t count, loff_t *ppos)
++{
++ struct ath_softc *sc = file->private_data;
++ struct ath_hw *ah = sc->sc_ah;
++ unsigned long diag;
++ char buf[32];
++ ssize_t len;
++
++ len = min(count, sizeof(buf) - 1);
++ if (copy_from_user(buf, user_buf, len))
++ return -EFAULT;
++
++ buf[len] = '\0';
++ if (kstrtoul(buf, 0, &diag))
++ return -EINVAL;
++
++ ah->diag = diag;
++ ath9k_hw_update_diag(ah);
++
++ return count;
++}
++
++static const struct file_operations fops_diag = {
++ .read = read_file_diag,
++ .write = write_file_diag,
++ .open = simple_open,
++ .owner = THIS_MODULE,
++ .llseek = default_llseek,
++};
++
++
+ int ath9k_init_debug(struct ath_hw *ah)
+ {
+ struct ath_common *common = ath9k_hw_common(ah);
+@@ -1392,6 +1491,12 @@ int ath9k_init_debug(struct ath_hw *ah)
+ ath9k_tx99_init_debug(sc);
+ ath9k_cmn_spectral_init_debug(&sc->spec_priv, sc->debug.debugfs_phy);
+
++#ifdef CONFIG_MAC80211_LEDS
++ debugfs_create_file("gpio_led", S_IWUSR,
++ sc->debug.debugfs_phy, sc, &fops_gpio_led);
++#endif
++ debugfs_create_file("diag", S_IRUSR | S_IWUSR, sc->debug.debugfs_phy,
++ sc, &fops_diag);
+ debugfs_create_devm_seqfile(sc->dev, "dma", sc->debug.debugfs_phy,
+ read_file_dma);
+ debugfs_create_devm_seqfile(sc->dev, "interrupt", sc->debug.debugfs_phy,
+@@ -1431,6 +1536,8 @@ int ath9k_init_debug(struct ath_hw *ah)
+
+ ath9k_cmn_debug_base_eeprom(sc->debug.debugfs_phy, sc->sc_ah);
+ ath9k_cmn_debug_modal_eeprom(sc->debug.debugfs_phy, sc->sc_ah);
++ ath9k_cmn_debug_eeprom(sc->debug.debugfs_phy, sc->sc_ah);
++ ath9k_cmn_debug_chanbw(sc->debug.debugfs_phy, sc->sc_ah);
+
+ debugfs_create_u32("gpio_mask", 0600,
+ sc->debug.debugfs_phy, &sc->sc_ah->gpio_mask);
+diff --git a/drivers/net/wireless/ath/ath9k/gpio.c b/drivers/net/wireless/ath/ath9k/gpio.c
+index a8101c9..e1449d7 100644
+--- a/drivers/net/wireless/ath/ath9k/gpio.c
++++ b/drivers/net/wireless/ath/ath9k/gpio.c
+@@ -15,13 +15,211 @@
+ */
+
+ #include "ath9k.h"
++#include <linux/ath9k_platform.h>
++#include <linux/gpio.h>
++#include <linux/platform_device.h>
++#include <linux/gpio_keys.h>
++
++#ifdef CPTCFG_MAC80211_LEDS
++
++#ifdef CONFIG_GPIOLIB
++
++/***************/
++/* GPIO Chip */
++/***************/
++
++/* gpio_chip handler : set GPIO to input */
++static int ath9k_gpio_pin_cfg_input(struct gpio_chip *chip, unsigned offset)
++{
++ struct ath9k_gpio_chip *gc = container_of(chip, struct ath9k_gpio_chip,
++ gchip);
++
++ ath9k_hw_gpio_request_in(gc->sc->sc_ah, offset, "ath9k-gpio");
++
++ return 0;
++}
++
++/* gpio_chip handler : set GPIO to output */
++static int ath9k_gpio_pin_cfg_output(struct gpio_chip *chip, unsigned offset,
++ int value)
++{
++ struct ath9k_gpio_chip *gc = container_of(chip, struct ath9k_gpio_chip,
++ gchip);
++
++ ath9k_hw_gpio_request_out(gc->sc->sc_ah, offset, "ath9k-gpio",
++ AR_GPIO_OUTPUT_MUX_AS_OUTPUT);
++ ath9k_hw_set_gpio(gc->sc->sc_ah, offset, value);
++
++ return 0;
++}
++
++/* gpio_chip handler : query GPIO direction (0=out, 1=in) */
++static int ath9k_gpio_pin_get_dir(struct gpio_chip *chip, unsigned offset)
++{
++ struct ath9k_gpio_chip *gc = container_of(chip, struct ath9k_gpio_chip,
++ gchip);
++ struct ath_hw *ah = gc->sc->sc_ah;
++
++ return !((REG_READ(ah, AR_GPIO_OE_OUT(ah)) >> (offset * 2)) & 3);
++}
++
++/* gpio_chip handler : get GPIO pin value */
++static int ath9k_gpio_pin_get(struct gpio_chip *chip, unsigned offset)
++{
++ struct ath9k_gpio_chip *gc = container_of(chip, struct ath9k_gpio_chip,
++ gchip);
++
++ return ath9k_hw_gpio_get(gc->sc->sc_ah, offset);
++}
++
++/* gpio_chip handler : set GPIO pin to value */
++static void ath9k_gpio_pin_set(struct gpio_chip *chip, unsigned offset,
++ int value)
++{
++ struct ath9k_gpio_chip *gc = container_of(chip, struct ath9k_gpio_chip,
++ gchip);
++
++ ath9k_hw_set_gpio(gc->sc->sc_ah, offset, value);
++}
++
++/* register GPIO chip */
++static void ath9k_register_gpio_chip(struct ath_softc *sc)
++{
++ struct ath9k_gpio_chip *gc;
++ struct ath_hw *ah = sc->sc_ah;
++
++ gc = kzalloc(sizeof(struct ath9k_gpio_chip), GFP_KERNEL);
++ if (!gc)
++ return;
++
++ gc->sc = sc;
++ snprintf(gc->label, sizeof(gc->label), "ath9k-%s",
++ wiphy_name(sc->hw->wiphy));
++#ifdef CONFIG_OF
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,5,0)
++ gc->gchip.parent = sc->dev;
++#else
++ gc->gchip.dev = sc->dev;
++#endif
++#endif
++ gc->gchip.label = gc->label;
++ gc->gchip.base = -1; /* determine base automatically */
++ gc->gchip.ngpio = ah->caps.num_gpio_pins;
++ gc->gchip.direction_input = ath9k_gpio_pin_cfg_input;
++ gc->gchip.direction_output = ath9k_gpio_pin_cfg_output;
++ gc->gchip.get_direction = ath9k_gpio_pin_get_dir;
++ gc->gchip.get = ath9k_gpio_pin_get;
++ gc->gchip.set = ath9k_gpio_pin_set;
++
++ if (gpiochip_add(&gc->gchip)) {
++ kfree(gc);
++ return;
++ }
++
++#ifdef CONFIG_OF
++ gc->gchip.owner = NULL;
++#endif
++ sc->gpiochip = gc;
++}
++
++/* remove GPIO chip */
++static void ath9k_unregister_gpio_chip(struct ath_softc *sc)
++{
++ struct ath9k_gpio_chip *gc = sc->gpiochip;
++
++ if (!gc)
++ return;
++
++ gpiochip_remove(&gc->gchip);
++ kfree(gc);
++ sc->gpiochip = NULL;
++}
++
++/******************/
++/* GPIO Buttons */
++/******************/
++
++/* add GPIO buttons */
++static void ath9k_init_buttons(struct ath_softc *sc)
++{
++ struct ath9k_platform_data *pdata = sc->dev->platform_data;
++ struct platform_device *pdev;
++ struct gpio_keys_platform_data gkpdata;
++ struct gpio_keys_button *bt;
++ int i;
++
++ if (!sc->gpiochip)
++ return;
++
++ if (!pdata || !pdata->btns || !pdata->num_btns)
++ return;
++
++ bt = devm_kmemdup(sc->dev, pdata->btns,
++ pdata->num_btns * sizeof(struct gpio_keys_button),
++ GFP_KERNEL);
++ if (!bt)
++ return;
++
++ for (i = 0; i < pdata->num_btns; i++) {
++ if (pdata->btns[i].gpio == sc->sc_ah->led_pin)
++ sc->sc_ah->led_pin = -1;
++
++ ath9k_hw_gpio_request_in(sc->sc_ah, pdata->btns[i].gpio,
++ "ath9k-gpio");
++ bt[i].gpio = sc->gpiochip->gchip.base + pdata->btns[i].gpio;
++ }
++
++ memset(&gkpdata, 0, sizeof(struct gpio_keys_platform_data));
++ gkpdata.buttons = bt;
++ gkpdata.nbuttons = pdata->num_btns;
++ gkpdata.poll_interval = pdata->btn_poll_interval;
++
++ pdev = platform_device_register_data(sc->dev, "gpio-keys-polled",
++ PLATFORM_DEVID_AUTO, &gkpdata,
++ sizeof(gkpdata));
++ if (!IS_ERR_OR_NULL(pdev))
++ sc->btnpdev = pdev;
++ else {
++ sc->btnpdev = NULL;
++ devm_kfree(sc->dev, bt);
++ }
++}
++
++/* remove GPIO buttons */
++static void ath9k_deinit_buttons(struct ath_softc *sc)
++{
++ if (!sc->gpiochip || !sc->btnpdev)
++ return;
++
++ platform_device_unregister(sc->btnpdev);
++
++ sc->btnpdev = NULL;
++}
++
++#else /* CONFIG_GPIOLIB */
++
++static inline void ath9k_register_gpio_chip(struct ath_softc *sc)
++{
++}
++
++static inline void ath9k_unregister_gpio_chip(struct ath_softc *sc)
++{
++}
++
++static inline void ath9k_init_buttons(struct ath_softc *sc)
++{
++}
++
++static inline void ath9k_deinit_buttons(struct ath_softc *sc)
++{
++}
++
++#endif /* CONFIG_GPIOLIB */
+
+ /********************************/
+ /* LED functions */
+ /********************************/
+
+-#ifdef CPTCFG_MAC80211_LEDS
+-
+ static void ath_fill_led_pin(struct ath_softc *sc)
+ {
+ struct ath_hw *ah = sc->sc_ah;
+@@ -39,62 +237,171 @@ static void ath_fill_led_pin(struct ath_softc *sc)
+ else
+ ah->led_pin = ATH_LED_PIN_DEF;
+ }
++}
++
++static void ath_led_brightness(struct led_classdev *led_cdev,
++ enum led_brightness brightness)
++{
++ struct ath_led *led = container_of(led_cdev, struct ath_led, cdev);
++ struct ath_softc *sc = led->sc;
++
++ ath9k_ps_wakeup(sc);
++ ath9k_hw_set_gpio(sc->sc_ah, led->gpio->gpio,
++ (brightness != LED_OFF) ^ led->gpio->active_low);
++ ath9k_ps_restore(sc);
++}
++
++static int ath_add_led(struct ath_softc *sc, struct ath_led *led)
++{
++ const struct gpio_led *gpio = led->gpio;
++ int ret;
++
++ led->cdev.name = gpio->name;
++ led->cdev.default_trigger = gpio->default_trigger;
++ led->cdev.brightness_set = ath_led_brightness;
++
++ ret = led_classdev_register(wiphy_dev(sc->hw->wiphy), &led->cdev);
++ if (ret < 0)
++ return ret;
++
++ led->sc = sc;
++ list_add(&led->list, &sc->leds);
+
+ /* Configure gpio for output */
+- ath9k_hw_gpio_request_out(ah, ah->led_pin, "ath9k-led",
++ ath9k_hw_gpio_request_out(sc->sc_ah, gpio->gpio, gpio->name,
+ AR_GPIO_OUTPUT_MUX_AS_OUTPUT);
+
+- /* LED off, active low */
+- ath9k_hw_set_gpio(ah, ah->led_pin, ah->config.led_active_high ? 0 : 1);
++ /* Set default LED state */
++ if (gpio->default_state == LEDS_GPIO_DEFSTATE_ON)
++ ath9k_hw_set_gpio(sc->sc_ah, gpio->gpio, !gpio->active_low);
++ else
++ ath9k_hw_set_gpio(sc->sc_ah, gpio->gpio, gpio->active_low);
++
++#ifdef CONFIG_GPIOLIB
++ /* If there is GPIO chip configured, reserve LED pin */
++ if (sc->gpiochip)
++ gpio_request(sc->gpiochip->gchip.base + gpio->gpio, gpio->name);
++#endif
++
++ return 0;
+ }
+
+-static void ath_led_brightness(struct led_classdev *led_cdev,
+- enum led_brightness brightness)
++int ath_create_gpio_led(struct ath_softc *sc, int gpio_num, const char *name,
++ const char *trigger, bool active_low)
+ {
+- struct ath_softc *sc = container_of(led_cdev, struct ath_softc, led_cdev);
+- u32 val = (brightness == LED_OFF);
++ struct ath_led *led;
++ struct gpio_led *gpio;
++ char *_name;
++ int ret;
++
++ led = kzalloc(sizeof(*led) + sizeof(*gpio) + strlen(name) + 1,
++ GFP_KERNEL);
++ if (!led)
++ return -ENOMEM;
+
+- if (sc->sc_ah->config.led_active_high)
+- val = !val;
++ led->gpio = gpio = (struct gpio_led *) (led + 1);
++ _name = (char *) (led->gpio + 1);
+
+- ath9k_hw_set_gpio(sc->sc_ah, sc->sc_ah->led_pin, val);
++ strcpy(_name, name);
++ gpio->name = _name;
++ gpio->gpio = gpio_num;
++ gpio->active_low = active_low;
++ gpio->default_trigger = trigger;
++
++ ret = ath_add_led(sc, led);
++ if (unlikely(ret < 0))
++ kfree(led);
++
++ return ret;
+ }
+
+-void ath_deinit_leds(struct ath_softc *sc)
++static int ath_create_platform_led(struct ath_softc *sc,
++ const struct gpio_led *gpio)
+ {
+- if (!sc->led_registered)
+- return;
++ struct ath_led *led;
++ int ret;
+
+- ath_led_brightness(&sc->led_cdev, LED_OFF);
+- led_classdev_unregister(&sc->led_cdev);
++ led = kzalloc(sizeof(*led), GFP_KERNEL);
++ if (!led)
++ return -ENOMEM;
+
+- ath9k_hw_gpio_free(sc->sc_ah, sc->sc_ah->led_pin);
++ led->gpio = gpio;
++ ret = ath_add_led(sc, led);
++ if (ret < 0)
++ kfree(led);
++
++ return ret;
++}
++
++void ath_deinit_leds(struct ath_softc *sc)
++{
++ struct ath_led *led;
++
++ ath9k_deinit_buttons(sc);
++ while (!list_empty(&sc->leds)) {
++ led = list_first_entry(&sc->leds, struct ath_led, list);
++#ifdef CONFIG_GPIOLIB
++ /* If there is GPIO chip configured, free LED pin */
++ if (sc->gpiochip)
++ gpio_free(sc->gpiochip->gchip.base + led->gpio->gpio);
++#endif
++ list_del(&led->list);
++ ath_led_brightness(&led->cdev, LED_OFF);
++ led_classdev_unregister(&led->cdev);
++ ath9k_hw_gpio_free(sc->sc_ah, led->gpio->gpio);
++ kfree(led);
++ }
++ ath9k_unregister_gpio_chip(sc);
+ }
+
+ void ath_init_leds(struct ath_softc *sc)
+ {
+- int ret;
++ struct ath9k_platform_data *pdata = sc->dev->platform_data;
++ struct device_node *np = sc->dev->of_node;
++ char led_name[32];
++ const char *trigger;
++ int i;
++
++ INIT_LIST_HEAD(&sc->leds);
+
+ if (AR_SREV_9100(sc->sc_ah))
+ return;
+
++ if (!np)
++ ath9k_register_gpio_chip(sc);
++
++ /* setup gpio controller only if requested and skip the led_pin setup */
++ if (of_property_read_bool(np, "gpio-controller")) {
++ ath9k_register_gpio_chip(sc);
++ return;
++ }
++
+ ath_fill_led_pin(sc);
++ ath9k_init_buttons(sc);
+
+- if (!ath9k_led_blink)
+- sc->led_cdev.default_trigger =
+- ieee80211_get_radio_led_name(sc->hw);
++ if (pdata && pdata->leds && pdata->num_leds)
++ for (i = 0; i < pdata->num_leds; i++) {
++ if (pdata->leds[i].gpio == sc->sc_ah->led_pin)
++ sc->sc_ah->led_pin = -1;
+
+- snprintf(sc->led_name, sizeof(sc->led_name),
+- "ath9k-%s", wiphy_name(sc->hw->wiphy));
+- sc->led_cdev.name = sc->led_name;
+- sc->led_cdev.brightness_set = ath_led_brightness;
++ ath_create_platform_led(sc, &pdata->leds[i]);
++ }
+
+- ret = led_classdev_register(wiphy_dev(sc->hw->wiphy), &sc->led_cdev);
+- if (ret < 0)
++ if (sc->sc_ah->led_pin < 0)
+ return;
+
+- sc->led_registered = true;
++ snprintf(led_name, sizeof(led_name), "ath9k-%s",
++ wiphy_name(sc->hw->wiphy));
++
++ if (ath9k_led_blink)
++ trigger = sc->led_default_trigger;
++ else
++ trigger = ieee80211_get_radio_led_name(sc->hw);
++
++ ath_create_gpio_led(sc, sc->sc_ah->led_pin, led_name, trigger,
++ !sc->sc_ah->config.led_active_high);
+ }
++
+ #endif
+
+ /*******************/
+diff --git a/drivers/net/wireless/ath/ath9k/hsr.c b/drivers/net/wireless/ath/ath9k/hsr.c
+new file mode 100644
+index 0000000..7d12d91
+--- /dev/null
++++ b/drivers/net/wireless/ath/ath9k/hsr.c
+@@ -0,0 +1,247 @@
++/*
++ *
++ * The MIT License (MIT)
++ *
++ * Copyright (c) 2015 Kirill Berezin
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining a copy
++ * of this software and associated documentation files (the "Software"), to deal
++ * in the Software without restriction, including without limitation the rights
++ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
++ * copies of the Software, and to permit persons to whom the Software is
++ * furnished to do so, subject to the following conditions:
++ *
++ * The above copyright notice and this permission notice shall be included in
++ * all copies or substantial portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
++ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
++ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
++ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
++ * SOFTWARE.
++ *
++ */
++
++#include <linux/io.h>
++#include <linux/slab.h>
++#include <linux/module.h>
++#include <linux/time.h>
++#include <linux/bitops.h>
++#include <linux/etherdevice.h>
++#include <linux/rtnetlink.h>
++#include <asm/unaligned.h>
++
++#include "hw.h"
++#include "ath9k.h"
++
++#define HSR_GPIO_CSN 8
++#define HSR_GPIO_CLK 6
++#define HSR_GPIO_DOUT 7
++#define HSR_GPIO_DIN 5
++
++/* delays are in useconds */
++#define HSR_DELAY_HALF_TICK 100
++#define HSR_DELAY_PRE_WRITE 75
++#define HSR_DELAY_FINAL 20000
++#define HSR_DELAY_TRAILING 200
++
++void ath9k_hsr_init(struct ath_hw *ah)
++{
++ ath9k_hw_gpio_request_in(ah, HSR_GPIO_DIN, NULL);
++ ath9k_hw_gpio_request_out(ah, HSR_GPIO_CSN, NULL,
++ AR_GPIO_OUTPUT_MUX_AS_OUTPUT);
++ ath9k_hw_gpio_request_out(ah, HSR_GPIO_CLK, NULL,
++ AR_GPIO_OUTPUT_MUX_AS_OUTPUT);
++ ath9k_hw_gpio_request_out(ah, HSR_GPIO_DOUT, NULL,
++ AR_GPIO_OUTPUT_MUX_AS_OUTPUT);
++
++ ath9k_hw_set_gpio(ah, HSR_GPIO_CSN, 1);
++ ath9k_hw_set_gpio(ah, HSR_GPIO_CLK, 0);
++ ath9k_hw_set_gpio(ah, HSR_GPIO_DOUT, 0);
++
++ udelay(HSR_DELAY_TRAILING);
++}
++
++static u32 ath9k_hsr_write_byte(struct ath_hw *ah, int delay, u32 value)
++{
++ struct ath_common *common = ath9k_hw_common(ah);
++ int i;
++ u32 rval = 0;
++
++ udelay(delay);
++
++ ath9k_hw_set_gpio(ah, HSR_GPIO_CLK, 0);
++ udelay(HSR_DELAY_HALF_TICK);
++
++ ath9k_hw_set_gpio(ah, HSR_GPIO_CSN, 0);
++ udelay(HSR_DELAY_HALF_TICK);
++
++ for (i = 0; i < 8; ++i) {
++ rval = rval << 1;
++
++ /* pattern is left to right, that is 7-th bit runs first */
++ ath9k_hw_set_gpio(ah, HSR_GPIO_DOUT, (value >> (7 - i)) & 0x1);
++ udelay(HSR_DELAY_HALF_TICK);
++
++ ath9k_hw_set_gpio(ah, HSR_GPIO_CLK, 1);
++ udelay(HSR_DELAY_HALF_TICK);
++
++ rval |= ath9k_hw_gpio_get(ah, HSR_GPIO_DIN);
++
++ ath9k_hw_set_gpio(ah, HSR_GPIO_CLK, 0);
++ udelay(HSR_DELAY_HALF_TICK);
++ }
++
++ ath9k_hw_set_gpio(ah, HSR_GPIO_CSN, 1);
++ udelay(HSR_DELAY_HALF_TICK);
++
++ ath_dbg(common, CONFIG, "ath9k_hsr_write_byte: write byte %d return value is %d %c\n",
++ value, rval, rval > 32 ? rval : '-');
++
++ return rval & 0xff;
++}
++
++static int ath9k_hsr_write_a_chain(struct ath_hw *ah, char *chain, int items)
++{
++ int status = 0;
++ int i = 0;
++ int err;
++
++ /* a preamble */
++ ath9k_hsr_write_byte(ah, HSR_DELAY_PRE_WRITE, 0);
++ status = ath9k_hsr_write_byte(ah, HSR_DELAY_PRE_WRITE, 0);
++
++ /* clear HSR's reply buffer */
++ if (status) {
++ int loop = 0;
++
++ for (loop = 0; (loop < 42) && status; ++loop)
++ status = ath9k_hsr_write_byte(ah, HSR_DELAY_PRE_WRITE,
++ 0);
++
++ if (loop >= 42) {
++ ATH_DBG_WARN(1,
++ "ath9k_hsr_write_a_chain: can't clear an output buffer after a 42 cycles.\n");
++ return -1;
++ }
++ }
++
++ for (i = 0; (i < items) && (chain[i] != 0); ++i)
++ ath9k_hsr_write_byte(ah, HSR_DELAY_PRE_WRITE, (u32)chain[i]);
++
++ ath9k_hsr_write_byte(ah, HSR_DELAY_PRE_WRITE, 0);
++ mdelay(HSR_DELAY_FINAL / 1000);
++
++ /* reply */
++ memset(chain, 0, items);
++
++ ath9k_hsr_write_byte(ah, HSR_DELAY_PRE_WRITE, 0);
++ udelay(HSR_DELAY_TRAILING);
++
++ for (i = 0; i < (items - 1); ++i) {
++ u32 ret;
++
++ ret = ath9k_hsr_write_byte(ah, HSR_DELAY_PRE_WRITE, 0);
++ if (ret != 0)
++ chain[i] = (char)ret;
++ else
++ break;
++
++ udelay(HSR_DELAY_TRAILING);
++ }
++
++ if (i <= 1)
++ return 0;
++
++ err = kstrtoint(chain + 1, 10, &i);
++ if (err)
++ return err;
++
++ return i;
++}
++
++int ath9k_hsr_disable(struct ath_hw *ah)
++{
++ char cmd[10] = {'b', '4', '0', 0, 0, 0, 0, 0, 0, 0};
++ int ret;
++
++ ret = ath9k_hsr_write_a_chain(ah, cmd, sizeof(cmd));
++ if ((ret > 0) && (*cmd == 'B'))
++ return 0;
++
++ return -1;
++}
++
++int ath9k_hsr_enable(struct ath_hw *ah, int bw, int fq)
++{
++ char cmd[10];
++ int ret;
++
++ /* Bandwidth argument is 0 sometimes. Assume default 802.11bgn
++ * 20MHz on invalid values
++ */
++ if ((bw != 5) && (bw != 10) && (bw != 20) && (bw != 40))
++ bw = 20;
++
++ memset(cmd, 0, sizeof(cmd));
++ *cmd = 'b';
++ snprintf(cmd + 1, 3, "%02d", bw);
++
++ ret = ath9k_hsr_write_a_chain(ah, cmd, sizeof(cmd));
++ if ((*cmd != 'B') || (ret != bw)) {
++ ATH_DBG_WARN(1,
++ "ath9k_hsr_enable: failed changing bandwidth -> set (%d,%d) reply (%d, %d)\n",
++ 'b', bw, *cmd, ret);
++ return -1;
++ }
++
++ memset(cmd, 0, sizeof(cmd));
++ *cmd = 'x';
++ ret = ath9k_hsr_write_a_chain(ah, cmd, sizeof(cmd));
++ if (*cmd != 'X') {
++ ATH_DBG_WARN(1,
++ "ath9k_hsr_enable: failed 'x' command -> reply (%d, %d)\n",
++ *cmd, ret);
++ return -1;
++ }
++
++ memset(cmd, 0, sizeof(cmd));
++ *cmd = 'm';
++ ret = ath9k_hsr_write_a_chain(ah, cmd, sizeof(cmd));
++ if (*cmd != 'M') {
++ ATH_DBG_WARN(1,
++ "ath9k_hsr_enable: failed 'm' command -> reply (%d, %d)\n",
++ *cmd, ret);
++ return -1;
++ }
++
++ memset(cmd, 0, sizeof(cmd));
++ *cmd = 'f';
++ snprintf(cmd + 1, 6, "%05d", fq);
++ ret = ath9k_hsr_write_a_chain(ah, cmd, sizeof(cmd));
++ if ((*cmd != 'F') && (ret != fq)) {
++ ATH_DBG_WARN(1,
++ "ath9k_hsr_enable: failed set frequency -> reply (%d, %d)\n",
++ *cmd, ret);
++ return -1;
++ }
++
++ return 0;
++}
++
++int ath9k_hsr_status(struct ath_hw *ah)
++{
++ char cmd[10] = {'s', 0, 0, 0, 0, 0, 0, 0, 0, 0};
++ int ret;
++
++ ret = ath9k_hsr_write_a_chain(ah, cmd, sizeof(cmd));
++ if (*cmd != 'S') {
++ ATH_DBG_WARN(1, "ath9k_hsr_status: returned %d,%d\n", *cmd,
++ ret);
++ return -1;
++ }
++
++ return 0;
++}
+diff --git a/drivers/net/wireless/ath/ath9k/hsr.h b/drivers/net/wireless/ath/ath9k/hsr.h
+new file mode 100644
+index 0000000..78af444
+--- /dev/null
++++ b/drivers/net/wireless/ath/ath9k/hsr.h
+@@ -0,0 +1,48 @@
++/*
++ * The MIT License (MIT)
++ *
++ * Copyright (c) 2015 Kirill Berezin
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining a copy
++ * of this software and associated documentation files (the "Software"), to deal
++ * in the Software without restriction, including without limitation the rights
++ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
++ * copies of the Software, and to permit persons to whom the Software is
++ * furnished to do so, subject to the following conditions:
++ *
++ * The above copyright notice and this permission notice shall be included in
++ * all copies or substantial portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
++ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
++ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
++ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
++ * SOFTWARE.
++ */
++
++#ifndef HSR_H
++#define HSR_H
++
++#ifdef CPTCFG_ATH9K_UBNTHSR
++
++void ath9k_hsr_init(struct ath_hw *ah);
++int ath9k_hsr_disable(struct ath_hw *ah);
++int ath9k_hsr_enable(struct ath_hw *ah, int bw, int fq);
++int ath9k_hsr_status(struct ath_hw *ah);
++
++#else
++static inline void ath9k_hsr_init(struct ath_hw *ah) {}
++
++static inline int ath9k_hsr_enable(struct ath_hw *ah, int bw, int fq)
++{
++ return 0;
++}
++
++static inline int ath9k_hsr_disable(struct ath_hw *ah) { return 0; }
++static inline int ath9k_hsr_status(struct ath_hw *ah) { return 0; }
++
++#endif
++
++#endif /* HSR_H */
+diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_debug.c b/drivers/net/wireless/ath/ath9k/htc_drv_debug.c
+index f7c6d9b..5c015ac 100644
+--- a/drivers/net/wireless/ath/ath9k/htc_drv_debug.c
++++ b/drivers/net/wireless/ath/ath9k/htc_drv_debug.c
+@@ -514,6 +514,8 @@ int ath9k_htc_init_debug(struct ath_hw *ah)
+
+ ath9k_cmn_debug_base_eeprom(priv->debug.debugfs_phy, priv->ah);
+ ath9k_cmn_debug_modal_eeprom(priv->debug.debugfs_phy, priv->ah);
++ ath9k_cmn_debug_eeprom(priv->debug.debugfs_phy, priv->ah);
++ ath9k_cmn_debug_chanbw(priv->debug.debugfs_phy, priv->ah);
+
+ return 0;
+ }
+diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_init.c b/drivers/net/wireless/ath/ath9k/htc_drv_init.c
+index fa02d9a..53e49b6 100644
+--- a/drivers/net/wireless/ath/ath9k/htc_drv_init.c
++++ b/drivers/net/wireless/ath/ath9k/htc_drv_init.c
+@@ -631,6 +631,7 @@ static int ath9k_init_priv(struct ath9k_htc_priv *priv,
+ priv->ah = ah;
+
+ common = ath9k_hw_common(ah);
++ common->ieee_ops = &ath9k_htc_ops;
+ common->ops = &ah->reg_ops;
+ common->ps_ops = &ath9k_htc_ps_ops;
+ common->bus_ops = &ath9k_usb_bus_ops;
+@@ -746,9 +747,9 @@ static void ath9k_set_hw_capab(struct ath9k_htc_priv *priv,
+
+ hw->wiphy->flags |= WIPHY_FLAG_IBSS_RSN |
+ WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL |
+- WIPHY_FLAG_HAS_CHANNEL_SWITCH;
+-
+- hw->wiphy->flags |= WIPHY_FLAG_SUPPORTS_TDLS;
++ WIPHY_FLAG_HAS_CHANNEL_SWITCH |
++ WIPHY_FLAG_SUPPORTS_5_10_MHZ |
++ WIPHY_FLAG_SUPPORTS_TDLS;
+
+ hw->queues = 4;
+ hw->max_listen_interval = 1;
+diff --git a/drivers/net/wireless/ath/ath9k/hw-ops.h b/drivers/net/wireless/ath/ath9k/hw-ops.h
+index 174d716..605abe1 100644
+--- a/drivers/net/wireless/ath/ath9k/hw-ops.h
++++ b/drivers/net/wireless/ath/ath9k/hw-ops.h
+@@ -100,6 +100,12 @@ static inline void ath9k_hw_tx99_set_txpower(struct ath_hw *ah, u8 power)
+ ath9k_hw_ops(ah)->tx99_set_txpower(ah, power);
+ }
+
++static inline void ath9k_hw_get_adc_entropy(struct ath_hw *ah,
++ u8 *buf, size_t len)
++{
++ ath9k_hw_ops(ah)->get_adc_entropy(ah, buf, len);
++}
++
+ #ifdef CPTCFG_ATH9K_BTCOEX_SUPPORT
+
+ static inline void ath9k_hw_set_bt_ant_diversity(struct ath_hw *ah, bool enable)
+diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c
+index fafe1f0..f53964b 100644
+--- a/drivers/net/wireless/ath/ath9k/hw.c
++++ b/drivers/net/wireless/ath/ath9k/hw.c
+@@ -247,6 +247,19 @@ void ath9k_hw_get_channel_centers(struct ath_hw *ah,
+ centers->synth_center + (extoff * HT40_CHANNEL_CENTER_SHIFT);
+ }
+
++static inline void ath9k_hw_disable_pll_lock_detect(struct ath_hw *ah)
++{
++ /* On AR9330 and AR9340 devices, some PHY registers must be
++ * tuned to gain better stability/performance. These registers
++ * might be changed while doing wlan reset so the registers must
++ * be reprogrammed after each reset.
++ */
++ REG_CLR_BIT(ah, AR_PHY_USB_CTRL1, BIT(20));
++ REG_RMW(ah, AR_PHY_USB_CTRL2,
++ (1 << 21) | (0xf << 22),
++ (1 << 21) | (0x3 << 22));
++}
++
+ /******************/
+ /* Chip Revisions */
+ /******************/
+@@ -402,13 +415,8 @@ static void ath9k_hw_init_config(struct ath_hw *ah)
+
+ ah->config.rx_intr_mitigation = true;
+
+- if (AR_SREV_9300_20_OR_LATER(ah)) {
+- ah->config.rimt_last = 500;
+- ah->config.rimt_first = 2000;
+- } else {
+- ah->config.rimt_last = 250;
+- ah->config.rimt_first = 700;
+- }
++ ah->config.rimt_last = 250;
++ ah->config.rimt_first = 500;
+
+ if (AR_SREV_9462(ah) || AR_SREV_9565(ah))
+ ah->config.pll_pwrsave = 7;
+@@ -667,6 +675,7 @@ int ath9k_hw_init(struct ath_hw *ah)
+
+ /* These are all the AR5008/AR9001/AR9002/AR9003 hardware family of chipsets */
+ switch (ah->hw_version.devid) {
++ case AR9300_DEVID_INVALID:
+ case AR5416_DEVID_PCI:
+ case AR5416_DEVID_PCIE:
+ case AR5416_AR9100_DEVID:
+@@ -1311,39 +1320,56 @@ void ath9k_hw_get_delta_slope_vals(struct ath_hw *ah, u32 coef_scaled,
+ *coef_exponent = coef_exp - 16;
+ }
+
+-/* AR9330 WAR:
+- * call external reset function to reset WMAC if:
+- * - doing a cold reset
+- * - we have pending frames in the TX queues.
+- */
+-static bool ath9k_hw_ar9330_reset_war(struct ath_hw *ah, int type)
++static bool ath9k_hw_need_external_reset(struct ath_hw *ah, int type)
+ {
+- int i, npend = 0;
++ int i;
+
+- for (i = 0; i < AR_NUM_QCU; i++) {
+- npend = ath9k_hw_numtxpending(ah, i);
+- if (npend)
+- break;
++ if (type == ATH9K_RESET_COLD)
++ return true;
++
++ if (AR_SREV_9550(ah))
++ return true;
++
++ /* AR9330 WAR:
++ * call external reset function to reset WMAC if:
++ * - doing a cold reset
++ * - we have pending frames in the TX queues.
++ */
++ if (AR_SREV_9330(ah)) {
++ for (i = 0; i < AR_NUM_QCU; i++) {
++ if (ath9k_hw_numtxpending(ah, i))
++ return true;
++ }
+ }
+
+- if (ah->external_reset &&
+- (npend || type == ATH9K_RESET_COLD)) {
+- int reset_err = 0;
++ return false;
++}
+
+- ath_dbg(ath9k_hw_common(ah), RESET,
+- "reset MAC via external reset\n");
++static bool ath9k_hw_external_reset(struct ath_hw *ah, int type)
++{
++ int err;
+
+- reset_err = ah->external_reset();
+- if (reset_err) {
+- ath_err(ath9k_hw_common(ah),
+- "External reset failed, err=%d\n",
+- reset_err);
+- return false;
+- }
++ if (!ah->external_reset || !ath9k_hw_need_external_reset(ah, type))
++ return true;
+
+- REG_WRITE(ah, AR_RTC_RESET(ah), 1);
++ ath_dbg(ath9k_hw_common(ah), RESET,
++ "reset MAC via external reset\n");
++
++ err = ah->external_reset();
++ if (err) {
++ ath_err(ath9k_hw_common(ah),
++ "External reset failed, err=%d\n", err);
++ return false;
+ }
+
++ if (AR_SREV_9550(ah)) {
++ REG_WRITE(ah, AR_RTC_RESET(ah), 0);
++ udelay(10);
++ }
++
++ REG_WRITE(ah, AR_RTC_RESET(ah), 1);
++ udelay(10);
++
+ return true;
+ }
+
+@@ -1396,24 +1422,24 @@ static bool ath9k_hw_set_reset(struct ath_hw *ah, int type)
+ rst_flags |= AR_RTC_RC_MAC_COLD;
+ }
+
+- if (AR_SREV_9330(ah)) {
+- if (!ath9k_hw_ar9330_reset_war(ah, type))
+- return false;
+- }
+-
+ if (ath9k_hw_mci_is_enabled(ah))
+ ar9003_mci_check_gpm_offset(ah);
+
+ /* DMA HALT added to resolve ar9300 and ar9580 bus error during
+- * RTC_RC reg read
++ * RTC_RC reg read. Also needed for AR9550 external reset
+ */
+- if (AR_SREV_9300(ah) || AR_SREV_9580(ah)) {
++ if (AR_SREV_9300(ah) || AR_SREV_9580(ah) || AR_SREV_9550(ah)) {
+ REG_SET_BIT(ah, AR_CFG, AR_CFG_HALT_REQ);
+ ath9k_hw_wait(ah, AR_CFG, AR_CFG_HALT_ACK, AR_CFG_HALT_ACK,
+ 20 * AH_WAIT_TIMEOUT);
+- REG_CLR_BIT(ah, AR_CFG, AR_CFG_HALT_REQ);
+ }
+
++ if (!AR_SREV_9100(ah))
++ ath9k_hw_external_reset(ah, type);
++
++ if (AR_SREV_9300(ah) || AR_SREV_9580(ah))
++ REG_CLR_BIT(ah, AR_CFG, AR_CFG_HALT_REQ);
++
+ REG_WRITE(ah, AR_RTC_RC(ah), rst_flags);
+
+ REGWRITE_BUFFER_FLUSH(ah);
+@@ -1434,8 +1460,15 @@ static bool ath9k_hw_set_reset(struct ath_hw *ah, int type)
+ if (!AR_SREV_9100(ah))
+ REG_WRITE(ah, AR_RC, 0);
+
+- if (AR_SREV_9100(ah))
++ if (AR_SREV_9100(ah)) {
++ /* Reset the AHB-WMAC interface */
++ if (ah->external_reset)
++ ah->external_reset();
+ udelay(50);
++ }
++
++ if (AR_SREV_9330(ah) || AR_SREV_9340(ah))
++ ath9k_hw_disable_pll_lock_detect(ah);
+
+ return true;
+ }
+@@ -1536,6 +1569,9 @@ static bool ath9k_hw_chip_reset(struct ath_hw *ah,
+ ar9003_hw_internal_regulator_apply(ah);
+ ath9k_hw_init_pll(ah, chan);
+
++ if (AR_SREV_9330(ah) || AR_SREV_9340(ah))
++ ath9k_hw_disable_pll_lock_detect(ah);
++
+ return true;
+ }
+
+@@ -1842,8 +1878,14 @@ static int ath9k_hw_do_fastcc(struct ath_hw *ah, struct ath9k_channel *chan)
+ if (AR_SREV_9271(ah))
+ ar9002_hw_load_ani_reg(ah, chan);
+
++ if (AR_SREV_9330(ah) || AR_SREV_9340(ah))
++ ath9k_hw_disable_pll_lock_detect(ah);
++
+ return 0;
+ fail:
++ if (AR_SREV_9330(ah) || AR_SREV_9340(ah))
++ ath9k_hw_disable_pll_lock_detect(ah);
++
+ return -EINVAL;
+ }
+
+@@ -1864,6 +1906,20 @@ u32 ath9k_hw_get_tsf_offset(struct timespec64 *last, struct timespec64 *cur)
+ }
+ EXPORT_SYMBOL(ath9k_hw_get_tsf_offset);
+
++void ath9k_hw_update_diag(struct ath_hw *ah)
++{
++ if (test_bit(ATH_DIAG_DISABLE_RX, &ah->diag))
++ REG_SET_BIT(ah, AR_DIAG_SW, AR_DIAG_RX_DIS);
++ else
++ REG_CLR_BIT(ah, AR_DIAG_SW, AR_DIAG_RX_DIS);
++
++ if (test_bit(ATH_DIAG_DISABLE_TX, &ah->diag))
++ REG_SET_BIT(ah, AR_DIAG_SW, AR_DIAG_LOOP_BACK);
++ else
++ REG_CLR_BIT(ah, AR_DIAG_SW, AR_DIAG_LOOP_BACK);
++}
++EXPORT_SYMBOL(ath9k_hw_update_diag);
++
+ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,
+ struct ath9k_hw_cal_data *caldata, bool fastcc)
+ {
+@@ -2072,6 +2128,7 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,
+ ar9003_hw_disable_phy_restart(ah);
+
+ ath9k_hw_apply_gpio_override(ah);
++ ath9k_hw_update_diag(ah);
+
+ if (AR_SREV_9565(ah) && common->bt_ant_diversity)
+ REG_SET_BIT(ah, AR_BTCOEX_WL_LNADIV, AR_BTCOEX_WL_LNADIV_FORCE_ON);
+@@ -2082,6 +2139,9 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,
+ ath9k_hw_set_radar_params(ah);
+ }
+
++ if (AR_SREV_9330(ah) || AR_SREV_9340(ah))
++ ath9k_hw_disable_pll_lock_detect(ah);
++
+ return 0;
+ }
+ EXPORT_SYMBOL(ath9k_hw_reset);
+@@ -2956,7 +3016,8 @@ void ath9k_hw_apply_txpower(struct ath_hw *ah, struct ath9k_channel *chan,
+ {
+ struct ath_regulatory *reg = ath9k_hw_regulatory(ah);
+ struct ieee80211_channel *channel;
+- int chan_pwr, new_pwr;
++ int chan_pwr, new_pwr, max_gain;
++ int ant_gain, ant_reduction = 0;
+ u16 ctl = NO_CTL;
+
+ if (!chan)
+@@ -2968,9 +3029,18 @@ void ath9k_hw_apply_txpower(struct ath_hw *ah, struct ath9k_channel *chan,
+ channel = chan->chan;
+ chan_pwr = min_t(int, channel->max_power * 2, MAX_COMBINED_POWER);
+ new_pwr = min_t(int, chan_pwr, reg->power_limit);
++ max_gain = chan_pwr - new_pwr + channel->max_antenna_gain * 2;
++
++ ant_gain = get_antenna_gain(ah, chan);
++ if (ant_gain > max_gain)
++ ant_reduction = ant_gain - max_gain;
++
++ /* FCC allows maximum antenna gain of 6 dBi */
++ if (reg->region == NL80211_DFS_FCC)
++ ant_reduction = max_t(int, ant_reduction - 12, 0);
+
+ ah->eep_ops->set_txpower(ah, chan, ctl,
+- get_antenna_gain(ah, chan), new_pwr, test);
++ ant_reduction, new_pwr, test);
+ }
+
+ void ath9k_hw_set_txpowerlimit(struct ath_hw *ah, u32 limit, bool test)
+diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h
+index 6243626..8d756dc 100644
+--- a/drivers/net/wireless/ath/ath9k/hw.h
++++ b/drivers/net/wireless/ath/ath9k/hw.h
+@@ -36,6 +36,7 @@
+
+ #define ATHEROS_VENDOR_ID 0x168c
+
++#define AR9300_DEVID_INVALID 0xabcd
+ #define AR5416_DEVID_PCI 0x0023
+ #define AR5416_DEVID_PCIE 0x0024
+ #define AR9160_DEVID_PCI 0x0027
+@@ -521,6 +522,12 @@ enum {
+ ATH9K_RESET_COLD,
+ };
+
++enum {
++ ATH_DIAG_DISABLE_RX,
++ ATH_DIAG_DISABLE_TX,
++ ATH_DIAG_TRIGGER_ERROR,
++};
++
+ struct ath9k_hw_version {
+ u32 magic;
+ u16 devid;
+@@ -716,6 +723,7 @@ struct ath_spec_scan {
+ * @config_pci_powersave:
+ * @calibrate: periodic calibration for NF, ANI, IQ, ADC gain, ADC-DC
+ *
++ * @get_adc_entropy: get entropy from the raw ADC I/Q output
+ * @spectral_scan_config: set parameters for spectral scan and enable/disable it
+ * @spectral_scan_trigger: trigger a spectral scan run
+ * @spectral_scan_wait: wait for a spectral scan run to finish
+@@ -738,6 +746,7 @@ struct ath_hw_ops {
+ struct ath_hw_antcomb_conf *antconf);
+ void (*antdiv_comb_conf_set)(struct ath_hw *ah,
+ struct ath_hw_antcomb_conf *antconf);
++ void (*get_adc_entropy)(struct ath_hw *ah, u8 *buf, size_t len);
+ void (*spectral_scan_config)(struct ath_hw *ah,
+ struct ath_spec_scan *param);
+ void (*spectral_scan_trigger)(struct ath_hw *ah);
+@@ -809,6 +818,8 @@ struct ath_hw {
+ u32 ah_flags;
+ s16 nf_override;
+
++ unsigned long diag;
++
+ bool reset_power_on;
+ bool htc_reset_init;
+
+@@ -1078,6 +1089,7 @@ void ath9k_hw_check_nav(struct ath_hw *ah);
+ bool ath9k_hw_check_alive(struct ath_hw *ah);
+
+ bool ath9k_hw_setpower(struct ath_hw *ah, enum ath9k_power_mode mode);
++void ath9k_hw_update_diag(struct ath_hw *ah);
+
+ /* Generic hw timer primitives */
+ struct ath_gen_timer *ath_gen_timer_alloc(struct ath_hw *ah,
+diff --git a/drivers/net/wireless/ath/ath9k/init.c b/drivers/net/wireless/ath/ath9k/init.c
+index 2458387..2f5266c 100644
+--- a/drivers/net/wireless/ath/ath9k/init.c
++++ b/drivers/net/wireless/ath/ath9k/init.c
+@@ -48,7 +48,7 @@ int ath9k_modparam_nohwcrypt;
+ module_param_named(nohwcrypt, ath9k_modparam_nohwcrypt, int, 0444);
+ MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption");
+
+-int ath9k_led_blink;
++int ath9k_led_blink = 1;
+ module_param_named(blink, ath9k_led_blink, int, 0444);
+ MODULE_PARM_DESC(blink, "Enable LED blink on activity");
+
+@@ -696,6 +696,12 @@ static int ath9k_of_init(struct ath_softc *sc)
+ return 0;
+ }
+
++static void ath9k_of_gpio_mask(struct ath_softc *sc)
++{
++ of_property_read_u32(sc->dev->of_node, "qca,gpio-mask",
++ &sc->sc_ah->caps.gpio_mask);
++}
++
+ static int ath9k_init_softc(u16 devid, struct ath_softc *sc,
+ const struct ath_bus_ops *bus_ops)
+ {
+@@ -733,6 +739,7 @@ static int ath9k_init_softc(u16 devid, struct ath_softc *sc,
+ if (!ath9k_is_chanctx_enabled())
+ sc->cur_chan->hw_queue_base = 0;
+
++ common->ieee_ops = &ath9k_ops;
+ common->ops = &ah->reg_ops;
+ common->bus_ops = bus_ops;
+ common->ps_ops = &ath9k_ps_ops;
+@@ -803,6 +810,9 @@ static int ath9k_init_softc(u16 devid, struct ath_softc *sc,
+ if (ret)
+ goto err_hw;
+
++ /* GPIO mask quirk */
++ ath9k_of_gpio_mask(sc);
++
+ ret = ath9k_init_queues(sc);
+ if (ret)
+ goto err_queues;
+@@ -870,7 +880,8 @@ static void ath9k_init_txpower_limits(struct ath_softc *sc)
+ if (ah->caps.hw_caps & ATH9K_HW_CAP_5GHZ)
+ ath9k_init_band_txpower(sc, NL80211_BAND_5GHZ);
+
+- ah->curchan = curchan;
++ if (curchan)
++ ah->curchan = curchan;
+ }
+
+ static const struct ieee80211_iface_limit if_limits[] = {
+@@ -882,6 +893,7 @@ static const struct ieee80211_iface_limit if_limits[] = {
+ BIT(NL80211_IFTYPE_AP) },
+ { .max = 1, .types = BIT(NL80211_IFTYPE_P2P_CLIENT) |
+ BIT(NL80211_IFTYPE_P2P_GO) },
++ { .max = 1, .types = BIT(NL80211_IFTYPE_ADHOC) },
+ };
+
+ #ifdef CPTCFG_ATH9K_CHANNEL_CONTEXT
+@@ -962,6 +974,7 @@ static void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw)
+ ieee80211_hw_set(hw, HOST_BROADCAST_PS_BUFFERING);
+ ieee80211_hw_set(hw, SUPPORT_FAST_XMIT);
+ ieee80211_hw_set(hw, SUPPORTS_CLONED_SKBS);
++ ieee80211_hw_set(hw, MFP_CAPABLE);
+
+ if (ath9k_ps_enable)
+ ieee80211_hw_set(hw, SUPPORTS_PS);
+@@ -974,9 +987,6 @@ static void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw)
+ IEEE80211_RADIOTAP_MCS_HAVE_STBC;
+ }
+
+- if (AR_SREV_9160_10_OR_LATER(sc->sc_ah) || ath9k_modparam_nohwcrypt)
+- ieee80211_hw_set(hw, MFP_CAPABLE);
+-
+ hw->wiphy->features |= NL80211_FEATURE_ACTIVE_MONITOR |
+ NL80211_FEATURE_AP_MODE_CHAN_WIDTH_CHANGE |
+ NL80211_FEATURE_P2P_GO_CTWIN;
+@@ -1049,6 +1059,18 @@ static void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw)
+ wiphy_ext_feature_set(hw->wiphy, NL80211_EXT_FEATURE_CAN_REPLACE_PTK0);
+ }
+
++static void ath_get_initial_entropy(struct ath_softc *sc)
++{
++ struct ath_hw *ah = sc->sc_ah;
++ char buf[256];
++
++ /* reuse last channel initialized by the tx power test */
++ ath9k_hw_reset(ah, ah->curchan, NULL, false);
++
++ ath9k_hw_get_adc_entropy(ah, buf, sizeof(buf));
++ add_device_randomness(buf, sizeof(buf));
++}
++
+ int ath9k_init_device(u16 devid, struct ath_softc *sc,
+ const struct ath_bus_ops *bus_ops)
+ {
+@@ -1089,13 +1111,15 @@ int ath9k_init_device(u16 devid, struct ath_softc *sc,
+
+ #ifdef CPTCFG_MAC80211_LEDS
+ /* must be initialized before ieee80211_register_hw */
+- sc->led_cdev.default_trigger = ieee80211_create_tpt_led_trigger(sc->hw,
++ sc->led_default_trigger = ieee80211_create_tpt_led_trigger(sc->hw,
+ IEEE80211_TPT_LEDTRIG_FL_RADIO, ath9k_tpt_blink,
+ ARRAY_SIZE(ath9k_tpt_blink));
+ #endif
+
+ wiphy_read_of_freq_limits(hw->wiphy);
+
++ ath_get_initial_entropy(sc);
++
+ /* Register with mac80211 */
+ error = ieee80211_register_hw(hw);
+ if (error)
+@@ -1179,25 +1203,25 @@ static int __init ath9k_init(void)
+ {
+ int error;
+
+- error = ath_pci_init();
++ error = ath_ahb_init();
+ if (error < 0) {
+- pr_err("No PCI devices found, driver not installed\n");
+ error = -ENODEV;
+ goto err_out;
+ }
+
+- error = ath_ahb_init();
++ error = ath_pci_init();
+ if (error < 0) {
++ pr_err("No PCI devices found, driver not installed\n");
+ error = -ENODEV;
+- goto err_pci_exit;
++ goto err_ahb_exit;
+ }
+
+ dmi_check_system(ath9k_quirks);
+
+ return 0;
+
+- err_pci_exit:
+- ath_pci_exit();
++ err_ahb_exit:
++ ath_ahb_exit();
+ err_out:
+ return error;
+ }
+diff --git a/drivers/net/wireless/ath/ath9k/mac.c b/drivers/net/wireless/ath/ath9k/mac.c
+index b070403..d8d14a5 100644
+--- a/drivers/net/wireless/ath/ath9k/mac.c
++++ b/drivers/net/wireless/ath/ath9k/mac.c
+@@ -678,13 +678,18 @@ void ath9k_hw_startpcureceive(struct ath_hw *ah, bool is_scanning)
+
+ ath9k_ani_reset(ah, is_scanning);
+
+- REG_CLR_BIT(ah, AR_DIAG_SW, (AR_DIAG_RX_DIS | AR_DIAG_RX_ABORT));
++ REG_CLR_BIT(ah, AR_DIAG_SW,
++ AR_DIAG_RX_DIS | AR_DIAG_RX_ABORT | AR_DIAG_FORCE_RX_CLEAR);
+ }
+ EXPORT_SYMBOL(ath9k_hw_startpcureceive);
+
+ void ath9k_hw_abortpcurecv(struct ath_hw *ah)
+ {
+- REG_SET_BIT(ah, AR_DIAG_SW, AR_DIAG_RX_ABORT | AR_DIAG_RX_DIS);
++ u32 reg = AR_DIAG_RX_DIS | AR_DIAG_RX_ABORT;
++
++ if (!IS_ENABLED(CPTCFG_ATH9K_TX99))
++ reg |= AR_DIAG_FORCE_RX_CLEAR;
++ REG_SET_BIT(ah, AR_DIAG_SW, reg);
+
+ ath9k_hw_disable_mib_counters(ah);
+ }
+diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c
+index 6d120df..2807d36 100644
+--- a/drivers/net/wireless/ath/ath9k/main.c
++++ b/drivers/net/wireless/ath/ath9k/main.c
+@@ -18,6 +18,7 @@
+ #include <linux/delay.h>
+ #include "ath9k.h"
+ #include "btcoex.h"
++#include "hsr.h"
+
+ static void ath9k_flush(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
+ u32 queues, bool drop);
+@@ -538,6 +539,11 @@ irqreturn_t ath_isr(int irq, void *dev)
+ return IRQ_HANDLED;
+ }
+
++ if (test_bit(ATH_DIAG_TRIGGER_ERROR, &ah->diag)) {
++ status |= ATH9K_INT_FATAL;
++ clear_bit(ATH_DIAG_TRIGGER_ERROR, &ah->diag);
++ }
++
+ /*
+ * If there are no status bits set, then this interrupt was not
+ * for me (should have been caught above).
+@@ -654,6 +660,7 @@ void ath_reset_work(struct work_struct *work)
+ static int ath9k_start(struct ieee80211_hw *hw)
+ {
+ struct ath_softc *sc = hw->priv;
++ struct device_node *np = sc->dev->of_node;
+ struct ath_hw *ah = sc->sc_ah;
+ struct ath_common *common = ath9k_hw_common(ah);
+ struct ieee80211_channel *curchan = sc->cur_chan->chandef.chan;
+@@ -732,6 +739,11 @@ static int ath9k_start(struct ieee80211_hw *hw)
+ AR_GPIO_OUTPUT_MUX_AS_OUTPUT);
+ }
+
++ if (of_property_read_bool(np, "ubnt,hsr")) {
++ ath9k_hsr_init(ah);
++ ath9k_hsr_disable(ah);
++ }
++
+ /*
+ * Reset key cache to sane defaults (all entries cleared) instead of
+ * semi-random values after suspend/resume.
+diff --git a/drivers/net/wireless/ath/ath9k/pci.c b/drivers/net/wireless/ath/ath9k/pci.c
+index 6421e49..20c7095 100644
+--- a/drivers/net/wireless/ath/ath9k/pci.c
++++ b/drivers/net/wireless/ath/ath9k/pci.c
+@@ -772,6 +772,7 @@ static const struct pci_device_id ath_pci_id_table[] = {
+ .driver_data = ATH9K_PCI_BT_ANT_DIV },
+ #endif
+
++ { PCI_VDEVICE(ATHEROS, 0xabcd) }, /* PCI-E internal chip default ID */
+ { 0 }
+ };
+
+diff --git a/drivers/net/wireless/ath/ath9k/phy.h b/drivers/net/wireless/ath/ath9k/phy.h
+index 4a1b992..af667a3 100644
+--- a/drivers/net/wireless/ath/ath9k/phy.h
++++ b/drivers/net/wireless/ath/ath9k/phy.h
+@@ -48,6 +48,9 @@
+ #define AR_PHY_PLL_CONTROL 0x16180
+ #define AR_PHY_PLL_MODE 0x16184
+
++#define AR_PHY_USB_CTRL1 0x16c84
++#define AR_PHY_USB_CTRL2 0x16c88
++
+ enum ath9k_ant_div_comb_lna_conf {
+ ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2,
+ ATH_ANT_DIV_COMB_LNA2,
+diff --git a/include/linux/ath9k_platform.h b/include/linux/ath9k_platform.h
+index 76860a4..e210108 100644
+--- a/include/linux/ath9k_platform.h
++++ b/include/linux/ath9k_platform.h
+@@ -46,6 +46,13 @@ struct ath9k_platform_data {
+ int (*external_reset)(void);
+
+ bool use_eeprom;
++
++ int num_leds;
++ const struct gpio_led *leds;
++
++ unsigned num_btns;
++ const struct gpio_keys_button *btns;
++ unsigned btn_poll_interval;
+ };
+
+ #endif /* _LINUX_ATH9K_PLATFORM_H */
+diff --git a/local-symbols b/local-symbols
+index b200b00..b5745bf 100644
+--- a/local-symbols
++++ b/local-symbols
+@@ -128,6 +128,7 @@ ATH9K_WOW=
+ ATH9K_RFKILL=
+ ATH9K_CHANNEL_CONTEXT=
+ ATH9K_PCOEM=
++ATH9K_UBNTHSR=
+ ATH9K_PCI_NO_EEPROM=
+ ATH9K_HTC=
+ ATH9K_HTC_DEBUGFS=
+--
+2.39.2
+
diff --git a/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/0005-sync-backports-patches-ath10k.patch b/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/0005-sync-backports-patches-ath10k.patch
new file mode 100644
index 0000000..feebf11
--- /dev/null
+++ b/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/0005-sync-backports-patches-ath10k.patch
@@ -0,0 +1,835 @@
+From 38cce019a8791ff3d295bd936362432cc592e061 Mon Sep 17 00:00:00 2001
+From: Shayne Chen <shayne.chen@mediatek.com>
+Date: Tue, 12 Mar 2024 11:27:11 +0800
+Subject: [PATCH 05/61] sync backports patches/ath10k
+
+---
+ drivers/net/wireless/ath/ath10k/Kconfig | 16 ++++
+ drivers/net/wireless/ath/ath10k/Makefile | 3 +-
+ drivers/net/wireless/ath/ath10k/core.c | 34 ++++++++
+ drivers/net/wireless/ath/ath10k/core.h | 12 +++
+ drivers/net/wireless/ath/ath10k/htt.h | 4 +
+ drivers/net/wireless/ath/ath10k/hw.h | 1 +
+ drivers/net/wireless/ath/ath10k/leds.c | 101 ++++++++++++++++++++++
+ drivers/net/wireless/ath/ath10k/leds.h | 41 +++++++++
+ drivers/net/wireless/ath/ath10k/mac.c | 66 +++++++++++++-
+ drivers/net/wireless/ath/ath10k/pci.c | 16 ++++
+ drivers/net/wireless/ath/ath10k/thermal.h | 2 +-
+ drivers/net/wireless/ath/ath10k/wmi-ops.h | 32 +++++++
+ drivers/net/wireless/ath/ath10k/wmi-tlv.c | 2 +
+ drivers/net/wireless/ath/ath10k/wmi.c | 54 ++++++++++++
+ drivers/net/wireless/ath/ath10k/wmi.h | 35 ++++++++
+ local-symbols | 2 +
+ 16 files changed, 415 insertions(+), 6 deletions(-)
+ create mode 100644 drivers/net/wireless/ath/ath10k/leds.c
+ create mode 100644 drivers/net/wireless/ath/ath10k/leds.h
+
+diff --git a/drivers/net/wireless/ath/ath10k/Kconfig b/drivers/net/wireless/ath/ath10k/Kconfig
+index d10c65d..5cabe0e 100644
+--- a/drivers/net/wireless/ath/ath10k/Kconfig
++++ b/drivers/net/wireless/ath/ath10k/Kconfig
+@@ -72,6 +72,16 @@ config ATH10K_DEBUGFS
+
+ If unsure, say Y to make it easier to debug problems.
+
++config ATH10K_LEDS
++ bool "Atheros ath10k LED support"
++ depends on ATH10K
++ select MAC80211_LEDS
++ select LEDS_CLASS
++ select NEW_LEDS
++ default y
++ ---help---
++ This option is necessary, if you want LED support for chipset connected led pins. If unsure, say N.
++
+ config ATH10K_SPECTRAL
+ bool "Atheros ath10k spectral scan support"
+ depends on ATH10K_DEBUGFS
+@@ -87,6 +97,12 @@ config ATH10K_TRACING
+ help
+ Select this to ath10k use tracing infrastructure.
+
++config ATH10K_THERMAL
++ bool "Atheros ath10k thermal monitoring support"
++ depends on THERMAL
++ ---help---
++ Select this to ath10k use hwmon for thermal measurement.
++
+ config ATH10K_DFS_CERTIFIED
+ bool "Atheros DFS support for certified platforms"
+ depends on ATH10K && CFG80211_CERTIFICATION_ONUS
+diff --git a/drivers/net/wireless/ath/ath10k/Makefile b/drivers/net/wireless/ath/ath10k/Makefile
+index 24d846a..e040d84 100644
+--- a/drivers/net/wireless/ath/ath10k/Makefile
++++ b/drivers/net/wireless/ath/ath10k/Makefile
+@@ -18,7 +18,8 @@ ath10k_core-y += mac.o \
+ ath10k_core-$(CPTCFG_ATH10K_SPECTRAL) += spectral.o
+ ath10k_core-$(CPTCFG_NL80211_TESTMODE) += testmode.o
+ ath10k_core-$(CPTCFG_ATH10K_TRACING) += trace.o
+-ath10k_core-$(CONFIG_THERMAL) += thermal.o
++ath10k_core-$(CPTCFG_ATH10K_THERMAL) += thermal.o
++ath10k_core-$(CPTCFG_ATH10K_LEDS) += leds.o
+ ath10k_core-$(CPTCFG_MAC80211_DEBUGFS) += debugfs_sta.o
+ ath10k_core-$(CONFIG_PM) += wow.o
+ ath10k_core-$(CONFIG_DEV_COREDUMP) += coredump.o
+diff --git a/drivers/net/wireless/ath/ath10k/core.c b/drivers/net/wireless/ath/ath10k/core.c
+index 9ce6f49..a168fdf 100644
+--- a/drivers/net/wireless/ath/ath10k/core.c
++++ b/drivers/net/wireless/ath/ath10k/core.c
+@@ -9,6 +9,7 @@
+ #include <linux/module.h>
+ #include <linux/firmware.h>
+ #include <linux/of.h>
++#include <linux/of_net.h>
+ #include <linux/property.h>
+ #include <linux/dmi.h>
+ #include <linux/ctype.h>
+@@ -27,6 +28,7 @@
+ #include "testmode.h"
+ #include "wmi-ops.h"
+ #include "coredump.h"
++#include "leds.h"
+
+ unsigned int ath10k_debug_mask;
+ EXPORT_SYMBOL(ath10k_debug_mask);
+@@ -66,6 +68,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
+ .dev_id = QCA988X_2_0_DEVICE_ID,
+ .bus = ATH10K_BUS_PCI,
+ .name = "qca988x hw2.0",
++ .led_pin = 1,
+ .patch_load_addr = QCA988X_HW_2_0_PATCH_LOAD_ADDR,
+ .uart_pin = 7,
+ .cc_wraparound_type = ATH10K_HW_CC_WRAP_SHIFTED_ALL,
+@@ -149,6 +152,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
+ .dev_id = QCA9887_1_0_DEVICE_ID,
+ .bus = ATH10K_BUS_PCI,
+ .name = "qca9887 hw1.0",
++ .led_pin = 1,
+ .patch_load_addr = QCA9887_HW_1_0_PATCH_LOAD_ADDR,
+ .uart_pin = 7,
+ .cc_wraparound_type = ATH10K_HW_CC_WRAP_SHIFTED_ALL,
+@@ -396,6 +400,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
+ .dev_id = QCA99X0_2_0_DEVICE_ID,
+ .bus = ATH10K_BUS_PCI,
+ .name = "qca99x0 hw2.0",
++ .led_pin = 17,
+ .patch_load_addr = QCA99X0_HW_2_0_PATCH_LOAD_ADDR,
+ .uart_pin = 7,
+ .otp_exe_param = 0x00000700,
+@@ -443,6 +448,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
+ .dev_id = QCA9984_1_0_DEVICE_ID,
+ .bus = ATH10K_BUS_PCI,
+ .name = "qca9984/qca9994 hw1.0",
++ .led_pin = 17,
+ .patch_load_addr = QCA9984_HW_1_0_PATCH_LOAD_ADDR,
+ .uart_pin = 7,
+ .cc_wraparound_type = ATH10K_HW_CC_WRAP_SHIFTED_EACH,
+@@ -497,6 +503,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
+ .dev_id = QCA9888_2_0_DEVICE_ID,
+ .bus = ATH10K_BUS_PCI,
+ .name = "qca9888 hw2.0",
++ .led_pin = 17,
+ .patch_load_addr = QCA9888_HW_2_0_PATCH_LOAD_ADDR,
+ .uart_pin = 7,
+ .cc_wraparound_type = ATH10K_HW_CC_WRAP_SHIFTED_EACH,
+@@ -3239,6 +3246,10 @@ int ath10k_core_start(struct ath10k *ar, enum ath10k_firmware_mode mode,
+ goto err_hif_stop;
+ }
+
++ status = ath10k_leds_start(ar);
++ if (status)
++ goto err_hif_stop;
++
+ return 0;
+
+ err_hif_stop:
+@@ -3405,6 +3416,8 @@ static int ath10k_core_probe_fw(struct ath10k *ar)
+
+ device_get_mac_address(ar->dev, ar->mac_addr);
+
++ of_get_mac_address(ar->dev->of_node, ar->mac_addr);
++
+ ret = ath10k_core_init_firmware_features(ar);
+ if (ret) {
+ ath10k_err(ar, "fatal problem with firmware features: %d\n",
+@@ -3497,9 +3510,18 @@ static void ath10k_core_register_work(struct work_struct *work)
+ goto err_spectral_destroy;
+ }
+
++ status = ath10k_leds_register(ar);
++ if (status) {
++ ath10k_err(ar, "could not register leds: %d\n",
++ status);
++ goto err_thermal_unregister;
++ }
++
+ set_bit(ATH10K_FLAG_CORE_REGISTERED, &ar->dev_flags);
+ return;
+
++err_thermal_unregister:
++ ath10k_thermal_unregister(ar);
+ err_spectral_destroy:
+ ath10k_spectral_destroy(ar);
+ err_debug_destroy:
+@@ -3524,6 +3546,16 @@ int ath10k_core_register(struct ath10k *ar,
+
+ queue_work(ar->workqueue, &ar->register_work);
+
++ /* OpenWrt requires all PHYs to be initialized to create the
++ * configuration files during bootup. ath10k violates this
++ * because it delays the creation of the PHY to a not well defined
++ * point in the future.
++ *
++ * Forcing the work to be done immediately works around this problem
++ * but may also delay the boot when firmware images cannot be found.
++ */
++ flush_workqueue(ar->workqueue);
++
+ return 0;
+ }
+ EXPORT_SYMBOL(ath10k_core_register);
+@@ -3535,6 +3567,8 @@ void ath10k_core_unregister(struct ath10k *ar)
+ if (!test_bit(ATH10K_FLAG_CORE_REGISTERED, &ar->dev_flags))
+ return;
+
++ ath10k_leds_unregister(ar);
++
+ ath10k_thermal_unregister(ar);
+ /* Stop spectral before unregistering from mac80211 to remove the
+ * relayfs debugfs file cleanly. Otherwise the parent debugfs tree
+diff --git a/drivers/net/wireless/ath/ath10k/core.h b/drivers/net/wireless/ath/ath10k/core.h
+index 2435291..8546f2f 100644
+--- a/drivers/net/wireless/ath/ath10k/core.h
++++ b/drivers/net/wireless/ath/ath10k/core.h
+@@ -15,6 +15,7 @@
+ #include <linux/pci.h>
+ #include <linux/uuid.h>
+ #include <linux/time.h>
++#include <linux/leds.h>
+
+ #include "htt.h"
+ #include "htc.h"
+@@ -1256,6 +1257,13 @@ struct ath10k {
+ bool utf_monitor;
+ } testmode;
+
++ struct {
++ struct gpio_led wifi_led;
++ struct led_classdev cdev;
++ char label[48];
++ u32 gpio_state_pin;
++ } leds;
++
+ struct {
+ /* protected by data_lock */
+ u32 rx_crc_err_drop;
+@@ -1305,6 +1313,10 @@ struct ath10k {
+ s32 tx_power_2g_limit;
+ s32 tx_power_5g_limit;
+
++#ifdef CPTCFG_MAC80211_LEDS
++ const char *led_default_trigger;
++#endif
++
+ /* must be last */
+ u8 drv_priv[] __aligned(sizeof(void *));
+ };
+diff --git a/drivers/net/wireless/ath/ath10k/htt.h b/drivers/net/wireless/ath/ath10k/htt.h
+index 603f6de..bea1d16 100644
+--- a/drivers/net/wireless/ath/ath10k/htt.h
++++ b/drivers/net/wireless/ath/ath10k/htt.h
+@@ -236,7 +236,11 @@ enum htt_rx_ring_flags {
+ };
+
+ #define HTT_RX_RING_SIZE_MIN 128
++#ifndef CONFIG_ATH10K_SMALLBUFFERS
+ #define HTT_RX_RING_SIZE_MAX 2048
++#else
++#define HTT_RX_RING_SIZE_MAX 512
++#endif
+ #define HTT_RX_RING_SIZE HTT_RX_RING_SIZE_MAX
+ #define HTT_RX_RING_FILL_LEVEL (((HTT_RX_RING_SIZE) / 2) - 1)
+ #define HTT_RX_RING_FILL_LEVEL_DUAL_MAC (HTT_RX_RING_SIZE - 1)
+diff --git a/drivers/net/wireless/ath/ath10k/hw.h b/drivers/net/wireless/ath/ath10k/hw.h
+index 3b26994..aeada6c 100644
+--- a/drivers/net/wireless/ath/ath10k/hw.h
++++ b/drivers/net/wireless/ath/ath10k/hw.h
+@@ -520,6 +520,7 @@ struct ath10k_hw_params {
+ const char *name;
+ u32 patch_load_addr;
+ int uart_pin;
++ int led_pin;
+ u32 otp_exe_param;
+
+ /* Type of hw cycle counter wraparound logic, for more info
+diff --git a/drivers/net/wireless/ath/ath10k/leds.c b/drivers/net/wireless/ath/ath10k/leds.c
+new file mode 100644
+index 0000000..be8f255
+--- /dev/null
++++ b/drivers/net/wireless/ath/ath10k/leds.c
+@@ -0,0 +1,101 @@
++/*
++ * Copyright (c) 2005-2011 Atheros Communications Inc.
++ * Copyright (c) 2011-2017 Qualcomm Atheros, Inc.
++ * Copyright (c) 2018 Sebastian Gottschall <s.gottschall@dd-wrt.com>
++ * Copyright (c) 2018, The Linux Foundation. All rights reserved.
++ *
++ * Permission to use, copy, modify, and/or distribute this software for any
++ * purpose with or without fee is hereby granted, provided that the above
++ * copyright notice and this permission notice appear in all copies.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
++ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
++ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
++ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
++ */
++
++#include <linux/leds.h>
++
++#include "core.h"
++#include "wmi.h"
++#include "wmi-ops.h"
++
++#include "leds.h"
++
++static int ath10k_leds_set_brightness_blocking(struct led_classdev *led_cdev,
++ enum led_brightness brightness)
++{
++ struct ath10k *ar = container_of(led_cdev, struct ath10k,
++ leds.cdev);
++ struct gpio_led *led = &ar->leds.wifi_led;
++
++ mutex_lock(&ar->conf_mutex);
++
++ if (ar->state != ATH10K_STATE_ON)
++ goto out;
++
++ ar->leds.gpio_state_pin = (brightness != LED_OFF) ^ led->active_low;
++ ath10k_wmi_gpio_output(ar, led->gpio, ar->leds.gpio_state_pin);
++
++out:
++ mutex_unlock(&ar->conf_mutex);
++
++ return 0;
++}
++
++int ath10k_leds_start(struct ath10k *ar)
++{
++ if (ar->hw_params.led_pin == 0)
++ /* leds not supported */
++ return 0;
++
++ /* under some circumstances, the gpio pin gets reconfigured
++ * to default state by the firmware, so we need to
++ * reconfigure it this behaviour has only ben seen on
++ * QCA9984 and QCA99XX devices so far
++ */
++ ath10k_wmi_gpio_config(ar, ar->hw_params.led_pin, 0,
++ WMI_GPIO_PULL_NONE, WMI_GPIO_INTTYPE_DISABLE);
++ ath10k_wmi_gpio_output(ar, ar->hw_params.led_pin, 1);
++
++ return 0;
++}
++
++int ath10k_leds_register(struct ath10k *ar)
++{
++ int ret;
++
++ if (ar->hw_params.led_pin == 0)
++ /* leds not supported */
++ return 0;
++
++ snprintf(ar->leds.label, sizeof(ar->leds.label), "ath10k-%s",
++ wiphy_name(ar->hw->wiphy));
++ ar->leds.wifi_led.active_low = 1;
++ ar->leds.wifi_led.gpio = ar->hw_params.led_pin;
++ ar->leds.wifi_led.name = ar->leds.label;
++ ar->leds.wifi_led.default_state = LEDS_GPIO_DEFSTATE_KEEP;
++
++ ar->leds.cdev.name = ar->leds.label;
++ ar->leds.cdev.brightness_set_blocking = ath10k_leds_set_brightness_blocking;
++ ar->leds.cdev.default_trigger = ar->led_default_trigger;
++
++ ret = led_classdev_register(wiphy_dev(ar->hw->wiphy), &ar->leds.cdev);
++ if (ret)
++ return ret;
++
++ return 0;
++}
++
++void ath10k_leds_unregister(struct ath10k *ar)
++{
++ if (ar->hw_params.led_pin == 0)
++ /* leds not supported */
++ return;
++
++ led_classdev_unregister(&ar->leds.cdev);
++}
++
+diff --git a/drivers/net/wireless/ath/ath10k/leds.h b/drivers/net/wireless/ath/ath10k/leds.h
+new file mode 100644
+index 0000000..a0f5c84
+--- /dev/null
++++ b/drivers/net/wireless/ath/ath10k/leds.h
+@@ -0,0 +1,41 @@
++/*
++ * Copyright (c) 2018, The Linux Foundation. All rights reserved.
++ *
++ * Permission to use, copy, modify, and/or distribute this software for any
++ * purpose with or without fee is hereby granted, provided that the above
++ * copyright notice and this permission notice appear in all copies.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
++ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
++ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
++ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
++ */
++#ifndef _LEDS_H_
++#define _LEDS_H_
++
++#include "core.h"
++
++#ifdef CPTCFG_ATH10K_LEDS
++void ath10k_leds_unregister(struct ath10k *ar);
++int ath10k_leds_start(struct ath10k *ar);
++int ath10k_leds_register(struct ath10k *ar);
++#else
++static inline void ath10k_leds_unregister(struct ath10k *ar)
++{
++}
++
++static inline int ath10k_leds_start(struct ath10k *ar)
++{
++ return 0;
++}
++
++static inline int ath10k_leds_register(struct ath10k *ar)
++{
++ return 0;
++}
++
++#endif
++#endif /* _LEDS_H_ */
+diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c
+index ec43216..f179dff 100644
+--- a/drivers/net/wireless/ath/ath10k/mac.c
++++ b/drivers/net/wireless/ath/ath10k/mac.c
+@@ -25,6 +25,7 @@
+ #include "wmi-tlv.h"
+ #include "wmi-ops.h"
+ #include "wow.h"
++#include "leds.h"
+
+ /*********/
+ /* Rates */
+@@ -1021,6 +1022,40 @@ static inline int ath10k_vdev_setup_sync(struct ath10k *ar)
+ return ar->last_wmi_vdev_start_status;
+ }
+
++static u32 ath10k_get_max_antenna_gain(struct ath10k *ar,
++ u32 ch_max_antenna_gain)
++{
++ u32 max_antenna_gain;
++
++ if (ar->dfs_detector && ar->dfs_detector->region == NL80211_DFS_FCC) {
++ /* FCC allows maximum antenna gain of 6 dBi. 15.247(b)(4):
++ *
++ * > (4) The conducted output power limit
++ * > specified in paragraph (b) of this section
++ * > is based on the use of antennas
++ * > with directional gains that do not exceed
++ * > 6 dBi. Except as shown in paragraph
++ * > (c) of this section, if transmitting
++ * > antennas of directional gain greater
++ * > than 6 dBi are used, the conducted
++ * > output power from the intentional radiator
++ * > shall be reduced below the stated
++ * > values in paragraphs (b)(1), (b)(2),
++ * > and (b)(3) of this section, as appropriate,
++ * > by the amount in dB that the
++ * > directional gain of the antenna exceeds
++ * > 6 dBi.
++ *
++ * https://www.gpo.gov/fdsys/pkg/CFR-2013-title47-vol1/pdf/CFR-2013-title47-vol1-sec15-247.pdf
++ */
++ max_antenna_gain = 6;
++ } else {
++ max_antenna_gain = 0;
++ }
++
++ return max(ch_max_antenna_gain, max_antenna_gain);
++}
++
+ static int ath10k_monitor_vdev_start(struct ath10k *ar, int vdev_id)
+ {
+ struct cfg80211_chan_def *chandef = NULL;
+@@ -1053,7 +1088,8 @@ static int ath10k_monitor_vdev_start(struct ath10k *ar, int vdev_id)
+ arg.channel.min_power = 0;
+ arg.channel.max_power = channel->max_power * 2;
+ arg.channel.max_reg_power = channel->max_reg_power * 2;
+- arg.channel.max_antenna_gain = channel->max_antenna_gain;
++ arg.channel.max_antenna_gain = ath10k_get_max_antenna_gain(ar,
++ channel->max_antenna_gain);
+
+ reinit_completion(&ar->vdev_setup_done);
+ reinit_completion(&ar->vdev_delete_done);
+@@ -1499,7 +1535,8 @@ static int ath10k_vdev_start_restart(struct ath10k_vif *arvif,
+ 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;
+- arg.channel.max_antenna_gain = chandef->chan->max_antenna_gain;
++ arg.channel.max_antenna_gain = ath10k_get_max_antenna_gain(ar,
++ chandef->chan->max_antenna_gain);
+
+ if (arvif->vdev_type == WMI_VDEV_TYPE_AP) {
+ arg.ssid = arvif->u.ap.ssid;
+@@ -3430,7 +3467,8 @@ static int ath10k_update_channel_list(struct ath10k *ar)
+ ch->min_power = 0;
+ ch->max_power = channel->max_power * 2;
+ ch->max_reg_power = channel->max_reg_power * 2;
+- ch->max_antenna_gain = channel->max_antenna_gain;
++ ch->max_antenna_gain = ath10k_get_max_antenna_gain(ar,
++ channel->max_antenna_gain);
+ ch->reg_class_id = 0; /* FIXME */
+
+ /* FIXME: why use only legacy modes, why not any
+@@ -9918,6 +9956,21 @@ static int ath10k_mac_init_rd(struct ath10k *ar)
+ return 0;
+ }
+
++#ifdef CPTCFG_MAC80211_LEDS
++static const struct ieee80211_tpt_blink ath10k_tpt_blink[] = {
++ { .throughput = 0 * 1024, .blink_time = 334 },
++ { .throughput = 1 * 1024, .blink_time = 260 },
++ { .throughput = 2 * 1024, .blink_time = 220 },
++ { .throughput = 5 * 1024, .blink_time = 190 },
++ { .throughput = 10 * 1024, .blink_time = 170 },
++ { .throughput = 25 * 1024, .blink_time = 150 },
++ { .throughput = 54 * 1024, .blink_time = 130 },
++ { .throughput = 120 * 1024, .blink_time = 110 },
++ { .throughput = 265 * 1024, .blink_time = 80 },
++ { .throughput = 586 * 1024, .blink_time = 50 },
++};
++#endif
++
+ int ath10k_mac_register(struct ath10k *ar)
+ {
+ static const u32 cipher_suites[] = {
+@@ -10036,7 +10089,6 @@ int ath10k_mac_register(struct ath10k *ar)
+ ieee80211_hw_set(ar->hw, CHANCTX_STA_CSA);
+ ieee80211_hw_set(ar->hw, QUEUE_CONTROL);
+ ieee80211_hw_set(ar->hw, SUPPORTS_TX_FRAG);
+- ieee80211_hw_set(ar->hw, REPORTS_LOW_ACK);
+
+ if (!test_bit(ATH10K_FLAG_RAW_MODE, &ar->dev_flags))
+ ieee80211_hw_set(ar->hw, SW_CRYPTO_CONTROL);
+@@ -10280,6 +10332,12 @@ int ath10k_mac_register(struct ath10k *ar)
+
+ ar->hw->weight_multiplier = ATH10K_AIRTIME_WEIGHT_MULTIPLIER;
+
++#ifdef CPTCFG_MAC80211_LEDS
++ ar->led_default_trigger = ieee80211_create_tpt_led_trigger(ar->hw,
++ IEEE80211_TPT_LEDTRIG_FL_RADIO, ath10k_tpt_blink,
++ ARRAY_SIZE(ath10k_tpt_blink));
++#endif
++
+ ret = ieee80211_register_hw(ar->hw);
+ if (ret) {
+ ath10k_err(ar, "failed to register ieee80211: %d\n", ret);
+diff --git a/drivers/net/wireless/ath/ath10k/pci.c b/drivers/net/wireless/ath/ath10k/pci.c
+index d7ac5ae..c7e8e90 100644
+--- a/drivers/net/wireless/ath/ath10k/pci.c
++++ b/drivers/net/wireless/ath/ath10k/pci.c
+@@ -132,7 +132,11 @@ static const struct ce_attr pci_host_ce_config_wlan[] = {
+ .flags = CE_ATTR_FLAGS,
+ .src_nentries = 0,
+ .src_sz_max = 2048,
++#ifndef CONFIG_ATH10K_SMALLBUFFERS
+ .dest_nentries = 512,
++#else
++ .dest_nentries = 128,
++#endif
+ .recv_cb = ath10k_pci_htt_htc_rx_cb,
+ },
+
+@@ -141,7 +145,11 @@ static const struct ce_attr pci_host_ce_config_wlan[] = {
+ .flags = CE_ATTR_FLAGS,
+ .src_nentries = 0,
+ .src_sz_max = 2048,
++#ifndef CONFIG_ATH10K_SMALLBUFFERS
+ .dest_nentries = 128,
++#else
++ .dest_nentries = 64,
++#endif
+ .recv_cb = ath10k_pci_htc_rx_cb,
+ },
+
+@@ -168,7 +176,11 @@ static const struct ce_attr pci_host_ce_config_wlan[] = {
+ .flags = CE_ATTR_FLAGS,
+ .src_nentries = 0,
+ .src_sz_max = 512,
++#ifndef CONFIG_ATH10K_SMALLBUFFERS
+ .dest_nentries = 512,
++#else
++ .dest_nentries = 128,
++#endif
+ .recv_cb = ath10k_pci_htt_rx_cb,
+ },
+
+@@ -193,7 +205,11 @@ static const struct ce_attr pci_host_ce_config_wlan[] = {
+ .flags = CE_ATTR_FLAGS,
+ .src_nentries = 0,
+ .src_sz_max = 2048,
++#ifndef CONFIG_ATH10K_SMALLBUFFERS
+ .dest_nentries = 128,
++#else
++ .dest_nentries = 96,
++#endif
+ .recv_cb = ath10k_pci_pktlog_rx_cb,
+ },
+
+diff --git a/drivers/net/wireless/ath/ath10k/thermal.h b/drivers/net/wireless/ath/ath10k/thermal.h
+index 1f4de9f..fcfa3c2 100644
+--- a/drivers/net/wireless/ath/ath10k/thermal.h
++++ b/drivers/net/wireless/ath/ath10k/thermal.h
+@@ -25,7 +25,7 @@ struct ath10k_thermal {
+ int temperature;
+ };
+
+-#if IS_REACHABLE(CONFIG_THERMAL)
++#if IS_REACHABLE(CPTCFG_ATH10K_THERMAL)
+ int ath10k_thermal_register(struct ath10k *ar);
+ void ath10k_thermal_unregister(struct ath10k *ar);
+ void ath10k_thermal_event_temperature(struct ath10k *ar, int temperature);
+diff --git a/drivers/net/wireless/ath/ath10k/wmi-ops.h b/drivers/net/wireless/ath/ath10k/wmi-ops.h
+index aa57d80..f3f6b59 100644
+--- a/drivers/net/wireless/ath/ath10k/wmi-ops.h
++++ b/drivers/net/wireless/ath/ath10k/wmi-ops.h
+@@ -226,7 +226,10 @@ struct wmi_ops {
+ const struct wmi_bb_timing_cfg_arg *arg);
+ struct sk_buff *(*gen_per_peer_per_tid_cfg)(struct ath10k *ar,
+ const struct wmi_per_peer_per_tid_cfg_arg *arg);
++ struct sk_buff *(*gen_gpio_config)(struct ath10k *ar, u32 gpio_num,
++ u32 input, u32 pull_type, u32 intr_mode);
+
++ struct sk_buff *(*gen_gpio_output)(struct ath10k *ar, u32 gpio_num, u32 set);
+ };
+
+ int ath10k_wmi_cmd_send(struct ath10k *ar, struct sk_buff *skb, u32 cmd_id);
+@@ -1122,6 +1125,35 @@ ath10k_wmi_force_fw_hang(struct ath10k *ar,
+ return ath10k_wmi_cmd_send(ar, skb, ar->wmi.cmd->force_fw_hang_cmdid);
+ }
+
++static inline int ath10k_wmi_gpio_config(struct ath10k *ar, u32 gpio_num,
++ u32 input, u32 pull_type, u32 intr_mode)
++{
++ struct sk_buff *skb;
++
++ if (!ar->wmi.ops->gen_gpio_config)
++ return -EOPNOTSUPP;
++
++ skb = ar->wmi.ops->gen_gpio_config(ar, gpio_num, input, pull_type, intr_mode);
++ if (IS_ERR(skb))
++ return PTR_ERR(skb);
++
++ return ath10k_wmi_cmd_send(ar, skb, ar->wmi.cmd->gpio_config_cmdid);
++}
++
++static inline int ath10k_wmi_gpio_output(struct ath10k *ar, u32 gpio_num, u32 set)
++{
++ struct sk_buff *skb;
++
++ if (!ar->wmi.ops->gen_gpio_config)
++ return -EOPNOTSUPP;
++
++ skb = ar->wmi.ops->gen_gpio_output(ar, gpio_num, set);
++ if (IS_ERR(skb))
++ return PTR_ERR(skb);
++
++ return ath10k_wmi_cmd_send(ar, skb, ar->wmi.cmd->gpio_output_cmdid);
++}
++
+ static inline int
+ ath10k_wmi_dbglog_cfg(struct ath10k *ar, u64 module_enable, u32 log_level)
+ {
+diff --git a/drivers/net/wireless/ath/ath10k/wmi-tlv.c b/drivers/net/wireless/ath/ath10k/wmi-tlv.c
+index aed97fd..dbaf26d 100644
+--- a/drivers/net/wireless/ath/ath10k/wmi-tlv.c
++++ b/drivers/net/wireless/ath/ath10k/wmi-tlv.c
+@@ -4606,6 +4606,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,
++ /* .gen_gpio_config not implemented */
++ /* .gen_gpio_output not implemented */
+ };
+
+ static const struct wmi_peer_flags_map wmi_tlv_peer_flags_map = {
+diff --git a/drivers/net/wireless/ath/ath10k/wmi.c b/drivers/net/wireless/ath/ath10k/wmi.c
+index 5d80988..6b428b4 100644
+--- a/drivers/net/wireless/ath/ath10k/wmi.c
++++ b/drivers/net/wireless/ath/ath10k/wmi.c
+@@ -7493,6 +7493,49 @@ ath10k_wmi_op_gen_peer_set_param(struct ath10k *ar, u32 vdev_id,
+ return skb;
+ }
+
++static struct sk_buff *ath10k_wmi_op_gen_gpio_config(struct ath10k *ar,
++ u32 gpio_num, u32 input,
++ u32 pull_type, u32 intr_mode)
++{
++ struct wmi_gpio_config_cmd *cmd;
++ struct sk_buff *skb;
++
++ skb = ath10k_wmi_alloc_skb(ar, sizeof(*cmd));
++ if (!skb)
++ return ERR_PTR(-ENOMEM);
++
++ cmd = (struct wmi_gpio_config_cmd *)skb->data;
++ cmd->pull_type = __cpu_to_le32(pull_type);
++ cmd->gpio_num = __cpu_to_le32(gpio_num);
++ cmd->input = __cpu_to_le32(input);
++ cmd->intr_mode = __cpu_to_le32(intr_mode);
++
++ ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi gpio_config gpio_num 0x%08x input 0x%08x pull_type 0x%08x intr_mode 0x%08x\n",
++ gpio_num, input, pull_type, intr_mode);
++
++ return skb;
++}
++
++static struct sk_buff *ath10k_wmi_op_gen_gpio_output(struct ath10k *ar,
++ u32 gpio_num, u32 set)
++{
++ struct wmi_gpio_output_cmd *cmd;
++ struct sk_buff *skb;
++
++ skb = ath10k_wmi_alloc_skb(ar, sizeof(*cmd));
++ if (!skb)
++ return ERR_PTR(-ENOMEM);
++
++ cmd = (struct wmi_gpio_output_cmd *)skb->data;
++ cmd->gpio_num = __cpu_to_le32(gpio_num);
++ cmd->set = __cpu_to_le32(set);
++
++ ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi gpio_output gpio_num 0x%08x set 0x%08x\n",
++ gpio_num, set);
++
++ return skb;
++}
++
+ static struct sk_buff *
+ ath10k_wmi_op_gen_set_psmode(struct ath10k *ar, u32 vdev_id,
+ enum wmi_sta_ps_mode psmode)
+@@ -9157,6 +9200,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,
++ .gen_gpio_config = ath10k_wmi_op_gen_gpio_config,
++ .gen_gpio_output = ath10k_wmi_op_gen_gpio_output,
++
+ /* .gen_bcn_tmpl not implemented */
+ /* .gen_prb_tmpl not implemented */
+ /* .gen_p2p_go_bcn_ie not implemented */
+@@ -9227,6 +9273,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,
++ .gen_gpio_config = ath10k_wmi_op_gen_gpio_config,
++ .gen_gpio_output = ath10k_wmi_op_gen_gpio_output,
+ /* .gen_bcn_tmpl not implemented */
+ /* .gen_prb_tmpl not implemented */
+ /* .gen_p2p_go_bcn_ie not implemented */
+@@ -9299,6 +9347,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,
++ .gen_gpio_config = ath10k_wmi_op_gen_gpio_config,
++ .gen_gpio_output = ath10k_wmi_op_gen_gpio_output,
+ /* .gen_pdev_enable_adaptive_cca not implemented */
+ };
+
+@@ -9370,6 +9420,8 @@ static const struct wmi_ops wmi_10_2_4_ops = {
+ 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,
++ .gen_gpio_config = ath10k_wmi_op_gen_gpio_config,
++ .gen_gpio_output = ath10k_wmi_op_gen_gpio_output,
+ /* .gen_bcn_tmpl not implemented */
+ /* .gen_prb_tmpl not implemented */
+ /* .gen_p2p_go_bcn_ie not implemented */
+@@ -9451,6 +9503,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,
++ .gen_gpio_config = ath10k_wmi_op_gen_gpio_config,
++ .gen_gpio_output = ath10k_wmi_op_gen_gpio_output,
+ };
+
+ int ath10k_wmi_attach(struct ath10k *ar)
+diff --git a/drivers/net/wireless/ath/ath10k/wmi.h b/drivers/net/wireless/ath/ath10k/wmi.h
+index 2379501..0faefc0 100644
+--- a/drivers/net/wireless/ath/ath10k/wmi.h
++++ b/drivers/net/wireless/ath/ath10k/wmi.h
+@@ -3034,6 +3034,41 @@ enum wmi_10_4_feature_mask {
+
+ };
+
++/* WMI_GPIO_CONFIG_CMDID */
++enum {
++ WMI_GPIO_PULL_NONE,
++ WMI_GPIO_PULL_UP,
++ WMI_GPIO_PULL_DOWN,
++};
++
++enum {
++ WMI_GPIO_INTTYPE_DISABLE,
++ WMI_GPIO_INTTYPE_RISING_EDGE,
++ WMI_GPIO_INTTYPE_FALLING_EDGE,
++ WMI_GPIO_INTTYPE_BOTH_EDGE,
++ WMI_GPIO_INTTYPE_LEVEL_LOW,
++ WMI_GPIO_INTTYPE_LEVEL_HIGH
++};
++
++/* WMI_GPIO_CONFIG_CMDID */
++struct wmi_gpio_config_cmd {
++ __le32 gpio_num; /* GPIO number to be setup */
++ __le32 input; /* 0 - Output/ 1 - Input */
++ __le32 pull_type; /* Pull type defined above */
++ __le32 intr_mode; /* Interrupt mode defined above (Input) */
++} __packed;
++
++/* WMI_GPIO_OUTPUT_CMDID */
++struct wmi_gpio_output_cmd {
++ __le32 gpio_num; /* GPIO number to be setup */
++ __le32 set; /* Set the GPIO pin*/
++} __packed;
++
++/* WMI_GPIO_INPUT_EVENTID */
++struct wmi_gpio_input_event {
++ __le32 gpio_num; /* GPIO number which changed state */
++} __packed;
++
+ struct wmi_ext_resource_config_10_4_cmd {
+ /* contains enum wmi_host_platform_type */
+ __le32 host_platform_config;
+diff --git a/local-symbols b/local-symbols
+index b5745bf..3d81ba5 100644
+--- a/local-symbols
++++ b/local-symbols
+@@ -160,6 +160,8 @@ ATH10K_SNOC=
+ ATH10K_DEBUG=
+ ATH10K_DEBUGFS=
+ ATH10K_SPECTRAL=
++ATH10K_THERMAL=
++ATH10K_LEDS=
+ ATH10K_TRACING=
+ ATH10K_DFS_CERTIFIED=
+ WCN36XX=
+--
+2.39.2
+
diff --git a/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/0006-sync-backports-patches-rt2x00.patch b/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/0006-sync-backports-patches-rt2x00.patch
new file mode 100644
index 0000000..39975b3
--- /dev/null
+++ b/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/0006-sync-backports-patches-rt2x00.patch
@@ -0,0 +1,1263 @@
+From a08aa9e789ade7bb35eb442afa6566368d5a318f Mon Sep 17 00:00:00 2001
+From: Shayne Chen <shayne.chen@mediatek.com>
+Date: Tue, 12 Mar 2024 11:27:40 +0800
+Subject: [PATCH 06/61] sync backports patches/rt2x00
+
+---
+ drivers/net/wireless/ralink/rt2x00/Kconfig | 23 +-
+ drivers/net/wireless/ralink/rt2x00/Makefile | 1 +
+ drivers/net/wireless/ralink/rt2x00/rt2800.h | 5 +
+ .../net/wireless/ralink/rt2x00/rt2800lib.c | 373 +++++++++++-------
+ .../net/wireless/ralink/rt2x00/rt2800lib.h | 24 ++
+ .../net/wireless/ralink/rt2x00/rt2800pci.c | 7 +
+ .../net/wireless/ralink/rt2x00/rt2800soc.c | 52 ++-
+ .../net/wireless/ralink/rt2x00/rt2800usb.c | 7 +
+ drivers/net/wireless/ralink/rt2x00/rt2x00.h | 15 +
+ .../net/wireless/ralink/rt2x00/rt2x00dev.c | 34 +-
+ .../net/wireless/ralink/rt2x00/rt2x00eeprom.c | 208 ++++++++++
+ .../net/wireless/ralink/rt2x00/rt2x00leds.c | 3 +
+ .../net/wireless/ralink/rt2x00/rt2x00soc.c | 16 +
+ .../net/wireless/ralink/rt2x00/rt2x00soc.h | 9 +
+ include/linux/rt2x00_platform.h | 23 ++
+ local-symbols | 1 +
+ 16 files changed, 635 insertions(+), 166 deletions(-)
+ create mode 100644 drivers/net/wireless/ralink/rt2x00/rt2x00eeprom.c
+ create mode 100644 include/linux/rt2x00_platform.h
+
+diff --git a/drivers/net/wireless/ralink/rt2x00/Kconfig b/drivers/net/wireless/ralink/rt2x00/Kconfig
+index 8f6e3d2..abaa51b 100644
+--- a/drivers/net/wireless/ralink/rt2x00/Kconfig
++++ b/drivers/net/wireless/ralink/rt2x00/Kconfig
+@@ -70,6 +70,7 @@ config RT2800PCI
+ select RT2X00_LIB_MMIO
+ select RT2X00_LIB_PCI
+ select RT2X00_LIB_FIRMWARE
++ select RT2X00_LIB_EEPROM
+ select RT2X00_LIB_CRYPTO
+ depends on CRC_CCITT
+ depends on EEPROM_93CX6
+@@ -211,13 +212,15 @@ endif
+ config RT2800SOC
+ tristate "Ralink WiSoC support"
+ depends on m
+- depends on SOC_RT288X || SOC_RT305X || SOC_MT7620
++ depends on SOC_RT288X || SOC_RT305X || SOC_RT3883 || SOC_MT7620
+ select RT2X00_LIB_SOC
+ select RT2X00_LIB_MMIO
+ select RT2X00_LIB_CRYPTO
+ select RT2X00_LIB_FIRMWARE
++ select RT2X00_LIB_EEPROM
+ select RT2800_LIB
+ select RT2800_LIB_MMIO
++ select MTD if SOC_RT288X || SOC_RT305X
+ help
+ This adds support for Ralink WiSoC devices.
+ Supported chips: RT2880, RT3050, RT3052, RT3350, RT3352.
+@@ -226,36 +229,37 @@ config RT2800SOC
+
+
+ config RT2800_LIB
+- tristate
++ tristate "RT2800 USB/PCI support"
+ depends on m
+
+ config RT2800_LIB_MMIO
+- tristate
++ tristate "RT2800 MMIO support"
+ depends on m
+ select RT2X00_LIB_MMIO
+ select RT2800_LIB
+
+ config RT2X00_LIB_MMIO
+- tristate
++ tristate "RT2x00 MMIO support"
+ depends on m
+
+ config RT2X00_LIB_PCI
+- tristate
++ tristate "RT2x00 PCI support"
+ depends on m
+ select RT2X00_LIB
+
+ config RT2X00_LIB_SOC
+- tristate
++ tristate "RT2x00 SoC support"
++ depends on SOC_RT288X || SOC_RT305X || SOC_RT3883 || SOC_MT7620
+ depends on m
+ select RT2X00_LIB
+
+ config RT2X00_LIB_USB
+- tristate
++ tristate "RT2x00 USB support"
+ depends on m
+ select RT2X00_LIB
+
+ config RT2X00_LIB
+- tristate
++ tristate "RT2x00 support"
+ depends on m
+
+ config RT2X00_LIB_FIRMWARE
+@@ -265,6 +269,9 @@ config RT2X00_LIB_FIRMWARE
+ config RT2X00_LIB_CRYPTO
+ bool
+
++config RT2X00_LIB_EEPROM
++ bool
++
+ config RT2X00_LIB_LEDS
+ bool
+ default y if (RT2X00_LIB=y && LEDS_CLASS=y) || (RT2X00_LIB=m && LEDS_CLASS!=n)
+diff --git a/drivers/net/wireless/ralink/rt2x00/Makefile b/drivers/net/wireless/ralink/rt2x00/Makefile
+index 4a2156b..94335ec 100644
+--- a/drivers/net/wireless/ralink/rt2x00/Makefile
++++ b/drivers/net/wireless/ralink/rt2x00/Makefile
+@@ -8,6 +8,7 @@ rt2x00lib-$(CPTCFG_RT2X00_LIB_DEBUGFS) += rt2x00debug.o
+ rt2x00lib-$(CPTCFG_RT2X00_LIB_CRYPTO) += rt2x00crypto.o
+ rt2x00lib-$(CPTCFG_RT2X00_LIB_FIRMWARE) += rt2x00firmware.o
+ rt2x00lib-$(CPTCFG_RT2X00_LIB_LEDS) += rt2x00leds.o
++rt2x00lib-$(CPTCFG_RT2X00_LIB_EEPROM) += rt2x00eeprom.o
+
+ obj-$(CPTCFG_RT2X00_LIB) += rt2x00lib.o
+ obj-$(CPTCFG_RT2X00_LIB_MMIO) += rt2x00mmio.o
+diff --git a/drivers/net/wireless/ralink/rt2x00/rt2800.h b/drivers/net/wireless/ralink/rt2x00/rt2800.h
+index 8930589..cbfa680 100644
+--- a/drivers/net/wireless/ralink/rt2x00/rt2800.h
++++ b/drivers/net/wireless/ralink/rt2x00/rt2800.h
+@@ -1056,6 +1056,11 @@
+ #define MIMO_PS_CFG_RX_STBY_POL FIELD32(0x00000010)
+ #define MIMO_PS_CFG_RX_RX_STBY0 FIELD32(0x00000020)
+
++#define BB_PA_MODE_CFG0 0x1214
++#define BB_PA_MODE_CFG1 0x1218
++#define RF_PA_MODE_CFG0 0x121C
++#define RF_PA_MODE_CFG1 0x1220
++
+ /*
+ * EDCA_AC0_CFG:
+ */
+diff --git a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
+index d2ab374..7461d2e 100644
+--- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
++++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
+@@ -25,6 +25,7 @@
+ #include <linux/kernel.h>
+ #include <linux/module.h>
+ #include <linux/slab.h>
++#include <linux/of.h>
+
+ #include "rt2x00.h"
+ #include "rt2800lib.h"
+@@ -304,6 +305,24 @@ static void rt2800_rf_write(struct rt2x00_dev *rt2x00dev,
+ mutex_unlock(&rt2x00dev->csr_mutex);
+ }
+
++void rt6352_enable_pa_pin(struct rt2x00_dev *rt2x00dev, int enable)
++{
++ if (!rt2x00dev->pinctrl)
++ return;
++
++ if (enable) {
++ if (!rt2x00dev->pins_default)
++ return;
++
++ pinctrl_select_state(rt2x00dev->pinctrl, rt2x00dev->pins_default);
++ } else {
++ if (!rt2x00dev->pins_pa_gpio)
++ return;
++
++ pinctrl_select_state(rt2x00dev->pinctrl, rt2x00dev->pins_pa_gpio);
++ }
++}
++
+ static const unsigned int rt2800_eeprom_map[EEPROM_WORD_COUNT] = {
+ [EEPROM_CHIP_ID] = 0x0000,
+ [EEPROM_VERSION] = 0x0001,
+@@ -3817,14 +3836,16 @@ static void rt2800_config_channel_rf7620(struct rt2x00_dev *rt2x00dev,
+ rt2x00_set_field8(&rfcsr, RFCSR19_K, rf->rf4);
+ rt2800_rfcsr_write(rt2x00dev, 19, rfcsr);
+
+- /* Default: XO=20MHz , SDM mode */
+- rfcsr = rt2800_rfcsr_read(rt2x00dev, 16);
+- rt2x00_set_field8(&rfcsr, RFCSR16_SDM_MODE_MT7620, 0x80);
+- rt2800_rfcsr_write(rt2x00dev, 16, rfcsr);
++ if (rt2800_hw_get_chipver(rt2x00dev) > 1) {
++ /* Default: XO=20MHz , SDM mode */
++ rfcsr = rt2800_rfcsr_read(rt2x00dev, 16);
++ rt2x00_set_field8(&rfcsr, RFCSR16_SDM_MODE_MT7620, 0x80);
++ rt2800_rfcsr_write(rt2x00dev, 16, rfcsr);
+
+- rfcsr = rt2800_rfcsr_read(rt2x00dev, 21);
+- rt2x00_set_field8(&rfcsr, RFCSR21_BIT8, 1);
+- rt2800_rfcsr_write(rt2x00dev, 21, rfcsr);
++ rfcsr = rt2800_rfcsr_read(rt2x00dev, 21);
++ rt2x00_set_field8(&rfcsr, RFCSR21_BIT8, 1);
++ rt2800_rfcsr_write(rt2x00dev, 21, rfcsr);
++ }
+
+ rfcsr = rt2800_rfcsr_read(rt2x00dev, 1);
+ rt2x00_set_field8(&rfcsr, RFCSR1_TX2_EN_MT7620,
+@@ -3858,18 +3879,23 @@ static void rt2800_config_channel_rf7620(struct rt2x00_dev *rt2x00dev,
+ rt2800_rfcsr_write_dccal(rt2x00dev, 59, 0x20);
+ }
+
+- if (conf_is_ht40(conf)) {
+- rt2800_rfcsr_write_dccal(rt2x00dev, 58, 0x08);
+- rt2800_rfcsr_write_dccal(rt2x00dev, 59, 0x08);
+- } else {
+- rt2800_rfcsr_write_dccal(rt2x00dev, 58, 0x28);
+- rt2800_rfcsr_write_dccal(rt2x00dev, 59, 0x28);
++ if (rt2800_hw_get_chipver(rt2x00dev) > 1) {
++ if (conf_is_ht40(conf)) {
++ rt2800_rfcsr_write_dccal(rt2x00dev, 58, 0x08);
++ rt2800_rfcsr_write_dccal(rt2x00dev, 59, 0x08);
++ } else {
++ rt2800_rfcsr_write_dccal(rt2x00dev, 58, 0x28);
++ rt2800_rfcsr_write_dccal(rt2x00dev, 59, 0x28);
++ }
+ }
+
+- rfcsr = rt2800_rfcsr_read(rt2x00dev, 28);
+- rt2x00_set_field8(&rfcsr, RFCSR28_CH11_HT40,
+- conf_is_ht40(conf) && (rf->channel == 11));
+- rt2800_rfcsr_write(rt2x00dev, 28, rfcsr);
++ if (rt2800_hw_get_chipver(rt2x00dev) > 1 &&
++ rt2800_hw_get_chipeco(rt2x00dev) == 2) {
++ rfcsr = rt2800_rfcsr_read(rt2x00dev, 28);
++ rt2x00_set_field8(&rfcsr, RFCSR28_CH11_HT40,
++ conf_is_ht40(conf) && (rf->channel == 11));
++ rt2800_rfcsr_write(rt2x00dev, 28, rfcsr);
++ }
+
+ if (!test_bit(DEVICE_STATE_SCANNING, &rt2x00dev->flags)) {
+ if (conf_is_ht40(conf)) {
+@@ -3983,25 +4009,29 @@ static void rt2800_config_alc_rt6352(struct rt2x00_dev *rt2x00dev,
+ if (unlikely(rt2800_wait_bbp_rf_ready(rt2x00dev, MAC_STATUS_CFG_BBP_RF_BUSY)))
+ rt2x00_warn(rt2x00dev, "RF busy while configuring ALC\n");
+
+- if (chan->center_freq > 2457) {
+- bbp = rt2800_bbp_read(rt2x00dev, 30);
+- bbp = 0x40;
+- rt2800_bbp_write(rt2x00dev, 30, bbp);
+- rt2800_rfcsr_write(rt2x00dev, 39, 0);
+- if (rt2x00_has_cap_external_lna_bg(rt2x00dev))
+- rt2800_rfcsr_write(rt2x00dev, 42, 0xfb);
+- else
+- rt2800_rfcsr_write(rt2x00dev, 42, 0x7b);
+- } else {
+- bbp = rt2800_bbp_read(rt2x00dev, 30);
+- bbp = 0x1f;
+- rt2800_bbp_write(rt2x00dev, 30, bbp);
+- rt2800_rfcsr_write(rt2x00dev, 39, 0x80);
+- if (rt2x00_has_cap_external_lna_bg(rt2x00dev))
+- rt2800_rfcsr_write(rt2x00dev, 42, 0xdb);
+- else
+- rt2800_rfcsr_write(rt2x00dev, 42, 0x5b);
++ if (rt2800_hw_get_chipver(rt2x00dev) > 1 &&
++ rt2800_hw_get_chipeco(rt2x00dev) >= 2) {
++ if (chan->center_freq > 2457) {
++ bbp = rt2800_bbp_read(rt2x00dev, 30);
++ bbp = 0x40;
++ rt2800_bbp_write(rt2x00dev, 30, bbp);
++ rt2800_rfcsr_write(rt2x00dev, 39, 0);
++ if (rt2x00_has_cap_external_lna_bg(rt2x00dev))
++ rt2800_rfcsr_write(rt2x00dev, 42, 0xfb);
++ else
++ rt2800_rfcsr_write(rt2x00dev, 42, 0x7b);
++ } else {
++ bbp = rt2800_bbp_read(rt2x00dev, 30);
++ bbp = 0x1f;
++ rt2800_bbp_write(rt2x00dev, 30, bbp);
++ rt2800_rfcsr_write(rt2x00dev, 39, 0x80);
++ if (rt2x00_has_cap_external_lna_bg(rt2x00dev))
++ rt2800_rfcsr_write(rt2x00dev, 42, 0xdb);
++ else
++ rt2800_rfcsr_write(rt2x00dev, 42, 0x5b);
++ }
+ }
++
+ rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, mac_sys_ctrl);
+
+ rt2800_vco_calibration(rt2x00dev);
+@@ -4494,7 +4524,8 @@ static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev,
+ if (rt2x00_rt(rt2x00dev, RT6352)) {
+ /* BBP for GLRT BW */
+ bbp = conf_is_ht40(conf) ?
+- 0x10 : rt2x00_has_cap_external_lna_bg(rt2x00dev) ?
++ 0x10 : !rt2x00_has_cap_external_lna_bg(rt2x00dev) ?
++ 0x1a : rt2800_hw_get_chippkg(rt2x00dev) == 1 ?
+ 0x15 : 0x1a;
+ rt2800_bbp_glrt_write(rt2x00dev, 141, bbp);
+
+@@ -5998,18 +6029,33 @@ static int rt2800_init_registers(struct rt2x00_dev *rt2x00dev)
+ } else if (rt2x00_rt(rt2x00dev, RT5350)) {
+ rt2800_register_write(rt2x00dev, TX_SW_CFG0, 0x00000404);
+ } else if (rt2x00_rt(rt2x00dev, RT6352)) {
+- rt2800_register_write(rt2x00dev, TX_SW_CFG0, 0x00000401);
+- rt2800_register_write(rt2x00dev, TX_SW_CFG1, 0x000C0001);
+- rt2800_register_write(rt2x00dev, TX_SW_CFG2, 0x00000000);
+- rt2800_register_write(rt2x00dev, TX_ALC_VGA3, 0x00000000);
+- rt2800_register_write(rt2x00dev, TX0_BB_GAIN_ATTEN, 0x0);
+- rt2800_register_write(rt2x00dev, TX1_BB_GAIN_ATTEN, 0x0);
+- rt2800_register_write(rt2x00dev, TX0_RF_GAIN_ATTEN, 0x6C6C666C);
+- rt2800_register_write(rt2x00dev, TX1_RF_GAIN_ATTEN, 0x6C6C666C);
+- rt2800_register_write(rt2x00dev, TX0_RF_GAIN_CORRECT,
+- 0x3630363A);
+- rt2800_register_write(rt2x00dev, TX1_RF_GAIN_CORRECT,
+- 0x3630363A);
++ if (rt2800_hw_get_chipver(rt2x00dev) <= 1) {
++ rt2800_register_write(rt2x00dev, TX_ALC_VGA3,
++ 0x00000000);
++ rt2800_register_write(rt2x00dev, BB_PA_MODE_CFG0,
++ 0x000055FF);
++ rt2800_register_write(rt2x00dev, BB_PA_MODE_CFG1,
++ 0x00550055);
++ rt2800_register_write(rt2x00dev, RF_PA_MODE_CFG0,
++ 0x000055FF);
++ rt2800_register_write(rt2x00dev, RF_PA_MODE_CFG1,
++ 0x00550055);
++ } else {
++ rt2800_register_write(rt2x00dev, TX_SW_CFG0, 0x00000401);
++ rt2800_register_write(rt2x00dev, TX_SW_CFG1, 0x000C0001);
++ rt2800_register_write(rt2x00dev, TX_SW_CFG2, 0x00000000);
++ rt2800_register_write(rt2x00dev, TX_ALC_VGA3, 0x00000000);
++ rt2800_register_write(rt2x00dev, TX0_BB_GAIN_ATTEN, 0x0);
++ rt2800_register_write(rt2x00dev, TX1_BB_GAIN_ATTEN, 0x0);
++ rt2800_register_write(rt2x00dev, TX0_RF_GAIN_ATTEN,
++ 0x6C6C666C);
++ rt2800_register_write(rt2x00dev, TX1_RF_GAIN_ATTEN,
++ 0x6C6C666C);
++ rt2800_register_write(rt2x00dev, TX0_RF_GAIN_CORRECT,
++ 0x3630363A);
++ rt2800_register_write(rt2x00dev, TX1_RF_GAIN_CORRECT,
++ 0x3630363A);
++ }
+ reg = rt2800_register_read(rt2x00dev, TX_ALC_CFG_1);
+ rt2x00_set_field32(®, TX_ALC_CFG_1_ROS_BUSY_EN, 0);
+ rt2800_register_write(rt2x00dev, TX_ALC_CFG_1, reg);
+@@ -7122,14 +7168,16 @@ static void rt2800_init_bbp_6352(struct rt2x00_dev *rt2x00dev)
+ rt2800_bbp_write(rt2x00dev, 188, 0x00);
+ rt2800_bbp_write(rt2x00dev, 189, 0x00);
+
+- rt2800_bbp_write(rt2x00dev, 91, 0x06);
+- rt2800_bbp_write(rt2x00dev, 92, 0x04);
+- rt2800_bbp_write(rt2x00dev, 93, 0x54);
+- rt2800_bbp_write(rt2x00dev, 99, 0x50);
+- rt2800_bbp_write(rt2x00dev, 148, 0x84);
+- rt2800_bbp_write(rt2x00dev, 167, 0x80);
+- rt2800_bbp_write(rt2x00dev, 178, 0xFF);
+- rt2800_bbp_write(rt2x00dev, 106, 0x13);
++ if (rt2800_hw_get_chipver(rt2x00dev) > 1) {
++ rt2800_bbp_write(rt2x00dev, 91, 0x06);
++ rt2800_bbp_write(rt2x00dev, 92, 0x04);
++ rt2800_bbp_write(rt2x00dev, 93, 0x54);
++ rt2800_bbp_write(rt2x00dev, 99, 0x50);
++ rt2800_bbp_write(rt2x00dev, 148, 0x84);
++ rt2800_bbp_write(rt2x00dev, 167, 0x80);
++ rt2800_bbp_write(rt2x00dev, 178, 0xFF);
++ rt2800_bbp_write(rt2x00dev, 106, 0x13);
++ }
+
+ /* BBP for G band GLRT function (BBP_128 ~ BBP_221) */
+ rt2800_bbp_glrt_write(rt2x00dev, 0, 0x00);
+@@ -10359,6 +10407,9 @@ static void rt2800_restore_rf_bbp_rt6352(struct rt2x00_dev *rt2x00dev)
+ rt2800_register_write(rt2x00dev, RF_BYPASS3, 0x0);
+ }
+
++ if (rt2800_hw_get_chippkg(rt2x00dev) != 1)
++ return;
++
+ if (rt2x00_has_cap_external_lna_bg(rt2x00dev)) {
+ rt2800_rfcsr_write_chanreg(rt2x00dev, 14, 0x16);
+ rt2800_rfcsr_write_chanreg(rt2x00dev, 17, 0x23);
+@@ -10403,8 +10454,10 @@ static void rt2800_calibration_rt6352(struct rt2x00_dev *rt2x00dev)
+ u32 reg;
+
+ if (rt2x00_has_cap_external_pa(rt2x00dev) ||
+- rt2x00_has_cap_external_lna_bg(rt2x00dev))
++ rt2x00_has_cap_external_lna_bg(rt2x00dev)) {
++ rt6352_enable_pa_pin(rt2x00dev, 0);
+ rt2800_restore_rf_bbp_rt6352(rt2x00dev);
++ }
+
+ rt2800_r_calibration(rt2x00dev);
+ rt2800_rf_self_txdc_cal(rt2x00dev);
+@@ -10422,6 +10475,8 @@ static void rt2800_calibration_rt6352(struct rt2x00_dev *rt2x00dev)
+ !rt2x00_has_cap_external_lna_bg(rt2x00dev))
+ return;
+
++ rt6352_enable_pa_pin(rt2x00dev, 1);
++
+ if (rt2x00_has_cap_external_pa(rt2x00dev)) {
+ reg = rt2800_register_read(rt2x00dev, RF_CONTROL3);
+ reg |= 0x00000101;
+@@ -10432,6 +10487,9 @@ static void rt2800_calibration_rt6352(struct rt2x00_dev *rt2x00dev)
+ rt2800_register_write(rt2x00dev, RF_BYPASS3, reg);
+ }
+
++ if (rt2800_hw_get_chippkg(rt2x00dev) != 1)
++ return;
++
+ if (rt2x00_has_cap_external_lna_bg(rt2x00dev)) {
+ rt2800_rfcsr_write_chanreg(rt2x00dev, 14, 0x66);
+ rt2800_rfcsr_write_chanreg(rt2x00dev, 17, 0x20);
+@@ -10522,31 +10580,36 @@ static void rt2800_init_rfcsr_6352(struct rt2x00_dev *rt2x00dev)
+ rt2800_rfcsr_write(rt2x00dev, 42, 0x5B);
+ rt2800_rfcsr_write(rt2x00dev, 43, 0x00);
+
+- rt2800_rfcsr_write(rt2x00dev, 11, 0x21);
+- if (rt2800_clk_is_20mhz(rt2x00dev))
+- rt2800_rfcsr_write(rt2x00dev, 13, 0x03);
+- else
+- rt2800_rfcsr_write(rt2x00dev, 13, 0x00);
+- rt2800_rfcsr_write(rt2x00dev, 14, 0x7C);
+- rt2800_rfcsr_write(rt2x00dev, 16, 0x80);
+- rt2800_rfcsr_write(rt2x00dev, 17, 0x99);
+- rt2800_rfcsr_write(rt2x00dev, 18, 0x99);
+- rt2800_rfcsr_write(rt2x00dev, 19, 0x09);
+- rt2800_rfcsr_write(rt2x00dev, 20, 0x50);
+- rt2800_rfcsr_write(rt2x00dev, 21, 0xB0);
+- rt2800_rfcsr_write(rt2x00dev, 22, 0x00);
+- rt2800_rfcsr_write(rt2x00dev, 23, 0x06);
+- rt2800_rfcsr_write(rt2x00dev, 24, 0x00);
+- rt2800_rfcsr_write(rt2x00dev, 25, 0x00);
+- rt2800_rfcsr_write(rt2x00dev, 26, 0x5D);
+- rt2800_rfcsr_write(rt2x00dev, 27, 0x00);
+- rt2800_rfcsr_write(rt2x00dev, 28, 0x61);
+- rt2800_rfcsr_write(rt2x00dev, 29, 0xB5);
+- rt2800_rfcsr_write(rt2x00dev, 43, 0x02);
++ if (rt2800_hw_get_chipver(rt2x00dev) > 1) {
++ rt2800_rfcsr_write(rt2x00dev, 11, 0x21);
++ if (rt2800_clk_is_20mhz(rt2x00dev))
++ rt2800_rfcsr_write(rt2x00dev, 13, 0x03);
++ else
++ rt2800_rfcsr_write(rt2x00dev, 13, 0x00);
++ rt2800_rfcsr_write(rt2x00dev, 14, 0x7C);
++ rt2800_rfcsr_write(rt2x00dev, 16, 0x80);
++ rt2800_rfcsr_write(rt2x00dev, 17, 0x99);
++ rt2800_rfcsr_write(rt2x00dev, 18, 0x99);
++ rt2800_rfcsr_write(rt2x00dev, 19, 0x09);
++ rt2800_rfcsr_write(rt2x00dev, 20, 0x50);
++ rt2800_rfcsr_write(rt2x00dev, 21, 0xB0);
++ rt2800_rfcsr_write(rt2x00dev, 22, 0x00);
++ rt2800_rfcsr_write(rt2x00dev, 23, 0x06);
++ rt2800_rfcsr_write(rt2x00dev, 24, 0x00);
++ rt2800_rfcsr_write(rt2x00dev, 25, 0x00);
++ rt2800_rfcsr_write(rt2x00dev, 26, 0x5D);
++ rt2800_rfcsr_write(rt2x00dev, 27, 0x00);
++ rt2800_rfcsr_write(rt2x00dev, 28, 0x61);
++ rt2800_rfcsr_write(rt2x00dev, 29, 0xB5);
++ rt2800_rfcsr_write(rt2x00dev, 43, 0x02);
++ }
+
+- rt2800_rfcsr_write(rt2x00dev, 28, 0x62);
+- rt2800_rfcsr_write(rt2x00dev, 29, 0xAD);
+- rt2800_rfcsr_write(rt2x00dev, 39, 0x80);
++ if (rt2800_hw_get_chipver(rt2x00dev) > 1 &&
++ rt2800_hw_get_chipeco(rt2x00dev) >= 2) {
++ rt2800_rfcsr_write(rt2x00dev, 28, 0x62);
++ rt2800_rfcsr_write(rt2x00dev, 29, 0xAD);
++ rt2800_rfcsr_write(rt2x00dev, 39, 0x80);
++ }
+
+ /* Initialize RF channel register to default value */
+ rt2800_rfcsr_write_chanreg(rt2x00dev, 0, 0x03);
+@@ -10612,63 +10675,71 @@ static void rt2800_init_rfcsr_6352(struct rt2x00_dev *rt2x00dev)
+
+ rt2800_rfcsr_write_bank(rt2x00dev, 6, 45, 0xC5);
+
+- rt2800_rfcsr_write_chanreg(rt2x00dev, 9, 0x47);
+- rt2800_rfcsr_write_chanreg(rt2x00dev, 10, 0x71);
+- rt2800_rfcsr_write_chanreg(rt2x00dev, 11, 0x33);
+- rt2800_rfcsr_write_chanreg(rt2x00dev, 14, 0x0E);
+- rt2800_rfcsr_write_chanreg(rt2x00dev, 17, 0x23);
+- rt2800_rfcsr_write_chanreg(rt2x00dev, 19, 0xA4);
+- rt2800_rfcsr_write_chanreg(rt2x00dev, 20, 0x02);
+- rt2800_rfcsr_write_chanreg(rt2x00dev, 21, 0x12);
+- rt2800_rfcsr_write_chanreg(rt2x00dev, 28, 0x1C);
+- rt2800_rfcsr_write_chanreg(rt2x00dev, 29, 0xEB);
+- rt2800_rfcsr_write_chanreg(rt2x00dev, 32, 0x7D);
+- rt2800_rfcsr_write_chanreg(rt2x00dev, 34, 0xD6);
+- rt2800_rfcsr_write_chanreg(rt2x00dev, 36, 0x08);
+- rt2800_rfcsr_write_chanreg(rt2x00dev, 38, 0xB4);
+- rt2800_rfcsr_write_chanreg(rt2x00dev, 43, 0xD3);
+- rt2800_rfcsr_write_chanreg(rt2x00dev, 44, 0xB3);
+- rt2800_rfcsr_write_chanreg(rt2x00dev, 45, 0xD5);
+- rt2800_rfcsr_write_chanreg(rt2x00dev, 46, 0x27);
+- rt2800_rfcsr_write_bank(rt2x00dev, 4, 47, 0x67);
+- rt2800_rfcsr_write_bank(rt2x00dev, 6, 47, 0x69);
+- rt2800_rfcsr_write_chanreg(rt2x00dev, 48, 0xFF);
+- rt2800_rfcsr_write_bank(rt2x00dev, 4, 54, 0x27);
+- rt2800_rfcsr_write_bank(rt2x00dev, 6, 54, 0x20);
+- rt2800_rfcsr_write_chanreg(rt2x00dev, 55, 0x66);
+- rt2800_rfcsr_write_chanreg(rt2x00dev, 56, 0xFF);
+- rt2800_rfcsr_write_chanreg(rt2x00dev, 57, 0x1C);
+- rt2800_rfcsr_write_chanreg(rt2x00dev, 58, 0x20);
+- rt2800_rfcsr_write_chanreg(rt2x00dev, 59, 0x6B);
+- rt2800_rfcsr_write_chanreg(rt2x00dev, 60, 0xF7);
+- rt2800_rfcsr_write_chanreg(rt2x00dev, 61, 0x09);
+-
+- rt2800_rfcsr_write_chanreg(rt2x00dev, 10, 0x51);
+- rt2800_rfcsr_write_chanreg(rt2x00dev, 14, 0x06);
+- rt2800_rfcsr_write_chanreg(rt2x00dev, 19, 0xA7);
+- rt2800_rfcsr_write_chanreg(rt2x00dev, 28, 0x2C);
+- rt2800_rfcsr_write_chanreg(rt2x00dev, 55, 0x64);
+- rt2800_rfcsr_write_chanreg(rt2x00dev, 8, 0x51);
+- rt2800_rfcsr_write_chanreg(rt2x00dev, 9, 0x36);
+- rt2800_rfcsr_write_chanreg(rt2x00dev, 11, 0x53);
+- rt2800_rfcsr_write_chanreg(rt2x00dev, 14, 0x16);
+-
+- rt2800_rfcsr_write_chanreg(rt2x00dev, 47, 0x6C);
+- rt2800_rfcsr_write_chanreg(rt2x00dev, 48, 0xFC);
+- rt2800_rfcsr_write_chanreg(rt2x00dev, 49, 0x1F);
+- rt2800_rfcsr_write_chanreg(rt2x00dev, 54, 0x27);
+- rt2800_rfcsr_write_chanreg(rt2x00dev, 55, 0x66);
+- rt2800_rfcsr_write_chanreg(rt2x00dev, 59, 0x6B);
+-
+- /* Initialize RF channel register for DRQFN */
+- rt2800_rfcsr_write_chanreg(rt2x00dev, 43, 0xD3);
+- rt2800_rfcsr_write_chanreg(rt2x00dev, 44, 0xE3);
+- rt2800_rfcsr_write_chanreg(rt2x00dev, 45, 0xE5);
+- rt2800_rfcsr_write_chanreg(rt2x00dev, 47, 0x28);
+- rt2800_rfcsr_write_chanreg(rt2x00dev, 55, 0x68);
+- rt2800_rfcsr_write_chanreg(rt2x00dev, 56, 0xF7);
+- rt2800_rfcsr_write_chanreg(rt2x00dev, 58, 0x02);
+- rt2800_rfcsr_write_chanreg(rt2x00dev, 60, 0xC7);
++ if (rt2800_hw_get_chipver(rt2x00dev) > 1) {
++ rt2800_rfcsr_write_chanreg(rt2x00dev, 9, 0x47);
++ rt2800_rfcsr_write_chanreg(rt2x00dev, 10, 0x71);
++ rt2800_rfcsr_write_chanreg(rt2x00dev, 11, 0x33);
++ rt2800_rfcsr_write_chanreg(rt2x00dev, 14, 0x0E);
++ rt2800_rfcsr_write_chanreg(rt2x00dev, 17, 0x23);
++ rt2800_rfcsr_write_chanreg(rt2x00dev, 19, 0xA4);
++ rt2800_rfcsr_write_chanreg(rt2x00dev, 20, 0x02);
++ rt2800_rfcsr_write_chanreg(rt2x00dev, 21, 0x12);
++ rt2800_rfcsr_write_chanreg(rt2x00dev, 28, 0x1C);
++ rt2800_rfcsr_write_chanreg(rt2x00dev, 29, 0xEB);
++ rt2800_rfcsr_write_chanreg(rt2x00dev, 32, 0x7D);
++ rt2800_rfcsr_write_chanreg(rt2x00dev, 34, 0xD6);
++ rt2800_rfcsr_write_chanreg(rt2x00dev, 36, 0x08);
++ rt2800_rfcsr_write_chanreg(rt2x00dev, 38, 0xB4);
++ rt2800_rfcsr_write_chanreg(rt2x00dev, 43, 0xD3);
++ rt2800_rfcsr_write_chanreg(rt2x00dev, 44, 0xB3);
++ rt2800_rfcsr_write_chanreg(rt2x00dev, 45, 0xD5);
++ rt2800_rfcsr_write_chanreg(rt2x00dev, 46, 0x27);
++ rt2800_rfcsr_write_bank(rt2x00dev, 4, 47, 0x67);
++ rt2800_rfcsr_write_bank(rt2x00dev, 6, 47, 0x69);
++ rt2800_rfcsr_write_chanreg(rt2x00dev, 48, 0xFF);
++ rt2800_rfcsr_write_bank(rt2x00dev, 4, 54, 0x27);
++ rt2800_rfcsr_write_bank(rt2x00dev, 6, 54, 0x20);
++ rt2800_rfcsr_write_chanreg(rt2x00dev, 55, 0x66);
++ rt2800_rfcsr_write_chanreg(rt2x00dev, 56, 0xFF);
++ rt2800_rfcsr_write_chanreg(rt2x00dev, 57, 0x1C);
++ rt2800_rfcsr_write_chanreg(rt2x00dev, 58, 0x20);
++ rt2800_rfcsr_write_chanreg(rt2x00dev, 59, 0x6B);
++ rt2800_rfcsr_write_chanreg(rt2x00dev, 60, 0xF7);
++ rt2800_rfcsr_write_chanreg(rt2x00dev, 61, 0x09);
++ }
++
++ if (rt2800_hw_get_chipver(rt2x00dev) > 1 &&
++ rt2800_hw_get_chipeco(rt2x00dev) >= 2) {
++ rt2800_rfcsr_write_chanreg(rt2x00dev, 10, 0x51);
++ rt2800_rfcsr_write_chanreg(rt2x00dev, 14, 0x06);
++ rt2800_rfcsr_write_chanreg(rt2x00dev, 19, 0xA7);
++ rt2800_rfcsr_write_chanreg(rt2x00dev, 28, 0x2C);
++ rt2800_rfcsr_write_chanreg(rt2x00dev, 55, 0x64);
++ rt2800_rfcsr_write_chanreg(rt2x00dev, 8, 0x51);
++ rt2800_rfcsr_write_chanreg(rt2x00dev, 9, 0x36);
++ rt2800_rfcsr_write_chanreg(rt2x00dev, 11, 0x53);
++ rt2800_rfcsr_write_chanreg(rt2x00dev, 14, 0x16);
++
++ rt2800_rfcsr_write_chanreg(rt2x00dev, 47, 0x6C);
++ rt2800_rfcsr_write_chanreg(rt2x00dev, 48, 0xFC);
++ rt2800_rfcsr_write_chanreg(rt2x00dev, 49, 0x1F);
++ rt2800_rfcsr_write_chanreg(rt2x00dev, 54, 0x27);
++ rt2800_rfcsr_write_chanreg(rt2x00dev, 55, 0x66);
++ rt2800_rfcsr_write_chanreg(rt2x00dev, 59, 0x6B);
++ }
++
++ if (rt2800_hw_get_chippkg(rt2x00dev) == 0 &&
++ rt2800_hw_get_chipver(rt2x00dev) == 1) {
++ /* Initialize RF channel register for DRQFN */
++ rt2800_rfcsr_write_chanreg(rt2x00dev, 43, 0xD3);
++ rt2800_rfcsr_write_chanreg(rt2x00dev, 44, 0xE3);
++ rt2800_rfcsr_write_chanreg(rt2x00dev, 45, 0xE5);
++ rt2800_rfcsr_write_chanreg(rt2x00dev, 47, 0x28);
++ rt2800_rfcsr_write_chanreg(rt2x00dev, 55, 0x68);
++ rt2800_rfcsr_write_chanreg(rt2x00dev, 56, 0xF7);
++ rt2800_rfcsr_write_chanreg(rt2x00dev, 58, 0x02);
++ rt2800_rfcsr_write_chanreg(rt2x00dev, 60, 0xC7);
++ }
+
+ /* Initialize RF DC calibration register to default value */
+ rt2800_rfcsr_write_dccal(rt2x00dev, 0, 0x47);
+@@ -10731,12 +10802,17 @@ static void rt2800_init_rfcsr_6352(struct rt2x00_dev *rt2x00dev)
+ rt2800_rfcsr_write_dccal(rt2x00dev, 62, 0x00);
+ rt2800_rfcsr_write_dccal(rt2x00dev, 63, 0x00);
+
+- rt2800_rfcsr_write_dccal(rt2x00dev, 3, 0x08);
+- rt2800_rfcsr_write_dccal(rt2x00dev, 4, 0x04);
+- rt2800_rfcsr_write_dccal(rt2x00dev, 5, 0x20);
++ if (rt2800_hw_get_chipver(rt2x00dev) > 1) {
++ rt2800_rfcsr_write_dccal(rt2x00dev, 3, 0x08);
++ rt2800_rfcsr_write_dccal(rt2x00dev, 4, 0x04);
++ rt2800_rfcsr_write_dccal(rt2x00dev, 5, 0x20);
++ }
+
+- rt2800_rfcsr_write_dccal(rt2x00dev, 5, 0x00);
+- rt2800_rfcsr_write_dccal(rt2x00dev, 17, 0x7C);
++ if (rt2800_hw_get_chipver(rt2x00dev) > 1 &&
++ rt2800_hw_get_chipeco(rt2x00dev) >= 2) {
++ rt2800_rfcsr_write_dccal(rt2x00dev, 5, 0x00);
++ rt2800_rfcsr_write_dccal(rt2x00dev, 17, 0x7C);
++ }
+
+ /* Do calibration and init PA/LNA */
+ rt2800_calibration_rt6352(rt2x00dev);
+@@ -11282,6 +11358,17 @@ static int rt2800_init_eeprom(struct rt2x00_dev *rt2x00dev)
+ rt2800_init_led(rt2x00dev, &rt2x00dev->led_assoc, LED_TYPE_ASSOC);
+ rt2800_init_led(rt2x00dev, &rt2x00dev->led_qual, LED_TYPE_QUALITY);
+
++ {
++ struct device_node *np = rt2x00dev->dev->of_node;
++ unsigned int led_polarity;
++
++ /* Allow overriding polarity from OF */
++ if (!of_property_read_u32(np, "ralink,led-polarity",
++ &led_polarity))
++ rt2x00_set_field16(&eeprom, EEPROM_FREQ_LED_POLARITY,
++ led_polarity);
++ }
++
+ rt2x00dev->led_mcu_reg = eeprom;
+ #endif /* CPTCFG_RT2X00_LIB_LEDS */
+
+diff --git a/drivers/net/wireless/ralink/rt2x00/rt2800lib.h b/drivers/net/wireless/ralink/rt2x00/rt2800lib.h
+index 194de67..a18140c 100644
+--- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.h
++++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.h
+@@ -76,6 +76,9 @@ struct rt2800_ops {
+ int (*drv_init_registers)(struct rt2x00_dev *rt2x00dev);
+ __le32 *(*drv_get_txwi)(struct queue_entry *entry);
+ unsigned int (*drv_get_dma_done)(struct data_queue *queue);
++ int (*hw_get_chippkg)(void);
++ int (*hw_get_chipver)(void);
++ int (*hw_get_chipeco)(void);
+ };
+
+ static inline u32 rt2800_register_read(struct rt2x00_dev *rt2x00dev,
+@@ -184,6 +187,27 @@ static inline unsigned int rt2800_drv_get_dma_done(struct data_queue *queue)
+ return rt2800ops->drv_get_dma_done(queue);
+ }
+
++static inline int rt2800_hw_get_chippkg(struct rt2x00_dev *rt2x00dev)
++{
++ const struct rt2800_ops *rt2800ops = rt2x00dev->ops->drv;
++
++ return rt2800ops->hw_get_chippkg();
++}
++
++static inline int rt2800_hw_get_chipver(struct rt2x00_dev *rt2x00dev)
++{
++ const struct rt2800_ops *rt2800ops = rt2x00dev->ops->drv;
++
++ return rt2800ops->hw_get_chipver();
++}
++
++static inline int rt2800_hw_get_chipeco(struct rt2x00_dev *rt2x00dev)
++{
++ const struct rt2800_ops *rt2800ops = rt2x00dev->ops->drv;
++
++ return rt2800ops->hw_get_chipeco();
++}
++
+ void rt2800_mcu_request(struct rt2x00_dev *rt2x00dev,
+ const u8 command, const u8 token,
+ const u8 arg0, const u8 arg1);
+diff --git a/drivers/net/wireless/ralink/rt2x00/rt2800pci.c b/drivers/net/wireless/ralink/rt2x00/rt2800pci.c
+index c891043..b041952 100644
+--- a/drivers/net/wireless/ralink/rt2x00/rt2800pci.c
++++ b/drivers/net/wireless/ralink/rt2x00/rt2800pci.c
+@@ -286,6 +286,10 @@ static int rt2800pci_read_eeprom(struct rt2x00_dev *rt2x00dev)
+ return retval;
+ }
+
++static int rt2800pci_get_chippkg(void) { return 0; }
++static int rt2800pci_get_chipver(void) { return 0; }
++static int rt2800pci_get_chipeco(void) { return 0; }
++
+ static const struct ieee80211_ops rt2800pci_mac80211_ops = {
+ .add_chanctx = ieee80211_emulate_add_chanctx,
+ .remove_chanctx = ieee80211_emulate_remove_chanctx,
+@@ -333,6 +337,9 @@ static const struct rt2800_ops rt2800pci_rt2800_ops = {
+ .drv_init_registers = rt2800mmio_init_registers,
+ .drv_get_txwi = rt2800mmio_get_txwi,
+ .drv_get_dma_done = rt2800mmio_get_dma_done,
++ .hw_get_chippkg = rt2800pci_get_chippkg,
++ .hw_get_chipver = rt2800pci_get_chipver,
++ .hw_get_chipeco = rt2800pci_get_chipeco,
+ };
+
+ static const struct rt2x00lib_ops rt2800pci_rt2x00_ops = {
+diff --git a/drivers/net/wireless/ralink/rt2x00/rt2800soc.c b/drivers/net/wireless/ralink/rt2x00/rt2800soc.c
+index 787dbf0..e0d7893 100644
+--- a/drivers/net/wireless/ralink/rt2x00/rt2800soc.c
++++ b/drivers/net/wireless/ralink/rt2x00/rt2800soc.c
+@@ -27,6 +27,12 @@
+ #include "rt2800lib.h"
+ #include "rt2800mmio.h"
+
++/* Needed to probe CHIP_VER register on MT7620 */
++#ifdef CONFIG_SOC_MT7620
++#include <asm/mach-ralink/ralink_regs.h>
++#include <asm/mach-ralink/mt7620.h>
++#endif
++
+ /* Allow hardware encryption to be disabled. */
+ static bool modparam_nohwcrypt;
+ module_param_named(nohwcrypt, modparam_nohwcrypt, bool, 0444);
+@@ -90,19 +96,6 @@ static int rt2800soc_set_device_state(struct rt2x00_dev *rt2x00dev,
+ return retval;
+ }
+
+-static int rt2800soc_read_eeprom(struct rt2x00_dev *rt2x00dev)
+-{
+- void __iomem *base_addr = ioremap(0x1F040000, EEPROM_SIZE);
+-
+- if (!base_addr)
+- return -ENOMEM;
+-
+- memcpy_fromio(rt2x00dev->eeprom, base_addr, EEPROM_SIZE);
+-
+- iounmap(base_addr);
+- return 0;
+-}
+-
+ /* Firmware functions */
+ static char *rt2800soc_get_firmware_name(struct rt2x00_dev *rt2x00dev)
+ {
+@@ -131,6 +124,27 @@ static int rt2800soc_write_firmware(struct rt2x00_dev *rt2x00dev,
+ return 0;
+ }
+
++#ifdef CONFIG_SOC_MT7620
++static int rt2800soc_get_chippkg(void)
++{
++ return mt7620_get_pkg();
++}
++
++static int rt2800soc_get_chipver(void)
++{
++ return mt7620_get_chipver();
++}
++
++static int rt2800soc_get_chipeco(void)
++{
++ return mt7620_get_eco();
++}
++#else
++static int rt2800soc_get_chippkg(void) { return 0; }
++static int rt2800soc_get_chipver(void) { return 0; }
++static int rt2800soc_get_chipeco(void) { return 0; }
++#endif
++
+ static const struct ieee80211_ops rt2800soc_mac80211_ops = {
+ .add_chanctx = ieee80211_emulate_add_chanctx,
+ .remove_chanctx = ieee80211_emulate_remove_chanctx,
+@@ -172,12 +186,15 @@ static const struct rt2800_ops rt2800soc_rt2800_ops = {
+ .register_multiread = rt2x00mmio_register_multiread,
+ .register_multiwrite = rt2x00mmio_register_multiwrite,
+ .regbusy_read = rt2x00mmio_regbusy_read,
+- .read_eeprom = rt2800soc_read_eeprom,
++ .read_eeprom = rt2x00lib_read_eeprom,
+ .hwcrypt_disabled = rt2800soc_hwcrypt_disabled,
+ .drv_write_firmware = rt2800soc_write_firmware,
+ .drv_init_registers = rt2800mmio_init_registers,
+ .drv_get_txwi = rt2800mmio_get_txwi,
+ .drv_get_dma_done = rt2800mmio_get_dma_done,
++ .hw_get_chippkg = rt2800soc_get_chippkg,
++ .hw_get_chipver = rt2800soc_get_chipver,
++ .hw_get_chipeco = rt2800soc_get_chipeco,
+ };
+
+ static const struct rt2x00lib_ops rt2800soc_rt2x00_ops = {
+@@ -243,10 +260,17 @@ static int rt2800soc_probe(struct platform_device *pdev)
+ return rt2x00soc_probe(pdev, &rt2800soc_ops);
+ }
+
++static const struct of_device_id rt2880_wmac_match[] = {
++ { .compatible = "ralink,rt2880-wmac" },
++ {},
++};
++MODULE_DEVICE_TABLE(of, rt2880_wmac_match);
++
+ static struct platform_driver rt2800soc_driver = {
+ .driver = {
+ .name = "rt2800_wmac",
+ .mod_name = KBUILD_MODNAME,
++ .of_match_table = rt2880_wmac_match,
+ },
+ .probe = rt2800soc_probe,
+ .remove = rt2x00soc_remove,
+diff --git a/drivers/net/wireless/ralink/rt2x00/rt2800usb.c b/drivers/net/wireless/ralink/rt2x00/rt2800usb.c
+index a37f8ea..2663447 100644
+--- a/drivers/net/wireless/ralink/rt2x00/rt2800usb.c
++++ b/drivers/net/wireless/ralink/rt2x00/rt2800usb.c
+@@ -628,6 +628,10 @@ static int rt2800usb_probe_hw(struct rt2x00_dev *rt2x00dev)
+ return 0;
+ }
+
++static int rt2800usb_get_chippkg(void) { return 0; }
++static int rt2800usb_get_chipver(void) { return 0; }
++static int rt2800usb_get_chipeco(void) { return 0; }
++
+ static const struct ieee80211_ops rt2800usb_mac80211_ops = {
+ .add_chanctx = ieee80211_emulate_add_chanctx,
+ .remove_chanctx = ieee80211_emulate_remove_chanctx,
+@@ -676,6 +680,9 @@ static const struct rt2800_ops rt2800usb_rt2800_ops = {
+ .drv_init_registers = rt2800usb_init_registers,
+ .drv_get_txwi = rt2800usb_get_txwi,
+ .drv_get_dma_done = rt2800usb_get_dma_done,
++ .hw_get_chippkg = rt2800usb_get_chippkg,
++ .hw_get_chipver = rt2800usb_get_chipver,
++ .hw_get_chipeco = rt2800usb_get_chipeco,
+ };
+
+ static const struct rt2x00lib_ops rt2800usb_rt2x00_ops = {
+diff --git a/drivers/net/wireless/ralink/rt2x00/rt2x00.h b/drivers/net/wireless/ralink/rt2x00/rt2x00.h
+index 0ac4ae9..27d283b 100644
+--- a/drivers/net/wireless/ralink/rt2x00/rt2x00.h
++++ b/drivers/net/wireless/ralink/rt2x00/rt2x00.h
+@@ -28,6 +28,8 @@
+ #include <linux/average.h>
+ #include <linux/usb.h>
+ #include <linux/clk.h>
++#include <linux/pinctrl/consumer.h>
++#include <linux/rt2x00_platform.h>
+
+ #include <net/mac80211.h>
+
+@@ -407,6 +409,7 @@ struct hw_mode_spec {
+ unsigned int supported_bands;
+ #define SUPPORT_BAND_2GHZ 0x00000001
+ #define SUPPORT_BAND_5GHZ 0x00000002
++#define SUPPORT_BAND_BOTH (SUPPORT_BAND_2GHZ | SUPPORT_BAND_5GHZ)
+
+ unsigned int supported_rates;
+ #define SUPPORT_RATE_CCK 0x00000001
+@@ -702,6 +705,7 @@ enum rt2x00_capability_flags {
+ REQUIRE_HT_TX_DESC,
+ REQUIRE_PS_AUTOWAKE,
+ REQUIRE_DELAYED_RFKILL,
++ REQUIRE_EEPROM_FILE,
+
+ /*
+ * Capabilities
+@@ -1024,6 +1028,11 @@ struct rt2x00_dev {
+
+ /* Clock for System On Chip devices. */
+ struct clk *clk;
++
++ /* pinctrl and states for System On Chip devices with PA/LNA. */
++ struct pinctrl *pinctrl;
++ struct pinctrl_state *pins_default;
++ struct pinctrl_state *pins_pa_gpio;
+ };
+
+ struct rt2x00_bar_list_entry {
+@@ -1271,6 +1280,12 @@ rt2x00_has_cap_external_pa(struct rt2x00_dev *rt2x00dev)
+ return rt2x00_has_cap_flag(rt2x00dev, CAPABILITY_EXTERNAL_PA_TX0);
+ }
+
++static inline bool
++rt2x00_has_cap_external_pa(struct rt2x00_dev *rt2x00dev)
++{
++ return rt2x00_has_cap_flag(rt2x00dev, CAPABILITY_EXTERNAL_PA_TX0);
++}
++
+ static inline bool
+ rt2x00_has_cap_double_antenna(struct rt2x00_dev *rt2x00dev)
+ {
+diff --git a/drivers/net/wireless/ralink/rt2x00/rt2x00dev.c b/drivers/net/wireless/ralink/rt2x00/rt2x00dev.c
+index 274524e..69f8d5a 100644
+--- a/drivers/net/wireless/ralink/rt2x00/rt2x00dev.c
++++ b/drivers/net/wireless/ralink/rt2x00/rt2x00dev.c
+@@ -990,6 +990,12 @@ static void rt2x00lib_rate(struct ieee80211_rate *entry,
+
+ void rt2x00lib_set_mac_address(struct rt2x00_dev *rt2x00dev, u8 *eeprom_mac_addr)
+ {
++ struct rt2x00_platform_data *pdata;
++
++ pdata = rt2x00dev->dev->platform_data;
++ if (pdata && pdata->mac_address)
++ ether_addr_copy(eeprom_mac_addr, pdata->mac_address);
++
+ of_get_mac_address(rt2x00dev->dev->of_node, eeprom_mac_addr);
+
+ if (!is_valid_ether_addr(eeprom_mac_addr)) {
+@@ -1007,6 +1013,32 @@ static int rt2x00lib_probe_hw_modes(struct rt2x00_dev *rt2x00dev,
+ struct ieee80211_rate *rates;
+ unsigned int num_rates;
+ unsigned int i;
++#ifdef CONFIG_OF
++ struct device_node *np = rt2x00dev->dev->of_node;
++ unsigned int enabled;
++ if (!of_property_read_u32(np, "ralink,2ghz",
++ &enabled) && !enabled)
++ spec->supported_bands &= ~SUPPORT_BAND_2GHZ;
++ if (!of_property_read_u32(np, "ralink,5ghz",
++ &enabled) && !enabled)
++ spec->supported_bands &= ~SUPPORT_BAND_5GHZ;
++#endif /* CONFIG_OF */
++
++ if (rt2x00dev->dev->platform_data) {
++ struct rt2x00_platform_data *pdata;
++
++ pdata = rt2x00dev->dev->platform_data;
++ if (pdata->disable_2ghz)
++ spec->supported_bands &= ~SUPPORT_BAND_2GHZ;
++ if (pdata->disable_5ghz)
++ spec->supported_bands &= ~SUPPORT_BAND_5GHZ;
++ }
++
++ if ((spec->supported_bands & SUPPORT_BAND_BOTH) == 0) {
++ rt2x00_err(rt2x00dev, "No supported bands\n");
++ return -EINVAL;
++ }
++
+
+ num_rates = 0;
+ if (spec->supported_rates & SUPPORT_RATE_CCK)
+@@ -1330,7 +1362,7 @@ static inline void rt2x00lib_set_if_combinations(struct rt2x00_dev *rt2x00dev)
+ */
+ if_limit = &rt2x00dev->if_limits_ap;
+ if_limit->max = rt2x00dev->ops->max_ap_intf;
+- if_limit->types = BIT(NL80211_IFTYPE_AP);
++ if_limit->types = BIT(NL80211_IFTYPE_AP) | BIT(NL80211_IFTYPE_STATION);
+ #ifdef CPTCFG_MAC80211_MESH
+ if_limit->types |= BIT(NL80211_IFTYPE_MESH_POINT);
+ #endif
+diff --git a/drivers/net/wireless/ralink/rt2x00/rt2x00eeprom.c b/drivers/net/wireless/ralink/rt2x00/rt2x00eeprom.c
+new file mode 100644
+index 0000000..15c4e0b
+--- /dev/null
++++ b/drivers/net/wireless/ralink/rt2x00/rt2x00eeprom.c
+@@ -0,0 +1,208 @@
++// SPDX-License-Identifier: GPL-2.0-or-later
++/* Copyright (C) 2004 - 2009 Ivo van Doorn <IvDoorn@gmail.com>
++ * Copyright (C) 2004 - 2009 Gertjan van Wingerde <gwingerde@gmail.com>
++ * <http://rt2x00.serialmonkey.com>
++ */
++
++/* Module: rt2x00lib
++ * Abstract: rt2x00 eeprom file loading routines.
++ */
++
++#include <linux/kernel.h>
++#include <linux/module.h>
++#if IS_ENABLED(CONFIG_MTD)
++#include <linux/mtd/mtd.h>
++#include <linux/mtd/partitions.h>
++#endif
++#include <linux/nvmem-consumer.h>
++#include <linux/of.h>
++
++#include "rt2x00.h"
++#include "rt2x00soc.h"
++
++static void rt2800lib_eeprom_swap(struct rt2x00_dev *rt2x00dev)
++{
++ struct device_node *np = rt2x00dev->dev->of_node;
++ size_t len = rt2x00dev->ops->eeprom_size;
++ int i;
++
++ if (!of_find_property(np, "ralink,eeprom-swap", NULL))
++ return;
++
++ for (i = 0; i < len / sizeof(u16); i++)
++ rt2x00dev->eeprom[i] = swab16(rt2x00dev->eeprom[i]);
++}
++
++#if IS_ENABLED(CONFIG_MTD)
++static int rt2800lib_read_eeprom_mtd(struct rt2x00_dev *rt2x00dev)
++{
++ int ret = -EINVAL;
++#ifdef CONFIG_OF
++ struct device_node *np = rt2x00dev->dev->of_node, *mtd_np = NULL;
++ int size, offset = 0;
++ struct mtd_info *mtd;
++ const char *part;
++ const __be32 *list;
++ phandle phandle;
++ size_t retlen;
++
++ list = of_get_property(np, "ralink,mtd-eeprom", &size);
++ if (!list)
++ return -ENOENT;
++
++ phandle = be32_to_cpup(list++);
++ if (phandle)
++ mtd_np = of_find_node_by_phandle(phandle);
++ if (!mtd_np) {
++ dev_err(rt2x00dev->dev, "failed to load mtd phandle\n");
++ return -EINVAL;
++ }
++
++ part = of_get_property(mtd_np, "label", NULL);
++ if (!part)
++ part = mtd_np->name;
++
++ mtd = get_mtd_device_nm(part);
++ if (IS_ERR(mtd)) {
++ dev_err(rt2x00dev->dev, "failed to get mtd device \"%s\"\n", part);
++ return PTR_ERR(mtd);
++ }
++
++ if (size > sizeof(*list))
++ offset = be32_to_cpup(list);
++
++ ret = mtd_read(mtd, offset, rt2x00dev->ops->eeprom_size,
++ &retlen, (u_char *)rt2x00dev->eeprom);
++ put_mtd_device(mtd);
++
++ if (retlen != rt2x00dev->ops->eeprom_size || ret) {
++ dev_err(rt2x00dev->dev, "failed to load eeprom from device \"%s\"\n", part);
++ return ret;
++ }
++
++ rt2800lib_eeprom_swap(rt2x00dev);
++
++ dev_info(rt2x00dev->dev, "loaded eeprom from mtd device \"%s\"\n", part);
++#endif
++
++ return ret;
++}
++#endif
++
++static int rt2800lib_read_eeprom_nvmem(struct rt2x00_dev *rt2x00dev)
++{
++ struct device_node *np = rt2x00dev->dev->of_node;
++ unsigned int len = rt2x00dev->ops->eeprom_size;
++ struct nvmem_cell *cell;
++ const void *data;
++ size_t retlen;
++ int ret = 0;
++
++ cell = of_nvmem_cell_get(np, "eeprom");
++ if (IS_ERR(cell))
++ return PTR_ERR(cell);
++
++ data = nvmem_cell_read(cell, &retlen);
++ nvmem_cell_put(cell);
++
++ if (IS_ERR(data))
++ return PTR_ERR(data);
++
++ if (retlen != len) {
++ dev_err(rt2x00dev->dev, "invalid eeprom size, required: 0x%04x\n", len);
++ ret = -EINVAL;
++ goto exit;
++ }
++
++ memcpy(rt2x00dev->eeprom, data, len);
++
++ rt2800lib_eeprom_swap(rt2x00dev);
++
++exit:
++ kfree(data);
++ return ret;
++}
++
++static const char *
++rt2x00lib_get_eeprom_file_name(struct rt2x00_dev *rt2x00dev)
++{
++ struct rt2x00_platform_data *pdata = rt2x00dev->dev->platform_data;
++#ifdef CONFIG_OF
++ struct device_node *np;
++ const char *eep;
++#endif
++
++ if (pdata && pdata->eeprom_file_name)
++ return pdata->eeprom_file_name;
++
++#ifdef CONFIG_OF
++ np = rt2x00dev->dev->of_node;
++ if (np && !of_property_read_string(np, "ralink,eeprom", &eep))
++ return eep;
++#endif
++
++ return NULL;
++}
++
++static int rt2x00lib_read_eeprom_file(struct rt2x00_dev *rt2x00dev)
++{
++ const struct firmware *ee;
++ const char *ee_name;
++ int retval;
++
++ ee_name = rt2x00lib_get_eeprom_file_name(rt2x00dev);
++ if (!ee_name && test_bit(REQUIRE_EEPROM_FILE, &rt2x00dev->cap_flags)) {
++ rt2x00_err(rt2x00dev, "Required EEPROM name is missing.");
++ return -EINVAL;
++ }
++
++ if (!ee_name)
++ return 0;
++
++ rt2x00_info(rt2x00dev, "Loading EEPROM data from '%s'.\n", ee_name);
++
++ retval = request_firmware(&ee, ee_name, rt2x00dev->dev);
++ if (retval) {
++ rt2x00_err(rt2x00dev, "Failed to request EEPROM.\n");
++ return retval;
++ }
++
++ if (!ee || !ee->size || !ee->data) {
++ rt2x00_err(rt2x00dev, "Failed to read EEPROM file.\n");
++ retval = -ENOENT;
++ goto err_exit;
++ }
++
++ if (ee->size != rt2x00dev->ops->eeprom_size) {
++ rt2x00_err(rt2x00dev,
++ "EEPROM file size is invalid, it should be %d bytes\n",
++ rt2x00dev->ops->eeprom_size);
++ retval = -EINVAL;
++ goto err_release_ee;
++ }
++
++ memcpy(rt2x00dev->eeprom, ee->data, rt2x00dev->ops->eeprom_size);
++
++err_release_ee:
++ release_firmware(ee);
++err_exit:
++ return retval;
++}
++
++int rt2x00lib_read_eeprom(struct rt2x00_dev *rt2x00dev)
++{
++ int ret;
++
++#if IS_ENABLED(CONFIG_MTD)
++ ret = rt2800lib_read_eeprom_mtd(rt2x00dev);
++ if (!ret)
++ return 0;
++#endif
++
++ ret = rt2800lib_read_eeprom_nvmem(rt2x00dev);
++ if (!ret)
++ return 0;
++
++ return rt2x00lib_read_eeprom_file(rt2x00dev);
++}
++EXPORT_SYMBOL_GPL(rt2x00lib_read_eeprom);
+diff --git a/drivers/net/wireless/ralink/rt2x00/rt2x00leds.c b/drivers/net/wireless/ralink/rt2x00/rt2x00leds.c
+index f5361d5..bad5ce2 100644
+--- a/drivers/net/wireless/ralink/rt2x00/rt2x00leds.c
++++ b/drivers/net/wireless/ralink/rt2x00/rt2x00leds.c
+@@ -98,6 +98,9 @@ static int rt2x00leds_register_led(struct rt2x00_dev *rt2x00dev,
+ led->led_dev.name = name;
+ led->led_dev.brightness = LED_OFF;
+
++ if (rt2x00_is_soc(rt2x00dev))
++ led->led_dev.brightness_set(&led->led_dev, LED_OFF);
++
+ retval = led_classdev_register(device, &led->led_dev);
+ if (retval) {
+ rt2x00_err(rt2x00dev, "Failed to register led handler\n");
+diff --git a/drivers/net/wireless/ralink/rt2x00/rt2x00soc.c b/drivers/net/wireless/ralink/rt2x00/rt2x00soc.c
+index eface61..541b718 100644
+--- a/drivers/net/wireless/ralink/rt2x00/rt2x00soc.c
++++ b/drivers/net/wireless/ralink/rt2x00/rt2x00soc.c
+@@ -86,6 +86,7 @@ int rt2x00soc_probe(struct platform_device *pdev, const struct rt2x00_ops *ops)
+ if (IS_ERR(rt2x00dev->clk))
+ rt2x00dev->clk = NULL;
+
++ set_bit(REQUIRE_EEPROM_FILE, &rt2x00dev->cap_flags);
+ rt2x00_set_chip_intf(rt2x00dev, RT2X00_CHIP_INTF_SOC);
+
+ retval = rt2x00soc_alloc_reg(rt2x00dev);
+@@ -96,6 +97,21 @@ int rt2x00soc_probe(struct platform_device *pdev, const struct rt2x00_ops *ops)
+ if (retval)
+ goto exit_free_reg;
+
++ rt2x00dev->pinctrl = devm_pinctrl_get(&pdev->dev);
++ if (IS_ERR(rt2x00dev->pinctrl)) {
++ rt2x00dev->pinctrl = NULL;
++ rt2x00dev->pins_default = NULL;
++ rt2x00dev->pins_pa_gpio = NULL;
++ } else {
++ rt2x00dev->pins_default = pinctrl_lookup_state(rt2x00dev->pinctrl, "default");
++ if (IS_ERR(rt2x00dev->pins_default))
++ rt2x00dev->pins_default = NULL;
++
++ rt2x00dev->pins_pa_gpio = pinctrl_lookup_state(rt2x00dev->pinctrl, "pa_gpio");
++ if (IS_ERR(rt2x00dev->pins_pa_gpio))
++ rt2x00dev->pins_pa_gpio = NULL;
++ }
++
+ return 0;
+
+ exit_free_reg:
+diff --git a/drivers/net/wireless/ralink/rt2x00/rt2x00soc.h b/drivers/net/wireless/ralink/rt2x00/rt2x00soc.h
+index 021fd06..21cd951 100644
+--- a/drivers/net/wireless/ralink/rt2x00/rt2x00soc.h
++++ b/drivers/net/wireless/ralink/rt2x00/rt2x00soc.h
+@@ -26,4 +26,13 @@ int rt2x00soc_resume(struct platform_device *pdev);
+ #define rt2x00soc_resume NULL
+ #endif /* CONFIG_PM */
+
++/*
++ * EEPROM file handlers.
++ */
++#ifdef CPTCFG_RT2X00_LIB_EEPROM
++int rt2x00lib_read_eeprom(struct rt2x00_dev *rt2x00dev);
++#else
++#define rt2x00lib_read_eeprom NULL
++#endif /* CPTCFG_RT2X00_LIB_EEPROM */
++
+ #endif /* RT2X00SOC_H */
+diff --git a/include/linux/rt2x00_platform.h b/include/linux/rt2x00_platform.h
+new file mode 100644
+index 0000000..e10377e
+--- /dev/null
++++ b/include/linux/rt2x00_platform.h
+@@ -0,0 +1,23 @@
++/*
++ * Platform data definition for the rt2x00 driver
++ *
++ * Copyright (C) 2011 Gabor Juhos <juhosg@openwrt.org>
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published
++ * by the Free Software Foundation.
++ *
++ */
++
++#ifndef _RT2X00_PLATFORM_H
++#define _RT2X00_PLATFORM_H
++
++struct rt2x00_platform_data {
++ char *eeprom_file_name;
++ const u8 *mac_address;
++
++ int disable_2ghz;
++ int disable_5ghz;
++};
++
++#endif /* _RT2X00_PLATFORM_H */
+diff --git a/local-symbols b/local-symbols
+index 3d81ba5..beafad9 100644
+--- a/local-symbols
++++ b/local-symbols
+@@ -331,6 +331,7 @@ RT2X00_LIB_FIRMWARE=
+ RT2X00_LIB_CRYPTO=
+ RT2X00_LIB_LEDS=
+ RT2X00_LIB_DEBUGFS=
++RT2X00_LIB_EEPROM=
+ RT2X00_DEBUG=
+ WLAN_VENDOR_REALTEK=
+ RTL8180=
+--
+2.39.2
+
diff --git a/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/0007-sync-backports-patches-subsys.patch b/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/0007-sync-backports-patches-subsys.patch
new file mode 100644
index 0000000..2ab7252
--- /dev/null
+++ b/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/0007-sync-backports-patches-subsys.patch
@@ -0,0 +1,941 @@
+From 3a7f4236d9d089c749bbc4ff537f8ff2437acf2e Mon Sep 17 00:00:00 2001
+From: Shayne Chen <shayne.chen@mediatek.com>
+Date: Tue, 12 Mar 2024 11:29:55 +0800
+Subject: [PATCH 07/61] sync backports patches/subsys
+
+Signed-off-by: Shayne Chen <shayne.chen@mediatek.com>
+---
+ include/net/cfg80211.h | 28 +++++++++++
+ net/mac80211/cfg.c | 2 +
+ net/mac80211/debugfs.c | 13 +++++-
+ net/mac80211/ieee80211_i.h | 4 ++
+ net/mac80211/main.c | 19 +-------
+ net/mac80211/mesh.c | 8 +++-
+ net/mac80211/mesh.h | 31 ++++++++++--
+ net/mac80211/mesh_pathtbl.c | 19 +++++---
+ net/mac80211/rc80211_minstrel_ht.c | 75 +++++++-----------------------
+ net/mac80211/rc80211_minstrel_ht.h | 2 +-
+ net/mac80211/rx.c | 13 ++++--
+ net/mac80211/sta_info.c | 29 +++++++-----
+ net/mac80211/tx.c | 46 +++++++++---------
+ net/wireless/ap.c | 6 +--
+ net/wireless/chan.c | 45 ++++++++++++++++++
+ net/wireless/core.c | 15 ------
+ net/wireless/core.h | 2 +
+ net/wireless/mlme.c | 7 +--
+ net/wireless/sysfs.c | 27 +++++++++--
+ 19 files changed, 240 insertions(+), 151 deletions(-)
+
+diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
+index 0b5799f..4c5daf9 100644
+--- a/include/net/cfg80211.h
++++ b/include/net/cfg80211.h
+@@ -189,6 +189,8 @@ enum ieee80211_channel_flags {
+ * @dfs_state: current state of this channel. Only relevant if radar is required
+ * on this channel.
+ * @dfs_state_entered: timestamp (jiffies) when the dfs state was entered.
++ * @dfs_state_last_available: timestamp (jiffies) of the last time when the
++ * channel was available.
+ * @dfs_cac_ms: DFS CAC time in milliseconds, this is valid for DFS channels.
+ * @psd: power spectral density (in dBm)
+ */
+@@ -206,6 +208,7 @@ struct ieee80211_channel {
+ int orig_mag, orig_mpwr;
+ enum nl80211_dfs_state dfs_state;
+ unsigned long dfs_state_entered;
++ unsigned long dfs_state_last_available;
+ unsigned int dfs_cac_ms;
+ s8 psd;
+ };
+@@ -1075,6 +1078,30 @@ int cfg80211_chandef_primary(const struct cfg80211_chan_def *chandef,
+ enum nl80211_chan_width primary_chan_width,
+ u16 *punctured);
+
++/**
++ * cfg80211_chandef_dfs_usable - checks if chandef is DFS usable and we
++ * can/need start CAC on such channel
++ * @wiphy: the wiphy to validate against
++ * @chandef: the channel definition to check
++ *
++ * Return: true if all channels available and at least
++ * one channel requires CAC (NL80211_DFS_USABLE)
++ */
++bool cfg80211_chandef_dfs_usable(struct wiphy *wiphy,
++ const struct cfg80211_chan_def *chandef);
++
++/**
++ * cfg80211_chandef_dfs_cac_time - get the DFS CAC time (in ms) for given
++ * channel definition
++ * @wiphy: the wiphy to validate against
++ * @chandef: the channel definition to check
++ *
++ * Returns: DFS CAC time (in ms) which applies for this channel definition
++ */
++unsigned int
++cfg80211_chandef_dfs_cac_time(struct wiphy *wiphy,
++ const struct cfg80211_chan_def *chandef);
++
+ /**
+ * nl80211_send_chandef - sends the channel definition.
+ * @msg: the msg to send channel definition
+@@ -3413,6 +3440,7 @@ enum wiphy_params_flags {
+ /* The per TXQ device queue limit in airtime */
+ #define IEEE80211_DEFAULT_AQL_TXQ_LIMIT_L 5000
+ #define IEEE80211_DEFAULT_AQL_TXQ_LIMIT_H 12000
++#define IEEE80211_DEFAULT_AQL_TXQ_LIMIT_BC 50000
+
+ /* The per interface airtime threshold to switch to lower queue limit */
+ #define IEEE80211_AQL_THRESHOLD 24000
+diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
+index db71792..72e64be 100644
+--- a/net/mac80211/cfg.c
++++ b/net/mac80211/cfg.c
+@@ -2851,6 +2851,8 @@ static int ieee80211_scan(struct wiphy *wiphy,
+ */
+ fallthrough;
+ case NL80211_IFTYPE_AP:
++ /* skip check */
++ break;
+ /*
+ * If the scan has been forced (and the driver supports
+ * forcing), don't care about being beaconing already.
+diff --git a/net/mac80211/debugfs.c b/net/mac80211/debugfs.c
+index c660138..f9c5ed8 100644
+--- a/net/mac80211/debugfs.c
++++ b/net/mac80211/debugfs.c
+@@ -215,11 +215,13 @@ static ssize_t aql_pending_read(struct file *file,
+ "VI %u us\n"
+ "BE %u us\n"
+ "BK %u us\n"
++ "BC/MC %u us\n"
+ "total %u us\n",
+ atomic_read(&local->aql_ac_pending_airtime[IEEE80211_AC_VO]),
+ atomic_read(&local->aql_ac_pending_airtime[IEEE80211_AC_VI]),
+ atomic_read(&local->aql_ac_pending_airtime[IEEE80211_AC_BE]),
+ atomic_read(&local->aql_ac_pending_airtime[IEEE80211_AC_BK]),
++ atomic_read(&local->aql_bc_pending_airtime),
+ atomic_read(&local->aql_total_pending_airtime));
+ return simple_read_from_buffer(user_buf, count, ppos,
+ buf, len);
+@@ -245,7 +247,8 @@ static ssize_t aql_txq_limit_read(struct file *file,
+ "VO %u %u\n"
+ "VI %u %u\n"
+ "BE %u %u\n"
+- "BK %u %u\n",
++ "BK %u %u\n"
++ "BC/MC %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],
+@@ -253,7 +256,8 @@ static ssize_t aql_txq_limit_read(struct file *file,
+ 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]);
++ local->aql_txq_limit_high[IEEE80211_AC_BK],
++ local->aql_txq_limit_bc);
+ return simple_read_from_buffer(user_buf, count, ppos,
+ buf, len);
+ }
+@@ -279,6 +283,11 @@ static ssize_t aql_txq_limit_write(struct file *file,
+ else
+ buf[count] = '\0';
+
++ if (sscanf(buf, "mcast %u", &q_limit_low) == 1) {
++ local->aql_txq_limit_bc = q_limit_low;
++ return count;
++ }
++
+ if (sscanf(buf, "%u %u %u", &ac, &q_limit_low, &q_limit_high) != 3)
+ return -EINVAL;
+
+diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
+index 4827825..c5781c3 100644
+--- a/net/mac80211/ieee80211_i.h
++++ b/net/mac80211/ieee80211_i.h
+@@ -102,6 +102,8 @@ ieee80211_sta_keep_active(struct sta_info *sta, u8 ac)
+ return time_before_eq(jiffies, sta->airtime[ac].last_active + HZ / 10);
+ }
+
++#define AIRTIME_QUANTUM_SHIFT 3
++
+ struct ieee80211_bss {
+ u32 device_ts_beacon, device_ts_presp;
+
+@@ -1343,10 +1345,12 @@ struct ieee80211_local {
+ spinlock_t handle_wake_tx_queue_lock;
+
+ u16 airtime_flags;
++ u32 aql_txq_limit_bc;
+ 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;
++ atomic_t aql_bc_pending_airtime;
+ atomic_t aql_ac_pending_airtime[IEEE80211_NUM_ACS];
+
+ const struct ieee80211_ops *ops;
+diff --git a/net/mac80211/main.c b/net/mac80211/main.c
+index 6518ca5..81a9645 100644
+--- a/net/mac80211/main.c
++++ b/net/mac80211/main.c
+@@ -944,6 +944,7 @@ struct ieee80211_hw *ieee80211_alloc_hw_nm(size_t priv_data_len,
+ spin_lock_init(&local->rx_path_lock);
+ spin_lock_init(&local->queue_stop_reason_lock);
+
++ local->aql_txq_limit_bc = IEEE80211_DEFAULT_AQL_TXQ_LIMIT_BC;
+ for (i = 0; i < IEEE80211_NUM_ACS; i++) {
+ INIT_LIST_HEAD(&local->active_txqs[i]);
+ spin_lock_init(&local->active_txq_lock[i]);
+@@ -1562,24 +1563,6 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
+ debugfs_hw_add(local);
+ rate_control_add_debugfs(local);
+
+- rtnl_lock();
+- wiphy_lock(hw->wiphy);
+-
+- /* add one default STA interface if supported */
+- if (local->hw.wiphy->interface_modes & BIT(NL80211_IFTYPE_STATION) &&
+- !ieee80211_hw_check(hw, NO_AUTO_VIF)) {
+- struct vif_params params = {0};
+-
+- result = ieee80211_if_add(local, "wlan%d", NET_NAME_ENUM, NULL,
+- NL80211_IFTYPE_STATION, ¶ms);
+- if (result)
+- wiphy_warn(local->hw.wiphy,
+- "Failed to add default virtual iface\n");
+- }
+-
+- wiphy_unlock(hw->wiphy);
+- rtnl_unlock();
+-
+ #ifdef CONFIG_INET
+ local->ifa_notifier.notifier_call = ieee80211_ifa_changed;
+ result = register_inetaddr_notifier(&local->ifa_notifier);
+diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c
+index 32475da..cbc9b5e 100644
+--- a/net/mac80211/mesh.c
++++ b/net/mac80211/mesh.c
+@@ -747,6 +747,9 @@ bool ieee80211_mesh_xmit_fast(struct ieee80211_sub_if_data *sdata,
+ struct sk_buff *skb, u32 ctrl_flags)
+ {
+ struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
++ struct ieee80211_mesh_fast_tx_key key = {
++ .type = MESH_FAST_TX_TYPE_LOCAL
++ };
+ struct ieee80211_mesh_fast_tx *entry;
+ struct ieee80211s_hdr *meshhdr;
+ u8 sa[ETH_ALEN] __aligned(2);
+@@ -782,7 +785,10 @@ bool ieee80211_mesh_xmit_fast(struct ieee80211_sub_if_data *sdata,
+ return false;
+ }
+
+- entry = mesh_fast_tx_get(sdata, skb->data);
++ ether_addr_copy(key.addr, skb->data);
++ if (!ether_addr_equal(skb->data + ETH_ALEN, sdata->vif.addr))
++ key.type = MESH_FAST_TX_TYPE_PROXIED;
++ entry = mesh_fast_tx_get(sdata, &key);
+ if (!entry)
+ return false;
+
+diff --git a/net/mac80211/mesh.h b/net/mac80211/mesh.h
+index c472b49..c0c357f 100644
+--- a/net/mac80211/mesh.h
++++ b/net/mac80211/mesh.h
+@@ -134,10 +134,34 @@ struct mesh_path {
+ #define MESH_FAST_TX_CACHE_THRESHOLD_SIZE 384
+ #define MESH_FAST_TX_CACHE_TIMEOUT 8000 /* msecs */
+
++/**
++ * enum ieee80211_mesh_fast_tx_type - cached mesh fast tx entry type
++ *
++ * @MESH_FAST_TX_TYPE_LOCAL: tx from the local vif address as SA
++ * @MESH_FAST_TX_TYPE_PROXIED: local tx with a different SA (e.g. bridged)
++ * @MESH_FAST_TX_TYPE_FORWARDED: forwarded from a different mesh point
++ */
++enum ieee80211_mesh_fast_tx_type {
++ MESH_FAST_TX_TYPE_LOCAL,
++ MESH_FAST_TX_TYPE_PROXIED,
++ MESH_FAST_TX_TYPE_FORWARDED,
++};
++
++/**
++ * struct ieee80211_mesh_fast_tx_key - cached mesh fast tx entry key
++ *
++ * @addr: The Ethernet DA for this entry
++ * @type: cache entry type
++ */
++struct ieee80211_mesh_fast_tx_key {
++ u8 addr[ETH_ALEN] __aligned(2);
++ enum ieee80211_mesh_fast_tx_type type;
++};
++
+ /**
+ * struct ieee80211_mesh_fast_tx - cached mesh fast tx entry
+ * @rhash: rhashtable pointer
+- * @addr_key: The Ethernet DA which is the key for this entry
++ * @key: the lookup key for this cache entry
+ * @fast_tx: base fast_tx data
+ * @hdr: cached mesh and rfc1042 headers
+ * @hdrlen: length of mesh + rfc1042
+@@ -148,7 +172,7 @@ struct mesh_path {
+ */
+ struct ieee80211_mesh_fast_tx {
+ struct rhash_head rhash;
+- u8 addr_key[ETH_ALEN] __aligned(2);
++ struct ieee80211_mesh_fast_tx_key key;
+
+ struct ieee80211_fast_tx fast_tx;
+ u8 hdr[sizeof(struct ieee80211s_hdr) + sizeof(rfc1042_header)];
+@@ -334,7 +358,8 @@ void mesh_path_tx_root_frame(struct ieee80211_sub_if_data *sdata);
+
+ bool mesh_action_is_path_sel(struct ieee80211_mgmt *mgmt);
+ struct ieee80211_mesh_fast_tx *
+-mesh_fast_tx_get(struct ieee80211_sub_if_data *sdata, const u8 *addr);
++mesh_fast_tx_get(struct ieee80211_sub_if_data *sdata,
++ struct ieee80211_mesh_fast_tx_key *key);
+ bool ieee80211_mesh_xmit_fast(struct ieee80211_sub_if_data *sdata,
+ struct sk_buff *skb, u32 ctrl_flags);
+ void mesh_fast_tx_cache(struct ieee80211_sub_if_data *sdata,
+diff --git a/net/mac80211/mesh_pathtbl.c b/net/mac80211/mesh_pathtbl.c
+index 91b55d6..93f6a03 100644
+--- a/net/mac80211/mesh_pathtbl.c
++++ b/net/mac80211/mesh_pathtbl.c
+@@ -37,8 +37,8 @@ static const struct rhashtable_params mesh_rht_params = {
+ static const struct rhashtable_params fast_tx_rht_params = {
+ .nelem_hint = 10,
+ .automatic_shrinking = true,
+- .key_len = ETH_ALEN,
+- .key_offset = offsetof(struct ieee80211_mesh_fast_tx, addr_key),
++ .key_len = sizeof(struct ieee80211_mesh_fast_tx_key),
++ .key_offset = offsetof(struct ieee80211_mesh_fast_tx, key),
+ .head_offset = offsetof(struct ieee80211_mesh_fast_tx, rhash),
+ .hashfn = mesh_table_hash,
+ };
+@@ -431,20 +431,21 @@ static void mesh_fast_tx_entry_free(struct mesh_tx_cache *cache,
+ }
+
+ struct ieee80211_mesh_fast_tx *
+-mesh_fast_tx_get(struct ieee80211_sub_if_data *sdata, const u8 *addr)
++mesh_fast_tx_get(struct ieee80211_sub_if_data *sdata,
++ struct ieee80211_mesh_fast_tx_key *key)
+ {
+ struct ieee80211_mesh_fast_tx *entry;
+ struct mesh_tx_cache *cache;
+
+ cache = &sdata->u.mesh.tx_cache;
+- entry = rhashtable_lookup(&cache->rht, addr, fast_tx_rht_params);
++ entry = rhashtable_lookup(&cache->rht, key, fast_tx_rht_params);
+ if (!entry)
+ return NULL;
+
+ if (!(entry->mpath->flags & MESH_PATH_ACTIVE) ||
+ mpath_expired(entry->mpath)) {
+ spin_lock_bh(&cache->walk_lock);
+- entry = rhashtable_lookup(&cache->rht, addr, fast_tx_rht_params);
++ entry = rhashtable_lookup(&cache->rht, key, fast_tx_rht_params);
+ if (entry)
+ mesh_fast_tx_entry_free(cache, entry);
+ spin_unlock_bh(&cache->walk_lock);
+@@ -489,18 +490,24 @@ void mesh_fast_tx_cache(struct ieee80211_sub_if_data *sdata,
+ if (!sta)
+ return;
+
++ build.key.type = MESH_FAST_TX_TYPE_LOCAL;
+ if ((meshhdr->flags & MESH_FLAGS_AE) == MESH_FLAGS_AE_A5_A6) {
+ /* This is required to keep the mppath alive */
+ mppath = mpp_path_lookup(sdata, meshhdr->eaddr1);
+ if (!mppath)
+ return;
+ build.mppath = mppath;
++ if (!ether_addr_equal(meshhdr->eaddr2, sdata->vif.addr))
++ build.key.type = MESH_FAST_TX_TYPE_PROXIED;
+ } else if (ieee80211_has_a4(hdr->frame_control)) {
+ mppath = mpath;
+ } else {
+ return;
+ }
+
++ if (!ether_addr_equal(hdr->addr4, sdata->vif.addr))
++ build.key.type = MESH_FAST_TX_TYPE_FORWARDED;
++
+ /* rate limit, in case fast xmit can't be enabled */
+ if (mppath->fast_tx_check == jiffies)
+ return;
+@@ -547,7 +554,7 @@ void mesh_fast_tx_cache(struct ieee80211_sub_if_data *sdata,
+ }
+ }
+
+- memcpy(build.addr_key, mppath->dst, ETH_ALEN);
++ memcpy(build.key.addr, mppath->dst, ETH_ALEN);
+ build.timestamp = jiffies;
+ build.fast_tx.band = info->band;
+ build.fast_tx.da_offs = offsetof(struct ieee80211_hdr, addr3);
+diff --git a/net/mac80211/rc80211_minstrel_ht.c b/net/mac80211/rc80211_minstrel_ht.c
+index 62f323a..74413d7 100644
+--- a/net/mac80211/rc80211_minstrel_ht.c
++++ b/net/mac80211/rc80211_minstrel_ht.c
+@@ -582,6 +582,14 @@ minstrel_ht_set_best_prob_rate(struct minstrel_ht_sta *mi, u16 *dest, u16 index)
+ int cur_tp_avg, cur_group, cur_idx;
+ int max_gpr_group, max_gpr_idx;
+ int max_gpr_tp_avg, max_gpr_prob;
++ int min_dur;
++
++ min_dur = max(minstrel_get_duration(mi->max_tp_rate[0]),
++ minstrel_get_duration(mi->max_tp_rate[1]));
++
++ /* make the rate at least 18% slower than max tp rates */
++ if (minstrel_get_duration(index) <= min_dur * 19 / 16)
++ return;
+
+ cur_group = MI_RATE_GROUP(index);
+ cur_idx = MI_RATE_IDX(index);
+@@ -603,11 +611,6 @@ minstrel_ht_set_best_prob_rate(struct minstrel_ht_sta *mi, u16 *dest, u16 index)
+ !minstrel_ht_is_legacy_group(max_tp_group))
+ return;
+
+- /* skip rates faster than max tp rate with lower prob */
+- if (minstrel_get_duration(mi->max_tp_rate[0]) > minstrel_get_duration(index) &&
+- mrs->prob_avg < max_tp_prob)
+- return;
+-
+ max_gpr_group = MI_RATE_GROUP(mg->max_group_prob_rate);
+ max_gpr_idx = MI_RATE_IDX(mg->max_group_prob_rate);
+ max_gpr_prob = mi->groups[max_gpr_group].rates[max_gpr_idx].prob_avg;
+@@ -665,40 +668,6 @@ minstrel_ht_assign_best_tp_rates(struct minstrel_ht_sta *mi,
+
+ }
+
+-/*
+- * Try to increase robustness of max_prob rate by decrease number of
+- * streams if possible.
+- */
+-static inline void
+-minstrel_ht_prob_rate_reduce_streams(struct minstrel_ht_sta *mi)
+-{
+- struct minstrel_mcs_group_data *mg;
+- int tmp_max_streams, group, tmp_idx, tmp_prob;
+- int tmp_tp = 0;
+-
+- if (!mi->sta->deflink.ht_cap.ht_supported)
+- return;
+-
+- group = MI_RATE_GROUP(mi->max_tp_rate[0]);
+- tmp_max_streams = minstrel_mcs_groups[group].streams;
+- for (group = 0; group < ARRAY_SIZE(minstrel_mcs_groups); group++) {
+- mg = &mi->groups[group];
+- if (!mi->supported[group] || group == MINSTREL_CCK_GROUP)
+- continue;
+-
+- tmp_idx = MI_RATE_IDX(mg->max_group_prob_rate);
+- 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)) {
+- mi->max_prob_rate = mg->max_group_prob_rate;
+- tmp_tp = minstrel_ht_get_tp_avg(mi, group,
+- tmp_idx,
+- tmp_prob);
+- }
+- }
+-}
+-
+ static u16
+ __minstrel_ht_get_sample_rate(struct minstrel_ht_sta *mi,
+ enum minstrel_sample_type type)
+@@ -771,7 +740,8 @@ minstrel_ht_calc_rate_stats(struct minstrel_priv *mp,
+ unsigned int cur_prob;
+
+ if (unlikely(mrs->attempts > 0)) {
+- cur_prob = MINSTREL_FRAC(mrs->success, mrs->attempts);
++ cur_prob = MINSTREL_FRAC(mrs->success + mrs->last_success,
++ mrs->attempts + mrs->last_attempts);
+ minstrel_filter_avg_add(&mrs->prob_avg,
+ &mrs->prob_avg_1, cur_prob);
+ mrs->att_hist += mrs->attempts;
+@@ -1177,8 +1147,6 @@ minstrel_ht_update_stats(struct minstrel_priv *mp, struct minstrel_ht_sta *mi)
+
+ mi->max_prob_rate = tmp_max_prob_rate;
+
+- /* Try to increase robustness of max_prob_rate*/
+- minstrel_ht_prob_rate_reduce_streams(mi);
+ minstrel_ht_refill_sample_rates(mi);
+
+ #ifdef CPTCFG_MAC80211_DEBUGFS
+@@ -1257,7 +1225,7 @@ minstrel_ht_ri_txstat_valid(struct minstrel_priv *mp,
+ }
+
+ static void
+-minstrel_downgrade_rate(struct minstrel_ht_sta *mi, u16 *idx, bool primary)
++minstrel_downgrade_prob_rate(struct minstrel_ht_sta *mi, u16 *idx)
+ {
+ int group, orig_group;
+
+@@ -1272,11 +1240,7 @@ minstrel_downgrade_rate(struct minstrel_ht_sta *mi, u16 *idx, bool primary)
+ minstrel_mcs_groups[orig_group].streams)
+ continue;
+
+- if (primary)
+- *idx = mi->groups[group].max_group_tp_rate[0];
+- else
+- *idx = mi->groups[group].max_group_tp_rate[1];
+- break;
++ *idx = mi->groups[group].max_group_prob_rate;
+ }
+ }
+
+@@ -1287,7 +1251,7 @@ minstrel_ht_tx_status(void *priv, struct ieee80211_supported_band *sband,
+ struct ieee80211_tx_info *info = st->info;
+ struct minstrel_ht_sta *mi = priv_sta;
+ struct ieee80211_tx_rate *ar = info->status.rates;
+- struct minstrel_rate_stats *rate, *rate2;
++ struct minstrel_rate_stats *rate;
+ struct minstrel_priv *mp = priv;
+ u32 update_interval = mp->update_interval;
+ bool last, update = false;
+@@ -1355,18 +1319,13 @@ minstrel_ht_tx_status(void *priv, struct ieee80211_supported_band *sband,
+ /*
+ * check for sudden death of spatial multiplexing,
+ * downgrade to a lower number of streams if necessary.
++ * only do this for the max_prob_rate to prevent spurious
++ * rate fluctuations when the link changes suddenly
+ */
+- rate = minstrel_get_ratestats(mi, mi->max_tp_rate[0]);
++ rate = minstrel_get_ratestats(mi, mi->max_prob_rate);
+ if (rate->attempts > 30 &&
+ 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 &&
+- rate2->success < rate2->attempts / 4) {
+- minstrel_downgrade_rate(mi, &mi->max_tp_rate[1], false);
++ minstrel_downgrade_prob_rate(mi, &mi->max_prob_rate);
+ update = true;
+ }
+ }
+diff --git a/net/mac80211/rc80211_minstrel_ht.h b/net/mac80211/rc80211_minstrel_ht.h
+index f385cf6..1f78a94 100644
+--- a/net/mac80211/rc80211_minstrel_ht.h
++++ b/net/mac80211/rc80211_minstrel_ht.h
+@@ -14,7 +14,7 @@
+
+ /* scaled fraction values */
+ #define MINSTREL_SCALE 12
+-#define MINSTREL_FRAC(val, div) (((val) << MINSTREL_SCALE) / div)
++#define MINSTREL_FRAC(val, div) (((val) << MINSTREL_SCALE) / (div))
+ #define MINSTREL_TRUNC(val) ((val) >> MINSTREL_SCALE)
+
+ #define EWMA_LEVEL 96 /* ewma weighting factor [/EWMA_DIV] */
+diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
+index 42ffd1e..be724c2 100644
+--- a/net/mac80211/rx.c
++++ b/net/mac80211/rx.c
+@@ -2767,7 +2767,10 @@ ieee80211_rx_mesh_fast_forward(struct ieee80211_sub_if_data *sdata,
+ struct sk_buff *skb, int hdrlen)
+ {
+ struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
+- struct ieee80211_mesh_fast_tx *entry = NULL;
++ struct ieee80211_mesh_fast_tx_key key = {
++ .type = MESH_FAST_TX_TYPE_FORWARDED
++ };
++ struct ieee80211_mesh_fast_tx *entry;
+ struct ieee80211s_hdr *mesh_hdr;
+ struct tid_ampdu_tx *tid_tx;
+ struct sta_info *sta;
+@@ -2776,9 +2779,13 @@ ieee80211_rx_mesh_fast_forward(struct ieee80211_sub_if_data *sdata,
+
+ mesh_hdr = (struct ieee80211s_hdr *)(skb->data + sizeof(eth));
+ if ((mesh_hdr->flags & MESH_FLAGS_AE) == MESH_FLAGS_AE_A5_A6)
+- entry = mesh_fast_tx_get(sdata, mesh_hdr->eaddr1);
++ ether_addr_copy(key.addr, mesh_hdr->eaddr1);
+ else if (!(mesh_hdr->flags & MESH_FLAGS_AE))
+- entry = mesh_fast_tx_get(sdata, skb->data);
++ ether_addr_copy(key.addr, skb->data);
++ else
++ return false;
++
++ entry = mesh_fast_tx_get(sdata, &key);
+ if (!entry)
+ return false;
+
+diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c
+index 32d050c..411a610 100644
+--- a/net/mac80211/sta_info.c
++++ b/net/mac80211/sta_info.c
+@@ -912,6 +912,7 @@ static int sta_info_insert_finish(struct sta_info *sta) __acquires(RCU)
+
+ if (ieee80211_vif_is_mesh(&sdata->vif))
+ mesh_accept_plinks_update(sdata);
++ ieee80211_check_fast_xmit(sta);
+
+ ieee80211_check_fast_xmit(sta);
+
+@@ -2354,28 +2355,27 @@ void ieee80211_sta_update_pending_airtime(struct ieee80211_local *local,
+ struct sta_info *sta, u8 ac,
+ u16 tx_airtime, bool tx_completed)
+ {
++ atomic_t *counter;
+ 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,
+- &sta->airtime[ac].aql_tx_pending);
++ if (sta)
++ counter = &sta->airtime[ac].aql_tx_pending;
++ else
++ counter = &local->aql_bc_pending_airtime;
+
++ if (!tx_completed) {
++ atomic_add(tx_airtime, counter);
+ atomic_add(tx_airtime, &local->aql_total_pending_airtime);
+ atomic_add(tx_airtime, &local->aql_ac_pending_airtime[ac]);
+ return;
+ }
+
+- if (sta) {
+- tx_pending = atomic_sub_return(tx_airtime,
+- &sta->airtime[ac].aql_tx_pending);
+- if (tx_pending < 0)
+- atomic_cmpxchg(&sta->airtime[ac].aql_tx_pending,
+- tx_pending, 0);
+- }
++ tx_pending = atomic_sub_return(tx_airtime, counter);
++ if (tx_pending < 0)
++ atomic_cmpxchg(counter, tx_pending, 0);
+
+ atomic_sub(tx_airtime, &local->aql_total_pending_airtime);
+ tx_pending = atomic_sub_return(tx_airtime,
+@@ -2439,6 +2439,13 @@ static void sta_stats_decode_rate(struct ieee80211_local *local, u32 rate,
+
+ sband = local->hw.wiphy->bands[band];
+
++ if (!sband) {
++ wiphy_warn(local->hw.wiphy,
++ "Invalid band %d\n",
++ band);
++ break;
++ }
++
+ if (WARN_ON_ONCE(!sband->bitrates))
+ break;
+
+diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
+index 141b094..f479d87 100644
+--- a/net/mac80211/tx.c
++++ b/net/mac80211/tx.c
+@@ -3978,9 +3978,8 @@ begin:
+ encap_out:
+ info->control.vif = vif;
+
+- if (tx.sta &&
+- wiphy_ext_feature_isset(local->hw.wiphy, NL80211_EXT_FEATURE_AQL)) {
+- bool ampdu = txq->ac != IEEE80211_AC_VO;
++ if (wiphy_ext_feature_isset(local->hw.wiphy, NL80211_EXT_FEATURE_AQL)) {
++ bool ampdu = txq->sta && txq->ac != IEEE80211_AC_VO;
+ u32 airtime;
+
+ airtime = ieee80211_calc_expected_tx_airtime(hw, vif, txq->sta,
+@@ -4043,6 +4042,7 @@ struct ieee80211_txq *ieee80211_next_txq(struct ieee80211_hw *hw, u8 ac)
+ struct ieee80211_txq *ret = NULL;
+ struct txq_info *txqi = NULL, *head = NULL;
+ bool found_eligible_txq = false;
++ bool aql_check;
+
+ spin_lock_bh(&local->active_txq_lock[ac]);
+
+@@ -4066,26 +4066,26 @@ struct ieee80211_txq *ieee80211_next_txq(struct ieee80211_hw *hw, u8 ac)
+ if (!head)
+ head = txqi;
+
++ aql_check = ieee80211_txq_airtime_check(hw, &txqi->txq);
++ if (aql_check)
++ found_eligible_txq = true;
++
+ if (txqi->txq.sta) {
+ struct sta_info *sta = container_of(txqi->txq.sta,
+ struct sta_info, sta);
+- bool aql_check = ieee80211_txq_airtime_check(hw, &txqi->txq);
+- s32 deficit = ieee80211_sta_deficit(sta, txqi->txq.ac);
+-
+- if (aql_check)
+- found_eligible_txq = true;
+-
+- if (deficit < 0)
++ if (ieee80211_sta_deficit(sta, txqi->txq.ac) < 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;
++ sta->airtime_weight << AIRTIME_QUANTUM_SHIFT;
++ aql_check = false;
+ }
+ }
+
++ if (!aql_check) {
++ list_move_tail(&txqi->schedule_order,
++ &local->active_txqs[txqi->txq.ac]);
++ goto begin;
++ }
++
+ if (txqi->schedule_round == local->schedule_round[ac])
+ goto out;
+
+@@ -4150,7 +4150,8 @@ bool ieee80211_txq_airtime_check(struct ieee80211_hw *hw,
+ return true;
+
+ if (!txq->sta)
+- return true;
++ return atomic_read(&local->aql_bc_pending_airtime) <
++ local->aql_txq_limit_bc;
+
+ if (unlikely(txq->tid == IEEE80211_NUM_TIDS))
+ return true;
+@@ -4199,15 +4200,15 @@ bool ieee80211_txq_may_transmit(struct ieee80211_hw *hw,
+
+ spin_lock_bh(&local->active_txq_lock[ac]);
+
+- if (!txqi->txq.sta)
+- goto out;
+-
+ if (list_empty(&txqi->schedule_order))
+ goto out;
+
+ if (!ieee80211_txq_schedule_airtime_check(local, ac))
+ goto out;
+
++ if (!txqi->txq.sta)
++ goto out;
++
+ list_for_each_entry_safe(iter, tmp, &local->active_txqs[ac],
+ schedule_order) {
+ if (iter == txqi)
+@@ -4220,7 +4221,8 @@ bool ieee80211_txq_may_transmit(struct ieee80211_hw *hw,
+ }
+ sta = container_of(iter->txq.sta, struct sta_info, sta);
+ if (ieee80211_sta_deficit(sta, ac) < 0)
+- sta->airtime[ac].deficit += sta->airtime_weight;
++ sta->airtime[ac].deficit += sta->airtime_weight <<
++ AIRTIME_QUANTUM_SHIFT;
+ list_move_tail(&iter->schedule_order, &local->active_txqs[ac]);
+ }
+
+@@ -4228,7 +4230,7 @@ bool ieee80211_txq_may_transmit(struct ieee80211_hw *hw,
+ if (sta->airtime[ac].deficit >= 0)
+ goto out;
+
+- sta->airtime[ac].deficit += sta->airtime_weight;
++ sta->airtime[ac].deficit += sta->airtime_weight << AIRTIME_QUANTUM_SHIFT;
+ list_move_tail(&txqi->schedule_order, &local->active_txqs[ac]);
+ spin_unlock_bh(&local->active_txq_lock[ac]);
+
+diff --git a/net/wireless/ap.c b/net/wireless/ap.c
+index 9a9a870..9cd0ab4 100644
+--- a/net/wireless/ap.c
++++ b/net/wireless/ap.c
+@@ -30,6 +30,9 @@ static int ___cfg80211_stop_ap(struct cfg80211_registered_device *rdev,
+ if (!wdev->links[link_id].ap.beacon_interval)
+ return -ENOENT;
+
++ cfg80211_update_last_available(wdev->wiphy,
++ &wdev->links[link_id].ap.chandef);
++
+ err = rdev_stop_ap(rdev, dev, link_id);
+ if (!err) {
+ wdev->conn_owner_nlportid = 0;
+@@ -41,9 +44,6 @@ static int ___cfg80211_stop_ap(struct cfg80211_registered_device *rdev,
+ if (notify)
+ nl80211_send_ap_stopped(wdev, link_id);
+
+- /* Should we apply the grace period during beaconing interface
+- * shutdown also?
+- */
+ cfg80211_sched_dfs_chan_update(rdev);
+ }
+
+diff --git a/net/wireless/chan.c b/net/wireless/chan.c
+index 14c27bc..4bac395 100644
+--- a/net/wireless/chan.c
++++ b/net/wireless/chan.c
+@@ -560,6 +560,8 @@ static void cfg80211_set_chans_dfs_state(struct wiphy *wiphy, u32 center_freq,
+
+ c->dfs_state = dfs_state;
+ c->dfs_state_entered = jiffies;
++ if (dfs_state == NL80211_DFS_AVAILABLE)
++ c->dfs_state_last_available = jiffies;
+ }
+ }
+
+@@ -1049,6 +1051,49 @@ static bool cfg80211_get_chans_dfs_available(struct wiphy *wiphy,
+ return true;
+ }
+
++static void
++__cfg80211_update_last_available(struct wiphy *wiphy,
++ u32 center_freq,
++ u32 bandwidth)
++{
++ struct ieee80211_channel *c;
++ u32 freq, start_freq, end_freq;
++
++ start_freq = cfg80211_get_start_freq(center_freq, bandwidth);
++ end_freq = cfg80211_get_end_freq(center_freq, bandwidth);
++
++ /*
++ * Check entire range of channels for the bandwidth.
++ * If any channel in between is disabled or has not
++ * had gone through CAC return false
++ */
++ for (freq = start_freq; freq <= end_freq; freq += MHZ_TO_KHZ(20)) {
++ c = ieee80211_get_channel_khz(wiphy, freq);
++ if (!c)
++ return;
++
++ c->dfs_state_last_available = jiffies;
++ }
++}
++
++void cfg80211_update_last_available(struct wiphy *wiphy,
++ const struct cfg80211_chan_def *chandef)
++{
++ int width;
++
++ width = cfg80211_chandef_get_width(chandef);
++ if (width < 0)
++ return;
++
++ __cfg80211_update_last_available(wiphy, MHZ_TO_KHZ(chandef->center_freq1),
++ width);
++ if (chandef->width != NL80211_CHAN_WIDTH_80P80)
++ return;
++
++ __cfg80211_update_last_available(wiphy, MHZ_TO_KHZ(chandef->center_freq2),
++ width);
++}
++
+ static bool cfg80211_chandef_dfs_available(struct wiphy *wiphy,
+ const struct cfg80211_chan_def *chandef)
+ {
+diff --git a/net/wireless/core.c b/net/wireless/core.c
+index 0cd5c78..ac9417e 100644
+--- a/net/wireless/core.c
++++ b/net/wireless/core.c
+@@ -662,21 +662,6 @@ static int wiphy_verify_combinations(struct wiphy *wiphy)
+ c->limits[j].max > 1))
+ return -EINVAL;
+
+- /*
+- * This isn't well-defined right now. If you have an
+- * IBSS interface, then its beacon interval may change
+- * by joining other networks, and nothing prevents it
+- * from doing that.
+- * So technically we probably shouldn't even allow AP
+- * and IBSS in the same interface, but it seems that
+- * some drivers support that, possibly only with fixed
+- * beacon intervals for IBSS.
+- */
+- if (WARN_ON(types & BIT(NL80211_IFTYPE_ADHOC) &&
+- c->beacon_int_min_gcd)) {
+- return -EINVAL;
+- }
+-
+ cnt += c->limits[j].max;
+ /*
+ * Don't advertise an unsupported type
+diff --git a/net/wireless/core.h b/net/wireless/core.h
+index 2e19279..7bef6b0 100644
+--- a/net/wireless/core.h
++++ b/net/wireless/core.h
+@@ -467,6 +467,8 @@ void cfg80211_set_dfs_state(struct wiphy *wiphy,
+ enum nl80211_dfs_state dfs_state);
+
+ void cfg80211_dfs_channels_update_work(struct work_struct *work);
++void cfg80211_update_last_available(struct wiphy *wiphy,
++ const struct cfg80211_chan_def *chandef);
+
+ void cfg80211_sched_dfs_chan_update(struct cfg80211_registered_device *rdev);
+
+diff --git a/net/wireless/mlme.c b/net/wireless/mlme.c
+index 3b0fe7c..c7e62eb 100644
+--- a/net/wireless/mlme.c
++++ b/net/wireless/mlme.c
+@@ -1037,6 +1037,8 @@ void cfg80211_dfs_channels_update_work(struct work_struct *work)
+ if (c->dfs_state == NL80211_DFS_UNAVAILABLE) {
+ time_dfs_update = IEEE80211_DFS_MIN_NOP_TIME_MS;
+ radar_event = NL80211_RADAR_NOP_FINISHED;
++ timeout = c->dfs_state_entered +
++ msecs_to_jiffies(time_dfs_update);
+ } else {
+ if (regulatory_pre_cac_allowed(wiphy) ||
+ cfg80211_any_wiphy_oper_chan(wiphy, c))
+@@ -1044,11 +1046,10 @@ void cfg80211_dfs_channels_update_work(struct work_struct *work)
+
+ time_dfs_update = REG_PRE_CAC_EXPIRY_GRACE_MS;
+ radar_event = NL80211_RADAR_PRE_CAC_EXPIRED;
++ timeout = c->dfs_state_last_available +
++ msecs_to_jiffies(time_dfs_update);
+ }
+
+- timeout = c->dfs_state_entered +
+- msecs_to_jiffies(time_dfs_update);
+-
+ if (time_after_eq(jiffies, timeout)) {
+ c->dfs_state = NL80211_DFS_USABLE;
+ c->dfs_state_entered = jiffies;
+diff --git a/net/wireless/sysfs.c b/net/wireless/sysfs.c
+index 1387106..49aac4c 100644
+--- a/net/wireless/sysfs.c
++++ b/net/wireless/sysfs.c
+@@ -24,18 +24,35 @@ static inline struct cfg80211_registered_device *dev_to_rdev(
+ return container_of(dev, struct cfg80211_registered_device, wiphy.dev);
+ }
+
+-#define SHOW_FMT(name, fmt, member) \
++#define SHOW_FMT(name, fmt, member, mode) \
+ static ssize_t name ## _show(struct device *dev, \
+ struct device_attribute *attr, \
+ char *buf) \
+ { \
+ return sprintf(buf, fmt "\n", dev_to_rdev(dev)->member); \
+ } \
+-static DEVICE_ATTR_RO(name)
++static DEVICE_ATTR_##mode(name)
+
+-SHOW_FMT(index, "%d", wiphy_idx);
+-SHOW_FMT(macaddress, "%pM", wiphy.perm_addr);
+-SHOW_FMT(address_mask, "%pM", wiphy.addr_mask);
++static ssize_t macaddress_store(struct device *dev,
++ struct device_attribute *attr,
++ const char *buf, size_t len)
++{
++ u8 mac[ETH_ALEN];
++
++ if (!mac_pton(buf, mac))
++ return -EINVAL;
++
++ if (buf[3 * ETH_ALEN - 1] && buf[3 * ETH_ALEN - 1] != '\n')
++ return -EINVAL;
++
++ memcpy(dev_to_rdev(dev)->wiphy.perm_addr, mac, ETH_ALEN);
++
++ return strnlen(buf, len);
++}
++
++SHOW_FMT(index, "%d", wiphy_idx, RO);
++SHOW_FMT(macaddress, "%pM", wiphy.perm_addr, RW);
++SHOW_FMT(address_mask, "%pM", wiphy.addr_mask, RO);
+
+ static ssize_t name_show(struct device *dev,
+ struct device_attribute *attr,
+--
+2.39.2
+
diff --git a/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/mtk-0001-mtk-mac80211-do-not-setup-twt-when-twt-responder-is-.patch b/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/0008-mtk-mac80211-do-not-setup-twt-when-twt-responder-is-.patch
similarity index 68%
rename from recipes-wifi/linux-mac80211/files/patches-6.x/subsys/mtk-0001-mtk-mac80211-do-not-setup-twt-when-twt-responder-is-.patch
rename to recipes-wifi/linux-mac80211/files/patches-6.x/subsys/0008-mtk-mac80211-do-not-setup-twt-when-twt-responder-is-.patch
index a054a6b..b7d52f5 100644
--- a/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/mtk-0001-mtk-mac80211-do-not-setup-twt-when-twt-responder-is-.patch
+++ b/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/0008-mtk-mac80211-do-not-setup-twt-when-twt-responder-is-.patch
@@ -1,7 +1,7 @@
-From 45ed016428208e89e136b5af7e50bec57d63fdf6 Mon Sep 17 00:00:00 2001
+From ab5065afa6302d7241b2252a6f2ebdba8dc9763b Mon Sep 17 00:00:00 2001
From: Peter Chiu <chui-hao.chiu@mediatek.com>
Date: Tue, 18 Jan 2022 20:29:44 +0800
-Subject: [PATCH 01/37] mtk: mac80211: do not setup twt when twt responder is
+Subject: [PATCH 08/61] mtk: mac80211: do not setup twt when twt responder is
false
---
@@ -9,10 +9,10 @@
1 file changed, 3 insertions(+)
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
-index 961ef53..c23b74a 100644
+index be724c2..89a1199 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
-@@ -3422,6 +3422,9 @@ ieee80211_process_rx_twt_action(struct ieee80211_rx_data *rx)
+@@ -3458,6 +3458,9 @@ ieee80211_process_rx_twt_action(struct ieee80211_rx_data *rx)
if (sdata->vif.type != NL80211_IFTYPE_AP)
return false;
@@ -23,5 +23,5 @@
return false;
--
-2.18.0
+2.39.2
diff --git a/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/mtk-0002-mtk-cfg80211-extend-CAC-time-for-weather-radar-chann.patch b/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/0009-mtk-cfg80211-extend-CAC-time-for-weather-radar-chann.patch
similarity index 80%
rename from recipes-wifi/linux-mac80211/files/patches-6.x/subsys/mtk-0002-mtk-cfg80211-extend-CAC-time-for-weather-radar-chann.patch
rename to recipes-wifi/linux-mac80211/files/patches-6.x/subsys/0009-mtk-cfg80211-extend-CAC-time-for-weather-radar-chann.patch
index c4f3a37..d5a498d 100644
--- a/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/mtk-0002-mtk-cfg80211-extend-CAC-time-for-weather-radar-chann.patch
+++ b/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/0009-mtk-cfg80211-extend-CAC-time-for-weather-radar-chann.patch
@@ -1,7 +1,7 @@
-From 3481facddee5af51f45c35d9d9dcd2586acbab38 Mon Sep 17 00:00:00 2001
+From e27e641fd771a6d882a61a889b9295cdab5dcc72 Mon Sep 17 00:00:00 2001
From: Shayne Chen <shayne.chen@mediatek.com>
Date: Tue, 29 Mar 2022 16:06:30 +0800
-Subject: [PATCH 02/37] mtk: cfg80211: extend CAC time for weather radar
+Subject: [PATCH 09/61] mtk: cfg80211: extend CAC time for weather radar
channels
Signed-off-by: Shayne Chen <shayne.chen@mediatek.com>
@@ -13,10 +13,10 @@
3 files changed, 11 insertions(+)
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
-index 0a825af..25f15d0 100644
+index 4c5daf9..d987b62 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
-@@ -149,6 +149,7 @@ enum ieee80211_channel_flags {
+@@ -163,6 +163,7 @@ enum ieee80211_channel_flags {
(IEEE80211_CHAN_NO_HT40PLUS | IEEE80211_CHAN_NO_HT40MINUS)
#define IEEE80211_DFS_MIN_CAC_TIME_MS 60000
@@ -25,10 +25,10 @@
/**
diff --git a/net/wireless/chan.c b/net/wireless/chan.c
-index 510079f..30a2f00 100644
+index 4bac395..2224329 100644
--- a/net/wireless/chan.c
+++ b/net/wireless/chan.c
-@@ -932,6 +932,13 @@ static unsigned int cfg80211_get_chans_dfs_cac_time(struct wiphy *wiphy,
+@@ -1152,6 +1152,13 @@ static unsigned int cfg80211_get_chans_dfs_cac_time(struct wiphy *wiphy,
if (!(c->flags & IEEE80211_CHAN_RADAR))
continue;
@@ -43,10 +43,10 @@
dfs_cac_ms = c->dfs_cac_ms;
}
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
-index 193e7d6..dd76503 100644
+index 3d11013..b8c8848 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
-@@ -10011,6 +10011,9 @@ static int nl80211_start_radar_detection(struct sk_buff *skb,
+@@ -10019,6 +10019,9 @@ static int nl80211_start_radar_detection(struct sk_buff *skb,
if (WARN_ON(!cac_time_ms))
cac_time_ms = IEEE80211_DFS_MIN_CAC_TIME_MS;
@@ -57,5 +57,5 @@
if (!err) {
wdev->links[0].ap.chandef = chandef;
--
-2.18.0
+2.39.2
diff --git a/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/mtk-0003-mtk-mac80211-it-s-invalid-case-when-frag_threshold-i.patch b/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/0010-mtk-mac80211-it-s-invalid-case-when-frag_threshold-i.patch
similarity index 71%
rename from recipes-wifi/linux-mac80211/files/patches-6.x/subsys/mtk-0003-mtk-mac80211-it-s-invalid-case-when-frag_threshold-i.patch
rename to recipes-wifi/linux-mac80211/files/patches-6.x/subsys/0010-mtk-mac80211-it-s-invalid-case-when-frag_threshold-i.patch
index 381e843..1fefb28 100644
--- a/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/mtk-0003-mtk-mac80211-it-s-invalid-case-when-frag_threshold-i.patch
+++ b/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/0010-mtk-mac80211-it-s-invalid-case-when-frag_threshold-i.patch
@@ -1,7 +1,7 @@
-From 5a633b424cf49f50e211aa89712150028532407f Mon Sep 17 00:00:00 2001
+From 639c4598fd67a554c8502d113eb64ef3cf7660d4 Mon Sep 17 00:00:00 2001
From: Bo Jiao <Bo.Jiao@mediatek.com>
Date: Fri, 1 Apr 2022 09:15:21 +0800
-Subject: [PATCH 03/37] mtk: mac80211: it's invalid case when frag_threshold is
+Subject: [PATCH 10/61] mtk: mac80211: it's invalid case when frag_threshold is
greater than 2346
Signed-off-by: Bo Jiao <Bo.Jiao@mediatek.com>
@@ -10,10 +10,10 @@
1 file changed, 3 insertions(+)
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
-index dd76503..508edc1 100644
+index b8c8848..54e19b1 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
-@@ -3651,6 +3651,9 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info)
+@@ -3701,6 +3701,9 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info)
goto out;
}
@@ -24,5 +24,5 @@
/*
* Fragments (apart from the last one) are required to
--
-2.18.0
+2.39.2
diff --git a/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/mtk-0005-mtk-cfg80211-implement-DFS-status-show-cac-and-nop-s.patch b/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/0011-mtk-cfg80211-implement-DFS-status-show-cac-and-nop-s.patch
similarity index 78%
rename from recipes-wifi/linux-mac80211/files/patches-6.x/subsys/mtk-0005-mtk-cfg80211-implement-DFS-status-show-cac-and-nop-s.patch
rename to recipes-wifi/linux-mac80211/files/patches-6.x/subsys/0011-mtk-cfg80211-implement-DFS-status-show-cac-and-nop-s.patch
index 79b5cc4..5b1cb2a 100644
--- a/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/mtk-0005-mtk-cfg80211-implement-DFS-status-show-cac-and-nop-s.patch
+++ b/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/0011-mtk-cfg80211-implement-DFS-status-show-cac-and-nop-s.patch
@@ -1,55 +1,66 @@
-From 3ef5311c371391368404bbe466ff1904155dac8f Mon Sep 17 00:00:00 2001
+From 60adbabe8df3bdbab9bd3c2146f19b4c83b69def Mon Sep 17 00:00:00 2001
From: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
Date: Thu, 22 Sep 2022 14:27:41 +0800
-Subject: [PATCH 05/37] mtk: cfg80211: implement DFS status show, cac and nop
+Subject: [PATCH 11/61] mtk: cfg80211: implement DFS status show, cac and nop
skip command via debugfs
Signed-off-by: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
+
+Refactor DFS debugfs command for MLO
+
+CR-Id: WCNCR00274293
+Signed-off-by: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
+Change-Id: I5e50523684bdc5086a18d36177e0d81530ba0e3f
---
include/net/cfg80211.h | 1 +
- net/mac80211/cfg.c | 20 +++
+ net/mac80211/cfg.c | 25 +++
net/wireless/core.h | 3 +
- net/wireless/debugfs.c | 311 +++++++++++++++++++++++++++++++++++++++-
+ net/wireless/debugfs.c | 326 +++++++++++++++++++++++++++++++++++++++-
net/wireless/mlme.c | 6 +
net/wireless/rdev-ops.h | 14 ++
- net/wireless/trace.h | 12 ++
- 7 files changed, 360 insertions(+), 7 deletions(-)
+ net/wireless/trace.h | 13 ++
+ 7 files changed, 381 insertions(+), 7 deletions(-)
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
-index 5b2e242..9567c1b 100644
+index d987b62..c55028f 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
-@@ -4841,6 +4841,7 @@ struct cfg80211_ops {
- struct link_station_del_parameters *params);
- int (*set_hw_timestamp)(struct wiphy *wiphy, struct net_device *dev,
+@@ -4965,6 +4965,7 @@ struct cfg80211_ops {
struct cfg80211_set_hw_timestamp *hwts);
-+ void (*skip_cac)(struct wireless_dev *wdev);
+ int (*set_ttlm)(struct wiphy *wiphy, struct net_device *dev,
+ struct cfg80211_ttlm_params *params);
++ void (*skip_cac)(struct wireless_dev *wdev, unsigned int link_id);
};
/*
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
-index 3c07357..af284d2 100644
+index 72e64be..3f4c129 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
-@@ -5057,6 +5057,25 @@ static int ieee80211_set_hw_timestamp(struct wiphy *wiphy,
- return local->ops->set_hw_timestamp(&local->hw, &sdata->vif, hwts);
+@@ -5055,6 +5055,30 @@ ieee80211_set_ttlm(struct wiphy *wiphy, struct net_device *dev,
+ return ieee80211_req_neg_ttlm(sdata, params);
}
+static void
-+ieee80211_skip_cac(struct wireless_dev *wdev)
++ieee80211_skip_cac(struct wireless_dev *wdev, unsigned int link_id)
+{
+ struct net_device *dev = wdev->netdev;
+ struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
-+ struct cfg80211_chan_def chandef = sdata->deflink.conf->chandef;
++ struct ieee80211_link_data *link;
+ unsigned int cac_time_ms;
+
-+ cancel_delayed_work(&sdata->deflink.dfs_cac_timer_work);
++ link = sdata_dereference(sdata->link[link_id], sdata);
++ if (!link)
++ return;
++
++ wiphy_delayed_work_cancel(sdata->local->hw.wiphy,
++ &link->dfs_cac_timer_work);
+ if (wdev->cac_started) {
-+ ieee80211_link_release_channel(&sdata->deflink);
++ ieee80211_link_release_channel(link);
+ cac_time_ms = wdev->cac_time_ms;
+ wdev->cac_start_time = jiffies -
+ msecs_to_jiffies(cac_time_ms + 1);
-+ cfg80211_cac_event(wdev->netdev, &chandef,
++ cfg80211_cac_event(wdev->netdev, &link->conf->chanreq.oper,
+ NL80211_RADAR_CAC_FINISHED, GFP_KERNEL);
+ }
+}
@@ -57,14 +68,14 @@
const struct cfg80211_ops mac80211_config_ops = {
.add_virtual_intf = ieee80211_add_iface,
.del_virtual_intf = ieee80211_del_iface,
-@@ -5169,4 +5188,5 @@ const struct cfg80211_ops mac80211_config_ops = {
- .mod_link_station = ieee80211_mod_link_station,
+@@ -5168,4 +5192,5 @@ const struct cfg80211_ops mac80211_config_ops = {
.del_link_station = ieee80211_del_link_station,
.set_hw_timestamp = ieee80211_set_hw_timestamp,
+ .set_ttlm = ieee80211_set_ttlm,
+ .skip_cac = ieee80211_skip_cac,
};
diff --git a/net/wireless/core.h b/net/wireless/core.h
-index 46aa2a0..8e9a2c9 100644
+index 7bef6b0..ae6b7fa 100644
--- a/net/wireless/core.h
+++ b/net/wireless/core.h
@@ -86,6 +86,9 @@ struct cfg80211_registered_device {
@@ -78,10 +89,10 @@
struct work_struct background_cac_abort_wk;
diff --git a/net/wireless/debugfs.c b/net/wireless/debugfs.c
-index 0878b16..a228a14 100644
+index 7c59a25..a246b2c 100644
--- a/net/wireless/debugfs.c
+++ b/net/wireless/debugfs.c
-@@ -9,6 +9,7 @@
+@@ -10,6 +10,7 @@
#include <linux/slab.h>
#include "core.h"
#include "debugfs.h"
@@ -89,7 +100,7 @@
#define DEBUGFS_READONLY_FILE(name, buflen, fmt, value...) \
static ssize_t name## _read(struct file *file, char __user *userbuf, \
-@@ -96,16 +97,312 @@ static const struct file_operations ht40allow_map_ops = {
+@@ -97,18 +98,329 @@ static const struct file_operations ht40allow_map_ops = {
.llseek = default_llseek,
};
@@ -142,21 +153,34 @@
+ unsigned int buf_size, unsigned int offset)
+{
+ struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
-+ struct cfg80211_chan_def *chandef = &wdev->links[0].ap.chandef;
++ struct cfg80211_chan_def *chandef;
+ struct cfg80211_chan_def *background_chandef = &rdev->background_radar_chandef;
+ enum nl80211_band band;
+ struct ieee80211_supported_band *sband;
+ struct ieee80211_channel *chan;
+ unsigned long jiffies_passed;
++ unsigned int link_id;
+ int i, remain_time = 0, wait_time_ms = 0;
+ bool is_background;
+
-+ offset += scnprintf(buf + offset, buf_size - offset, "DFS Channel:\n");
++ for (band = 0; band < NUM_NL80211_BANDS; band++)
++ if (wiphy->bands[band] &&
++ wiphy->bands[band]->band == NL80211_BAND_5GHZ)
++ sband = wiphy->bands[band];
+
-+ for (band = 0; band < NUM_NL80211_BANDS; band++) {
-+ sband = wiphy->bands[band];
-+ if (!sband)
++ if (!sband) {
++ offset += scnprintf(buf + offset, buf_size - offset, "No 5G band\n");
++ return offset;
++ }
++
++ for_each_valid_link(wdev, link_id) {
++ chandef = wdev_chandef(wdev, link_id);
++ if (!chandef || !chandef->chan ||
++ chandef->chan->band != NL80211_BAND_5GHZ)
+ continue;
++
++ offset += scnprintf(buf + offset, buf_size - offset,
++ "Link %d DFS channel:\n", link_id);
+ for (i = 0; i < sband->n_channels; i++) {
+ is_background = false;
+ chan = &sband->channels[i];
@@ -304,33 +328,35 @@
+ struct wiphy *wiphy = data;
+ struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
+ struct wireless_dev *wdev;
-+ struct cfg80211_chan_def *chandef;
-+ unsigned int skip_mode = val;
++ struct cfg80211_chan_def *c;
++ unsigned int link_id, skip_mode = val;
+ unsigned long cac_time;
-+ struct ieee80211_channel *chan;
+
+ if (!skip_mode || skip_mode > (CAC_SKIP_MASK | CAC_SKIP_BACKGROUND_MASK))
+ return 0;
+
+ list_for_each_entry(wdev, &wiphy->wdev_list, list) {
-+ if ((skip_mode & CAC_SKIP_MASK) && wdev->links[0].ap.chandef.chan) {
-+ chandef = &wdev->links[0].ap.chandef;
-+ chan = chandef->chan;
++ if (skip_mode & CAC_SKIP_MASK) {
++ for_each_valid_link(wdev, link_id) {
++ c = wdev_chandef(wdev, link_id);
++ if (!c || !c->chan ||
++ c->chan->band != NL80211_BAND_5GHZ)
++ continue;
+
-+ if ((cfg80211_chandef_dfs_required(wiphy, chandef, wdev->iftype) > 0) &&
-+ cfg80211_chandef_dfs_usable(wiphy, chandef) && wdev->cac_started) {
-+ rdev_skip_cac(rdev, wdev);
++ if (cfg80211_chandef_dfs_required(wiphy, c, wdev->iftype) > 0 &&
++ cfg80211_chandef_dfs_usable(wiphy, c) && wdev->cac_started) {
++ rdev_skip_cac(rdev, wdev, link_id);
++ }
+ }
+ }
+
+ if ((skip_mode & CAC_SKIP_BACKGROUND_MASK) &&
+ rdev->background_radar_wdev == wdev &&
+ rdev->background_radar_chandef.chan) {
-+ chandef = &rdev->background_radar_chandef;
-+ chan = chandef->chan;
++ c = &rdev->background_radar_chandef;
+
-+ if ((cfg80211_chandef_dfs_required(wiphy, chandef, wdev->iftype) > 0) &&
-+ cfg80211_chandef_dfs_usable(wiphy, chandef) &&
++ if ((cfg80211_chandef_dfs_required(wiphy, c, wdev->iftype) > 0) &&
++ cfg80211_chandef_dfs_usable(wiphy, c) &&
+ rdev->background_cac_started) {
+ // Let current jiffies > dfs_state_entered_jiffies + CAC time
+ cac_time = rdev->background_cac_time_ms;
@@ -409,11 +435,13 @@
+ DEBUGFS_ADD(dfs_skip_cac, 0600);
+ DEBUGFS_ADD(dfs_available_reset, 0600);
}
+
+ struct debugfs_read_work {
diff --git a/net/wireless/mlme.c b/net/wireless/mlme.c
-index 3cdfbd2..70b4013 100644
+index c7e62eb..d42b65b 100644
--- a/net/wireless/mlme.c
+++ b/net/wireless/mlme.c
-@@ -1069,13 +1069,16 @@ __cfg80211_background_cac_event(struct cfg80211_registered_device *rdev,
+@@ -1177,13 +1177,16 @@ __cfg80211_background_cac_event(struct cfg80211_registered_device *rdev,
queue_work(cfg80211_wq, &rdev->propagate_cac_done_wk);
cfg80211_sched_dfs_chan_update(rdev);
wdev = rdev->background_radar_wdev;
@@ -430,7 +458,7 @@
break;
default:
return;
-@@ -1095,6 +1098,7 @@ cfg80211_background_cac_event(struct cfg80211_registered_device *rdev,
+@@ -1203,6 +1206,7 @@ cfg80211_background_cac_event(struct cfg80211_registered_device *rdev,
chandef, event);
wiphy_unlock(&rdev->wiphy);
}
@@ -438,7 +466,7 @@
void cfg80211_background_cac_done_wk(struct work_struct *work)
{
-@@ -1156,8 +1160,10 @@ cfg80211_start_background_radar_detection(struct cfg80211_registered_device *rde
+@@ -1264,8 +1268,10 @@ cfg80211_start_background_radar_detection(struct cfg80211_registered_device *rde
if (!cac_time_ms)
cac_time_ms = IEEE80211_DFS_MIN_CAC_TIME_MS;
@@ -450,51 +478,52 @@
__cfg80211_background_cac_event(rdev, wdev, chandef,
NL80211_RADAR_CAC_STARTED);
diff --git a/net/wireless/rdev-ops.h b/net/wireless/rdev-ops.h
-index 72c1282..5a4854c 100644
+index 466828f..2ae7fc5 100644
--- a/net/wireless/rdev-ops.h
+++ b/net/wireless/rdev-ops.h
-@@ -1524,4 +1524,18 @@ rdev_set_hw_timestamp(struct cfg80211_registered_device *rdev,
+@@ -1542,4 +1542,18 @@ rdev_set_ttlm(struct cfg80211_registered_device *rdev,
return ret;
}
+
+static inline int
+rdev_skip_cac(struct cfg80211_registered_device *rdev,
-+ struct wireless_dev *wdev)
++ struct wireless_dev *wdev, unsigned int link_id)
+{
+ if (!rdev->ops->skip_cac)
+ return -EOPNOTSUPP;
+
-+ trace_rdev_skip_cac(wdev);
-+ rdev->ops->skip_cac(wdev);
++ trace_rdev_skip_cac(wdev, link_id);
++ rdev->ops->skip_cac(wdev, link_id);
+ trace_rdev_return_void(&rdev->wiphy);
+
+ return 0;
+}
#endif /* __CFG80211_RDEV_OPS */
diff --git a/net/wireless/trace.h b/net/wireless/trace.h
-index fc955a9..01dcfd3 100644
+index 7073a70..aa3284f 100644
--- a/net/wireless/trace.h
+++ b/net/wireless/trace.h
-@@ -3981,6 +3981,18 @@ TRACE_EVENT(cfg80211_links_removed,
- __entry->link_mask)
+@@ -4005,6 +4005,19 @@ TRACE_EVENT(rdev_set_ttlm,
+ WIPHY_PR_ARG, NETDEV_PR_ARG)
);
+TRACE_EVENT(rdev_skip_cac,
-+ TP_PROTO(struct wireless_dev *wdev),
-+
-+ TP_ARGS(wdev),
-+
-+ TP_STRUCT__entry(WDEV_ENTRY),
-+
-+ TP_fast_assign(WDEV_ASSIGN;),
-+
-+ TP_printk(WDEV_PR_FMT, WDEV_PR_ARG)
++ TP_PROTO(struct wireless_dev *wdev, unsigned int link_id),
++ TP_ARGS(wdev, link_id),
++ TP_STRUCT__entry(
++ WDEV_ENTRY
++ __field(unsigned int, link_id)
++ ),
++ TP_fast_assign(
++ WDEV_ASSIGN;
++ __entry->link_id = link_id;
++ ),
++ TP_printk(WDEV_PR_FMT ", link_id: %d", WDEV_PR_ARG, __entry->link_id)
+);
-+
#endif /* !__RDEV_OPS_TRACE || TRACE_HEADER_MULTI_READ */
#undef TRACE_INCLUDE_PATH
--
-2.18.0
+2.39.2
diff --git a/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/mtk-0006-mtk-mac80211-Set-TWT-Information-Frame-Disabled-bit-.patch b/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/0012-mtk-mac80211-Set-TWT-Information-Frame-Disabled-bit-.patch
similarity index 75%
rename from recipes-wifi/linux-mac80211/files/patches-6.x/subsys/mtk-0006-mtk-mac80211-Set-TWT-Information-Frame-Disabled-bit-.patch
rename to recipes-wifi/linux-mac80211/files/patches-6.x/subsys/0012-mtk-mac80211-Set-TWT-Information-Frame-Disabled-bit-.patch
index 05fc4c3..ee54b68 100644
--- a/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/mtk-0006-mtk-mac80211-Set-TWT-Information-Frame-Disabled-bit-.patch
+++ b/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/0012-mtk-mac80211-Set-TWT-Information-Frame-Disabled-bit-.patch
@@ -1,7 +1,7 @@
-From a00c69d75f0ed444651391781f46351ea1417779 Mon Sep 17 00:00:00 2001
+From f3260628a2860a7af6176205fb201ffe7a5334e7 Mon Sep 17 00:00:00 2001
From: Howard Hsu <howard-yh.hsu@mediatek.com>
Date: Tue, 4 Oct 2022 10:47:05 +0800
-Subject: [PATCH 06/37] mtk: mac80211: Set TWT Information Frame Disabled bit
+Subject: [PATCH 12/61] mtk: mac80211: Set TWT Information Frame Disabled bit
as 1.
This modification means that current implementation do not support twt information frame.
@@ -10,10 +10,10 @@
1 file changed, 1 insertion(+)
diff --git a/net/mac80211/s1g.c b/net/mac80211/s1g.c
-index c1f964e..d9d84db 100644
+index d4ed0c0..27eccbb 100644
--- a/net/mac80211/s1g.c
+++ b/net/mac80211/s1g.c
-@@ -101,6 +101,7 @@ ieee80211_s1g_rx_twt_setup(struct ieee80211_sub_if_data *sdata,
+@@ -102,6 +102,7 @@ ieee80211_s1g_rx_twt_setup(struct ieee80211_sub_if_data *sdata,
struct ieee80211_twt_params *twt_agrt = (void *)twt->params;
twt_agrt->req_type &= cpu_to_le16(~IEEE80211_TWT_REQTYPE_REQUEST);
@@ -22,5 +22,5 @@
/* broadcast TWT not supported yet */
if (twt->control & IEEE80211_TWT_CONTROL_NEG_TYPE_BROADCAST) {
--
-2.18.0
+2.39.2
diff --git a/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/0013-mtk-mac80211-check-the-control-channel-before-downgr.patch b/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/0013-mtk-mac80211-check-the-control-channel-before-downgr.patch
new file mode 100644
index 0000000..4671638
--- /dev/null
+++ b/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/0013-mtk-mac80211-check-the-control-channel-before-downgr.patch
@@ -0,0 +1,55 @@
+From 32cfa2d7e115d5cdeeb130fbec61a248e9fe3676 Mon Sep 17 00:00:00 2001
+From: Evelyn Tsai <evelyn.tsai@mediatek.com>
+Date: Fri, 16 Dec 2022 03:31:06 +0800
+Subject: [PATCH 13/61] mtk: mac80211: check the control channel before
+ downgrading the bandwidth
+
+Change-Id: I25f0495818194a18e4acf23d6c45393f12e32080
+---
+ net/mac80211/mlme.c | 23 +++++++++++++++++++++++
+ 1 file changed, 23 insertions(+)
+
+diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
+index b653c7d..77e5898 100644
+--- a/net/mac80211/mlme.c
++++ b/net/mac80211/mlme.c
+@@ -4994,6 +4994,26 @@ ieee80211_determine_our_sta_mode_assoc(struct ieee80211_sub_if_data *sdata,
+ conn->bw_limit, tmp.bw_limit);
+ }
+
++static bool ieee80211_check_same_ctrl_channel(struct ieee80211_sub_if_data *sdata,
++ const struct cfg80211_chan_def *chandef)
++{
++ struct ieee80211_local *local = sdata->local;
++ struct ieee80211_chanctx *ctx;
++
++ lockdep_assert_wiphy(local->hw.wiphy);
++
++ list_for_each_entry(ctx, &local->chanctx_list, list) {
++ if (ctx->replace_state == IEEE80211_CHANCTX_WILL_BE_REPLACED)
++ continue;
++ if (ctx->mode == IEEE80211_CHANCTX_EXCLUSIVE)
++ continue;
++ if (chandef->chan == ctx->conf.def.chan)
++ return true;
++ }
++
++ return false;
++}
++
+ static int ieee80211_prep_channel(struct ieee80211_sub_if_data *sdata,
+ struct ieee80211_link_data *link,
+ int link_id,
+@@ -5073,6 +5093,9 @@ static int ieee80211_prep_channel(struct ieee80211_sub_if_data *sdata,
+ chanreq.oper.width == NL80211_CHAN_WIDTH_10)
+ return ret;
+
++ if (!ret || !ieee80211_check_same_ctrl_channel(sdata, &chanreq.oper))
++ return ret;
++
+ while (ret && chanreq.oper.width != NL80211_CHAN_WIDTH_20_NOHT) {
+ ieee80211_chanreq_downgrade(&chanreq, conn);
+
+--
+2.39.2
+
diff --git a/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/mtk-0008-mtk-mac80211-fix-tx-amsdu-aggregation.patch b/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/0014-mtk-mac80211-fix-tx-amsdu-aggregation.patch
similarity index 87%
rename from recipes-wifi/linux-mac80211/files/patches-6.x/subsys/mtk-0008-mtk-mac80211-fix-tx-amsdu-aggregation.patch
rename to recipes-wifi/linux-mac80211/files/patches-6.x/subsys/0014-mtk-mac80211-fix-tx-amsdu-aggregation.patch
index 87b4945..8c29c26 100644
--- a/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/mtk-0008-mtk-mac80211-fix-tx-amsdu-aggregation.patch
+++ b/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/0014-mtk-mac80211-fix-tx-amsdu-aggregation.patch
@@ -1,7 +1,7 @@
-From 500f2f8a8f6690f496f35da6b75ab559298f4403 Mon Sep 17 00:00:00 2001
+From ead7bd30ec2e85057d69c23429fe7cc2a184e45c Mon Sep 17 00:00:00 2001
From: TomLiu <tomml.liu@mediatek.com>
Date: Wed, 14 Dec 2022 00:26:50 -0800
-Subject: [PATCH 08/37] mtk: mac80211: fix tx amsdu aggregation
+Subject: [PATCH 14/61] mtk: mac80211: fix tx amsdu aggregation
---
include/net/mac80211.h | 7 +++++++
@@ -9,10 +9,10 @@
2 files changed, 11 insertions(+), 2 deletions(-)
diff --git a/include/net/mac80211.h b/include/net/mac80211.h
-index 4eac89a..dcff7af 100644
+index c8375b1..8cda233 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
-@@ -2924,6 +2924,13 @@ static inline void _ieee80211_hw_set(struct ieee80211_hw *hw,
+@@ -3043,6 +3043,13 @@ static inline void _ieee80211_hw_set(struct ieee80211_hw *hw,
}
#define ieee80211_hw_set(hw, flg) _ieee80211_hw_set(hw, IEEE80211_HW_##flg)
@@ -27,7 +27,7 @@
* struct ieee80211_scan_request - hw scan request
*
diff --git a/net/mac80211/agg-tx.c b/net/mac80211/agg-tx.c
-index b6b7726..80cd642 100644
+index 21d55dc..068b5b9 100644
--- a/net/mac80211/agg-tx.c
+++ b/net/mac80211/agg-tx.c
@@ -66,7 +66,8 @@ static void ieee80211_send_addba_request(struct ieee80211_sub_if_data *sdata,
@@ -51,5 +51,5 @@
capab |= u16_encode_bits(tid, IEEE80211_ADDBA_PARAM_TID_MASK);
capab |= u16_encode_bits(agg_size, IEEE80211_ADDBA_PARAM_BUF_SIZE_MASK);
--
-2.18.0
+2.39.2
diff --git a/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/mtk-0009-mtk-mac80211-add-fill-receive-path-ops-to-get-wed-id.patch b/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/0015-mtk-mac80211-add-fill-receive-path-ops-to-get-wed-id.patch
similarity index 76%
rename from recipes-wifi/linux-mac80211/files/patches-6.x/subsys/mtk-0009-mtk-mac80211-add-fill-receive-path-ops-to-get-wed-id.patch
rename to recipes-wifi/linux-mac80211/files/patches-6.x/subsys/0015-mtk-mac80211-add-fill-receive-path-ops-to-get-wed-id.patch
index 7e8993c..d02a2c0 100644
--- a/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/mtk-0009-mtk-mac80211-add-fill-receive-path-ops-to-get-wed-id.patch
+++ b/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/0015-mtk-mac80211-add-fill-receive-path-ops-to-get-wed-id.patch
@@ -1,9 +1,10 @@
-From 02ac6da3f76e0da03d30d5b7b59f24190495accd Mon Sep 17 00:00:00 2001
+From 5c16c13e56474ee77a9bd8ea59aeaeaae8923ea8 Mon Sep 17 00:00:00 2001
From: Sujuan Chen <sujuan.chen@mediatek.com>
Date: Wed, 18 May 2022 15:10:22 +0800
-Subject: [PATCH 09/37] mtk: mac80211: add fill receive path ops to get wed idx
+Subject: [PATCH 15/61] mtk: mac80211: add fill receive path ops to get wed idx
Signed-off-by: Sujuan Chen <sujuan.chen@mediatek.com>
+Change-Id: Ib3dbf4a1d960e4b0aad3ebdb1327912ae087f877
---
include/net/mac80211.h | 5 +++++
net/mac80211/driver-ops.h | 13 +++++++++++++
@@ -12,22 +13,22 @@
4 files changed, 50 insertions(+)
diff --git a/include/net/mac80211.h b/include/net/mac80211.h
-index dcff7af..65ba482 100644
+index 8cda233..01cfcc0 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
-@@ -4258,6 +4258,8 @@ struct ieee80211_prep_tx_info {
- * disable background CAC/radar detection.
- * @net_fill_forward_path: Called from .ndo_fill_forward_path in order to
+@@ -4390,6 +4390,8 @@ struct ieee80211_prep_tx_info {
* resolve a path for hardware flow offloading
+ * @can_activate_links: Checks if a specific active_links bitmap is
+ * supported by the driver.
+ * @net_fill_receive_path: Called from .ndo_fill_receive_path in order to
+ * get a path for hardware flow offloading
* @change_vif_links: Change the valid links on an interface, note that while
* removing the old link information is still valid (link_conf pointer),
* but may immediately disappear after the function returns. The old or
-@@ -4634,6 +4636,9 @@ struct ieee80211_ops {
- struct ieee80211_sta *sta,
- struct net_device_path_ctx *ctx,
- struct net_device_path *path);
+@@ -4778,6 +4780,9 @@ struct ieee80211_ops {
+ bool (*can_activate_links)(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ u16 active_links);
+ int (*net_fill_receive_path)(struct ieee80211_hw *hw,
+ struct net_device_path_ctx *ctx,
+ struct net_device_path *path);
@@ -35,10 +36,10 @@
struct ieee80211_vif *vif,
u16 old_links, u16 new_links,
diff --git a/net/mac80211/driver-ops.h b/net/mac80211/driver-ops.h
-index 7d8cec9..576f893 100644
+index 1eda9ec..9be87b8 100644
--- a/net/mac80211/driver-ops.h
+++ b/net/mac80211/driver-ops.h
-@@ -1524,6 +1524,19 @@ static inline int drv_net_fill_forward_path(struct ieee80211_local *local,
+@@ -1649,6 +1649,19 @@ static inline int drv_net_fill_forward_path(struct ieee80211_local *local,
return ret;
}
@@ -59,10 +60,10 @@
struct ieee80211_sub_if_data *sdata,
struct net_device *dev,
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c
-index 6e3bfb4..4de8d3d 100644
+index 6363e8c..0ae31a9 100644
--- a/net/mac80211/iface.c
+++ b/net/mac80211/iface.c
-@@ -930,6 +930,28 @@ out:
+@@ -988,6 +988,28 @@ out:
return ret;
}
@@ -89,21 +90,21 @@
+}
+
static const struct net_device_ops ieee80211_dataif_8023_ops = {
- .ndo_open = ieee80211_open,
- .ndo_stop = ieee80211_stop,
-@@ -939,6 +961,7 @@ static const struct net_device_ops ieee80211_dataif_8023_ops = {
- .ndo_set_mac_address = ieee80211_change_mac,
- .ndo_get_stats64 = ieee80211_get_stats64,
+ #if LINUX_VERSION_IS_LESS(4,10,0)
+ .ndo_change_mtu = __change_mtu,
+@@ -1006,6 +1028,7 @@ static const struct net_device_ops ieee80211_dataif_8023_ops = {
+ #endif
+
.ndo_fill_forward_path = ieee80211_netdev_fill_forward_path,
+ .ndo_fill_receive_path = ieee80211_netdev_fill_receive_path,
.ndo_setup_tc = ieee80211_netdev_setup_tc,
};
diff --git a/net/mac80211/util.c b/net/mac80211/util.c
-index 172173b..fd82488 100644
+index cda398d..dd06bd2 100644
--- a/net/mac80211/util.c
+++ b/net/mac80211/util.c
-@@ -868,6 +868,15 @@ struct wireless_dev *ieee80211_vif_to_wdev(struct ieee80211_vif *vif)
+@@ -874,6 +874,15 @@ struct wireless_dev *ieee80211_vif_to_wdev(struct ieee80211_vif *vif)
}
EXPORT_SYMBOL_GPL(ieee80211_vif_to_wdev);
@@ -120,5 +121,5 @@
* Nothing should have been stuffed into the workqueue during
* the suspend->resume cycle. Since we can't check each caller
--
-2.18.0
+2.39.2
diff --git a/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/mtk-0011-mtk-mac80211-track-obss-color-bitmap.patch b/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/0016-mtk-mac80211-track-obss-color-bitmap.patch
similarity index 73%
rename from recipes-wifi/linux-mac80211/files/patches-6.x/subsys/mtk-0011-mtk-mac80211-track-obss-color-bitmap.patch
rename to recipes-wifi/linux-mac80211/files/patches-6.x/subsys/0016-mtk-mac80211-track-obss-color-bitmap.patch
index 89bb49e..dbbfb55 100644
--- a/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/mtk-0011-mtk-mac80211-track-obss-color-bitmap.patch
+++ b/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/0016-mtk-mac80211-track-obss-color-bitmap.patch
@@ -1,24 +1,26 @@
-From c4919b0d1dd5c92c081852be3ef37511f0406475 Mon Sep 17 00:00:00 2001
+From 71be2e718dc884fb35433338dc21d6547b237819 Mon Sep 17 00:00:00 2001
From: Yi-Chia Hsieh <yi-chia.hsieh@mediatek.com>
Date: Mon, 13 Mar 2023 05:23:37 +0800
-Subject: [PATCH 11/37] mtk: mac80211: track obss color bitmap
+Subject: [PATCH 16/61] mtk: mac80211: track obss color bitmap
Track OBSS BSS color when receive their beacon.
Adding 2 tracepoint for debug, usage:
echo 1 > /sys/kernel/debug/tracing/events/mac80211/bss_color_bitmap/enable
echo 1 > /sys/kernel/debug/tracing/events/mac80211/bss_color_collision/enable
+
+Change-Id: I24ebcc3181c05476b41107ce8fe7f3d4c8907e81
---
include/net/mac80211.h | 1 +
net/mac80211/rx.c | 6 +++++-
- net/mac80211/trace.h | 21 +++++++++++++++++++++
- 3 files changed, 27 insertions(+), 1 deletion(-)
+ net/mac80211/trace.h | 22 ++++++++++++++++++++++
+ 3 files changed, 28 insertions(+), 1 deletion(-)
diff --git a/include/net/mac80211.h b/include/net/mac80211.h
-index 65ba482..1a13d47 100644
+index 01cfcc0..965a026 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
-@@ -744,6 +744,7 @@ struct ieee80211_bss_conf {
+@@ -762,6 +762,7 @@ struct ieee80211_bss_conf {
} he_oper;
struct ieee80211_he_obss_pd he_obss_pd;
struct cfg80211_he_bss_color he_bss_color;
@@ -27,10 +29,10 @@
u32 unsol_bcast_probe_resp_interval;
struct cfg80211_bitrate_mask beacon_tx_rate;
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
-index c23b74a..2df16de 100644
+index 89a1199..65982a6 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
-@@ -3355,9 +3355,13 @@ ieee80211_rx_check_bss_color_collision(struct ieee80211_rx_data *rx)
+@@ -3395,9 +3395,13 @@ ieee80211_rx_check_bss_color_collision(struct ieee80211_rx_data *rx)
color = le32_get_bits(he_oper->he_oper_params,
IEEE80211_HE_OPERATION_BSS_COLOR_MASK);
@@ -40,19 +42,20 @@
+ // trace_bss_color_bitmap(color, bss_conf->used_color_bitmap);
if (color == bss_conf->he_bss_color.color)
ieee80211_obss_color_collision_notify(&rx->sdata->vif,
-- BIT_ULL(color),
-+ bss_conf->used_color_bitmap,
- GFP_ATOMIC);
+- BIT_ULL(color));
++ bss_conf->used_color_bitmap);
}
}
+
diff --git a/net/mac80211/trace.h b/net/mac80211/trace.h
-index b8c53b4..814aed6 100644
+index 8e758b5..9ec45ce 100644
--- a/net/mac80211/trace.h
+++ b/net/mac80211/trace.h
-@@ -3060,6 +3060,27 @@ TRACE_EVENT(stop_queue,
+@@ -3145,6 +3145,28 @@ TRACE_EVENT(drv_neg_ttlm_res,
+ LOCAL_PR_ARG, VIF_PR_ARG, __entry->res
)
);
-
++
+TRACE_EVENT(bss_color_bitmap,
+ TP_PROTO(u8 color,
+ u64 color_bitmap),
@@ -78,5 +81,5 @@
#undef TRACE_INCLUDE_PATH
--
-2.18.0
+2.39.2
diff --git a/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/mtk-0013-mtk-mac80211-update-max_bssid_indicator-based-on-rea.patch b/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/0017-mtk-mac80211-update-max_bssid_indicator-based-on-rea.patch
similarity index 65%
rename from recipes-wifi/linux-mac80211/files/patches-6.x/subsys/mtk-0013-mtk-mac80211-update-max_bssid_indicator-based-on-rea.patch
rename to recipes-wifi/linux-mac80211/files/patches-6.x/subsys/0017-mtk-mac80211-update-max_bssid_indicator-based-on-rea.patch
index 3f0264a..31e8a28 100644
--- a/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/mtk-0013-mtk-mac80211-update-max_bssid_indicator-based-on-rea.patch
+++ b/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/0017-mtk-mac80211-update-max_bssid_indicator-based-on-rea.patch
@@ -1,18 +1,22 @@
-From 27ea38045f6ef4a8296d8e019114aa1508e3ad9f Mon Sep 17 00:00:00 2001
-From: Evelyn Tsai <evelyn.tsai@mediatek.com>
+From cd9eddae9afaece218189e1d3ccaffe256b3ccc8 Mon Sep 17 00:00:00 2001
+From: "Allen.Ye" <allen.ye@mediatek.com>
Date: Fri, 14 Apr 2023 05:05:17 +0800
-Subject: [PATCH 13/37] mtk: mac80211: update max_bssid_indicator based on real
+Subject: [PATCH 17/61] mtk: mac80211: update max_bssid_indicator based on real
BSS numbers
+Fix max_bssid_indicator get empty value due to wrong pointer.
+
+CR-Id: WCNCR00259302
+Change-Id: I2a9bcd96e9432569a9968ba9e519c55ebe13cdfe
---
net/mac80211/cfg.c | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
-index de3d181..9b9be1a 100644
+index 3f4c129..cb91223 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
-@@ -1186,9 +1186,11 @@ ieee80211_assign_beacon(struct ieee80211_sub_if_data *sdata,
+@@ -1167,9 +1167,11 @@ ieee80211_assign_beacon(struct ieee80211_sub_if_data *sdata,
/* copy in optional mbssid_ies */
if (mbssid) {
u8 *pos = new->tail + new->tail_len;
@@ -24,7 +28,7 @@
pos += ieee80211_copy_mbssid_beacon(pos, new->mbssid_ies,
mbssid);
if (rnr) {
-@@ -1197,8 +1199,7 @@ ieee80211_assign_beacon(struct ieee80211_sub_if_data *sdata,
+@@ -1178,8 +1180,7 @@ ieee80211_assign_beacon(struct ieee80211_sub_if_data *sdata,
ieee80211_copy_rnr_beacon(pos, new->rnr_ies, rnr);
}
/* update bssid_indicator */
@@ -35,5 +39,5 @@
if (csa) {
--
-2.18.0
+2.39.2
diff --git a/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/mtk-0014-mtk-mac80211-support-configurable-addba-resp-time.patch b/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/0018-mtk-mac80211-support-configurable-addba-resp-time.patch
similarity index 84%
rename from recipes-wifi/linux-mac80211/files/patches-6.x/subsys/mtk-0014-mtk-mac80211-support-configurable-addba-resp-time.patch
rename to recipes-wifi/linux-mac80211/files/patches-6.x/subsys/0018-mtk-mac80211-support-configurable-addba-resp-time.patch
index 3b04947..a4b0d15 100644
--- a/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/mtk-0014-mtk-mac80211-support-configurable-addba-resp-time.patch
+++ b/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/0018-mtk-mac80211-support-configurable-addba-resp-time.patch
@@ -1,14 +1,14 @@
-From 9b75b1851bdef31b88ebdce320c65e41cc12b7aa Mon Sep 17 00:00:00 2001
+From cc6fe6fd359d941ccd376aa6f185eaeb0020fb04 Mon Sep 17 00:00:00 2001
From: Lian Chen <lian.chen@mediatek.com>
Date: Wed, 7 Jun 2023 15:30:34 +0800
-Subject: [PATCH 14/37] mtk: mac80211: support configurable addba resp time.
+Subject: [PATCH 18/61] mtk: mac80211: support configurable addba resp time.
---
net/mac80211/agg-tx.c | 8 +++++++-
1 file changed, 7 insertions(+), 1 deletion(-)
diff --git a/net/mac80211/agg-tx.c b/net/mac80211/agg-tx.c
-index 80cd642..7f66e69 100644
+index 068b5b9..af3d8e6 100644
--- a/net/mac80211/agg-tx.c
+++ b/net/mac80211/agg-tx.c
@@ -16,10 +16,16 @@
@@ -29,7 +29,7 @@
* DOC: TX A-MPDU aggregation
*
@@ -466,7 +472,7 @@ static void ieee80211_send_addba_with_timeout(struct sta_info *sta,
- lockdep_assert_held(&sta->ampdu_mlme.mtx);
+ lockdep_assert_wiphy(sta->local->hw.wiphy);
/* activate the timer for the recipient's addBA response */
- mod_timer(&tid_tx->addba_resp_timer, jiffies + ADDBA_RESP_INTERVAL);
@@ -38,5 +38,5 @@
sta->sta.addr, tid);
--
-2.18.0
+2.39.2
diff --git a/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/mtk-0015-mtk-mac80211-add-sta-assisted-DFS-state-update-mecha.patch b/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/0019-mtk-mac80211-add-sta-assisted-DFS-state-update-mecha.patch
similarity index 73%
rename from recipes-wifi/linux-mac80211/files/patches-6.x/subsys/mtk-0015-mtk-mac80211-add-sta-assisted-DFS-state-update-mecha.patch
rename to recipes-wifi/linux-mac80211/files/patches-6.x/subsys/0019-mtk-mac80211-add-sta-assisted-DFS-state-update-mecha.patch
index 6fc06d2..244689c 100644
--- a/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/mtk-0015-mtk-mac80211-add-sta-assisted-DFS-state-update-mecha.patch
+++ b/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/0019-mtk-mac80211-add-sta-assisted-DFS-state-update-mecha.patch
@@ -1,22 +1,23 @@
-From c30a607cc3e06ced08c3b93f13706fb158a4d137 Mon Sep 17 00:00:00 2001
+From 103b24de6741cb11d088e6e2be478c7839d32ec4 Mon Sep 17 00:00:00 2001
From: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
Date: Mon, 20 Feb 2023 14:25:24 +0800
-Subject: [PATCH 15/37] mtk: mac80211: add sta-assisted DFS state update
+Subject: [PATCH 19/61] mtk: mac80211: add sta-assisted DFS state update
mechanism
Signed-off-by: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
+Change-Id: Ida821ebb42825cd1895eaccfbbfda1106e598009
---
include/net/cfg80211.h | 14 +++++++++
include/uapi/linux/nl80211.h | 6 ++++
- net/mac80211/mlme.c | 12 ++++++++
- net/wireless/chan.c | 60 ++++++++++++++++++++++++++++++++++++
- 4 files changed, 92 insertions(+)
+ net/mac80211/mlme.c | 14 +++++++++
+ net/wireless/chan.c | 61 ++++++++++++++++++++++++++++++++++++
+ 4 files changed, 95 insertions(+)
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
-index 9567c1b..0b5a4e6 100644
+index c55028f..19cf7f7 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
-@@ -8526,6 +8526,20 @@ void cfg80211_cac_event(struct net_device *netdev,
+@@ -8679,6 +8679,20 @@ void cfg80211_cac_event(struct net_device *netdev,
const struct cfg80211_chan_def *chandef,
enum nl80211_radar_event event, gfp_t gfp);
@@ -38,10 +39,10 @@
* cfg80211_background_cac_abort - Channel Availability Check offchan abort event
* @wiphy: the wiphy
diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h
-index 72ef4d9..60c6f79 100644
+index f917bc6..7999a65 100644
--- a/include/uapi/linux/nl80211.h
+++ b/include/uapi/linux/nl80211.h
-@@ -6671,6 +6671,10 @@ enum nl80211_smps_mode {
+@@ -6822,6 +6822,10 @@ enum nl80211_smps_mode {
* applicable for ETSI dfs domain where pre-CAC is valid for ever.
* @NL80211_RADAR_CAC_STARTED: Channel Availability Check has been started,
* should be generated by HW if NL80211_EXT_FEATURE_DFS_OFFLOAD is enabled.
@@ -52,7 +53,7 @@
*/
enum nl80211_radar_event {
NL80211_RADAR_DETECTED,
-@@ -6679,6 +6683,8 @@ enum nl80211_radar_event {
+@@ -6830,6 +6834,8 @@ enum nl80211_radar_event {
NL80211_RADAR_NOP_FINISHED,
NL80211_RADAR_PRE_CAC_EXPIRED,
NL80211_RADAR_CAC_STARTED,
@@ -62,44 +63,46 @@
/**
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
-index 24d34d4..6077e89 100644
+index 77e5898..52d1cd8 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
-@@ -1981,6 +1981,11 @@ ieee80211_sta_process_chanswitch(struct ieee80211_link_data *link,
- IEEE80211_QUEUE_STOP_REASON_CSA);
- mutex_unlock(&local->mtx);
+@@ -2170,6 +2170,11 @@ ieee80211_sta_process_chanswitch(struct ieee80211_link_data *link,
+ sdata->csa_blocked_tx = true;
+ }
+ cfg80211_sta_update_dfs_state(&sdata->wdev,
-+ &sdata->vif.bss_conf.chandef,
-+ &link->csa_chandef,
++ &link->conf->chanreq.oper,
++ &link->csa_chanreq.oper,
+ sdata->vif.cfg.assoc);
+
- cfg80211_ch_switch_started_notify(sdata->dev, &csa_ie.chandef,
+ cfg80211_ch_switch_started_notify(sdata->dev, &csa_ie.chanreq.oper,
link->link_id, csa_ie.count,
- csa_ie.mode, 0);
-@@ -3066,6 +3071,10 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata,
- sizeof(sdata->vif.bss_conf.tx_pwr_env));
-
- ieee80211_vif_set_links(sdata, 0, 0);
+ csa_ie.mode);
+@@ -3245,6 +3250,10 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata,
+ link = sdata_dereference(sdata->link[link_id], sdata);
+ if (!link)
+ continue;
+
-+ cfg80211_sta_update_dfs_state(&sdata->wdev,
-+ &sdata->vif.bss_conf.chandef,
-+ NULL, sdata->vif.cfg.assoc);
- }
-
- static void ieee80211_reset_ap_probe(struct ieee80211_sub_if_data *sdata)
-@@ -5469,6 +5478,9 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata,
- event.u.mlme.status = MLME_SUCCESS;
- drv_event_callback(sdata->local, sdata, &event);
- sdata_info(sdata, "associated\n");
+ cfg80211_sta_update_dfs_state(&sdata->wdev,
-+ &sdata->vif.bss_conf.chandef,
++ &link->conf->chanreq.oper,
+ NULL, sdata->vif.cfg.assoc);
+ ieee80211_link_release_channel(link);
+ }
- info.success = 1;
+@@ -5512,6 +5521,11 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata,
+ for (ac = 0; ac < IEEE80211_NUM_ACS; ac++)
+ if (link->tx_conf[ac].uapsd)
+ resp.uapsd_queues |= ieee80211_ac_to_qos_mask[ac];
++
++ if (status_code == WLAN_STATUS_SUCCESS)
++ cfg80211_sta_update_dfs_state(&sdata->wdev,
++ &link->conf->chanreq.oper,
++ NULL, sdata->vif.cfg.assoc);
}
+
+ if (ieee80211_vif_is_mld(&sdata->vif)) {
diff --git a/net/wireless/chan.c b/net/wireless/chan.c
-index 30a2f00..41644e2 100644
+index 2224329..c851db8 100644
--- a/net/wireless/chan.c
+++ b/net/wireless/chan.c
@@ -14,6 +14,7 @@
@@ -110,7 +113,7 @@
static bool cfg80211_valid_60g_freq(u32 freq)
{
-@@ -1438,6 +1439,65 @@ bool cfg80211_any_usable_channels(struct wiphy *wiphy,
+@@ -1671,6 +1672,66 @@ bool cfg80211_any_usable_channels(struct wiphy *wiphy,
}
EXPORT_SYMBOL(cfg80211_any_usable_channels);
@@ -138,7 +141,8 @@
+ enum nl80211_dfs_state dfs_state = NL80211_DFS_USABLE;
+ enum nl80211_radar_event event = NL80211_RADAR_STA_CAC_EXPIRED;
+
-+ if (!bss_chandef)
++ if (!bss_chandef || !bss_chandef->chan ||
++ bss_chandef->chan->band != NL80211_BAND_5GHZ)
+ return;
+
+ /* assume csa channel is cac completed */
@@ -177,5 +181,5 @@
unsigned int link_id)
{
--
-2.18.0
+2.39.2
diff --git a/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/mtk-0016-mtk-nl80211-Mark-DFS-channel-as-available-for-CSA.patch b/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/0020-mtk-nl80211-Mark-DFS-channel-as-available-for-CSA.patch
similarity index 76%
rename from recipes-wifi/linux-mac80211/files/patches-6.x/subsys/mtk-0016-mtk-nl80211-Mark-DFS-channel-as-available-for-CSA.patch
rename to recipes-wifi/linux-mac80211/files/patches-6.x/subsys/0020-mtk-nl80211-Mark-DFS-channel-as-available-for-CSA.patch
index e216b2d..1810958 100644
--- a/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/mtk-0016-mtk-nl80211-Mark-DFS-channel-as-available-for-CSA.patch
+++ b/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/0020-mtk-nl80211-Mark-DFS-channel-as-available-for-CSA.patch
@@ -1,17 +1,17 @@
-From e915ce4271b5d63fb7018295f0bd853e38b198c0 Mon Sep 17 00:00:00 2001
+From 0be90bf2df2df04a24a376f1aab1078874a7d5cc Mon Sep 17 00:00:00 2001
From: "himanshu.goyal" <himanshu.goyal@mediatek.com>
Date: Fri, 17 Mar 2023 17:36:01 +0800
-Subject: [PATCH 16/37] mtk: nl80211: Mark DFS channel as available for CSA.
+Subject: [PATCH 20/61] mtk: nl80211: Mark DFS channel as available for CSA.
---
net/wireless/nl80211.c | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
-index c652a01..3046677 100644
+index 54e19b1..7085133 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
-@@ -10269,6 +10269,11 @@ skip_beacons:
+@@ -10247,6 +10247,11 @@ skip_beacons:
if (err)
goto free;
@@ -24,5 +24,5 @@
wdev->iftype)) {
err = -EINVAL;
--
-2.18.0
+2.39.2
diff --git a/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/mtk-0017-mtk-cfg80211-fix-early-return-in-cfg80211_stop_backg.patch b/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/0021-mtk-cfg80211-fix-early-return-in-cfg80211_stop_backg.patch
similarity index 77%
rename from recipes-wifi/linux-mac80211/files/patches-6.x/subsys/mtk-0017-mtk-cfg80211-fix-early-return-in-cfg80211_stop_backg.patch
rename to recipes-wifi/linux-mac80211/files/patches-6.x/subsys/0021-mtk-cfg80211-fix-early-return-in-cfg80211_stop_backg.patch
index f607975..acb1a8a 100644
--- a/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/mtk-0017-mtk-cfg80211-fix-early-return-in-cfg80211_stop_backg.patch
+++ b/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/0021-mtk-cfg80211-fix-early-return-in-cfg80211_stop_backg.patch
@@ -1,7 +1,7 @@
-From e95e57878ced57d49e5aefe777f8922761d2f8f1 Mon Sep 17 00:00:00 2001
+From 5f16034ca52f980a612f1fddb4d730480d12decd Mon Sep 17 00:00:00 2001
From: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
Date: Thu, 27 Jul 2023 10:25:59 +0800
-Subject: [PATCH 17/37] mtk: cfg80211: fix early return in
+Subject: [PATCH 21/61] mtk: cfg80211: fix early return in
cfg80211_stop_background_radar_detection
Signed-off-by: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
@@ -10,10 +10,10 @@
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/net/wireless/mlme.c b/net/wireless/mlme.c
-index 70b4013..e264609 100644
+index d42b65b..56095b3 100644
--- a/net/wireless/mlme.c
+++ b/net/wireless/mlme.c
-@@ -1184,9 +1184,9 @@ void cfg80211_stop_background_radar_detection(struct wireless_dev *wdev)
+@@ -1292,9 +1292,9 @@ void cfg80211_stop_background_radar_detection(struct wireless_dev *wdev)
return;
rdev_set_radar_background(rdev, NULL);
@@ -25,5 +25,5 @@
+ rdev->background_radar_wdev = NULL; /* Release offchain ownership */
}
--
-2.18.0
+2.39.2
diff --git a/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/mtk-0018-mtk-cfg80211-add-background-radar-stop-when-backgrou.patch b/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/0022-mtk-cfg80211-add-background-radar-stop-when-backgrou.patch
similarity index 77%
rename from recipes-wifi/linux-mac80211/files/patches-6.x/subsys/mtk-0018-mtk-cfg80211-add-background-radar-stop-when-backgrou.patch
rename to recipes-wifi/linux-mac80211/files/patches-6.x/subsys/0022-mtk-cfg80211-add-background-radar-stop-when-backgrou.patch
index b4d9669..c8c5f69 100644
--- a/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/mtk-0018-mtk-cfg80211-add-background-radar-stop-when-backgrou.patch
+++ b/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/0022-mtk-cfg80211-add-background-radar-stop-when-backgrou.patch
@@ -1,7 +1,7 @@
-From 7aa02107ca82d71f0a6f2d892bbf72b76fe8d2d0 Mon Sep 17 00:00:00 2001
+From b4960511afc66cff070b19204da6e8cc54cf9630 Mon Sep 17 00:00:00 2001
From: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
Date: Thu, 27 Jul 2023 10:27:04 +0800
-Subject: [PATCH 18/37] mtk: cfg80211: add background radar stop when
+Subject: [PATCH 22/61] mtk: cfg80211: add background radar stop when
background channel is overlapped with operating channel
Signed-off-by: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
@@ -10,10 +10,10 @@
1 file changed, 4 insertions(+)
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
-index 3046677..2be678c 100644
+index 7085133..1f1856b 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
-@@ -10040,6 +10040,10 @@ static int nl80211_start_radar_detection(struct sk_buff *skb,
+@@ -10031,6 +10031,10 @@ static int nl80211_start_radar_detection(struct sk_buff *skb,
wdev->cac_started = true;
wdev->cac_start_time = jiffies;
wdev->cac_time_ms = cac_time_ms;
@@ -25,5 +25,5 @@
unlock:
wiphy_unlock(wiphy);
--
-2.18.0
+2.39.2
diff --git a/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/mtk-0019-mtk-mac80211-avoid-kernel-warning-of-check_flush_dep.patch b/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/0023-mtk-mac80211-avoid-kernel-warning-of-check_flush_dep.patch
similarity index 72%
rename from recipes-wifi/linux-mac80211/files/patches-6.x/subsys/mtk-0019-mtk-mac80211-avoid-kernel-warning-of-check_flush_dep.patch
rename to recipes-wifi/linux-mac80211/files/patches-6.x/subsys/0023-mtk-mac80211-avoid-kernel-warning-of-check_flush_dep.patch
index 748cf7c..6fdac3c 100644
--- a/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/mtk-0019-mtk-mac80211-avoid-kernel-warning-of-check_flush_dep.patch
+++ b/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/0023-mtk-mac80211-avoid-kernel-warning-of-check_flush_dep.patch
@@ -1,7 +1,7 @@
-From b72e19fd852a014531dcfc667eb82f2a26b9196b Mon Sep 17 00:00:00 2001
+From 9ccc4eaa0168f60bd9f78f4122433ec0528a70cd Mon Sep 17 00:00:00 2001
From: Evelyn Tsai <evelyn.tsai@mediatek.com>
Date: Thu, 3 Aug 2023 07:17:44 +0800
-Subject: [PATCH 19/37] mtk: mac80211: avoid kernel warning of
+Subject: [PATCH 23/61] mtk: mac80211: avoid kernel warning of
check_flush_dependency
---
@@ -9,10 +9,10 @@
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/net/mac80211/main.c b/net/mac80211/main.c
-index a7acd22..168f09d 100644
+index 81a9645..e9d8581 100644
--- a/net/mac80211/main.c
+++ b/net/mac80211/main.c
-@@ -1286,7 +1286,7 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
+@@ -1458,7 +1458,7 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
hw->queues = IEEE80211_MAX_QUEUES;
local->workqueue =
@@ -22,5 +22,5 @@
result = -ENOMEM;
goto fail_workqueue;
--
-2.18.0
+2.39.2
diff --git a/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/mtk-0020-mtk-mac80211-avoid-calling-switch_vif_chanctx-when-u.patch b/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/0024-mtk-mac80211-avoid-calling-switch_vif_chanctx-when-u.patch
similarity index 69%
rename from recipes-wifi/linux-mac80211/files/patches-6.x/subsys/mtk-0020-mtk-mac80211-avoid-calling-switch_vif_chanctx-when-u.patch
rename to recipes-wifi/linux-mac80211/files/patches-6.x/subsys/0024-mtk-mac80211-avoid-calling-switch_vif_chanctx-when-u.patch
index bb3981b..edfa07a 100644
--- a/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/mtk-0020-mtk-mac80211-avoid-calling-switch_vif_chanctx-when-u.patch
+++ b/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/0024-mtk-mac80211-avoid-calling-switch_vif_chanctx-when-u.patch
@@ -1,19 +1,20 @@
-From 4accf70da3e00dfc1021d751310b4564fb1fad3f Mon Sep 17 00:00:00 2001
+From d9d2bfeed54c0506a2f387354464d3ef474e1777 Mon Sep 17 00:00:00 2001
From: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
Date: Mon, 7 Aug 2023 19:00:53 +0800
-Subject: [PATCH 20/37] mtk: mac80211: avoid calling switch_vif_chanctx when
+Subject: [PATCH 24/61] mtk: mac80211: avoid calling switch_vif_chanctx when
use_chanctx is false
Signed-off-by: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
+Change-Id: I2876d763ed1ecb5b7c7e5c53b2623dcd34ece774
---
net/mac80211/chan.c | 14 ++++++++------
1 file changed, 8 insertions(+), 6 deletions(-)
diff --git a/net/mac80211/chan.c b/net/mac80211/chan.c
-index 6895275..96f1ad0 100644
+index 32094ef..8043d1d 100644
--- a/net/mac80211/chan.c
+++ b/net/mac80211/chan.c
-@@ -1304,13 +1304,15 @@ ieee80211_link_use_reserved_reassign(struct ieee80211_link_data *link)
+@@ -1219,13 +1219,15 @@ ieee80211_link_use_reserved_reassign(struct ieee80211_link_data *link)
list_del(&link->reserved_chanctx_list);
link->reserved_chanctx = NULL;
@@ -21,13 +22,13 @@
- CHANCTX_SWMODE_REASSIGN_VIF);
- if (err) {
- if (ieee80211_chanctx_refcount(local, new_ctx) == 0)
-- ieee80211_free_chanctx(local, new_ctx);
-+ if (local->use_chanctx) {
+- ieee80211_free_chanctx(local, new_ctx, false);
++ if (!local->emulate_chanctx) {
+ err = drv_switch_vif_chanctx(local, vif_chsw, 1,
+ CHANCTX_SWMODE_REASSIGN_VIF);
+ if (err) {
+ if (ieee80211_chanctx_refcount(local, new_ctx) == 0)
-+ ieee80211_free_chanctx(local, new_ctx);
++ ieee80211_free_chanctx(local, new_ctx, false);
- goto out;
+ goto out;
@@ -36,5 +37,5 @@
list_move(&link->assigned_chanctx_list, &new_ctx->assigned_links);
--
-2.18.0
+2.39.2
diff --git a/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/mtk-0023-mtk-mac80211-add-EHT-BA1024-support.patch b/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/0025-mtk-mac80211-add-EHT-BA1024-support.patch
similarity index 88%
rename from recipes-wifi/linux-mac80211/files/patches-6.x/subsys/mtk-0023-mtk-mac80211-add-EHT-BA1024-support.patch
rename to recipes-wifi/linux-mac80211/files/patches-6.x/subsys/0025-mtk-mac80211-add-EHT-BA1024-support.patch
index d7d7c9f..c16cfe8 100644
--- a/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/mtk-0023-mtk-mac80211-add-EHT-BA1024-support.patch
+++ b/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/0025-mtk-mac80211-add-EHT-BA1024-support.patch
@@ -1,7 +1,7 @@
-From 33ad860265ded8546ac378d721e1b7d0142e069c Mon Sep 17 00:00:00 2001
+From 61947ae7c04a86c4d6526d080e37e53fe4d17599 Mon Sep 17 00:00:00 2001
From: MeiChia Chiu <meichia.chiu@mediatek.com>
Date: Sun, 25 Dec 2022 22:43:46 +0800
-Subject: [PATCH 23/37] mtk: mac80211: add EHT BA1024 support
+Subject: [PATCH 25/61] mtk: mac80211: add EHT BA1024 support
---
include/linux/ieee80211.h | 2 ++
@@ -9,10 +9,10 @@
2 files changed, 45 insertions(+), 2 deletions(-)
diff --git a/include/linux/ieee80211.h b/include/linux/ieee80211.h
-index e53b73e..2eb145e 100644
+index 95c39b7..70f0135 100644
--- a/include/linux/ieee80211.h
+++ b/include/linux/ieee80211.h
-@@ -1343,6 +1343,8 @@ struct ieee80211_mgmt {
+@@ -1391,6 +1391,8 @@ struct ieee80211_mgmt {
__le16 status;
__le16 capab;
__le16 timeout;
@@ -22,7 +22,7 @@
struct{
u8 action_code;
diff --git a/net/mac80211/agg-tx.c b/net/mac80211/agg-tx.c
-index 7f66e69..b8b8e22 100644
+index af3d8e6..5cf478e 100644
--- a/net/mac80211/agg-tx.c
+++ b/net/mac80211/agg-tx.c
@@ -72,10 +72,17 @@ static void ieee80211_send_addba_request(struct ieee80211_sub_if_data *sdata,
@@ -73,7 +73,7 @@
} else {
/*
* We really should use what the driver told us it will
-@@ -998,13 +1017,35 @@ void ieee80211_process_addba_resp(struct ieee80211_local *local,
+@@ -980,8 +999,10 @@ void ieee80211_process_addba_resp(struct ieee80211_local *local,
{
struct tid_ampdu_tx *tid_tx;
struct ieee80211_txq *txq;
@@ -82,7 +82,9 @@
bool amsdu;
+ int ext_ie_len;
- capab = le16_to_cpu(mgmt->u.action.u.addba_resp.capab);
+ lockdep_assert_wiphy(sta->local->hw.wiphy);
+
+@@ -989,6 +1010,26 @@ void ieee80211_process_addba_resp(struct ieee80211_local *local,
amsdu = capab & IEEE80211_ADDBA_PARAM_AMSDU_MASK;
tid = u16_get_bits(capab, IEEE80211_ADDBA_PARAM_TID_MASK);
buf_size = u16_get_bits(capab, IEEE80211_ADDBA_PARAM_BUF_SIZE_MASK);
@@ -110,5 +112,5 @@
txq = sta->sta.txq[tid];
--
-2.18.0
+2.39.2
diff --git a/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/mtk-0024-mtk-mac80211-add-rate-duration-for-EHT-rate.patch b/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/0026-mtk-mac80211-add-rate-duration-for-EHT-rate.patch
similarity index 98%
rename from recipes-wifi/linux-mac80211/files/patches-6.x/subsys/mtk-0024-mtk-mac80211-add-rate-duration-for-EHT-rate.patch
rename to recipes-wifi/linux-mac80211/files/patches-6.x/subsys/0026-mtk-mac80211-add-rate-duration-for-EHT-rate.patch
index 5db0a2f..91b1b07 100644
--- a/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/mtk-0024-mtk-mac80211-add-rate-duration-for-EHT-rate.patch
+++ b/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/0026-mtk-mac80211-add-rate-duration-for-EHT-rate.patch
@@ -1,14 +1,14 @@
-From f3a735030c257da9f8a4248802270dba37c26eb4 Mon Sep 17 00:00:00 2001
+From f2f18cce7c4d2467312ccebd927308d65d5cc27b Mon Sep 17 00:00:00 2001
From: Bo Jiao <Bo.Jiao@mediatek.com>
Date: Sun, 25 Dec 2022 22:43:46 +0800
-Subject: [PATCH 24/37] mtk: mac80211: add rate duration for EHT rate.
+Subject: [PATCH 26/61] mtk: mac80211: add rate duration for EHT rate.
---
net/mac80211/airtime.c | 349 ++++++++++++++++++++++++++++++++++++++++-
1 file changed, 346 insertions(+), 3 deletions(-)
diff --git a/net/mac80211/airtime.c b/net/mac80211/airtime.c
-index e8ebd34..b1de6d0 100644
+index fdf8b65..370477c 100644
--- a/net/mac80211/airtime.c
+++ b/net/mac80211/airtime.c
@@ -55,10 +55,21 @@
@@ -436,5 +436,5 @@
if (stat->encoding != RX_ENC_LEGACY)
return true;
--
-2.18.0
+2.39.2
diff --git a/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/mtk-0025-mtk-mac80211-add-send-bar-action-when-recieve-addba-.patch b/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/0027-mtk-mac80211-add-send-bar-action-when-recieve-addba-.patch
similarity index 75%
rename from recipes-wifi/linux-mac80211/files/patches-6.x/subsys/mtk-0025-mtk-mac80211-add-send-bar-action-when-recieve-addba-.patch
rename to recipes-wifi/linux-mac80211/files/patches-6.x/subsys/0027-mtk-mac80211-add-send-bar-action-when-recieve-addba-.patch
index 401c8a8..8de0ea7 100644
--- a/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/mtk-0025-mtk-mac80211-add-send-bar-action-when-recieve-addba-.patch
+++ b/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/0027-mtk-mac80211-add-send-bar-action-when-recieve-addba-.patch
@@ -1,7 +1,7 @@
-From 9e9286abe5cb3ff378b01046d19ddba0944562e1 Mon Sep 17 00:00:00 2001
+From baa27bc8d70bab050630a127c7d58d140ac9ed21 Mon Sep 17 00:00:00 2001
From: ye he <ye.he@mediatek.com>
Date: Wed, 22 Feb 2023 16:09:32 +0800
-Subject: [PATCH 25/37] mtk: mac80211: add send bar action when recieve addba
+Subject: [PATCH 27/61] mtk: mac80211: add send bar action when recieve addba
rsp
Signed-off-by: ye he <ye.he@mediatek.com>
@@ -10,10 +10,10 @@
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/net/mac80211/agg-tx.c b/net/mac80211/agg-tx.c
-index b8b8e22..285433a 100644
+index 5cf478e..8480b64 100644
--- a/net/mac80211/agg-tx.c
+++ b/net/mac80211/agg-tx.c
-@@ -1098,7 +1098,8 @@ next:
+@@ -1080,7 +1080,8 @@ next:
tid_tx->buf_size = buf_size;
tid_tx->amsdu = amsdu;
@@ -24,5 +24,5 @@
ieee80211_agg_tx_operational(local, sta, tid);
--
-2.18.0
+2.39.2
diff --git a/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/mtk-0026-mtk-mac80211-inrease-beacon-loss-count.patch b/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/0028-mtk-mac80211-inrease-beacon-loss-count.patch
similarity index 79%
rename from recipes-wifi/linux-mac80211/files/patches-6.x/subsys/mtk-0026-mtk-mac80211-inrease-beacon-loss-count.patch
rename to recipes-wifi/linux-mac80211/files/patches-6.x/subsys/0028-mtk-mac80211-inrease-beacon-loss-count.patch
index 6f6a98b..c6a9e9d 100644
--- a/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/mtk-0026-mtk-mac80211-inrease-beacon-loss-count.patch
+++ b/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/0028-mtk-mac80211-inrease-beacon-loss-count.patch
@@ -1,7 +1,7 @@
-From 2733993c8fb2e6392cddd718c1b95164c49af642 Mon Sep 17 00:00:00 2001
+From 235df226520ae9c161bed6fe45920331662b26e6 Mon Sep 17 00:00:00 2001
From: Amit Khatri <amit.khatri@mediatek.com>
Date: Thu, 6 Apr 2023 21:37:33 +0800
-Subject: [PATCH 26/37] mtk: mac80211: inrease beacon loss count
+Subject: [PATCH 28/61] mtk: mac80211: inrease beacon loss count
as per eagle code beacone loss time out is
4 seconds.
@@ -16,10 +16,10 @@
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
-index 6077e89..47a6590 100644
+index 52d1cd8..a27682e 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
-@@ -61,7 +61,7 @@ MODULE_PARM_DESC(max_probe_tries,
+@@ -66,7 +66,7 @@ MODULE_PARM_DESC(max_probe_tries,
* probe on beacon miss before declaring the connection lost
* default to what we want.
*/
@@ -29,5 +29,5 @@
MODULE_PARM_DESC(beacon_loss_count,
"Number of beacon intervals before we decide beacon was lost.");
--
-2.18.0
+2.39.2
diff --git a/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/mtk-0027-mtk-cfg80211-add-support-for-updating-background-cha.patch b/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/0029-mtk-cfg80211-add-support-for-updating-background-cha.patch
similarity index 86%
rename from recipes-wifi/linux-mac80211/files/patches-6.x/subsys/mtk-0027-mtk-cfg80211-add-support-for-updating-background-cha.patch
rename to recipes-wifi/linux-mac80211/files/patches-6.x/subsys/0029-mtk-cfg80211-add-support-for-updating-background-cha.patch
index 1f46543..ffc8f1c 100644
--- a/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/mtk-0027-mtk-cfg80211-add-support-for-updating-background-cha.patch
+++ b/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/0029-mtk-cfg80211-add-support-for-updating-background-cha.patch
@@ -1,7 +1,7 @@
-From c35a634d57fc0a12d7415c05aaf239e29e0e8357 Mon Sep 17 00:00:00 2001
+From e4e9d4cdfc3b5e27a3ad3f05810a96447ccf1f56 Mon Sep 17 00:00:00 2001
From: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
Date: Wed, 5 Jul 2023 09:49:02 +0800
-Subject: [PATCH 27/37] mtk: cfg80211: add support for updating background
+Subject: [PATCH 29/61] mtk: cfg80211: add support for updating background
channel
Signed-off-by: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
@@ -12,10 +12,10 @@
3 files changed, 32 insertions(+)
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
-index 19c8abe..2e499ed 100644
+index 19cf7f7..bd516d1 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
-@@ -8540,6 +8540,20 @@ void cfg80211_sta_update_dfs_state(struct wireless_dev *wdev,
+@@ -8693,6 +8693,20 @@ void cfg80211_sta_update_dfs_state(struct wireless_dev *wdev,
const struct cfg80211_chan_def *csa_chandef,
bool associated);
@@ -37,10 +37,10 @@
* cfg80211_background_cac_abort - Channel Availability Check offchan abort event
* @wiphy: the wiphy
diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h
-index 60c6f79..6e96ad9 100644
+index 7999a65..e859c96 100644
--- a/include/uapi/linux/nl80211.h
+++ b/include/uapi/linux/nl80211.h
-@@ -6671,6 +6671,10 @@ enum nl80211_smps_mode {
+@@ -6822,6 +6822,10 @@ enum nl80211_smps_mode {
* applicable for ETSI dfs domain where pre-CAC is valid for ever.
* @NL80211_RADAR_CAC_STARTED: Channel Availability Check has been started,
* should be generated by HW if NL80211_EXT_FEATURE_DFS_OFFLOAD is enabled.
@@ -51,7 +51,7 @@
* @NL80211_RADAR_STA_CAC_SKIPPED: STA set the DFS state to available
* when receiving CSA/assoc resp
* @NL80211_RADAR_STA_CAC_EXPIRED: STA set the DFS state to usable
-@@ -6683,6 +6687,8 @@ enum nl80211_radar_event {
+@@ -6834,6 +6838,8 @@ enum nl80211_radar_event {
NL80211_RADAR_NOP_FINISHED,
NL80211_RADAR_PRE_CAC_EXPIRED,
NL80211_RADAR_CAC_STARTED,
@@ -61,10 +61,10 @@
NL80211_RADAR_STA_CAC_EXPIRED,
};
diff --git a/net/wireless/mlme.c b/net/wireless/mlme.c
-index e264609..8e77205 100644
+index 56095b3..3da7886 100644
--- a/net/wireless/mlme.c
+++ b/net/wireless/mlme.c
-@@ -1173,6 +1173,18 @@ cfg80211_start_background_radar_detection(struct cfg80211_registered_device *rde
+@@ -1281,6 +1281,18 @@ cfg80211_start_background_radar_detection(struct cfg80211_registered_device *rde
return 0;
}
@@ -84,5 +84,5 @@
{
struct wiphy *wiphy = wdev->wiphy;
--
-2.18.0
+2.39.2
diff --git a/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/mtk-0028-mtk-mac80211-Allow-STA-interface-to-set-TX-queue-par.patch b/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/0030-mtk-mac80211-Allow-STA-interface-to-set-TX-queue-par.patch
similarity index 73%
rename from recipes-wifi/linux-mac80211/files/patches-6.x/subsys/mtk-0028-mtk-mac80211-Allow-STA-interface-to-set-TX-queue-par.patch
rename to recipes-wifi/linux-mac80211/files/patches-6.x/subsys/0030-mtk-mac80211-Allow-STA-interface-to-set-TX-queue-par.patch
index 9affe14..ca8cdc0 100644
--- a/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/mtk-0028-mtk-mac80211-Allow-STA-interface-to-set-TX-queue-par.patch
+++ b/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/0030-mtk-mac80211-Allow-STA-interface-to-set-TX-queue-par.patch
@@ -1,7 +1,7 @@
-From 180f80da3952be05a0177b565559a16dee708925 Mon Sep 17 00:00:00 2001
+From bfe137c0bceae36a34e766d2623893c4b1cbdd53 Mon Sep 17 00:00:00 2001
From: Michael Lee <michael-cy.lee@mediatek.com>
Date: Fri, 7 Jul 2023 17:17:30 +0800
-Subject: [PATCH 28/37] mtk: mac80211: Allow STA interface to set TX queue
+Subject: [PATCH 30/61] mtk: mac80211: Allow STA interface to set TX queue
parameters
Signed-off-by: Michael Lee <michael-cy.lee@mediatek.com>
@@ -10,10 +10,10 @@
1 file changed, 1 insertion(+)
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
-index 2be678c..aed186f 100644
+index 1f1856b..079fedf 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
-@@ -3498,6 +3498,7 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info)
+@@ -3557,6 +3557,7 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info)
}
if (netdev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP &&
@@ -22,5 +22,5 @@
result = -EINVAL;
goto out;
--
-2.18.0
+2.39.2
diff --git a/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/mtk-0029-mtk-mac80211-export-ieee80211_tpt_led_trig_tx-rx-for.patch b/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/0031-mtk-mac80211-export-ieee80211_tpt_led_trig_tx-rx-for.patch
similarity index 88%
rename from recipes-wifi/linux-mac80211/files/patches-6.x/subsys/mtk-0029-mtk-mac80211-export-ieee80211_tpt_led_trig_tx-rx-for.patch
rename to recipes-wifi/linux-mac80211/files/patches-6.x/subsys/0031-mtk-mac80211-export-ieee80211_tpt_led_trig_tx-rx-for.patch
index 0af68c3..f070841 100644
--- a/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/mtk-0029-mtk-mac80211-export-ieee80211_tpt_led_trig_tx-rx-for.patch
+++ b/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/0031-mtk-mac80211-export-ieee80211_tpt_led_trig_tx-rx-for.patch
@@ -1,7 +1,7 @@
-From ef1f8c941108eca2665a6caff0cd016c36584d76 Mon Sep 17 00:00:00 2001
+From 2a5c863cc42d21d20a25496426696c95cea45312 Mon Sep 17 00:00:00 2001
From: Yi-Chia Hsieh <yi-chia.hsieh@mediatek.com>
Date: Fri, 23 Jun 2023 05:53:50 +0800
-Subject: [PATCH 29/37] mtk: mac80211: export ieee80211_tpt_led_trig_tx/rx for
+Subject: [PATCH 31/61] mtk: mac80211: export ieee80211_tpt_led_trig_tx/rx for
driver
Whenever the H/W path is enabled and traffic is in the binding state,
@@ -22,10 +22,10 @@
5 files changed, 36 insertions(+), 20 deletions(-)
diff --git a/include/net/mac80211.h b/include/net/mac80211.h
-index 361fe92..d641b18 100644
+index 965a026..860ad6e 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
-@@ -4747,6 +4747,8 @@ __ieee80211_create_tpt_led_trigger(struct ieee80211_hw *hw,
+@@ -4893,6 +4893,8 @@ __ieee80211_create_tpt_led_trigger(struct ieee80211_hw *hw,
unsigned int flags,
const struct ieee80211_tpt_blink *blink_table,
unsigned int blink_table_len);
@@ -34,7 +34,7 @@
#endif
/**
* ieee80211_get_tx_led_name - get name of TX LED
-@@ -4857,6 +4859,21 @@ ieee80211_create_tpt_led_trigger(struct ieee80211_hw *hw, unsigned int flags,
+@@ -5003,6 +5005,21 @@ ieee80211_create_tpt_led_trigger(struct ieee80211_hw *hw, unsigned int flags,
#endif
}
@@ -57,7 +57,7 @@
* ieee80211_unregister_hw - Unregister a hardware device
*
diff --git a/net/mac80211/led.c b/net/mac80211/led.c
-index c60d070..0ecc3ea 100644
+index b992430..3109501 100644
--- a/net/mac80211/led.c
+++ b/net/mac80211/led.c
@@ -364,6 +364,22 @@ __ieee80211_create_tpt_led_trigger(struct ieee80211_hw *hw,
@@ -111,10 +111,10 @@
-#endif
-}
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
-index fead07e..1541e9c 100644
+index 65982a6..fe3d9fb 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
-@@ -5401,7 +5401,7 @@ void ieee80211_rx_list(struct ieee80211_hw *hw, struct ieee80211_sta *pubsta,
+@@ -5469,7 +5469,7 @@ void ieee80211_rx_list(struct ieee80211_hw *hw, struct ieee80211_sta *pubsta,
if (skb) {
if ((status->flag & RX_FLAG_8023) ||
ieee80211_is_data_present(hdr->frame_control))
@@ -124,10 +124,10 @@
if (status->flag & RX_FLAG_8023)
__ieee80211_rx_handle_8023(hw, pubsta, skb, list);
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
-index 019fc77..c8fade8 100644
+index f479d87..344f4bf 100644
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
-@@ -4323,7 +4323,7 @@ void __ieee80211_subif_start_xmit(struct sk_buff *skb,
+@@ -4340,7 +4340,7 @@ void __ieee80211_subif_start_xmit(struct sk_buff *skb,
len = 0;
out:
if (len)
@@ -136,7 +136,7 @@
rcu_read_unlock();
}
-@@ -4649,7 +4649,7 @@ static void ieee80211_8023_xmit(struct ieee80211_sub_if_data *sdata,
+@@ -4671,7 +4671,7 @@ static void ieee80211_8023_xmit(struct ieee80211_sub_if_data *sdata,
sta->deflink.tx_stats.packets[queue] += skbs;
sta->deflink.tx_stats.bytes[queue] += len;
@@ -146,5 +146,5 @@
ieee80211_tx_8023(sdata, skb, sta, false);
--
-2.18.0
+2.39.2
diff --git a/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/mtk-0030-mtk-mac80211-add-packet-count-input-for-dev_sw_netst.patch b/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/0032-mtk-mac80211-add-packet-count-input-for-dev_sw_netst.patch
similarity index 88%
rename from recipes-wifi/linux-mac80211/files/patches-6.x/subsys/mtk-0030-mtk-mac80211-add-packet-count-input-for-dev_sw_netst.patch
rename to recipes-wifi/linux-mac80211/files/patches-6.x/subsys/0032-mtk-mac80211-add-packet-count-input-for-dev_sw_netst.patch
index c33da52..d879e5e 100644
--- a/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/mtk-0030-mtk-mac80211-add-packet-count-input-for-dev_sw_netst.patch
+++ b/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/0032-mtk-mac80211-add-packet-count-input-for-dev_sw_netst.patch
@@ -1,7 +1,7 @@
-From 4e785260ea9523efea8deb29f3f7ec7a7dab5128 Mon Sep 17 00:00:00 2001
+From fc5c4fd0f0edc27c7a21e43a51e1a90a2f7b17b2 Mon Sep 17 00:00:00 2001
From: Yi-Chia Hsieh <yi-chia.hsieh@mediatek.com>
Date: Tue, 22 Aug 2023 05:02:53 +0800
-Subject: [PATCH 30/37] mtk: mac80211: add packet count input for
+Subject: [PATCH 32/61] mtk: mac80211: add packet count input for
dev_sw_netstat_rx_add
---
@@ -53,10 +53,10 @@
}
#endif /* < 5.10 */
diff --git a/drivers/net/usb/qmi_wwan.c b/drivers/net/usb/qmi_wwan.c
-index 6c2c1e5..3bc64d8 100644
+index f7f640f..436e37d 100644
--- a/drivers/net/usb/qmi_wwan.c
+++ b/drivers/net/usb/qmi_wwan.c
-@@ -210,7 +210,7 @@ static int qmimux_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
+@@ -228,7 +228,7 @@ static int qmimux_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
net->stats.rx_errors++;
return 0;
} else {
@@ -66,7 +66,7 @@
skip:
diff --git a/drivers/net/wireless/quantenna/qtnfmac/pcie/pearl_pcie.c b/drivers/net/wireless/quantenna/qtnfmac/pcie/pearl_pcie.c
-index 8c23a77..8f201ea 100644
+index c1a53e1..01ff00f 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/pcie/pearl_pcie.c
+++ b/drivers/net/wireless/quantenna/qtnfmac/pcie/pearl_pcie.c
@@ -756,7 +756,7 @@ static int qtnf_pcie_pearl_rx_poll(struct napi_struct *napi, int budget)
@@ -79,7 +79,7 @@
napi_gro_receive(napi, skb);
} else {
diff --git a/drivers/net/wireless/quantenna/qtnfmac/pcie/topaz_pcie.c b/drivers/net/wireless/quantenna/qtnfmac/pcie/topaz_pcie.c
-index d833625..0a7bb97 100644
+index ef5c069..8136745 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/pcie/topaz_pcie.c
+++ b/drivers/net/wireless/quantenna/qtnfmac/pcie/topaz_pcie.c
@@ -662,7 +662,7 @@ static int qtnf_topaz_rx_poll(struct napi_struct *napi, int budget)
@@ -92,10 +92,10 @@
netif_receive_skb(skb);
} else {
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
-index 1541e9c..7a80945 100644
+index fe3d9fb..da3fc51 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
-@@ -853,7 +853,7 @@ ieee80211_rx_monitor(struct ieee80211_local *local, struct sk_buff *origskb,
+@@ -863,7 +863,7 @@ ieee80211_rx_monitor(struct ieee80211_local *local, struct sk_buff *origskb,
if (skb) {
skb->dev = sdata->dev;
@@ -104,7 +104,7 @@
netif_receive_skb(skb);
}
}
-@@ -2631,7 +2631,7 @@ ieee80211_deliver_skb(struct ieee80211_rx_data *rx)
+@@ -2672,7 +2672,7 @@ ieee80211_deliver_skb(struct ieee80211_rx_data *rx)
skb = rx->skb;
xmit_skb = NULL;
@@ -113,7 +113,7 @@
if (rx->sta) {
/* The seqno index has the same property as needed
-@@ -4054,7 +4054,7 @@ static void ieee80211_rx_cooked_monitor(struct ieee80211_rx_data *rx,
+@@ -4111,7 +4111,7 @@ static void ieee80211_rx_cooked_monitor(struct ieee80211_rx_data *rx,
}
prev_dev = sdata->dev;
@@ -122,7 +122,7 @@
}
if (prev_dev) {
-@@ -4762,7 +4762,7 @@ static void ieee80211_rx_8023(struct ieee80211_rx_data *rx,
+@@ -4819,7 +4819,7 @@ static void ieee80211_rx_8023(struct ieee80211_rx_data *rx,
skb->dev = fast_rx->dev;
@@ -132,5 +132,5 @@
/* The seqno index has the same property as needed
* for the rx_msdu field, i.e. it is IEEE80211_NUM_TIDS
--
-2.18.0
+2.39.2
diff --git a/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/mtk-0031-mtk-mac80211-add-per-bss-flag-to-support-vendors-cou.patch b/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/0033-mtk-mac80211-add-per-bss-flag-to-support-vendors-cou.patch
similarity index 75%
rename from recipes-wifi/linux-mac80211/files/patches-6.x/subsys/mtk-0031-mtk-mac80211-add-per-bss-flag-to-support-vendors-cou.patch
rename to recipes-wifi/linux-mac80211/files/patches-6.x/subsys/0033-mtk-mac80211-add-per-bss-flag-to-support-vendors-cou.patch
index 7690697..081bd72 100644
--- a/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/mtk-0031-mtk-mac80211-add-per-bss-flag-to-support-vendors-cou.patch
+++ b/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/0033-mtk-mac80211-add-per-bss-flag-to-support-vendors-cou.patch
@@ -1,9 +1,10 @@
-From f500b4d7d2eb30f46fe0b75afb7b9bd94f96cf55 Mon Sep 17 00:00:00 2001
+From 4d85822963f5d150be638d78ea84c5199f80d676 Mon Sep 17 00:00:00 2001
From: Yi-Chia Hsieh <yi-chia.hsieh@mediatek.com>
Date: Wed, 16 Aug 2023 07:23:34 +0800
-Subject: [PATCH 31/37] mtk: mac80211: add per-bss flag to support vendors
+Subject: [PATCH 33/61] mtk: mac80211: add per-bss flag to support vendors
counter
+Change-Id: I73fcae64d933c66b9eef9b6f55f7bb1e4ce19501
---
include/uapi/linux/nl80211.h | 1 +
net/mac80211/rx.c | 8 ++++++--
@@ -11,22 +12,22 @@
3 files changed, 17 insertions(+), 5 deletions(-)
diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h
-index 6e96ad9..b1555bb 100644
+index e859c96..220d20d 100644
--- a/include/uapi/linux/nl80211.h
+++ b/include/uapi/linux/nl80211.h
-@@ -6471,6 +6471,7 @@ enum nl80211_ext_feature_index {
- NL80211_EXT_FEATURE_PUNCT,
- NL80211_EXT_FEATURE_SECURE_NAN,
- NL80211_EXT_FEATURE_AUTH_AND_DEAUTH_RANDOM_TA,
+@@ -6620,6 +6620,7 @@ enum nl80211_ext_feature_index {
+ NL80211_EXT_FEATURE_OWE_OFFLOAD_AP,
+ NL80211_EXT_FEATURE_DFS_CONCURRENT,
+ NL80211_EXT_FEATURE_SPP_AMSDU_SUPPORT,
+ NL80211_EXT_FEATURE_STAS_COUNT,
/* add new features before the definition below */
NUM_NL80211_EXT_FEATURES,
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
-index 7a80945..0cf8c59 100644
+index da3fc51..06725f3 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
-@@ -2631,7 +2631,9 @@ ieee80211_deliver_skb(struct ieee80211_rx_data *rx)
+@@ -2672,7 +2672,9 @@ ieee80211_deliver_skb(struct ieee80211_rx_data *rx)
skb = rx->skb;
xmit_skb = NULL;
@@ -37,7 +38,7 @@
if (rx->sta) {
/* The seqno index has the same property as needed
-@@ -4762,7 +4764,9 @@ static void ieee80211_rx_8023(struct ieee80211_rx_data *rx,
+@@ -4819,7 +4821,9 @@ static void ieee80211_rx_8023(struct ieee80211_rx_data *rx,
skb->dev = fast_rx->dev;
@@ -49,10 +50,10 @@
/* The seqno index has the same property as needed
* for the rx_msdu field, i.e. it is IEEE80211_NUM_TIDS
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
-index c8fade8..0f6c960 100644
+index 344f4bf..a2ed041 100644
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
-@@ -3541,7 +3541,9 @@ ieee80211_xmit_fast_finish(struct ieee80211_sub_if_data *sdata,
+@@ -3559,7 +3559,9 @@ ieee80211_xmit_fast_finish(struct ieee80211_sub_if_data *sdata,
if (key)
info->control.hw_key = &key->conf;
@@ -63,7 +64,7 @@
if (hdr->frame_control & cpu_to_le16(IEEE80211_STYPE_QOS_DATA)) {
tid = skb->priority & IEEE80211_QOS_CTL_TAG1D_MASK;
-@@ -4313,7 +4315,9 @@ void __ieee80211_subif_start_xmit(struct sk_buff *skb,
+@@ -4330,7 +4332,9 @@ void __ieee80211_subif_start_xmit(struct sk_buff *skb,
goto out;
}
@@ -74,9 +75,9 @@
ieee80211_xmit(sdata, sta, skb);
}
-@@ -4645,7 +4649,10 @@ static void ieee80211_8023_xmit(struct ieee80211_sub_if_data *sdata,
- info->ack_frame_id = ieee80211_store_ack_skb(local, skb,
- &info->flags, NULL);
+@@ -4667,7 +4671,10 @@ static void ieee80211_8023_xmit(struct ieee80211_sub_if_data *sdata,
+ info->status_data_idr = 1;
+ }
- dev_sw_netstats_tx_add(dev, skbs, len);
+ if (!wiphy_ext_feature_isset(sta->local->hw.wiphy,
@@ -87,5 +88,5 @@
sta->deflink.tx_stats.bytes[queue] += len;
--
-2.18.0
+2.39.2
diff --git a/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/mtk-0032-mtk-mac80211-set-eht_support-to-false-when-AP-is-not.patch b/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/0034-mtk-mac80211-set-eht_support-to-false-when-AP-is-not.patch
similarity index 66%
rename from recipes-wifi/linux-mac80211/files/patches-6.x/subsys/mtk-0032-mtk-mac80211-set-eht_support-to-false-when-AP-is-not.patch
rename to recipes-wifi/linux-mac80211/files/patches-6.x/subsys/0034-mtk-mac80211-set-eht_support-to-false-when-AP-is-not.patch
index cf32642..9faae94 100644
--- a/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/mtk-0032-mtk-mac80211-set-eht_support-to-false-when-AP-is-not.patch
+++ b/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/0034-mtk-mac80211-set-eht_support-to-false-when-AP-is-not.patch
@@ -1,19 +1,21 @@
-From c117e28dd0caf91f0d1ce7516ba6aa90f8bb07f4 Mon Sep 17 00:00:00 2001
+From 2531350e6d261ef54adb85ce59c5012dc4d5db90 Mon Sep 17 00:00:00 2001
From: MeiChia Chiu <meichia.chiu@mediatek.com>
Date: Wed, 25 Oct 2023 13:37:00 +0800
-Subject: [PATCH 32/37] mtk: mac80211: set eht_support to false when AP is not
+Subject: [PATCH 34/61] mtk: mac80211: set eht_support to false when AP is not
in EHT mode
+CR-ID: WCNCR00240597
+Change-Id: I826428e26ba70a0e77fcc8c9bc0dca440060e880
Signed-off-by: MeiChia Chiu <meichia.chiu@mediatek.com>
---
net/mac80211/cfg.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
-index 9b9be1a..cf694bc 100644
+index cb91223..215b5d2 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
-@@ -1378,6 +1378,7 @@ static int ieee80211_start_ap(struct wiphy *wiphy, struct net_device *dev,
+@@ -1384,6 +1384,7 @@ static int ieee80211_start_ap(struct wiphy *wiphy, struct net_device *dev,
link_conf->eht_su_beamformer = false;
link_conf->eht_su_beamformee = false;
link_conf->eht_mu_beamformer = false;
@@ -22,5 +24,5 @@
if (sdata->vif.type == NL80211_IFTYPE_AP &&
--
-2.18.0
+2.39.2
diff --git a/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/mtk-0033-mtk-mac80211-Add-cert-mode-to-disable-ba-timeout.patch b/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/0035-mtk-mac80211-Add-cert-mode-to-disable-ba-timeout.patch
similarity index 82%
rename from recipes-wifi/linux-mac80211/files/patches-6.x/subsys/mtk-0033-mtk-mac80211-Add-cert-mode-to-disable-ba-timeout.patch
rename to recipes-wifi/linux-mac80211/files/patches-6.x/subsys/0035-mtk-mac80211-Add-cert-mode-to-disable-ba-timeout.patch
index eb4281e..50e53f9 100644
--- a/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/mtk-0033-mtk-mac80211-Add-cert-mode-to-disable-ba-timeout.patch
+++ b/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/0035-mtk-mac80211-Add-cert-mode-to-disable-ba-timeout.patch
@@ -1,12 +1,19 @@
-From bc5e57c30a65a64e74ef4d8c355a4a4c83673c73 Mon Sep 17 00:00:00 2001
+From ba967d748120a6681f3e0f106dfaf3ad882034c0 Mon Sep 17 00:00:00 2001
From: "Allen.Ye" <allen.ye@mediatek.com>
Date: Thu, 9 Nov 2023 11:37:37 +0800
-Subject: [PATCH 33/37] mtk: mac80211: Add cert mode to disable ba timeout
+Subject: [PATCH 35/61] mtk: mac80211: Add cert mode to disable ba timeout
Add a switch of certification mode in debugfs as cert_mode. In the case
we use it to disable BA timeout from STA to prevent crashing STA.
+CR-Id: WCNCR00259302
+Change-Id: I537715030d2eeae3c795725093c79c4878086f1a
Signed-off-by: Allen.Ye <allen.ye@mediatek.com>
+
+Move the variable 'cert_mode' from ieee80211_local to ieee80211_hw
+
+CR-Id: WCNCR00289305
+Signed-off-by: Michael-CY Lee <michael-cy.lee@mediatek.com>
---
include/net/mac80211.h | 6 ++++++
net/mac80211/agg-tx.c | 5 ++++-
@@ -14,10 +21,10 @@
3 files changed, 59 insertions(+), 1 deletion(-)
diff --git a/include/net/mac80211.h b/include/net/mac80211.h
-index d641b18..ba8343f 100644
+index 860ad6e..89bba19 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
-@@ -2910,8 +2910,14 @@ struct ieee80211_hw {
+@@ -3028,8 +3028,14 @@ struct ieee80211_hw {
u32 max_mtu;
const s8 *tx_power_levels;
u8 max_txpwr_levels_idx;
@@ -33,10 +40,10 @@
enum ieee80211_hw_flags flg)
{
diff --git a/net/mac80211/agg-tx.c b/net/mac80211/agg-tx.c
-index 285433a..a2f1e14 100644
+index 8480b64..7117576 100644
--- a/net/mac80211/agg-tx.c
+++ b/net/mac80211/agg-tx.c
-@@ -1108,7 +1108,10 @@ next:
+@@ -1090,7 +1090,10 @@ next:
tid_tx->timeout =
le16_to_cpu(mgmt->u.action.u.addba_resp.timeout);
@@ -49,10 +56,10 @@
TU_TO_EXP_TIME(tid_tx->timeout));
tid_tx->last_tx = jiffies;
diff --git a/net/mac80211/debugfs.c b/net/mac80211/debugfs.c
-index 006b46d..8c29786 100644
+index f9c5ed8..d655a19 100644
--- a/net/mac80211/debugfs.c
+++ b/net/mac80211/debugfs.c
-@@ -449,6 +449,54 @@ static const struct file_operations reset_ops = {
+@@ -450,6 +450,54 @@ static const struct file_operations reset_ops = {
};
#endif
@@ -107,7 +114,7 @@
static const char *hw_flag_names[] = {
#define FLAG(F) [IEEE80211_HW_##F] = #F
FLAG(HAS_RATE_CONTROL),
-@@ -680,6 +728,7 @@ void debugfs_hw_add(struct ieee80211_local *local)
+@@ -684,6 +732,7 @@ void debugfs_hw_add(struct ieee80211_local *local)
debugfs_create_u32("aql_threshold", 0600,
phyd, &local->aql_threshold);
@@ -116,5 +123,5 @@
#ifdef CPTCFG_MAC80211_DEBUG_COUNTERS
--
-2.18.0
+2.39.2
diff --git a/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/bp-0002-backports-update-kernel-version-check-for-eth_hw_add.patch b/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/0036-backports-update-kernel-version-check-for-eth_hw_add.patch
similarity index 85%
rename from recipes-wifi/linux-mac80211/files/patches-6.x/subsys/bp-0002-backports-update-kernel-version-check-for-eth_hw_add.patch
rename to recipes-wifi/linux-mac80211/files/patches-6.x/subsys/0036-backports-update-kernel-version-check-for-eth_hw_add.patch
index f6699a6..95fac53 100644
--- a/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/bp-0002-backports-update-kernel-version-check-for-eth_hw_add.patch
+++ b/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/0036-backports-update-kernel-version-check-for-eth_hw_add.patch
@@ -1,13 +1,15 @@
-From ad78259cef325771ddf30132bd0c80e4a11b4841 Mon Sep 17 00:00:00 2001
+From 0bf57d6aacff7859372d546ef491f2722098bc0c Mon Sep 17 00:00:00 2001
From: Shayne Chen <shayne.chen@mediatek.com>
Date: Mon, 27 Nov 2023 16:39:36 +0800
-Subject: [PATCH 2/3] backports: update kernel version check for
+Subject: [PATCH 36/61] backports: update kernel version check for
eth_hw_addr_set()
Kernel v5.4.260 has added this API, so update kernel version check in
backports include.
+CR-Id: WCNCR00238098
Signed-off-by: Shayne Chen <shayne.chen@mediatek.com>
+Change-Id: I708aabbe51de9d480932ce03b30d004bf1d67ebd
---
backport-include/linux/etherdevice.h | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
@@ -35,5 +37,5 @@
#if LINUX_VERSION_IS_LESS(5,16,0)
static inline int backport_device_get_mac_address(struct device *dev, char *addr)
--
-2.18.0
+2.39.2
diff --git a/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/mtk-0034-mtk-mac80211-ACS-channel-time-is-reset-by-ch_restore.patch b/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/0037-mac80211-mtk-ACS-channel-time-is-reset-by-ch_restore.patch
similarity index 73%
rename from recipes-wifi/linux-mac80211/files/patches-6.x/subsys/mtk-0034-mtk-mac80211-ACS-channel-time-is-reset-by-ch_restore.patch
rename to recipes-wifi/linux-mac80211/files/patches-6.x/subsys/0037-mac80211-mtk-ACS-channel-time-is-reset-by-ch_restore.patch
index b6e976a..88560ce 100644
--- a/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/mtk-0034-mtk-mac80211-ACS-channel-time-is-reset-by-ch_restore.patch
+++ b/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/0037-mac80211-mtk-ACS-channel-time-is-reset-by-ch_restore.patch
@@ -1,7 +1,7 @@
-From 618d7f6ad1b398bc21258559c80928febba3dfac Mon Sep 17 00:00:00 2001
+From 9c1106eb80f31723780a6eb098b5c146a33d45a2 Mon Sep 17 00:00:00 2001
From: "fancy.liu" <fancy.liu@mediatek.com>
Date: Wed, 29 Nov 2023 13:51:13 +0800
-Subject: [PATCH 34/37] mtk: mac80211: ACS channel time is reset by ch_restore
+Subject: [PATCH 37/61] mac80211: mtk: ACS channel time is reset by ch_restore
Issue:
There's a chance that the channel time for duty channel is zero in ACS
@@ -22,19 +22,21 @@
Mac80211 scan state will be set in scanning, and will be reset after
scan done and before restore to duty channel.
+CR-Id: WCNCR00357653
Signed-off-by: fancy.liu <fancy.liu@mediatek.com>
+Change-Id: I480a956c8a362929040d941247d74ff0e5d06ffb
---
include/net/mac80211.h | 7 +++++++
net/mac80211/util.c | 9 +++++++++
2 files changed, 16 insertions(+)
diff --git a/include/net/mac80211.h b/include/net/mac80211.h
-index ba8343f..453466a 100644
+index 89bba19..d7b1f9d 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
-@@ -7485,4 +7485,11 @@ int ieee80211_set_active_links(struct ieee80211_vif *vif, u16 active_links);
- void ieee80211_set_active_links_async(struct ieee80211_vif *vif,
- u16 active_links);
+@@ -7665,4 +7665,11 @@ int ieee80211_emulate_switch_vif_chanctx(struct ieee80211_hw *hw,
+ int n_vifs,
+ enum ieee80211_chanctx_switch_mode mode);
+/**
+ * ieee80211_get_scanning - get scanning bitmask
@@ -45,12 +47,12 @@
+
#endif /* MAC80211_H */
diff --git a/net/mac80211/util.c b/net/mac80211/util.c
-index fd82488..f0bb4e8 100644
+index dd06bd2..55f1566 100644
--- a/net/mac80211/util.c
+++ b/net/mac80211/util.c
-@@ -5154,3 +5154,12 @@ void ieee80211_fragment_element(struct sk_buff *skb, u8 *len_pos, u8 frag_id)
-
- *len_pos = elem_len;
+@@ -4340,3 +4340,12 @@ ieee80211_min_bw_limit_from_chandef(struct cfg80211_chan_def *chandef)
+ return IEEE80211_CONN_BW_LIMIT_20;
+ }
}
+
+unsigned long ieee80211_get_scanning(struct ieee80211_hw *hw)
@@ -62,5 +64,5 @@
+EXPORT_SYMBOL(ieee80211_get_scanning);
+
--
-2.18.0
+2.39.2
diff --git a/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/mtk-0035-mtk-mac80211-Fix-SMPS-action-frame-cap-check.patch b/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/0038-mtk-mac80211-Fix-SMPS-action-frame-cap-check.patch
similarity index 76%
rename from recipes-wifi/linux-mac80211/files/patches-6.x/subsys/mtk-0035-mtk-mac80211-Fix-SMPS-action-frame-cap-check.patch
rename to recipes-wifi/linux-mac80211/files/patches-6.x/subsys/0038-mtk-mac80211-Fix-SMPS-action-frame-cap-check.patch
index 794407f..f958799 100644
--- a/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/mtk-0035-mtk-mac80211-Fix-SMPS-action-frame-cap-check.patch
+++ b/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/0038-mtk-mac80211-Fix-SMPS-action-frame-cap-check.patch
@@ -1,22 +1,24 @@
-From 9ff05c938d2a2b82d022aa8f671d2333cd8a992a Mon Sep 17 00:00:00 2001
+From 8a8535abf02e5cb6f0dcaf924e33183a1a1fa410 Mon Sep 17 00:00:00 2001
From: "Allen.Ye" <allen.ye@mediatek.com>
Date: Thu, 30 Nov 2023 14:01:29 +0800
-Subject: [PATCH 35/37] mtk: mac80211: Fix SMPS action frame cap check
+Subject: [PATCH 38/61] mtk: mac80211: Fix SMPS action frame cap check
Fix SMPS action frame cap check.
Due to 6G band doesn't have HT cap, we change cap check into each action
frame section.
+CR-Id: WCNCR00259302
Signed-off-by: Allen.Ye <allen.ye@mediatek.com>
+Change-Id: I65d2cc29efdb4a78ac670890842496a2056fc2ba
---
net/mac80211/rx.c | 8 +++++---
1 file changed, 5 insertions(+), 3 deletions(-)
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
-index 0cf8c59..fe3a538 100644
+index 06725f3..1d273ef 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
-@@ -3493,9 +3493,6 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx)
+@@ -3528,9 +3528,6 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx)
switch (mgmt->u.action.category) {
case WLAN_CATEGORY_HT:
@@ -26,7 +28,7 @@
if (sdata->vif.type != NL80211_IFTYPE_STATION &&
sdata->vif.type != NL80211_IFTYPE_MESH_POINT &&
-@@ -3514,6 +3511,11 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx)
+@@ -3549,6 +3546,11 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx)
enum ieee80211_smps_mode smps_mode;
struct sta_opmode_info sta_opmode = {};
@@ -39,5 +41,5 @@
sdata->vif.type != NL80211_IFTYPE_AP_VLAN)
goto handled;
--
-2.18.0
+2.39.2
diff --git a/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/0039-mtk-mac80211-allow-multiple-links-for-STA-vif.patch b/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/0039-mtk-mac80211-allow-multiple-links-for-STA-vif.patch
new file mode 100644
index 0000000..4c56b5c
--- /dev/null
+++ b/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/0039-mtk-mac80211-allow-multiple-links-for-STA-vif.patch
@@ -0,0 +1,29 @@
+From 9de692d990d4d83e957ea89e3fc23367f696bbc3 Mon Sep 17 00:00:00 2001
+From: Shayne Chen <shayne.chen@mediatek.com>
+Date: Thu, 19 Oct 2023 00:27:15 +0800
+Subject: [PATCH 39/61] mtk: mac80211: allow multiple links for STA vif
+
+Signed-off-by: Shayne Chen <shayne.chen@mediatek.com>
+Change-Id: I92d07be6ec87523ef3fdc3855151daea382eb290
+---
+ net/mac80211/link.c | 3 ---
+ 1 file changed, 3 deletions(-)
+
+diff --git a/net/mac80211/link.c b/net/mac80211/link.c
+index 43f9672..a33a845 100644
+--- a/net/mac80211/link.c
++++ b/net/mac80211/link.c
+@@ -168,10 +168,7 @@ static void ieee80211_set_vif_links_bitmaps(struct ieee80211_sub_if_data *sdata,
+ WARN_ON(dormant_links);
+ break;
+ case NL80211_IFTYPE_STATION:
+- if (sdata->vif.active_links)
+- break;
+ sdata->vif.active_links = valid_links & ~dormant_links;
+- WARN_ON(hweight16(sdata->vif.active_links) > 1);
+ break;
+ default:
+ WARN_ON(1);
+--
+2.39.2
+
diff --git a/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/0040-mtk-mac80211-increase-association-timeout-time.patch b/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/0040-mtk-mac80211-increase-association-timeout-time.patch
new file mode 100644
index 0000000..ff69c5a
--- /dev/null
+++ b/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/0040-mtk-mac80211-increase-association-timeout-time.patch
@@ -0,0 +1,30 @@
+From 48d97cc83f3098481fbc2a6d38da75e94703708f Mon Sep 17 00:00:00 2001
+From: Shayne Chen <shayne.chen@mediatek.com>
+Date: Thu, 19 Oct 2023 00:35:11 +0800
+Subject: [PATCH 40/61] mtk: mac80211: increase association timeout time
+
+Prevent from sending multiple association requests while AP is already
+hanlding the request.
+
+Signed-off-by: Shayne Chen <shayne.chen@mediatek.com>
+Change-Id: I5ea21682b2498c73acc88095a665db1a3f7e7302
+---
+ net/mac80211/mlme.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
+index a27682e..84ea805 100644
+--- a/net/mac80211/mlme.c
++++ b/net/mac80211/mlme.c
+@@ -7202,7 +7202,7 @@ void ieee80211_sta_work(struct ieee80211_sub_if_data *sdata)
+ */
+ if (status_acked) {
+ ifmgd->assoc_data->timeout =
+- jiffies + IEEE80211_ASSOC_TIMEOUT_SHORT;
++ jiffies + IEEE80211_ASSOC_TIMEOUT_SHORT * 4;
+ run_again(sdata, ifmgd->assoc_data->timeout);
+ } else {
+ ifmgd->assoc_data->timeout = jiffies - 1;
+--
+2.39.2
+
diff --git a/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/0041-mtk-mac80211-fix-crash-when-starting-tx-ba-session.patch b/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/0041-mtk-mac80211-fix-crash-when-starting-tx-ba-session.patch
new file mode 100644
index 0000000..7427cc3
--- /dev/null
+++ b/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/0041-mtk-mac80211-fix-crash-when-starting-tx-ba-session.patch
@@ -0,0 +1,28 @@
+From c115759fb0b11ba3ce09d078e8609203dc5e772f Mon Sep 17 00:00:00 2001
+From: Bo Jiao <Bo.Jiao@mediatek.com>
+Date: Fri, 10 Nov 2023 15:34:57 +0800
+Subject: [PATCH 41/61] mtk: mac80211: fix crash when starting tx ba session
+
+Signed-off-by: Bo Jiao <Bo.Jiao@mediatek.com>
+Change-Id: I62a463f9a37b25d4a2bfaff00e721c369e532e98
+---
+ net/mac80211/agg-tx.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/net/mac80211/agg-tx.c b/net/mac80211/agg-tx.c
+index 7117576..da9b7f0 100644
+--- a/net/mac80211/agg-tx.c
++++ b/net/mac80211/agg-tx.c
+@@ -642,7 +642,8 @@ int ieee80211_start_tx_ba_session(struct ieee80211_sta *pubsta, u16 tid,
+ "Requested to start BA session on reserved tid=%d", tid))
+ return -EINVAL;
+
+- if (!pubsta->deflink.ht_cap.ht_supported &&
++ if (!sta->sdata->vif.active_links &&
++ !pubsta->deflink.ht_cap.ht_supported &&
+ sta->sdata->vif.bss_conf.chanreq.oper.chan->band != NL80211_BAND_6GHZ)
+ return -EINVAL;
+
+--
+2.39.2
+
diff --git a/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/0042-mtk-mac80211-use-link-address-for-eapol-source-in-ie.patch b/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/0042-mtk-mac80211-use-link-address-for-eapol-source-in-ie.patch
new file mode 100644
index 0000000..09b76a0
--- /dev/null
+++ b/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/0042-mtk-mac80211-use-link-address-for-eapol-source-in-ie.patch
@@ -0,0 +1,31 @@
+From 7ec8b9cd491c09f83dfc03976fa0160f89c60eb1 Mon Sep 17 00:00:00 2001
+From: Shayne Chen <shayne.chen@mediatek.com>
+Date: Tue, 19 Dec 2023 17:42:56 +0800
+Subject: [PATCH 42/61] mtk: mac80211: use link address for eapol source in
+ ieee80211_tx_control_port()
+
+Signed-off-by: Shayne Chen <shayne.chen@mediatek.com>
+Change-Id: I67453fa4299a25a921a971cd5a2b7098844c5b8d
+---
+ net/mac80211/tx.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
+index a2ed041..e72bb7e 100644
+--- a/net/mac80211/tx.c
++++ b/net/mac80211/tx.c
+@@ -6237,9 +6237,10 @@ int ieee80211_tx_control_port(struct wiphy *wiphy, struct net_device *dev,
+ * for MLO STA, the SA should be the AP MLD address, but
+ * the link ID has been selected already
+ */
+- if (sta && sta->sta.mlo)
++ if (sta && sta->sta.mlo && link_id == IEEE80211_LINK_UNSPECIFIED)
+ memcpy(ehdr->h_source, sdata->vif.addr, ETH_ALEN);
+ }
++
+ rcu_read_unlock();
+
+ start_xmit:
+--
+2.39.2
+
diff --git a/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/0043-cfg80211-mtk-implement-DFS-radar-detect-for-MLO.patch b/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/0043-cfg80211-mtk-implement-DFS-radar-detect-for-MLO.patch
new file mode 100644
index 0000000..6ad3b95
--- /dev/null
+++ b/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/0043-cfg80211-mtk-implement-DFS-radar-detect-for-MLO.patch
@@ -0,0 +1,473 @@
+From 1c581514b49ffe917cb40d4e073c56b6d1f47416 Mon Sep 17 00:00:00 2001
+From: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
+Date: Fri, 19 Jan 2024 14:35:17 +0800
+Subject: [PATCH 43/61] cfg80211: mtk: implement DFS radar detect for MLO
+
+Implement DFS radar detect for MLO
+1. Add link id info for radar detection in MLD
+2. Note that the radar detection flow requires channel switch, which is not yet
+complete in MLO, so postpone it.
+ (a) cac_started, cac_start_time should be moved into wdev->link, but
+channel switch will use it, so wait until channel switch is completed.
+ (b) ieee80211_dfs_cac_cancel, ieee80211_dfs_radar_detected_work, ...
+
+CR-Id: WCNCR00274293
+Signed-off-by: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
+Change-Id: Ic3004607081ae407dd05095769f9e2855a068dd2
+
+rework radar detected flow for mlo
+
+CR-Id: WCNCR00274293
+Signed-off-by: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
+Change-Id: I1c76d0b12db52fdb14e73c410d7da69de65bf115
+---
+ include/net/cfg80211.h | 4 +++-
+ net/mac80211/cfg.c | 26 +++++++++++++++++++-------
+ net/mac80211/ieee80211_i.h | 2 +-
+ net/mac80211/main.c | 6 +++---
+ net/mac80211/pm.c | 9 ++++++++-
+ net/mac80211/util.c | 26 +++++++++++++++++++-------
+ net/wireless/core.c | 4 ++--
+ net/wireless/mlme.c | 4 ++--
+ net/wireless/nl80211.c | 10 +++++-----
+ net/wireless/rdev-ops.h | 13 +++++++------
+ net/wireless/reg.c | 15 +++++++++------
+ net/wireless/trace.h | 28 ++++++++++++++++++++++------
+ 12 files changed, 100 insertions(+), 47 deletions(-)
+
+diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
+index bd516d1..e55309b 100644
+--- a/include/net/cfg80211.h
++++ b/include/net/cfg80211.h
+@@ -4856,10 +4856,12 @@ struct cfg80211_ops {
+
+ int (*start_radar_detection)(struct wiphy *wiphy,
+ struct net_device *dev,
++ unsigned int link_id,
+ struct cfg80211_chan_def *chandef,
+ u32 cac_time_ms);
+ void (*end_cac)(struct wiphy *wiphy,
+- struct net_device *dev);
++ struct net_device *dev,
++ unsigned int link_id);
+ int (*update_ft_ies)(struct wiphy *wiphy, struct net_device *dev,
+ struct cfg80211_update_ft_ies_params *ftie);
+ int (*crit_proto_start)(struct wiphy *wiphy,
+diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
+index 215b5d2..3233e2a 100644
+--- a/net/mac80211/cfg.c
++++ b/net/mac80211/cfg.c
+@@ -3443,12 +3443,14 @@ static int ieee80211_set_bitrate_mask(struct wiphy *wiphy,
+
+ static int ieee80211_start_radar_detection(struct wiphy *wiphy,
+ struct net_device *dev,
++ unsigned int link_id,
+ struct cfg80211_chan_def *chandef,
+ u32 cac_time_ms)
+ {
+ struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+ struct ieee80211_chan_req chanreq = { .oper = *chandef };
+ struct ieee80211_local *local = sdata->local;
++ struct ieee80211_link_data *link;
+ int err;
+
+ lockdep_assert_wiphy(local->hw.wiphy);
+@@ -3458,16 +3460,20 @@ static int ieee80211_start_radar_detection(struct wiphy *wiphy,
+ goto out_unlock;
+ }
+
++ link = sdata_dereference(sdata->link[link_id], sdata);
++ if (!link)
++ return -ENOLINK;
++
+ /* whatever, but channel contexts should not complain about that one */
+- sdata->deflink.smps_mode = IEEE80211_SMPS_OFF;
+- sdata->deflink.needed_rx_chains = local->rx_chains;
++ link->smps_mode = IEEE80211_SMPS_OFF;
++ link->needed_rx_chains = local->rx_chains;
+
+- err = ieee80211_link_use_channel(&sdata->deflink, &chanreq,
++ err = ieee80211_link_use_channel(link, &chanreq,
+ IEEE80211_CHANCTX_SHARED);
+ if (err)
+ goto out_unlock;
+
+- wiphy_delayed_work_queue(wiphy, &sdata->deflink.dfs_cac_timer_work,
++ wiphy_delayed_work_queue(wiphy, &link->dfs_cac_timer_work,
+ msecs_to_jiffies(cac_time_ms));
+
+ out_unlock:
+@@ -3475,23 +3481,29 @@ static int ieee80211_start_radar_detection(struct wiphy *wiphy,
+ }
+
+ static void ieee80211_end_cac(struct wiphy *wiphy,
+- struct net_device *dev)
++ struct net_device *dev,
++ unsigned int link_id)
+ {
+ struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+ struct ieee80211_local *local = sdata->local;
++ struct ieee80211_link_data *link;
+
+ lockdep_assert_wiphy(local->hw.wiphy);
+
++ link = sdata_dereference(sdata->link[link_id], sdata);
++ if (!link)
++ return;
++
+ list_for_each_entry(sdata, &local->interfaces, list) {
+ /* it might be waiting for the local->mtx, but then
+ * by the time it gets it, sdata->wdev.cac_started
+ * will no longer be true
+ */
+ wiphy_delayed_work_cancel(wiphy,
+- &sdata->deflink.dfs_cac_timer_work);
++ &link->dfs_cac_timer_work);
+
+ if (sdata->wdev.cac_started) {
+- ieee80211_link_release_channel(&sdata->deflink);
++ ieee80211_link_release_channel(link);
+ sdata->wdev.cac_started = false;
+ }
+ }
+diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
+index c5781c3..608e442 100644
+--- a/net/mac80211/ieee80211_i.h
++++ b/net/mac80211/ieee80211_i.h
+@@ -2592,7 +2592,7 @@ void ieee80211_recalc_chanctx_min_def(struct ieee80211_local *local,
+ bool ieee80211_is_radar_required(struct ieee80211_local *local);
+
+ void ieee80211_dfs_cac_timer_work(struct wiphy *wiphy, struct wiphy_work *work);
+-void ieee80211_dfs_cac_cancel(struct ieee80211_local *local);
++void ieee80211_dfs_cac_cancel(struct ieee80211_local *local, unsigned int link_id);
+ void ieee80211_dfs_radar_detected_work(struct wiphy *wiphy,
+ struct wiphy_work *work);
+ int ieee80211_send_action_csa(struct ieee80211_sub_if_data *sdata,
+diff --git a/net/mac80211/main.c b/net/mac80211/main.c
+index e9d8581..f6f0509 100644
+--- a/net/mac80211/main.c
++++ b/net/mac80211/main.c
+@@ -1173,8 +1173,8 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
+ if (comb->num_different_channels > 1)
+ return -EINVAL;
+ }
+- } else {
+- /* DFS is not supported with multi-channel combinations yet */
++ }/* else {
++ // DFS is not supported with multi-channel combinations yet
+ for (i = 0; i < local->hw.wiphy->n_iface_combinations; i++) {
+ const struct ieee80211_iface_combination *comb;
+
+@@ -1184,7 +1184,7 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
+ comb->num_different_channels > 1)
+ return -EINVAL;
+ }
+- }
++ } */
+
+ /* Only HW csum features are currently compatible with mac80211 */
+ if (WARN_ON(hw->netdev_features & ~MAC80211_SUPPORTED_FEATURES))
+diff --git a/net/mac80211/pm.c b/net/mac80211/pm.c
+index c1fa26e..5a25245 100644
+--- a/net/mac80211/pm.c
++++ b/net/mac80211/pm.c
+@@ -22,6 +22,7 @@ int __ieee80211_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan)
+ {
+ struct ieee80211_local *local = hw_to_local(hw);
+ struct ieee80211_sub_if_data *sdata;
++ struct ieee80211_chanctx *ctx;
+ struct sta_info *sta;
+
+ if (!local->open_count)
+@@ -32,7 +33,13 @@ int __ieee80211_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan)
+
+ ieee80211_scan_cancel(local);
+
+- ieee80211_dfs_cac_cancel(local);
++ list_for_each_entry(ctx, &local->chanctx_list, list) {
++ struct ieee80211_link_data *link, *tmp;
++
++ list_for_each_entry_safe(link, tmp, &ctx->assigned_links,
++ assigned_chanctx_list)
++ ieee80211_dfs_cac_cancel(local, link->link_id);
++ }
+
+ ieee80211_roc_purge(local, NULL);
+
+diff --git a/net/mac80211/util.c b/net/mac80211/util.c
+index 55f1566..e5ac902 100644
+--- a/net/mac80211/util.c
++++ b/net/mac80211/util.c
+@@ -3450,9 +3450,10 @@ u64 ieee80211_calculate_rx_timestamp(struct ieee80211_local *local,
+ return ts;
+ }
+
+-void ieee80211_dfs_cac_cancel(struct ieee80211_local *local)
++void ieee80211_dfs_cac_cancel(struct ieee80211_local *local, unsigned int link_id)
+ {
+ struct ieee80211_sub_if_data *sdata;
++ struct ieee80211_link_data *link;
+ struct cfg80211_chan_def chandef;
+
+ lockdep_assert_wiphy(local->hw.wiphy);
+@@ -3462,12 +3463,20 @@ void ieee80211_dfs_cac_cancel(struct ieee80211_local *local)
+ * by the time it gets it, sdata->wdev.cac_started
+ * will no longer be true
+ */
++ link = sdata_dereference(sdata->link[link_id], sdata);
++ if (!link)
++ continue;
++
++ if (link->conf->chanreq.oper.chan &&
++ link->conf->chanreq.oper.chan->band != NL80211_BAND_5GHZ)
++ return;
++
+ wiphy_delayed_work_cancel(local->hw.wiphy,
+- &sdata->deflink.dfs_cac_timer_work);
++ &link->dfs_cac_timer_work);
+
+ if (sdata->wdev.cac_started) {
+- chandef = sdata->vif.bss_conf.chanreq.oper;
+- ieee80211_link_release_channel(&sdata->deflink);
++ chandef = link->conf->chanreq.oper;
++ ieee80211_link_release_channel(link);
+ cfg80211_cac_event(sdata->dev,
+ &chandef,
+ NL80211_RADAR_CAC_ABORTED,
+@@ -3483,20 +3492,23 @@ void ieee80211_dfs_radar_detected_work(struct wiphy *wiphy,
+ container_of(work, struct ieee80211_local, radar_detected_work);
+ struct cfg80211_chan_def chandef = local->hw.conf.chandef;
+ struct ieee80211_chanctx *ctx;
++ struct ieee80211_link_data *link, *tmp;
+ int num_chanctx = 0;
+
+ lockdep_assert_wiphy(local->hw.wiphy);
+
+ list_for_each_entry(ctx, &local->chanctx_list, list) {
+- if (ctx->replace_state == IEEE80211_CHANCTX_REPLACES_OTHER)
++ if (ctx->replace_state == IEEE80211_CHANCTX_REPLACES_OTHER ||
++ !ctx->conf.def.chan || ctx->conf.def.chan->band != NL80211_BAND_5GHZ)
+ continue;
+
+ num_chanctx++;
+ chandef = ctx->conf.def;
++ list_for_each_entry_safe(link, tmp, &ctx->assigned_links,
++ assigned_chanctx_list)
++ ieee80211_dfs_cac_cancel(local, link->link_id);
+ }
+
+- ieee80211_dfs_cac_cancel(local);
+-
+ if (num_chanctx > 1)
+ /* XXX: multi-channel is not supported yet */
+ WARN_ON(1);
+diff --git a/net/wireless/core.c b/net/wireless/core.c
+index ac9417e..16f40f3 100644
+--- a/net/wireless/core.c
++++ b/net/wireless/core.c
+@@ -629,10 +629,10 @@ static int wiphy_verify_combinations(struct wiphy *wiphy)
+ if (WARN_ON(!c->num_different_channels))
+ return -EINVAL;
+
+- /* DFS only works on one channel. */
++ /* DFS only works on one channel.
+ if (WARN_ON(c->radar_detect_widths &&
+ (c->num_different_channels > 1)))
+- return -EINVAL;
++ return -EINVAL; */
+
+ if (WARN_ON(!c->n_limits))
+ return -EINVAL;
+diff --git a/net/wireless/mlme.c b/net/wireless/mlme.c
+index 3da7886..a957989 100644
+--- a/net/wireless/mlme.c
++++ b/net/wireless/mlme.c
+@@ -1118,9 +1118,9 @@ void cfg80211_cac_event(struct net_device *netdev,
+ struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
+ unsigned long timeout;
+
+- /* not yet supported */
++ /* not yet supported
+ if (wdev->valid_links)
+- return;
++ return; */
+
+ trace_cfg80211_cac_event(netdev, event);
+
+diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
+index 079fedf..2045cdc 100644
+--- a/net/wireless/nl80211.c
++++ b/net/wireless/nl80211.c
+@@ -9964,6 +9964,7 @@ static int nl80211_start_radar_detection(struct sk_buff *skb,
+ struct cfg80211_chan_def chandef;
+ enum nl80211_dfs_regions dfs_region;
+ unsigned int cac_time_ms;
++ unsigned int link_id = nl80211_link_id(info->attrs);
+ int err = -EINVAL;
+
+ flush_delayed_work(&rdev->dfs_update_channels_wk);
+@@ -9998,7 +9999,7 @@ static int nl80211_start_radar_detection(struct sk_buff *skb,
+ goto unlock;
+ }
+
+- if (netif_carrier_ok(dev)) {
++ if (!wdev->valid_links && netif_carrier_ok(dev)) {
+ err = -EBUSY;
+ goto unlock;
+ }
+@@ -10026,9 +10027,9 @@ static int nl80211_start_radar_detection(struct sk_buff *skb,
+ pr_info("%s: region = %u, center freq1 = %u, center freq2 = %u, cac time ms = %u\n",
+ __func__, dfs_region, chandef.center_freq1, chandef.center_freq2, cac_time_ms);
+
+- err = rdev_start_radar_detection(rdev, dev, &chandef, cac_time_ms);
++ err = rdev_start_radar_detection(rdev, dev, link_id, &chandef, cac_time_ms);
+ if (!err) {
+- wdev->links[0].ap.chandef = chandef;
++ wdev->links[link_id].ap.chandef = chandef;
+ wdev->cac_started = true;
+ wdev->cac_start_time = jiffies;
+ wdev->cac_time_ms = cac_time_ms;
+@@ -17304,8 +17305,7 @@ static const struct genl_small_ops nl80211_small_ops[] = {
+ .doit = nl80211_start_radar_detection,
+ .flags = GENL_UNS_ADMIN_PERM,
+ .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP |
+- NL80211_FLAG_NO_WIPHY_MTX |
+- NL80211_FLAG_MLO_UNSUPPORTED),
++ NL80211_FLAG_NO_WIPHY_MTX),
+ },
+ {
+ .cmd = NL80211_CMD_GET_PROTOCOL_FEATURES,
+diff --git a/net/wireless/rdev-ops.h b/net/wireless/rdev-ops.h
+index 2ae7fc5..561637c 100644
+--- a/net/wireless/rdev-ops.h
++++ b/net/wireless/rdev-ops.h
+@@ -1197,15 +1197,16 @@ rdev_tdls_cancel_channel_switch(struct cfg80211_registered_device *rdev,
+ static inline int
+ rdev_start_radar_detection(struct cfg80211_registered_device *rdev,
+ struct net_device *dev,
++ unsigned int link_id,
+ struct cfg80211_chan_def *chandef,
+ u32 cac_time_ms)
+ {
+ int ret = -EOPNOTSUPP;
+
+- trace_rdev_start_radar_detection(&rdev->wiphy, dev, chandef,
+- cac_time_ms);
++ trace_rdev_start_radar_detection(&rdev->wiphy, dev, link_id,
++ chandef, cac_time_ms);
+ if (rdev->ops->start_radar_detection)
+- ret = rdev->ops->start_radar_detection(&rdev->wiphy, dev,
++ ret = rdev->ops->start_radar_detection(&rdev->wiphy, dev, link_id,
+ chandef, cac_time_ms);
+ trace_rdev_return_int(&rdev->wiphy, ret);
+ return ret;
+@@ -1213,11 +1214,11 @@ rdev_start_radar_detection(struct cfg80211_registered_device *rdev,
+
+ static inline void
+ rdev_end_cac(struct cfg80211_registered_device *rdev,
+- struct net_device *dev)
++ struct net_device *dev, unsigned int link_id)
+ {
+- trace_rdev_end_cac(&rdev->wiphy, dev);
++ trace_rdev_end_cac(&rdev->wiphy, dev, link_id);
+ if (rdev->ops->end_cac)
+- rdev->ops->end_cac(&rdev->wiphy, dev);
++ rdev->ops->end_cac(&rdev->wiphy, dev, link_id);
+ trace_rdev_return_void(&rdev->wiphy);
+ }
+
+diff --git a/net/wireless/reg.c b/net/wireless/reg.c
+index 2c0c1f1..6883aa0 100644
+--- a/net/wireless/reg.c
++++ b/net/wireless/reg.c
+@@ -4246,17 +4246,20 @@ static void cfg80211_check_and_end_cac(struct cfg80211_registered_device *rdev)
+ */
+ list_for_each_entry(wdev, &rdev->wiphy.wdev_list, list) {
+ struct cfg80211_chan_def *chandef;
++ unsigned int link_id;
+
+ if (!wdev->cac_started)
+ continue;
+
+- /* FIXME: radar detection is tied to link 0 for now */
+- chandef = wdev_chandef(wdev, 0);
+- if (!chandef)
+- continue;
++ for_each_valid_link(wdev, link_id) {
++ chandef = wdev_chandef(wdev, link_id);
++ if (!chandef || !chandef->chan ||
++ chandef->chan->band != NL80211_BAND_5GHZ)
++ continue;
+
+- if (!cfg80211_chandef_dfs_usable(&rdev->wiphy, chandef))
+- rdev_end_cac(rdev, wdev->netdev);
++ if (!cfg80211_chandef_dfs_usable(&rdev->wiphy, chandef))
++ rdev_end_cac(rdev, wdev->netdev, link_id);
++ }
+ }
+ }
+
+diff --git a/net/wireless/trace.h b/net/wireless/trace.h
+index aa3284f..22b1fcc 100644
+--- a/net/wireless/trace.h
++++ b/net/wireless/trace.h
+@@ -731,9 +731,22 @@ DEFINE_EVENT(wiphy_netdev_evt, rdev_flush_pmksa,
+ TP_ARGS(wiphy, netdev)
+ );
+
+-DEFINE_EVENT(wiphy_netdev_evt, rdev_end_cac,
+- TP_PROTO(struct wiphy *wiphy, struct net_device *netdev),
+- TP_ARGS(wiphy, netdev)
++TRACE_EVENT(rdev_end_cac,
++ TP_PROTO(struct wiphy *wiphy, struct net_device *netdev,
++ unsigned int link_id),
++ TP_ARGS(wiphy, netdev, link_id),
++ TP_STRUCT__entry(
++ WIPHY_ENTRY
++ NETDEV_ENTRY
++ __field(u32, link_id)
++ ),
++ TP_fast_assign(
++ WIPHY_ASSIGN;
++ NETDEV_ASSIGN;
++ __entry->link_id = link_id;
++ ),
++ TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", link_id=%u",
++ WIPHY_PR_ARG, NETDEV_PR_ARG, __entry->link_id)
+ );
+
+ DECLARE_EVENT_CLASS(station_add_change,
+@@ -2577,24 +2590,27 @@ TRACE_EVENT(rdev_external_auth,
+
+ TRACE_EVENT(rdev_start_radar_detection,
+ TP_PROTO(struct wiphy *wiphy, struct net_device *netdev,
++ unsigned int link_id,
+ struct cfg80211_chan_def *chandef,
+ u32 cac_time_ms),
+- TP_ARGS(wiphy, netdev, chandef, cac_time_ms),
++ TP_ARGS(wiphy, netdev, link_id, chandef, cac_time_ms),
+ TP_STRUCT__entry(
+ WIPHY_ENTRY
+ NETDEV_ENTRY
++ __field(u32, link_id)
+ CHAN_DEF_ENTRY
+ __field(u32, cac_time_ms)
+ ),
+ TP_fast_assign(
+ WIPHY_ASSIGN;
+ NETDEV_ASSIGN;
++ __entry->link_id = link_id;
+ CHAN_DEF_ASSIGN(chandef);
+ __entry->cac_time_ms = cac_time_ms;
+ ),
+- TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", " CHAN_DEF_PR_FMT
++ TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", link_id=%u, " CHAN_DEF_PR_FMT
+ ", cac_time_ms=%u",
+- WIPHY_PR_ARG, NETDEV_PR_ARG, CHAN_DEF_PR_ARG,
++ WIPHY_PR_ARG, NETDEV_PR_ARG, __entry->link_id, CHAN_DEF_PR_ARG,
+ __entry->cac_time_ms)
+ );
+
+--
+2.39.2
+
diff --git a/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/0044-mtk-wifi-mac80211-add-wds-mlo-support.patch b/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/0044-mtk-wifi-mac80211-add-wds-mlo-support.patch
new file mode 100644
index 0000000..a82a203
--- /dev/null
+++ b/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/0044-mtk-wifi-mac80211-add-wds-mlo-support.patch
@@ -0,0 +1,125 @@
+From 14fd30e05515edba0fcca8a7238d402cb2d9dd27 Mon Sep 17 00:00:00 2001
+From: Peter Chiu <chui-hao.chiu@mediatek.com>
+Date: Fri, 19 Jan 2024 15:22:00 +0800
+Subject: [PATCH 44/61] mtk: wifi: mac80211: add wds mlo support
+
+Support WDS mode when using MLO.
+1. Remove use_4addr check.
+2. Copy link information to AP_VLAN interface.
+3. Fill 4addr nullfunc by mld address.
+
+CR-Id: WCNCR00240772
+Signed-off-by: Peter Chiu <chui-hao.chiu@mediatek.com>
+Change-Id: I620bb51e47965c2558751ae266609dad61d421b6
+---
+ net/mac80211/cfg.c | 7 -------
+ net/mac80211/iface.c | 19 +++++++++++--------
+ net/mac80211/mlme.c | 15 +++++++++------
+ 3 files changed, 20 insertions(+), 21 deletions(-)
+
+diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
+index 3233e2a..0cb68fb 100644
+--- a/net/mac80211/cfg.c
++++ b/net/mac80211/cfg.c
+@@ -229,10 +229,6 @@ static int ieee80211_change_iface(struct wiphy *wiphy,
+ if (params->use_4addr == ifmgd->use_4addr)
+ return 0;
+
+- /* FIXME: no support for 4-addr MLO yet */
+- if (ieee80211_vif_is_mld(&sdata->vif))
+- return -EOPNOTSUPP;
+-
+ sdata->u.mgd.use_4addr = params->use_4addr;
+ if (!ifmgd->associated)
+ return 0;
+@@ -4922,9 +4918,6 @@ static int ieee80211_add_intf_link(struct wiphy *wiphy,
+
+ lockdep_assert_wiphy(sdata->local->hw.wiphy);
+
+- if (wdev->use_4addr)
+- return -EOPNOTSUPP;
+-
+ return ieee80211_vif_set_links(sdata, wdev->valid_links, 0);
+ }
+
+diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c
+index 0ae31a9..083da12 100644
+--- a/net/mac80211/iface.c
++++ b/net/mac80211/iface.c
+@@ -381,19 +381,22 @@ static int ieee80211_check_concurrent_iface(struct ieee80211_sub_if_data *sdata,
+ nsdata->vif.type))
+ return -ENOTUNIQ;
+
+- /* No support for VLAN with MLO yet */
+- if (iftype == NL80211_IFTYPE_AP_VLAN &&
+- sdata->wdev.use_4addr &&
+- nsdata->vif.type == NL80211_IFTYPE_AP &&
+- nsdata->vif.valid_links)
+- return -EOPNOTSUPP;
+-
+ /*
+ * can only add VLANs to enabled APs
+ */
+ if (iftype == NL80211_IFTYPE_AP_VLAN &&
+- nsdata->vif.type == NL80211_IFTYPE_AP)
++ nsdata->vif.type == NL80211_IFTYPE_AP) {
++ int i;
++
+ sdata->bss = &nsdata->u.ap;
++ sdata->vif.valid_links = nsdata->vif.valid_links;
++ sdata->vif.active_links = nsdata->vif.active_links;
++ sdata->vif.dormant_links = nsdata->vif.dormant_links;
++ for (i = 0; i < IEEE80211_MLD_MAX_NUM_LINKS; i++) {
++ sdata->link[i] = nsdata->link[i];
++ sdata->vif.link_conf[i] = nsdata->vif.link_conf[i];
++ }
++ }
+ }
+ }
+
+diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
+index 84ea805..674f3f5 100644
+--- a/net/mac80211/mlme.c
++++ b/net/mac80211/mlme.c
+@@ -1829,6 +1829,7 @@ void ieee80211_send_4addr_nullfunc(struct ieee80211_local *local,
+ {
+ struct sk_buff *skb;
+ struct ieee80211_hdr *nullfunc;
++ u8 assoc_link_id = ifmgd->assoc_data->assoc_link_id;
+ __le16 fc;
+
+ if (WARN_ON(sdata->vif.type != NL80211_IFTYPE_STATION))
+@@ -1844,11 +1845,17 @@ void ieee80211_send_4addr_nullfunc(struct ieee80211_local *local,
+ fc = cpu_to_le16(IEEE80211_FTYPE_DATA | IEEE80211_STYPE_NULLFUNC |
+ IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS);
+ nullfunc->frame_control = fc;
+- memcpy(nullfunc->addr1, sdata->deflink.u.mgd.bssid, ETH_ALEN);
+ memcpy(nullfunc->addr2, sdata->vif.addr, ETH_ALEN);
+- memcpy(nullfunc->addr3, sdata->deflink.u.mgd.bssid, ETH_ALEN);
+ memcpy(nullfunc->addr4, sdata->vif.addr, ETH_ALEN);
+
++ if (ieee80211_vif_is_mld(&sdata->vif)) {
++ memcpy(nullfunc->addr1, sdata->vif.cfg.ap_addr, ETH_ALEN);
++ memcpy(nullfunc->addr3, sdata->vif.cfg.ap_addr, ETH_ALEN);
++ } else {
++ memcpy(nullfunc->addr1, sdata->deflink.u.mgd.bssid, ETH_ALEN);
++ memcpy(nullfunc->addr3, sdata->deflink.u.mgd.bssid, ETH_ALEN);
++ }
++
+ IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT;
+ IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_CTL_USE_MINRATE;
+ ieee80211_tx_skb(sdata, skb);
+@@ -8229,10 +8236,6 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata,
+ for (i = 0; i < IEEE80211_MLD_MAX_NUM_LINKS; i++)
+ size += req->links[i].elems_len;
+
+- /* FIXME: no support for 4-addr MLO yet */
+- if (sdata->u.mgd.use_4addr && req->link_id >= 0)
+- return -EOPNOTSUPP;
+-
+ assoc_data = kzalloc(size, GFP_KERNEL);
+ if (!assoc_data)
+ return -ENOMEM;
+--
+2.39.2
+
diff --git a/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/0045-mtk-mac80211-fix-ieee80211_probe_client-warning.patch b/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/0045-mtk-mac80211-fix-ieee80211_probe_client-warning.patch
new file mode 100644
index 0000000..7f3eef0
--- /dev/null
+++ b/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/0045-mtk-mac80211-fix-ieee80211_probe_client-warning.patch
@@ -0,0 +1,39 @@
+From 9a234460e4fcc0013ade098c9e8efb6f201068fc Mon Sep 17 00:00:00 2001
+From: Shayne Chen <shayne.chen@mediatek.com>
+Date: Mon, 29 Jan 2024 18:37:15 +0800
+Subject: [PATCH 45/61] mtk: mac80211: fix ieee80211_probe_client warning
+
+Only get chanctx for non-mld VIF.
+
+CR-Id: WCNCR00238098
+Change-Id: I0a6861fc16d11e97fb29b775d5e641925b7dd92f
+Signed-off-by: Shayne Chen <shayne.chen@mediatek.com>
+---
+ net/mac80211/cfg.c | 10 ++++++----
+ 1 file changed, 6 insertions(+), 4 deletions(-)
+
+diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
+index 0cb68fb..6e3b28e 100644
+--- a/net/mac80211/cfg.c
++++ b/net/mac80211/cfg.c
+@@ -4211,11 +4211,13 @@ static int ieee80211_probe_client(struct wiphy *wiphy, struct net_device *dev,
+ qos = sta->sta.wme;
+
+ chanctx_conf = rcu_dereference(sdata->vif.bss_conf.chanctx_conf);
+- if (WARN_ON(!chanctx_conf)) {
+- ret = -EINVAL;
+- goto unlock;
++ if (!ieee80211_vif_is_mld(&sdata->vif)) {
++ if (WARN_ON(!chanctx_conf)) {
++ ret = -EINVAL;
++ goto unlock;
++ }
+ }
+- band = chanctx_conf->def.chan->band;
++ band = chanctx_conf ? chanctx_conf->def.chan->band : 0;
+
+ if (qos) {
+ fc = cpu_to_le16(IEEE80211_FTYPE_DATA |
+--
+2.39.2
+
diff --git a/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/0046-mtk-mac80211-remove-link-0-warn-on-in-rate_control_r.patch b/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/0046-mtk-mac80211-remove-link-0-warn-on-in-rate_control_r.patch
new file mode 100644
index 0000000..745751b
--- /dev/null
+++ b/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/0046-mtk-mac80211-remove-link-0-warn-on-in-rate_control_r.patch
@@ -0,0 +1,43 @@
+From b22d9da27623db1d7c3bf7f677afcdb99ec5ec27 Mon Sep 17 00:00:00 2001
+From: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
+Date: Wed, 31 Jan 2024 11:40:28 +0800
+Subject: [PATCH 46/61] mtk: mac80211: remove link != 0 warn on in
+ rate_control_rate_update for mlo channel switch
+
+Remove link warning for mlo channel switch
+
+CR-Id: WCNCR00274293
+Signed-off-by: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
+---
+ net/mac80211/rate.c | 10 ++++++++--
+ 1 file changed, 8 insertions(+), 2 deletions(-)
+
+diff --git a/net/mac80211/rate.c b/net/mac80211/rate.c
+index bbdd3b8..8f54562 100644
+--- a/net/mac80211/rate.c
++++ b/net/mac80211/rate.c
+@@ -100,13 +100,19 @@ void rate_control_rate_update(struct ieee80211_local *local,
+ struct ieee80211_sta *ista = &sta->sta;
+ void *priv_sta = sta->rate_ctrl_priv;
+ struct ieee80211_chanctx_conf *chanctx_conf;
++ struct ieee80211_link_data *link;
+
+- WARN_ON(link_id != 0);
++ // WARN_ON(link_id != 0);
+
+ if (ref && ref->ops->rate_update) {
+ rcu_read_lock();
+
+- chanctx_conf = rcu_dereference(sta->sdata->vif.bss_conf.chanctx_conf);
++ link = rcu_dereference(sta->sdata->link[link_id]);
++ if (!link) {
++ rcu_read_unlock();
++ return;
++ }
++ chanctx_conf = rcu_dereference(link->conf->chanctx_conf);
+ if (WARN_ON(!chanctx_conf)) {
+ rcu_read_unlock();
+ return;
+--
+2.39.2
+
diff --git a/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/0047-mtk-mac80211-fix-radar-required-of-link-issue-in-res.patch b/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/0047-mtk-mac80211-fix-radar-required-of-link-issue-in-res.patch
new file mode 100644
index 0000000..d3324ff
--- /dev/null
+++ b/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/0047-mtk-mac80211-fix-radar-required-of-link-issue-in-res.patch
@@ -0,0 +1,41 @@
+From 588692667ae3d8a198760c19d335d33b0dca6ba0 Mon Sep 17 00:00:00 2001
+From: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
+Date: Thu, 1 Feb 2024 17:46:49 +0800
+Subject: [PATCH 47/61] mtk: mac80211: fix radar required of link issue in
+ reserve_reassign and reserve_assign
+
+link->radar_required is not updated in
+ieee80211_link_use_reserved_assign & ieee80211_link_use_reserved_reassign
+This will lead to DFS RDD init incomplete (RDD_CAC_START, RDD_CAC_END &
+RDD_DET_MODE is not set to fw)
+
+CR-Id: WCNCR00274293
+Signed-off-by: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
+Change-Id: I44eeb32be5ff42202639f94418d079930369fde9
+---
+ net/mac80211/chan.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/net/mac80211/chan.c b/net/mac80211/chan.c
+index 8043d1d..ac22524 100644
+--- a/net/mac80211/chan.c
++++ b/net/mac80211/chan.c
+@@ -1207,6 +1207,7 @@ ieee80211_link_use_reserved_reassign(struct ieee80211_link_data *link)
+ if (link_conf->chanreq.oper.width != link->reserved.oper.width)
+ changed = BSS_CHANGED_BANDWIDTH;
+
++ link->radar_required = link->reserved_radar_required;
+ ieee80211_link_update_chanreq(link, &link->reserved);
+
+ _ieee80211_change_chanctx(local, new_ctx, old_ctx, chanreq, link);
+@@ -1290,6 +1291,7 @@ ieee80211_link_use_reserved_assign(struct ieee80211_link_data *link)
+ list_del(&link->reserved_chanctx_list);
+ link->reserved_chanctx = NULL;
+
++ link->radar_required = link->reserved_radar_required;
+ err = ieee80211_assign_link_chanctx(link, new_ctx);
+ if (err) {
+ if (ieee80211_chanctx_refcount(local, new_ctx) == 0)
+--
+2.39.2
+
diff --git a/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/0048-mtk-cfg80211-rework-cac-started-cac-start-time-for-m.patch b/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/0048-mtk-cfg80211-rework-cac-started-cac-start-time-for-m.patch
new file mode 100644
index 0000000..eb3bca0
--- /dev/null
+++ b/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/0048-mtk-cfg80211-rework-cac-started-cac-start-time-for-m.patch
@@ -0,0 +1,390 @@
+From d65bfb08d34fadb98ad271a91365004e8b674b84 Mon Sep 17 00:00:00 2001
+From: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
+Date: Thu, 1 Feb 2024 10:57:39 +0800
+Subject: [PATCH 48/61] mtk: cfg80211: rework cac started, cac start time for
+ multi-link support
+
+CR-Id: WCNCR00274293
+Signed-off-by: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
+Change-Id: Ib47630f1a01fd0d4bf7edb1964b2907f2b4ec8f3
+---
+ include/net/cfg80211.h | 20 ++++++++++++++------
+ net/mac80211/cfg.c | 26 +++++++++++++-------------
+ net/mac80211/iface.c | 22 +++++++++++++++-------
+ net/mac80211/mlme.c | 4 ++--
+ net/mac80211/pm.c | 10 ++++------
+ net/mac80211/scan.c | 2 +-
+ net/mac80211/util.c | 6 +++---
+ net/wireless/debugfs.c | 10 ++++++----
+ net/wireless/mlme.c | 13 +++++++------
+ net/wireless/nl80211.c | 8 ++++----
+ net/wireless/reg.c | 4 ++--
+ 11 files changed, 71 insertions(+), 54 deletions(-)
+
+diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
+index e55309b..e88cc1e 100644
+--- a/include/net/cfg80211.h
++++ b/include/net/cfg80211.h
+@@ -6223,11 +6223,6 @@ struct wireless_dev {
+ u32 owner_nlportid;
+ bool nl_owner_dead;
+
+- /* FIXME: need to rework radar detection for MLO */
+- bool cac_started;
+- unsigned long cac_start_time;
+- unsigned int cac_time_ms;
+-
+ #ifdef CPTCFG_CFG80211_WEXT
+ /* wext data */
+ struct {
+@@ -6294,8 +6289,11 @@ struct wireless_dev {
+ struct cfg80211_internal_bss *current_bss;
+ } client;
+ };
++ unsigned long cac_start_time;
++ unsigned int cac_time_ms;
+ } links[IEEE80211_MLD_MAX_NUM_LINKS];
+ u16 valid_links;
++ u16 cac_links;
+ };
+
+ static inline const u8 *wdev_address(struct wireless_dev *wdev)
+@@ -6350,6 +6348,15 @@ static inline void WARN_INVALID_LINK_ID(struct wireless_dev *wdev,
+ if (!(link_info)->valid_links || \
+ ((link_info)->valid_links & BIT(link_id)))
+
++#define for_each_cac_link(link_info, link_id) \
++ for (link_id = 0; \
++ link_id < ((link_info)->cac_links ? \
++ ARRAY_SIZE((link_info)->links) : 1); \
++ link_id++) \
++ if (!(link_info)->cac_links || \
++ ((link_info)->cac_links & BIT(link_id)))
++
++
+ /**
+ * DOC: Utility functions
+ *
+@@ -8669,6 +8676,7 @@ void cfg80211_sta_opmode_change_notify(struct net_device *dev, const u8 *mac,
+ /**
+ * cfg80211_cac_event - Channel availability check (CAC) event
+ * @netdev: network device
++ * @link_id: the link ID for MLO, must be 0 for non-MLO
+ * @chandef: chandef for the current channel
+ * @event: type of event
+ * @gfp: context flags
+@@ -8677,7 +8685,7 @@ void cfg80211_sta_opmode_change_notify(struct net_device *dev, const u8 *mac,
+ * or aborted. This must be called to notify the completion of a CAC process,
+ * also by full-MAC drivers.
+ */
+-void cfg80211_cac_event(struct net_device *netdev,
++void cfg80211_cac_event(struct net_device *netdev, unsigned int link_id,
+ const struct cfg80211_chan_def *chandef,
+ enum nl80211_radar_event event, gfp_t gfp);
+
+diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
+index 6e3b28e..871623d 100644
+--- a/net/mac80211/cfg.c
++++ b/net/mac80211/cfg.c
+@@ -1658,10 +1658,10 @@ static int ieee80211_stop_ap(struct wiphy *wiphy, struct net_device *dev,
+ ieee80211_link_info_change_notify(sdata, link,
+ BSS_CHANGED_BEACON_ENABLED);
+
+- if (sdata->wdev.cac_started) {
++ if (sdata->wdev.cac_links & BIT(link_id)) {
+ chandef = link_conf->chanreq.oper;
+ wiphy_delayed_work_cancel(wiphy, &link->dfs_cac_timer_work);
+- cfg80211_cac_event(sdata->dev, &chandef,
++ cfg80211_cac_event(sdata->dev, link_id, &chandef,
+ NL80211_RADAR_CAC_ABORTED,
+ GFP_KERNEL);
+ }
+@@ -3492,15 +3492,15 @@ static void ieee80211_end_cac(struct wiphy *wiphy,
+
+ list_for_each_entry(sdata, &local->interfaces, list) {
+ /* it might be waiting for the local->mtx, but then
+- * by the time it gets it, sdata->wdev.cac_started
++ * by the time it gets it, sdata->wdev.cac_links & BIT(link_id)
+ * will no longer be true
+ */
+ wiphy_delayed_work_cancel(wiphy,
+ &link->dfs_cac_timer_work);
+
+- if (sdata->wdev.cac_started) {
++ if (sdata->wdev.cac_links & BIT(link_id)) {
+ ieee80211_link_release_channel(link);
+- sdata->wdev.cac_started = false;
++ sdata->wdev.cac_links &= ~BIT(link_id);
+ }
+ }
+ }
+@@ -3959,12 +3959,12 @@ __ieee80211_channel_switch(struct wiphy *wiphy, struct net_device *dev,
+ if (!list_empty(&local->roc_list) || local->scanning)
+ return -EBUSY;
+
+- if (sdata->wdev.cac_started)
+- return -EBUSY;
+-
+ if (WARN_ON(link_id >= IEEE80211_MLD_MAX_NUM_LINKS))
+ return -EINVAL;
+
++ if (sdata->wdev.cac_links & BIT(link_id))
++ return -EBUSY;
++
+ link_data = wiphy_dereference(wiphy, sdata->link[link_id]);
+ if (!link_data)
+ return -ENOLINK;
+@@ -5078,12 +5078,12 @@ ieee80211_skip_cac(struct wireless_dev *wdev, unsigned int link_id)
+
+ wiphy_delayed_work_cancel(sdata->local->hw.wiphy,
+ &link->dfs_cac_timer_work);
+- if (wdev->cac_started) {
++ if (wdev->cac_links & BIT(link_id)) {
+ ieee80211_link_release_channel(link);
+- cac_time_ms = wdev->cac_time_ms;
+- wdev->cac_start_time = jiffies -
+- msecs_to_jiffies(cac_time_ms + 1);
+- cfg80211_cac_event(wdev->netdev, &link->conf->chanreq.oper,
++ cac_time_ms = wdev->links[link_id].cac_time_ms;
++ wdev->links[link_id].cac_start_time = jiffies -
++ msecs_to_jiffies(cac_time_ms + 1);
++ cfg80211_cac_event(wdev->netdev, link_id, &link->conf->chanreq.oper,
+ NL80211_RADAR_CAC_FINISHED, GFP_KERNEL);
+ }
+ }
+diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c
+index 083da12..cdeb787 100644
+--- a/net/mac80211/iface.c
++++ b/net/mac80211/iface.c
+@@ -559,13 +559,21 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, bool going_do
+ wiphy_delayed_work_cancel(local->hw.wiphy,
+ &sdata->deflink.dfs_cac_timer_work);
+
+- if (sdata->wdev.cac_started) {
+- chandef = sdata->vif.bss_conf.chanreq.oper;
+- WARN_ON(local->suspended);
+- ieee80211_link_release_channel(&sdata->deflink);
+- cfg80211_cac_event(sdata->dev, &chandef,
+- NL80211_RADAR_CAC_ABORTED,
+- GFP_KERNEL);
++ if (sdata->wdev.cac_links) {
++ struct ieee80211_link_data *link;
++ unsigned int link_id;
++
++ for_each_cac_link(&sdata->wdev, link_id) {
++ link = sdata_dereference(sdata->link[link_id], sdata);
++ if (!link)
++ continue;
++ chandef = link->conf->chanreq.oper;
++ WARN_ON(local->suspended);
++ ieee80211_link_release_channel(link);
++ cfg80211_cac_event(sdata->dev, link_id, &chandef,
++ NL80211_RADAR_CAC_ABORTED,
++ GFP_KERNEL);
++ }
+ }
+
+ if (sdata->vif.type == NL80211_IFTYPE_AP) {
+diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
+index 674f3f5..e4564de 100644
+--- a/net/mac80211/mlme.c
++++ b/net/mac80211/mlme.c
+@@ -2611,9 +2611,9 @@ void ieee80211_dfs_cac_timer_work(struct wiphy *wiphy, struct wiphy_work *work)
+
+ lockdep_assert_wiphy(sdata->local->hw.wiphy);
+
+- if (sdata->wdev.cac_started) {
++ if (sdata->wdev.cac_links & BIT(link->link_id)) {
+ ieee80211_link_release_channel(link);
+- cfg80211_cac_event(sdata->dev, &chandef,
++ cfg80211_cac_event(sdata->dev, link->link_id, &chandef,
+ NL80211_RADAR_CAC_FINISHED,
+ GFP_KERNEL);
+ }
+diff --git a/net/mac80211/pm.c b/net/mac80211/pm.c
+index 5a25245..6fae264 100644
+--- a/net/mac80211/pm.c
++++ b/net/mac80211/pm.c
+@@ -22,7 +22,6 @@ int __ieee80211_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan)
+ {
+ struct ieee80211_local *local = hw_to_local(hw);
+ struct ieee80211_sub_if_data *sdata;
+- struct ieee80211_chanctx *ctx;
+ struct sta_info *sta;
+
+ if (!local->open_count)
+@@ -33,12 +32,11 @@ int __ieee80211_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan)
+
+ ieee80211_scan_cancel(local);
+
+- list_for_each_entry(ctx, &local->chanctx_list, list) {
+- struct ieee80211_link_data *link, *tmp;
++ list_for_each_entry(sdata, &local->interfaces, list) {
++ unsigned int link_id;
+
+- list_for_each_entry_safe(link, tmp, &ctx->assigned_links,
+- assigned_chanctx_list)
+- ieee80211_dfs_cac_cancel(local, link->link_id);
++ for_each_cac_link(&sdata->wdev, link_id)
++ ieee80211_dfs_cac_cancel(local, link_id);
+ }
+
+ ieee80211_roc_purge(local, NULL);
+diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c
+index 977f8eb..5a430cb 100644
+--- a/net/mac80211/scan.c
++++ b/net/mac80211/scan.c
+@@ -584,7 +584,7 @@ static bool __ieee80211_can_leave_ch(struct ieee80211_sub_if_data *sdata)
+ return false;
+
+ list_for_each_entry(sdata_iter, &local->interfaces, list) {
+- if (sdata_iter->wdev.cac_started)
++ if (sdata_iter->wdev.cac_links)
+ return false;
+ }
+
+diff --git a/net/mac80211/util.c b/net/mac80211/util.c
+index e5ac902..732232a 100644
+--- a/net/mac80211/util.c
++++ b/net/mac80211/util.c
+@@ -3460,7 +3460,7 @@ void ieee80211_dfs_cac_cancel(struct ieee80211_local *local, unsigned int link_i
+
+ list_for_each_entry(sdata, &local->interfaces, list) {
+ /* it might be waiting for the local->mtx, but then
+- * by the time it gets it, sdata->wdev.cac_started
++ * by the time it gets it, sdata->wdev.cac_links & BIT(link_id)
+ * will no longer be true
+ */
+ link = sdata_dereference(sdata->link[link_id], sdata);
+@@ -3474,10 +3474,10 @@ void ieee80211_dfs_cac_cancel(struct ieee80211_local *local, unsigned int link_i
+ wiphy_delayed_work_cancel(local->hw.wiphy,
+ &link->dfs_cac_timer_work);
+
+- if (sdata->wdev.cac_started) {
++ if (sdata->wdev.cac_links & BIT(link_id)) {
+ chandef = link->conf->chanreq.oper;
+ ieee80211_link_release_channel(link);
+- cfg80211_cac_event(sdata->dev,
++ cfg80211_cac_event(sdata->dev, link_id,
+ &chandef,
+ NL80211_RADAR_CAC_ABORTED,
+ GFP_KERNEL);
+diff --git a/net/wireless/debugfs.c b/net/wireless/debugfs.c
+index a246b2c..cbeed9f 100644
+--- a/net/wireless/debugfs.c
++++ b/net/wireless/debugfs.c
+@@ -187,10 +187,11 @@ static int dfs_status_read_wdev(struct wiphy *wiphy, struct wireless_dev *wdev,
+ if (remain_time > wait_time_ms)
+ remain_time = 0;
+ } else if (chan->dfs_state == NL80211_DFS_USABLE) {
+- if (wdev->cac_started &&
++ if ((wdev->cac_links & BIT(link_id)) &&
+ cfg80211_is_sub_chan(chandef, chan, false)) {
+- jiffies_passed = jiffies - wdev->cac_start_time;
+- wait_time_ms = wdev->cac_time_ms;
++ jiffies_passed = jiffies -
++ wdev->links[link_id].cac_start_time;
++ wait_time_ms = wdev->links[link_id].cac_time_ms;
+ remain_time = (wait_time_ms -
+ jiffies_to_msecs(jiffies_passed));
+ }
+@@ -336,7 +337,8 @@ dfs_cac_skip(void *data, u64 val)
+ continue;
+
+ if (cfg80211_chandef_dfs_required(wiphy, c, wdev->iftype) > 0 &&
+- cfg80211_chandef_dfs_usable(wiphy, c) && wdev->cac_started) {
++ cfg80211_chandef_dfs_usable(wiphy, c) &&
++ (wdev->cac_links & BIT(link_id))) {
+ rdev_skip_cac(rdev, wdev, link_id);
+ }
+ }
+diff --git a/net/wireless/mlme.c b/net/wireless/mlme.c
+index a957989..265c2f2 100644
+--- a/net/wireless/mlme.c
++++ b/net/wireless/mlme.c
+@@ -1109,7 +1109,7 @@ void __cfg80211_radar_event(struct wiphy *wiphy,
+ }
+ EXPORT_SYMBOL(__cfg80211_radar_event);
+
+-void cfg80211_cac_event(struct net_device *netdev,
++void cfg80211_cac_event(struct net_device *netdev, unsigned int link_id,
+ const struct cfg80211_chan_def *chandef,
+ enum nl80211_radar_event event, gfp_t gfp)
+ {
+@@ -1124,13 +1124,14 @@ void cfg80211_cac_event(struct net_device *netdev,
+
+ trace_cfg80211_cac_event(netdev, event);
+
+- if (WARN_ON(!wdev->cac_started && event != NL80211_RADAR_CAC_STARTED))
++ if (WARN_ON(!(wdev->cac_links & BIT(link_id)) &&
++ event != NL80211_RADAR_CAC_STARTED))
+ return;
+
+ switch (event) {
+ case NL80211_RADAR_CAC_FINISHED:
+- timeout = wdev->cac_start_time +
+- msecs_to_jiffies(wdev->cac_time_ms);
++ timeout = wdev->links[link_id].cac_start_time +
++ msecs_to_jiffies(wdev->links[link_id].cac_time_ms);
+ WARN_ON(!time_after_eq(jiffies, timeout));
+ cfg80211_set_dfs_state(wiphy, chandef, NL80211_DFS_AVAILABLE);
+ memcpy(&rdev->cac_done_chandef, chandef,
+@@ -1139,10 +1140,10 @@ void cfg80211_cac_event(struct net_device *netdev,
+ cfg80211_sched_dfs_chan_update(rdev);
+ fallthrough;
+ case NL80211_RADAR_CAC_ABORTED:
+- wdev->cac_started = false;
++ wdev->cac_links &= ~BIT(link_id);
+ break;
+ case NL80211_RADAR_CAC_STARTED:
+- wdev->cac_started = true;
++ wdev->cac_links |= BIT(link_id);
+ break;
+ default:
+ WARN_ON(1);
+diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
+index 2045cdc..2a34884 100644
+--- a/net/wireless/nl80211.c
++++ b/net/wireless/nl80211.c
+@@ -10004,7 +10004,7 @@ static int nl80211_start_radar_detection(struct sk_buff *skb,
+ goto unlock;
+ }
+
+- if (wdev->cac_started) {
++ if (wdev->cac_links & BIT(link_id)) {
+ err = -EBUSY;
+ goto unlock;
+ }
+@@ -10030,9 +10030,9 @@ static int nl80211_start_radar_detection(struct sk_buff *skb,
+ err = rdev_start_radar_detection(rdev, dev, link_id, &chandef, cac_time_ms);
+ if (!err) {
+ wdev->links[link_id].ap.chandef = chandef;
+- wdev->cac_started = true;
+- wdev->cac_start_time = jiffies;
+- wdev->cac_time_ms = cac_time_ms;
++ wdev->cac_links |= BIT(link_id);
++ wdev->links[link_id].cac_start_time = jiffies;
++ wdev->links[link_id].cac_time_ms = cac_time_ms;
+ if (rdev->background_cac_started &&
+ cfg80211_is_sub_chan(&chandef, rdev->background_radar_chandef.chan, false)) {
+ cfg80211_stop_background_radar_detection(rdev->background_radar_wdev);
+diff --git a/net/wireless/reg.c b/net/wireless/reg.c
+index 6883aa0..ebe0ed4 100644
+--- a/net/wireless/reg.c
++++ b/net/wireless/reg.c
+@@ -4248,10 +4248,10 @@ static void cfg80211_check_and_end_cac(struct cfg80211_registered_device *rdev)
+ struct cfg80211_chan_def *chandef;
+ unsigned int link_id;
+
+- if (!wdev->cac_started)
++ if (!wdev->cac_links)
+ continue;
+
+- for_each_valid_link(wdev, link_id) {
++ for_each_cac_link(wdev, link_id) {
+ chandef = wdev_chandef(wdev, link_id);
+ if (!chandef || !chandef->chan ||
+ chandef->chan->band != NL80211_BAND_5GHZ)
+--
+2.39.2
+
diff --git a/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/0049-mtk-mac80211-remove-links-when-removing-AP_VLAN-inte.patch b/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/0049-mtk-mac80211-remove-links-when-removing-AP_VLAN-inte.patch
new file mode 100644
index 0000000..d6fd5f4
--- /dev/null
+++ b/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/0049-mtk-mac80211-remove-links-when-removing-AP_VLAN-inte.patch
@@ -0,0 +1,94 @@
+From cf275081660642ebfc9aaef0722ac499922fb17b Mon Sep 17 00:00:00 2001
+From: Peter Chiu <chui-hao.chiu@mediatek.com>
+Date: Tue, 6 Feb 2024 15:03:49 +0800
+Subject: [PATCH 49/61] mtk: mac80211: remove links when removing AP_VLAN
+ interface
+
+Remove links information when removing AP_VLAN interface.
+Without this patch, there would be a kernel crash when station disconnect
+from AP.
+
+CR-Id: WCNCR00240772
+Signed-off-by: Peter Chiu <chui-hao.chiu@mediatek.com>
+Change-Id: Idffdc83cd6a13bc01b7f877fb748a8a08e99c212
+---
+ net/mac80211/cfg.c | 14 ++++++++++++++
+ net/mac80211/iface.c | 4 ++--
+ net/mac80211/mlme.c | 1 -
+ net/wireless/util.c | 8 ++++++++
+ 4 files changed, 24 insertions(+), 3 deletions(-)
+
+diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
+index 871623d..c3b9d10 100644
+--- a/net/mac80211/cfg.c
++++ b/net/mac80211/cfg.c
+@@ -4929,6 +4929,20 @@ static void ieee80211_del_intf_link(struct wiphy *wiphy,
+ {
+ struct ieee80211_sub_if_data *sdata = IEEE80211_WDEV_TO_SUB_IF(wdev);
+
++ if (wdev->iftype == NL80211_IFTYPE_AP_VLAN) {
++ int i;
++
++ sdata->vif.valid_links = 0;
++ sdata->vif.active_links = 0;
++ sdata->vif.dormant_links = 0;
++ for (i = 0; i < IEEE80211_MLD_MAX_NUM_LINKS; i++) {
++ rcu_assign_pointer(sdata->link[i], NULL);
++ rcu_assign_pointer(sdata->vif.link_conf[i], NULL);
++ }
++
++ return;
++ }
++
+ lockdep_assert_wiphy(sdata->local->hw.wiphy);
+
+ ieee80211_vif_set_links(sdata, wdev->valid_links, 0);
+diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c
+index cdeb787..83b579a 100644
+--- a/net/mac80211/iface.c
++++ b/net/mac80211/iface.c
+@@ -393,8 +393,8 @@ static int ieee80211_check_concurrent_iface(struct ieee80211_sub_if_data *sdata,
+ sdata->vif.active_links = nsdata->vif.active_links;
+ sdata->vif.dormant_links = nsdata->vif.dormant_links;
+ for (i = 0; i < IEEE80211_MLD_MAX_NUM_LINKS; i++) {
+- sdata->link[i] = nsdata->link[i];
+- sdata->vif.link_conf[i] = nsdata->vif.link_conf[i];
++ rcu_assign_pointer(sdata->link[i], nsdata->link[i]);
++ rcu_assign_pointer(sdata->vif.link_conf[i], nsdata->vif.link_conf[i]);
+ }
+ }
+ }
+diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
+index e4564de..ebdcf57 100644
+--- a/net/mac80211/mlme.c
++++ b/net/mac80211/mlme.c
+@@ -1829,7 +1829,6 @@ void ieee80211_send_4addr_nullfunc(struct ieee80211_local *local,
+ {
+ struct sk_buff *skb;
+ struct ieee80211_hdr *nullfunc;
+- u8 assoc_link_id = ifmgd->assoc_data->assoc_link_id;
+ __le16 fc;
+
+ if (WARN_ON(sdata->vif.type != NL80211_IFTYPE_STATION))
+diff --git a/net/wireless/util.c b/net/wireless/util.c
+index 2bde8a3..d03f612 100644
+--- a/net/wireless/util.c
++++ b/net/wireless/util.c
+@@ -2826,6 +2826,14 @@ void cfg80211_remove_links(struct wireless_dev *wdev)
+ {
+ unsigned int link_id;
+
++ if (wdev->iftype == NL80211_IFTYPE_AP_VLAN) {
++ struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
++
++ if (rdev->ops->del_intf_link)
++ rdev->ops->del_intf_link(&rdev->wiphy, wdev, 0);
++
++ return;
++ }
+ /*
+ * links are controlled by upper layers (userspace/cfg)
+ * only for AP mode, so only remove them here for AP
+--
+2.39.2
+
diff --git a/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/mtk-0037-mtk-mac80211-fix-AP-mgmt-not-encrypted-in-WDS-mode-w.patch b/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/0050-mtk-mac80211-fix-AP-mgmt-not-encrypted-in-WDS-mode-w.patch
similarity index 77%
rename from recipes-wifi/linux-mac80211/files/patches-6.x/subsys/mtk-0037-mtk-mac80211-fix-AP-mgmt-not-encrypted-in-WDS-mode-w.patch
rename to recipes-wifi/linux-mac80211/files/patches-6.x/subsys/0050-mtk-mac80211-fix-AP-mgmt-not-encrypted-in-WDS-mode-w.patch
index d0d5004..25fbe6c 100644
--- a/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/mtk-0037-mtk-mac80211-fix-AP-mgmt-not-encrypted-in-WDS-mode-w.patch
+++ b/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/0050-mtk-mac80211-fix-AP-mgmt-not-encrypted-in-WDS-mode-w.patch
@@ -1,7 +1,7 @@
-From 84a875b2506fb720f902540ba23815e7b6958d92 Mon Sep 17 00:00:00 2001
+From de8d3f6fa5fdebd105e1c7e99f635c94e7f37344 Mon Sep 17 00:00:00 2001
From: Michael-CY Lee <michael-cy.lee@mediatek.com>
Date: Thu, 25 Jan 2024 14:07:23 +0800
-Subject: [PATCH 37/37] mtk: mac80211: fix AP mgmt not encrypted in WDS mode
+Subject: [PATCH 50/61] mtk: mac80211: fix AP mgmt not encrypted in WDS mode
with PMF on
In ieee80211_tx_prepare(), if tx->sta is still NULL after calling
@@ -9,6 +9,7 @@
if called to find sta from AP_VLAN, and then interface type & 4-addr
using is checked.
+Change-Id: Ie94fbb22ca2cf7a96d94897e74314b5c61153380
CR-Id: WCNCR00289305
Signed-off-by: Michael-CY Lee <michael-cy.lee@mediatek.com>
---
@@ -16,10 +17,10 @@
1 file changed, 7 insertions(+)
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
-index 0f6c960..8f85193 100644
+index e72bb7e..2808bc2 100644
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
-@@ -1241,6 +1241,13 @@ ieee80211_tx_prepare(struct ieee80211_sub_if_data *sdata,
+@@ -1234,6 +1234,13 @@ ieee80211_tx_prepare(struct ieee80211_sub_if_data *sdata,
if (!tx->sta && !is_multicast_ether_addr(hdr->addr1)) {
tx->sta = sta_info_get(sdata, hdr->addr1);
aggr_check = true;
@@ -34,5 +35,5 @@
}
--
-2.18.0
+2.39.2
diff --git a/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/0051-mtk-mac80211-fix-ieee80211_ht_cap_ie_to_sta_ht_cap-w.patch b/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/0051-mtk-mac80211-fix-ieee80211_ht_cap_ie_to_sta_ht_cap-w.patch
new file mode 100644
index 0000000..e31009b
--- /dev/null
+++ b/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/0051-mtk-mac80211-fix-ieee80211_ht_cap_ie_to_sta_ht_cap-w.patch
@@ -0,0 +1,35 @@
+From edef4ae672b3d124b573c1c9856d6435f30b6bb5 Mon Sep 17 00:00:00 2001
+From: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
+Date: Thu, 15 Feb 2024 14:30:02 +0800
+Subject: [PATCH 51/61] mtk: mac80211: fix ieee80211_ht_cap_ie_to_sta_ht_cap
+ warn on
+
+Fix ieee80211_ht_cap_ie_to_sta_ht_cap warning.
+For MLD with a 2/5G primary link, auth/assoc is done in the 2G or 5G link.
+Therefore, 6G link will enter ieee80211_ht_cap_ie_to_sta_ht_cap, as elems->ht_cap_elem of 2/5G is NOT NULL.
+This should be avoided; otherwise, if 6G is bw 320, then the warning will be triggered.
+
+CR-Id: WCNCR00274293
+Signed-off-by: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
+Change-Id: I3be945036afe677a54e328685fd2fe7b725c6ed5
+---
+ net/mac80211/mlme.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
+index ebdcf57..b9d10e9 100644
+--- a/net/mac80211/mlme.c
++++ b/net/mac80211/mlme.c
+@@ -4398,7 +4398,8 @@ static bool ieee80211_assoc_config_link(struct ieee80211_link_data *link,
+ sband = local->hw.wiphy->bands[link->conf->chanreq.oper.chan->band];
+
+ /* Set up internal HT/VHT capabilities */
+- if (elems->ht_cap_elem && link->u.mgd.conn.mode >= IEEE80211_CONN_MODE_HT)
++ if (elems->ht_cap_elem && link->u.mgd.conn.mode >= IEEE80211_CONN_MODE_HT &&
++ !is_6ghz)
+ ieee80211_ht_cap_ie_to_sta_ht_cap(sdata, sband,
+ elems->ht_cap_elem,
+ link_sta);
+--
+2.39.2
+
diff --git a/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/0052-mtk-mac80211-fix-mac-address-to-support-hw-path-in-s.patch b/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/0052-mtk-mac80211-fix-mac-address-to-support-hw-path-in-s.patch
new file mode 100644
index 0000000..ffba153
--- /dev/null
+++ b/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/0052-mtk-mac80211-fix-mac-address-to-support-hw-path-in-s.patch
@@ -0,0 +1,34 @@
+From 9bd4c9f67e46919eff0f755bfe675a6ac5c1ac4e Mon Sep 17 00:00:00 2001
+From: Peter Chiu <chui-hao.chiu@mediatek.com>
+Date: Fri, 16 Feb 2024 17:38:22 +0800
+Subject: [PATCH 52/61] mtk: mac80211: fix mac address to support hw path in
+ station mode
+
+Use AP's MLD address instead of using deflink.
+
+CR-Id: WCNCR00240772
+Signed-off-by: Peter Chiu <chui-hao.chiu@mediatek.com>
+Change-Id: I6df2419d165406ef9b31ccb19600685d121e6d56
+---
+ net/mac80211/iface.c | 5 ++++-
+ 1 file changed, 4 insertions(+), 1 deletion(-)
+
+diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c
+index 83b579a..026436e 100644
+--- a/net/mac80211/iface.c
++++ b/net/mac80211/iface.c
+@@ -983,7 +983,10 @@ static int ieee80211_netdev_fill_forward_path(struct net_device_path_ctx *ctx,
+ }
+ }
+
+- sta = sta_info_get(sdata, sdata->deflink.u.mgd.bssid);
++ if (ieee80211_vif_is_mld(&sdata->vif))
++ sta = sta_info_get(sdata, sdata->vif.cfg.ap_addr);
++ else
++ sta = sta_info_get(sdata, sdata->deflink.u.mgd.bssid);
+ break;
+ default:
+ goto out;
+--
+2.39.2
+
diff --git a/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/0053-mtk-mac80211-workaround-for-configuring-txpower-in-m.patch b/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/0053-mtk-mac80211-workaround-for-configuring-txpower-in-m.patch
new file mode 100644
index 0000000..3318c20
--- /dev/null
+++ b/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/0053-mtk-mac80211-workaround-for-configuring-txpower-in-m.patch
@@ -0,0 +1,165 @@
+From e564e83652ae93e37f624eac45f98d3ee17cb811 Mon Sep 17 00:00:00 2001
+From: Allen Ye <allen.ye@mediatek.com>
+Date: Thu, 22 Feb 2024 15:21:49 +0800
+Subject: [PATCH 53/61] mtk: mac80211: workaround for configuring txpower in
+ mld ap
+
+As for mt76 design, we expect to set txpower per link. So, we add
+another parameter to ieee80211_recalc_txpower function to set
+txpower to per link. For the functions that mac80211 don't pass link
+id to which, we specify to use the FIRST link as the parameter.
+
+Apply the patch will make uci and iw set txpower commamd only effect
+the link which id is 0 when we enable mld AP.
+
+CR-Id: WCNCR00259302
+---
+ net/mac80211/cfg.c | 15 ++++++++++++---
+ net/mac80211/chan.c | 4 ++--
+ net/mac80211/ieee80211_i.h | 5 +++--
+ net/mac80211/iface.c | 15 ++++++++-------
+ net/mac80211/mlme.c | 2 +-
+ 5 files changed, 26 insertions(+), 15 deletions(-)
+
+diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
+index c3b9d10..cca3e08 100644
+--- a/net/mac80211/cfg.c
++++ b/net/mac80211/cfg.c
+@@ -3059,7 +3059,11 @@ static int ieee80211_set_tx_power(struct wiphy *wiphy,
+ sdata->vif.bss_conf.txpower_type = txp_type;
+ }
+
+- ieee80211_recalc_txpower(sdata, update_txp_type);
++ /* Due to mac80211 not pass link id to here, use first link for now */
++ if (ieee80211_vif_is_mld(&sdata->vif))
++ ieee80211_recalc_txpower(sdata, update_txp_type, sdata->link[0]);
++ else
++ ieee80211_recalc_txpower(sdata, update_txp_type, &sdata->deflink);
+
+ return 0;
+ }
+@@ -3090,7 +3094,12 @@ static int ieee80211_set_tx_power(struct wiphy *wiphy,
+ list_for_each_entry(sdata, &local->interfaces, list) {
+ if (sdata->vif.type == NL80211_IFTYPE_MONITOR)
+ continue;
+- ieee80211_recalc_txpower(sdata, update_txp_type);
++ /* Due to mac80211 not pass link id to here, use first link for now */
++ if (ieee80211_vif_is_mld(&sdata->vif))
++ ieee80211_recalc_txpower(sdata, update_txp_type, sdata->link[0]);
++ else
++ ieee80211_recalc_txpower(sdata, update_txp_type, &sdata->deflink);
++
+ }
+
+ if (has_monitor) {
+@@ -3102,7 +3111,7 @@ static int ieee80211_set_tx_power(struct wiphy *wiphy,
+ update_txp_type = true;
+ sdata->vif.bss_conf.txpower_type = txp_type;
+
+- ieee80211_recalc_txpower(sdata, update_txp_type);
++ ieee80211_recalc_txpower(sdata, update_txp_type, &sdata->deflink);
+ }
+ }
+
+diff --git a/net/mac80211/chan.c b/net/mac80211/chan.c
+index ac22524..f09cac4 100644
+--- a/net/mac80211/chan.c
++++ b/net/mac80211/chan.c
+@@ -842,7 +842,7 @@ out:
+ }
+
+ if (new_ctx && ieee80211_chanctx_num_assigned(local, new_ctx) > 0) {
+- ieee80211_recalc_txpower(sdata, false);
++ ieee80211_recalc_txpower(sdata, false, link);
+ ieee80211_recalc_chanctx_min_def(local, new_ctx, NULL);
+ }
+
+@@ -1570,7 +1570,7 @@ static int ieee80211_vif_use_reserved_switch(struct ieee80211_local *local)
+ link,
+ changed);
+
+- ieee80211_recalc_txpower(sdata, false);
++ ieee80211_recalc_txpower(sdata, false, link);
+ }
+
+ ieee80211_recalc_chanctx_chantype(local, ctx);
+diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
+index 608e442..6f1b783 100644
+--- a/net/mac80211/ieee80211_i.h
++++ b/net/mac80211/ieee80211_i.h
+@@ -2023,9 +2023,10 @@ void ieee80211_sdata_stop(struct ieee80211_sub_if_data *sdata);
+ int ieee80211_add_virtual_monitor(struct ieee80211_local *local);
+ void ieee80211_del_virtual_monitor(struct ieee80211_local *local);
+
+-bool __ieee80211_recalc_txpower(struct ieee80211_sub_if_data *sdata);
++bool __ieee80211_recalc_txpower(struct ieee80211_sub_if_data *sdata,
++ struct ieee80211_link_data *link);
+ void ieee80211_recalc_txpower(struct ieee80211_sub_if_data *sdata,
+- bool update_bss);
++ bool update_bss, struct ieee80211_link_data *link);
+ void ieee80211_recalc_offload(struct ieee80211_local *local);
+
+ static inline bool ieee80211_sdata_running(struct ieee80211_sub_if_data *sdata)
+diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c
+index 026436e..3400811 100644
+--- a/net/mac80211/iface.c
++++ b/net/mac80211/iface.c
+@@ -44,13 +44,14 @@
+
+ static void ieee80211_iface_work(struct wiphy *wiphy, struct wiphy_work *work);
+
+-bool __ieee80211_recalc_txpower(struct ieee80211_sub_if_data *sdata)
++bool __ieee80211_recalc_txpower(struct ieee80211_sub_if_data *sdata,
++ struct ieee80211_link_data *link)
+ {
+ struct ieee80211_chanctx_conf *chanctx_conf;
+ int power;
+
+ rcu_read_lock();
+- chanctx_conf = rcu_dereference(sdata->vif.bss_conf.chanctx_conf);
++ chanctx_conf = rcu_dereference(link->conf->chanctx_conf);
+ if (!chanctx_conf) {
+ rcu_read_unlock();
+ return false;
+@@ -65,8 +66,8 @@ bool __ieee80211_recalc_txpower(struct ieee80211_sub_if_data *sdata)
+ if (sdata->deflink.ap_power_level != IEEE80211_UNSET_POWER_LEVEL)
+ power = min(power, sdata->deflink.ap_power_level);
+
+- if (power != sdata->vif.bss_conf.txpower) {
+- sdata->vif.bss_conf.txpower = power;
++ if (power != link->conf->txpower) {
++ link->conf->txpower = power;
+ ieee80211_hw_config(sdata->local, 0);
+ return true;
+ }
+@@ -75,11 +76,11 @@ bool __ieee80211_recalc_txpower(struct ieee80211_sub_if_data *sdata)
+ }
+
+ void ieee80211_recalc_txpower(struct ieee80211_sub_if_data *sdata,
+- bool update_bss)
++ bool update_bss, struct ieee80211_link_data *link)
+ {
+- if (__ieee80211_recalc_txpower(sdata) ||
++ if (__ieee80211_recalc_txpower(sdata, link) ||
+ (update_bss && ieee80211_sdata_running(sdata)))
+- ieee80211_link_info_change_notify(sdata, &sdata->deflink,
++ ieee80211_link_info_change_notify(sdata, link,
+ BSS_CHANGED_TXPOWER);
+ }
+
+diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
+index b9d10e9..2efd98e 100644
+--- a/net/mac80211/mlme.c
++++ b/net/mac80211/mlme.c
+@@ -2362,7 +2362,7 @@ static u64 ieee80211_handle_pwr_constr(struct ieee80211_link_data *link,
+ }
+
+ link->ap_power_level = new_ap_level;
+- if (__ieee80211_recalc_txpower(sdata))
++ if (__ieee80211_recalc_txpower(sdata, link))
+ return BSS_CHANGED_TXPOWER;
+ return 0;
+ }
+--
+2.39.2
+
diff --git a/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/0054-mtk-mac80211-send-broadcast-multicast-mgmt.-via-all-.patch b/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/0054-mtk-mac80211-send-broadcast-multicast-mgmt.-via-all-.patch
new file mode 100644
index 0000000..35c82f2
--- /dev/null
+++ b/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/0054-mtk-mac80211-send-broadcast-multicast-mgmt.-via-all-.patch
@@ -0,0 +1,49 @@
+From 487ac10c66d16a0dd2ef526b7223cce87cbded40 Mon Sep 17 00:00:00 2001
+From: Michael-CY Lee <michael-cy.lee@mediatek.com>
+Date: Wed, 21 Feb 2024 16:32:13 +0800
+Subject: [PATCH 54/61] mtk: mac80211: send broadcast/multicast mgmt. via all
+ links.
+
+This patch makes broadcast/multicast mgmt. be sent via all links.
+
+CR-Id: WCNCR00289305
+Signed-off-by: Michael-CY Lee <michael-cy.lee@mediatek.com>
+Change-id: Id1bd06694a73cc29b3f571a57c4c864ee3742441
+---
+ net/mac80211/offchannel.c | 20 +++++++++++++++++++-
+ 1 file changed, 19 insertions(+), 1 deletion(-)
+
+diff --git a/net/mac80211/offchannel.c b/net/mac80211/offchannel.c
+index 3ed5fc5..ec1d7a1 100644
+--- a/net/mac80211/offchannel.c
++++ b/net/mac80211/offchannel.c
+@@ -976,7 +976,25 @@ int ieee80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev,
+ }
+
+ if (!need_offchan) {
+- ieee80211_tx_skb_tid(sdata, skb, 7, link_id);
++ unsigned long links = sdata->vif.active_links;
++ if (is_multicast_ether_addr(mgmt->da) && hweight16(links) > 1) {
++ unsigned int link;
++ struct sk_buff *dskb;
++
++ for_each_set_bit(link, &links, IEEE80211_MLD_MAX_NUM_LINKS) {
++ dskb = skb_clone(skb, GFP_ATOMIC);
++ if (dskb) {
++ ieee80211_tx_skb_tid(sdata, dskb, 7, link);
++ } else {
++ ret = -ENOMEM;
++ kfree_skb(skb);
++ goto out_unlock;
++ }
++ }
++ kfree_skb(skb);
++ } else {
++ ieee80211_tx_skb_tid(sdata, skb, 7, link_id);
++ }
+ ret = 0;
+ goto out_unlock;
+ }
+--
+2.39.2
+
diff --git a/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/0055-mtk-mac80211-fix-mlo-BW-160-channel-switch-issue.patch b/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/0055-mtk-mac80211-fix-mlo-BW-160-channel-switch-issue.patch
new file mode 100644
index 0000000..cd79879
--- /dev/null
+++ b/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/0055-mtk-mac80211-fix-mlo-BW-160-channel-switch-issue.patch
@@ -0,0 +1,32 @@
+From 6d5903a35436fb71f4a245f7b9ddd6279d640adc Mon Sep 17 00:00:00 2001
+From: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
+Date: Fri, 15 Mar 2024 14:34:11 +0800
+Subject: [PATCH 55/61] mtk: mac80211: fix mlo BW 160 channel switch issue
+
+The link_id argument for cfg80211_ch_switch_started_notify is missing
+after maintainer rebasing for chanreq
+The original commit has link_id instead of 0
+https://patchwork.kernel.org/project/linux-wireless/list/?series=821321&state=*
+
+CR-Id: WCNCR00274293
+Signed-off-by: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
+---
+ net/mac80211/cfg.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
+index cca3e08..856c956 100644
+--- a/net/mac80211/cfg.c
++++ b/net/mac80211/cfg.c
+@@ -4045,7 +4045,7 @@ __ieee80211_channel_switch(struct wiphy *wiphy, struct net_device *dev,
+ }
+
+ cfg80211_ch_switch_started_notify(sdata->dev,
+- &link_data->csa_chanreq.oper, 0,
++ &link_data->csa_chanreq.oper, link_id,
+ params->count, params->block_tx);
+
+ if (changed) {
+--
+2.39.2
+
diff --git a/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/0056-mtk-mac80211-extend-IEEE80211_KEY_FLAG_GENERATE_MMIE.patch b/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/0056-mtk-mac80211-extend-IEEE80211_KEY_FLAG_GENERATE_MMIE.patch
new file mode 100644
index 0000000..3a2ff85
--- /dev/null
+++ b/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/0056-mtk-mac80211-extend-IEEE80211_KEY_FLAG_GENERATE_MMIE.patch
@@ -0,0 +1,64 @@
+From 67aa5809167470add6b82fb0049ce6d33327592e Mon Sep 17 00:00:00 2001
+From: Michael-CY Lee <michael-cy.lee@mediatek.com>
+Date: Thu, 21 Mar 2024 10:58:59 +0800
+Subject: [PATCH 56/61] mtk: mac80211: extend IEEE80211_KEY_FLAG_GENERATE_MMIE
+ to other ciphers
+
+This commit extends the flag IEEE80211_KEY_FLAG_GENERATE_MMIE to
+CMAC-256 and GMAC for the same reason that this flag was added.
+(a0b449: mac80211: add IEEE80211_KEY_FLAG_GENERATE_MMIE to ieee80211_key_flags)
+
+CR-Id: WCNCR00289305
+Signed-off-by: Michael-CY Lee <michael-cy.lee@mediatek.com>
+Change-Id: I0ce5f8894de42a42e257ffce75c51399a440f003
+---
+ net/mac80211/wpa.c | 12 ++++++++++--
+ 1 file changed, 10 insertions(+), 2 deletions(-)
+
+diff --git a/net/mac80211/wpa.c b/net/mac80211/wpa.c
+index daf1bcc..e66f917 100644
+--- a/net/mac80211/wpa.c
++++ b/net/mac80211/wpa.c
+@@ -903,7 +903,8 @@ ieee80211_crypto_aes_cmac_256_encrypt(struct ieee80211_tx_data *tx)
+
+ info = IEEE80211_SKB_CB(skb);
+
+- if (info->control.hw_key)
++ if (info->control.hw_key &&
++ !(key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_MMIE))
+ return TX_CONTINUE;
+
+ if (WARN_ON(skb_tailroom(skb) < sizeof(*mmie)))
+@@ -919,6 +920,9 @@ ieee80211_crypto_aes_cmac_256_encrypt(struct ieee80211_tx_data *tx)
+
+ bip_ipn_set64(mmie->sequence_number, pn64);
+
++ if (info->control.hw_key)
++ return TX_CONTINUE;
++
+ bip_aad(skb, aad);
+
+ /* MIC = AES-256-CMAC(IGTK, AAD || Management Frame Body || MMIE, 128)
+@@ -1048,7 +1052,8 @@ ieee80211_crypto_aes_gmac_encrypt(struct ieee80211_tx_data *tx)
+
+ info = IEEE80211_SKB_CB(skb);
+
+- if (info->control.hw_key)
++ if (info->control.hw_key &&
++ !(key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_MMIE))
+ return TX_CONTINUE;
+
+ if (WARN_ON(skb_tailroom(skb) < sizeof(*mmie)))
+@@ -1064,6 +1069,9 @@ ieee80211_crypto_aes_gmac_encrypt(struct ieee80211_tx_data *tx)
+
+ bip_ipn_set64(mmie->sequence_number, pn64);
+
++ if (info->control.hw_key)
++ return TX_CONTINUE;
++
+ bip_aad(skb, aad);
+
+ hdr = (struct ieee80211_hdr *)skb->data;
+--
+2.39.2
+
diff --git a/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/0057-mtk-wifi-mt76-mt7996-not-to-check-need_offchan-for-M.patch b/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/0057-mtk-wifi-mt76-mt7996-not-to-check-need_offchan-for-M.patch
new file mode 100644
index 0000000..1995700
--- /dev/null
+++ b/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/0057-mtk-wifi-mt76-mt7996-not-to-check-need_offchan-for-M.patch
@@ -0,0 +1,33 @@
+From 4bd23c637585903378fcd35828cd9d0e01d7d565 Mon Sep 17 00:00:00 2001
+From: Michael-CY Lee <michael-cy.lee@mediatek.com>
+Date: Mon, 25 Mar 2024 18:59:35 +0800
+Subject: [PATCH 57/61] mtk: wifi: mt76: mt7996: not to check 'need_offchan'
+ for MLD multicast mgmt.
+
+Multicast mgmt. sent by the MLD AP should be transmitted via all links,
+so it is not necessary to check 'need_offchan'.
+
+CR-Id: WCNCR00289305
+Signed-off-by: Michael-CY Lee <michael-cy.lee@mediatek.com>
+Change-Id: I850d337ea98456b8d81fd767ceea1727333aa6ca
+---
+ net/mac80211/offchannel.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/net/mac80211/offchannel.c b/net/mac80211/offchannel.c
+index ec1d7a1..a571be0 100644
+--- a/net/mac80211/offchannel.c
++++ b/net/mac80211/offchannel.c
+@@ -874,7 +874,8 @@ int ieee80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev,
+ /* Check if the operating channel is the requested channel */
+ if (!params->chan && mlo_sta) {
+ need_offchan = false;
+- } else if (!need_offchan) {
++ } else if (!need_offchan && !(ieee80211_vif_is_mld(&sdata->vif) &&
++ is_multicast_ether_addr(mgmt->da))) {
+ struct ieee80211_chanctx_conf *chanctx_conf = NULL;
+ int i;
+
+--
+2.39.2
+
diff --git a/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/0058-mtk-wifi-mt76-mt7996-assign-link-address-to-the-head.patch b/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/0058-mtk-wifi-mt76-mt7996-assign-link-address-to-the-head.patch
new file mode 100644
index 0000000..eb8db1a
--- /dev/null
+++ b/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/0058-mtk-wifi-mt76-mt7996-assign-link-address-to-the-head.patch
@@ -0,0 +1,54 @@
+From 70e027ce4ac9e4de16829c88ee846b7e12f14953 Mon Sep 17 00:00:00 2001
+From: Michael-CY Lee <michael-cy.lee@mediatek.com>
+Date: Mon, 25 Mar 2024 16:26:34 +0800
+Subject: [PATCH 58/61] mtk: wifi: mt76: mt7996: assign link address to the
+ header of broadcast mgmt.
+
+AAD calculation should use link addr as input for broadcast mgmt. skb.
+This commit assigns link address to the header of cloned broadcast mgmt.
+for the correct AAD calculation.
+
+CR-Id: WCNCR00289305
+Signed-off-by: Michael-CY Lee <michael-cy.lee@mediatek.com>
+Change-Id: Ieeee17cc2121fdbc9eb34f171f2d4da583d91154
+---
+ net/mac80211/offchannel.c | 16 +++++++++++++---
+ 1 file changed, 13 insertions(+), 3 deletions(-)
+
+diff --git a/net/mac80211/offchannel.c b/net/mac80211/offchannel.c
+index a571be0..15948f9 100644
+--- a/net/mac80211/offchannel.c
++++ b/net/mac80211/offchannel.c
+@@ -981,16 +981,26 @@ int ieee80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev,
+ if (is_multicast_ether_addr(mgmt->da) && hweight16(links) > 1) {
+ unsigned int link;
+ struct sk_buff *dskb;
++ struct ieee80211_hdr *hdr;
++ struct ieee80211_bss_conf *conf;
+
+ for_each_set_bit(link, &links, IEEE80211_MLD_MAX_NUM_LINKS) {
++ conf = rcu_dereference(sdata->vif.link_conf[link]);
++ if (!conf)
++ continue;
++
+ dskb = skb_clone(skb, GFP_ATOMIC);
+- if (dskb) {
+- ieee80211_tx_skb_tid(sdata, dskb, 7, link);
+- } else {
++ if (!dskb) {
+ ret = -ENOMEM;
+ kfree_skb(skb);
+ goto out_unlock;
+ }
++
++ /* Assign link address */
++ hdr = (void *)dskb->data;
++ memcpy(hdr->addr2, conf->addr, ETH_ALEN);
++ memcpy(hdr->addr3, conf->addr, ETH_ALEN);
++ ieee80211_tx_skb_tid(sdata, dskb, 7, link);
+ }
+ kfree_skb(skb);
+ } else {
+--
+2.39.2
+
diff --git a/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/0059-mtk-wifi-mt76-mt7996-Do-MLD-address-translation-befo.patch b/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/0059-mtk-wifi-mt76-mt7996-Do-MLD-address-translation-befo.patch
new file mode 100644
index 0000000..2a098b4
--- /dev/null
+++ b/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/0059-mtk-wifi-mt76-mt7996-Do-MLD-address-translation-befo.patch
@@ -0,0 +1,45 @@
+From 0f6fde17638d83518432f95ef7b75f2ef883ff1e Mon Sep 17 00:00:00 2001
+From: Michael-CY Lee <michael-cy.lee@mediatek.com>
+Date: Tue, 26 Mar 2024 11:36:35 +0800
+Subject: [PATCH 59/61] mtk: wifi: mt76: mt7996: Do MLD address translation
+ before STA process BMC mgmt. frame
+
+In the function ieee80211_prepare_and_rx_handle(), BMC mgmt. frames are
+not MLD translated since the AAD calculation needs the header being link
+addressed. However, after the AAD calculation, STA processes the mgmt.
+frames on an MLD level, and it fails to match the link address in the
+header with the self MLD address.
+
+This commit does MLD address translation again after the AAD calculation
+and before STA's mgmt. frames processing.
+
+CR-Id: WCNCR00289305
+Signed-off-by: Michael-CY Lee <michael-cy.lee@mediatek.com>
+Change-Id: I2a96ced315780b09f0cfc142f0f09b5f4a9a7312
+---
+ net/mac80211/mlme.c | 9 +++++++++
+ 1 file changed, 9 insertions(+)
+
+diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
+index 2efd98e..e4d5eac 100644
+--- a/net/mac80211/mlme.c
++++ b/net/mac80211/mlme.c
+@@ -6931,6 +6931,15 @@ void ieee80211_sta_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata,
+ return;
+ }
+
++ /* Do MLD address translation for Multicast/Broadcast frame. */
++ if (is_multicast_ether_addr(mgmt->da) && !ieee80211_is_probe_resp(fc) &&
++ !ieee80211_is_beacon(fc)) {
++ if (ether_addr_equal(mgmt->sa, link->conf->bssid))
++ ether_addr_copy(mgmt->sa, sdata->vif.cfg.ap_addr);
++ if (ether_addr_equal(mgmt->bssid, link->conf->bssid))
++ ether_addr_copy(mgmt->bssid, sdata->vif.cfg.ap_addr);
++ }
++
+ switch (fc & IEEE80211_FCTL_STYPE) {
+ case IEEE80211_STYPE_BEACON:
+ ieee80211_rx_mgmt_beacon(link, (void *)mgmt,
+--
+2.39.2
+
diff --git a/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/0060-mtk-wifi-mac80211-defer-enabling-beacon-for-MLD-AP.patch b/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/0060-mtk-wifi-mac80211-defer-enabling-beacon-for-MLD-AP.patch
new file mode 100644
index 0000000..a3ead0e
--- /dev/null
+++ b/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/0060-mtk-wifi-mac80211-defer-enabling-beacon-for-MLD-AP.patch
@@ -0,0 +1,46 @@
+From 5b90a58e50482689a246cfce127bc44ad05f79af Mon Sep 17 00:00:00 2001
+From: Shayne Chen <shayne.chen@mediatek.com>
+Date: Fri, 12 Apr 2024 11:45:41 +0800
+Subject: [PATCH 60/61] mtk: wifi: mac80211: defer enabling beacon for MLD AP
+
+Do not enable beacon on the first beacon update (NL80211_CMD_NEW_BEACON)
+for MLD AP, let it start from the next beacon update
+(NL80211_CMD_SET_BEACON).
+This is used to make sure that MLD AP start beacon after all links
+finish settings.
+
+CR-Id: WCNCR00238098
+Signed-off-by: Shayne Chen <shayne.chen@mediatek.com>
+Change-Id: Id2a4137b9101bae3777037f8d26b0380bfe1da48
+---
+ net/mac80211/cfg.c | 7 ++++++-
+ 1 file changed, 6 insertions(+), 1 deletion(-)
+
+diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
+index 856c956..e091ccd 100644
+--- a/net/mac80211/cfg.c
++++ b/net/mac80211/cfg.c
+@@ -1424,7 +1424,7 @@ static int ieee80211_start_ap(struct wiphy *wiphy, struct net_device *dev,
+ }
+
+ link_conf->dtim_period = params->dtim_period;
+- link_conf->enable_beacon = true;
++ link_conf->enable_beacon = !ieee80211_vif_is_mld(&sdata->vif);
+ link_conf->allow_p2p_go_ps = sdata->vif.p2p;
+ link_conf->twt_responder = params->twt_responder;
+ link_conf->he_obss_pd = params->he_obss_pd;
+@@ -1491,6 +1491,11 @@ static int ieee80211_start_ap(struct wiphy *wiphy, struct net_device *dev,
+ ieee80211_recalc_dtim(local, sdata);
+ ieee80211_vif_cfg_change_notify(sdata, BSS_CHANGED_SSID);
+ ieee80211_link_info_change_notify(sdata, link, changed);
++ /* for MLD AP, enable_beacon is false during the first beacon set,
++ * enable it after that. This allows userspace to control the
++ * beacon enable timing.
++ */
++ link_conf->enable_beacon = true;
+
+ if (ieee80211_num_beaconing_links(sdata) <= 1)
+ netif_carrier_on(dev);
+--
+2.39.2
+
diff --git a/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/0061-mtk-wifi-mac80211-fix-radar-trigger-issue-due-to-ref.patch b/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/0061-mtk-wifi-mac80211-fix-radar-trigger-issue-due-to-ref.patch
new file mode 100644
index 0000000..6673cb6
--- /dev/null
+++ b/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/0061-mtk-wifi-mac80211-fix-radar-trigger-issue-due-to-ref.patch
@@ -0,0 +1,31 @@
+From 250ed9ee9f5f7e422dd4d96c1ba328b517c55040 Mon Sep 17 00:00:00 2001
+From: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
+Date: Thu, 18 Apr 2024 18:08:48 +0800
+Subject: [PATCH 61/61] mtk: wifi: mac80211: fix radar trigger issue due to
+ refactoring to single wiphy
+
+Since we change to single wiphy, we cannot directly return during cac cancel if the link conf in local->interfaces list is not for 5G band.
+local->interfaces might contain 2/5/6G sdata
+
+CR-Id: WCNCR00274293
+Signed-off-by: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
+---
+ net/mac80211/util.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/net/mac80211/util.c b/net/mac80211/util.c
+index 732232a..d030ebc 100644
+--- a/net/mac80211/util.c
++++ b/net/mac80211/util.c
+@@ -3469,7 +3469,7 @@ void ieee80211_dfs_cac_cancel(struct ieee80211_local *local, unsigned int link_i
+
+ if (link->conf->chanreq.oper.chan &&
+ link->conf->chanreq.oper.chan->band != NL80211_BAND_5GHZ)
+- return;
++ continue;
+
+ wiphy_delayed_work_cancel(local->hw.wiphy,
+ &link->dfs_cac_timer_work);
+--
+2.39.2
+
diff --git a/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/110-mac80211_keep_keys_on_stop_ap.patch b/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/110-mac80211_keep_keys_on_stop_ap.patch
deleted file mode 100644
index 7bf99be..0000000
--- a/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/110-mac80211_keep_keys_on_stop_ap.patch
+++ /dev/null
@@ -1,19 +0,0 @@
-From: Felix Fietkau <nbd@nbd.name>
-Date: Mon, 27 Oct 2014 00:00:00 +0100
-Subject: [PATCH] mac80211: preseve AP mode keys across STA reconnect
-
-Used for AP+STA support in OpenWrt - preserve AP mode keys across STA reconnect
----
- net/mac80211/cfg.c | 1 -
- 1 file changed, 1 deletion(-)
-
---- a/net/mac80211/cfg.c
-+++ b/net/mac80211/cfg.c
-@@ -1635,7 +1635,6 @@ static int ieee80211_stop_ap(struct wiph
- link_conf->bssid_indicator = 0;
-
- __sta_info_flush(sdata, true);
-- ieee80211_free_keys(sdata, true);
-
- link_conf->enable_beacon = false;
- sdata->beacon_rate_set = false;
diff --git a/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/120-cfg80211_allow_perm_addr_change.patch b/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/120-cfg80211_allow_perm_addr_change.patch
deleted file mode 100644
index f315ae5..0000000
--- a/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/120-cfg80211_allow_perm_addr_change.patch
+++ /dev/null
@@ -1,52 +0,0 @@
-From: Felix Fietkau <nbd@nbd.name>
-Date: Thu, 11 Dec 2014 00:00:00 +0100
-Subject: [PATCH] cfg80211: add support for changing the device mac address via
- sysfs
-
----
- net/wireless/sysfs.c | 27 ++++++++++++++++++++++-----
- 1 file changed, 22 insertions(+), 5 deletions(-)
-
---- a/net/wireless/sysfs.c
-+++ b/net/wireless/sysfs.c
-@@ -24,18 +24,35 @@ static inline struct cfg80211_registered
- return container_of(dev, struct cfg80211_registered_device, wiphy.dev);
- }
-
--#define SHOW_FMT(name, fmt, member) \
-+#define SHOW_FMT(name, fmt, member, mode) \
- static ssize_t name ## _show(struct device *dev, \
- struct device_attribute *attr, \
- char *buf) \
- { \
- return sprintf(buf, fmt "\n", dev_to_rdev(dev)->member); \
- } \
--static DEVICE_ATTR_RO(name)
-+static DEVICE_ATTR_##mode(name)
-
--SHOW_FMT(index, "%d", wiphy_idx);
--SHOW_FMT(macaddress, "%pM", wiphy.perm_addr);
--SHOW_FMT(address_mask, "%pM", wiphy.addr_mask);
-+static ssize_t macaddress_store(struct device *dev,
-+ struct device_attribute *attr,
-+ const char *buf, size_t len)
-+{
-+ u8 mac[ETH_ALEN];
-+
-+ if (!mac_pton(buf, mac))
-+ return -EINVAL;
-+
-+ if (buf[3 * ETH_ALEN - 1] && buf[3 * ETH_ALEN - 1] != '\n')
-+ return -EINVAL;
-+
-+ memcpy(dev_to_rdev(dev)->wiphy.perm_addr, mac, ETH_ALEN);
-+
-+ return strnlen(buf, len);
-+}
-+
-+SHOW_FMT(index, "%d", wiphy_idx, RO);
-+SHOW_FMT(macaddress, "%pM", wiphy.perm_addr, RW);
-+SHOW_FMT(address_mask, "%pM", wiphy.addr_mask, RO);
-
- static ssize_t name_show(struct device *dev,
- struct device_attribute *attr,
diff --git a/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/130-disable_auto_vif.patch b/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/130-disable_auto_vif.patch
deleted file mode 100644
index 43507f2..0000000
--- a/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/130-disable_auto_vif.patch
+++ /dev/null
@@ -1,27 +0,0 @@
---- a/net/mac80211/main.c
-+++ b/net/mac80211/main.c
-@@ -1393,24 +1393,6 @@ int ieee80211_register_hw(struct ieee802
- debugfs_hw_add(local);
- rate_control_add_debugfs(local);
-
-- rtnl_lock();
-- wiphy_lock(hw->wiphy);
--
-- /* add one default STA interface if supported */
-- if (local->hw.wiphy->interface_modes & BIT(NL80211_IFTYPE_STATION) &&
-- !ieee80211_hw_check(hw, NO_AUTO_VIF)) {
-- struct vif_params params = {0};
--
-- result = ieee80211_if_add(local, "wlan%d", NET_NAME_ENUM, NULL,
-- NL80211_IFTYPE_STATION, ¶ms);
-- if (result)
-- wiphy_warn(local->hw.wiphy,
-- "Failed to add default virtual iface\n");
-- }
--
-- wiphy_unlock(hw->wiphy);
-- rtnl_unlock();
--
- #ifdef CONFIG_INET
- local->ifa_notifier.notifier_call = ieee80211_ifa_changed;
- result = register_inetaddr_notifier(&local->ifa_notifier);
diff --git a/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/210-ap_scan.patch b/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/210-ap_scan.patch
deleted file mode 100644
index 1e9676f..0000000
--- a/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/210-ap_scan.patch
+++ /dev/null
@@ -1,19 +0,0 @@
-From: Felix Fietkau <nbd@nbd.name>
-Date: Wed, 3 Oct 2012 00:00:00 +0200
-Subject: [PATCH] mac80211: allow scans in access point mode (for site survey)
-
----
- net/mac80211/cfg.c | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
---- a/net/mac80211/cfg.c
-+++ b/net/mac80211/cfg.c
-@@ -2847,6 +2847,8 @@ static int ieee80211_scan(struct wiphy *
- */
- fallthrough;
- case NL80211_IFTYPE_AP:
-+ /* skip check */
-+ break;
- /*
- * If the scan has been forced (and the driver supports
- * forcing), don't care about being beaconing already.
diff --git a/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/301-mac80211-sta-randomize-BA-session-dialog-token-alloc.patch b/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/301-mac80211-sta-randomize-BA-session-dialog-token-alloc.patch
deleted file mode 100644
index 1034e2c..0000000
--- a/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/301-mac80211-sta-randomize-BA-session-dialog-token-alloc.patch
+++ /dev/null
@@ -1,42 +0,0 @@
-From b478e06a16a8baa00c5ecc87c1d636981f2206d5 Mon Sep 17 00:00:00 2001
-From: Johannes Berg <johannes.berg@intel.com>
-Date: Tue, 29 Oct 2019 10:25:25 +0100
-Subject: [PATCH] mac80211: sta: randomize BA session dialog token allocator
-
-We currently always start the dialog token generator at zero,
-so the first dialog token we use is always 1. This would be
-OK if we had a perfect guarantee that we always do a proper
-deauth/re-auth handshake, but in IBSS mode this doesn't always
-happen properly.
-
-To make problems with block ack (aggregation) sessions getting
-stuck less likely, randomize the dialog token so if we start a
-new session but the peer still has old state for us, it can
-better detect this.
-
-This is really just a workaround to make things a bit more
-robust than they are now - a better fix would be to do a full
-authentication handshake in IBSS mode upon having discovered a
-new station, and on the receiver resetting the state (removing
-and re-adding the station) on receiving the authentication
-packet.
-
-Signed-off-by: Johannes Berg <johannes.berg@intel.com>
----
- net/mac80211/sta_info.c | 1 +
- 1 file changed, 1 insertion(+)
-
---- a/net/mac80211/sta_info.c
-+++ b/net/mac80211/sta_info.c
-@@ -561,6 +561,11 @@ __sta_info_alloc(struct ieee80211_sub_if
- INIT_WORK(&sta->drv_deliver_wk, sta_deliver_ps_frames);
- INIT_WORK(&sta->ampdu_mlme.work, ieee80211_ba_session_work);
- mutex_init(&sta->ampdu_mlme.mtx);
-+#if LINUX_VERSION_IS_LESS(6,2,0)
-+ sta->ampdu_mlme.dialog_token_allocator = prandom_u32_max(U8_MAX);
-+#else
-+ sta->ampdu_mlme.dialog_token_allocator = get_random_u32_below(U8_MAX);
-+#endif
- #ifdef CPTCFG_MAC80211_MESH
- if (ieee80211_vif_is_mesh(&sdata->vif)) {
- sta->mesh = kzalloc(sizeof(*sta->mesh), gfp);
diff --git a/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/302-mac80211-minstrel_ht-fix-MINSTREL_FRAC-macro.patch b/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/302-mac80211-minstrel_ht-fix-MINSTREL_FRAC-macro.patch
deleted file mode 100644
index 0d475b7..0000000
--- a/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/302-mac80211-minstrel_ht-fix-MINSTREL_FRAC-macro.patch
+++ /dev/null
@@ -1,21 +0,0 @@
-From: Felix Fietkau <nbd@nbd.name>
-Date: Wed, 28 Apr 2021 21:03:13 +0200
-Subject: [PATCH] mac80211: minstrel_ht: fix MINSTREL_FRAC macro
-
-Add missing braces to avoid issues with e.g. using additions in the
-div expression
-
-Signed-off-by: Felix Fietkau <nbd@nbd.name>
----
-
---- a/net/mac80211/rc80211_minstrel_ht.h
-+++ b/net/mac80211/rc80211_minstrel_ht.h
-@@ -14,7 +14,7 @@
-
- /* scaled fraction values */
- #define MINSTREL_SCALE 12
--#define MINSTREL_FRAC(val, div) (((val) << MINSTREL_SCALE) / div)
-+#define MINSTREL_FRAC(val, div) (((val) << MINSTREL_SCALE) / (div))
- #define MINSTREL_TRUNC(val) ((val) >> MINSTREL_SCALE)
-
- #define EWMA_LEVEL 96 /* ewma weighting factor [/EWMA_DIV] */
diff --git a/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/303-mac80211-minstrel_ht-reduce-fluctuations-in-rate-pro.patch b/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/303-mac80211-minstrel_ht-reduce-fluctuations-in-rate-pro.patch
deleted file mode 100644
index f26477e..0000000
--- a/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/303-mac80211-minstrel_ht-reduce-fluctuations-in-rate-pro.patch
+++ /dev/null
@@ -1,30 +0,0 @@
-From: Felix Fietkau <nbd@nbd.name>
-Date: Sat, 6 Feb 2021 16:08:01 +0100
-Subject: [PATCH] mac80211: minstrel_ht: reduce fluctuations in rate
- probability stats
-
-In some scenarios when there is a lot of fluctuation in packet error rates,
-rate switching can be amplified when the statistics get skewed by time slots
-with very few tries.
-Make the input data to the moving average more smooth by adding the
-success/attempts count from the last stats window as well. This has the
-advantage of smoothing the data without introducing any extra lag to sampling
-rates.
-This significantly improves rate stability on a strong test link subjected to
-periodic noise bursts generated with a SDR
-
-Signed-off-by: Felix Fietkau <nbd@nbd.name>
----
-
---- a/net/mac80211/rc80211_minstrel_ht.c
-+++ b/net/mac80211/rc80211_minstrel_ht.c
-@@ -769,7 +769,8 @@ minstrel_ht_calc_rate_stats(struct minst
- unsigned int cur_prob;
-
- if (unlikely(mrs->attempts > 0)) {
-- cur_prob = MINSTREL_FRAC(mrs->success, mrs->attempts);
-+ cur_prob = MINSTREL_FRAC(mrs->success + mrs->last_success,
-+ mrs->attempts + mrs->last_attempts);
- minstrel_filter_avg_add(&mrs->prob_avg,
- &mrs->prob_avg_1, cur_prob);
- mrs->att_hist += mrs->attempts;
diff --git a/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/304-mac80211-minstrel_ht-rework-rate-downgrade-code-and-.patch b/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/304-mac80211-minstrel_ht-rework-rate-downgrade-code-and-.patch
deleted file mode 100644
index 9b3cc3a..0000000
--- a/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/304-mac80211-minstrel_ht-rework-rate-downgrade-code-and-.patch
+++ /dev/null
@@ -1,151 +0,0 @@
-From: Felix Fietkau <nbd@nbd.name>
-Date: Sat, 6 Feb 2021 16:33:14 +0100
-Subject: [PATCH] mac80211: minstrel_ht: rework rate downgrade code and
- max_prob rate selection
-
-The current fallback code for fast rate switching on potentially failing rates
-is triggering too often if there is some strong noise on the channel. This can
-lead to wild fluctuations in the rate selection.
-Additionally, switching down to max_prob_rate can create a significant gap down
-in throughput, especially when using only 2 spatial streams, because max_prob_rate
-is limited to using fewer streams than the max_tp rates.
-In order to improve throughput without reducing reliability too much, use the
-rate downgrade code for the max_prob_rate only, and allow the non-downgraded
-max_prob_rate to use as many spatial streams as the max_tp rates
-
-Signed-off-by: Felix Fietkau <nbd@nbd.name>
----
-
---- a/net/mac80211/rc80211_minstrel_ht.c
-+++ b/net/mac80211/rc80211_minstrel_ht.c
-@@ -580,6 +580,14 @@ minstrel_ht_set_best_prob_rate(struct mi
- int cur_tp_avg, cur_group, cur_idx;
- int max_gpr_group, max_gpr_idx;
- int max_gpr_tp_avg, max_gpr_prob;
-+ int min_dur;
-+
-+ min_dur = max(minstrel_get_duration(mi->max_tp_rate[0]),
-+ minstrel_get_duration(mi->max_tp_rate[1]));
-+
-+ /* make the rate at least 18% slower than max tp rates */
-+ if (minstrel_get_duration(index) <= min_dur * 19 / 16)
-+ return;
-
- cur_group = MI_RATE_GROUP(index);
- cur_idx = MI_RATE_IDX(index);
-@@ -601,11 +609,6 @@ minstrel_ht_set_best_prob_rate(struct mi
- !minstrel_ht_is_legacy_group(max_tp_group))
- return;
-
-- /* skip rates faster than max tp rate with lower prob */
-- if (minstrel_get_duration(mi->max_tp_rate[0]) > minstrel_get_duration(index) &&
-- mrs->prob_avg < max_tp_prob)
-- return;
--
- max_gpr_group = MI_RATE_GROUP(mg->max_group_prob_rate);
- max_gpr_idx = MI_RATE_IDX(mg->max_group_prob_rate);
- max_gpr_prob = mi->groups[max_gpr_group].rates[max_gpr_idx].prob_avg;
-@@ -663,40 +666,6 @@ minstrel_ht_assign_best_tp_rates(struct
-
- }
-
--/*
-- * Try to increase robustness of max_prob rate by decrease number of
-- * streams if possible.
-- */
--static inline void
--minstrel_ht_prob_rate_reduce_streams(struct minstrel_ht_sta *mi)
--{
-- struct minstrel_mcs_group_data *mg;
-- int tmp_max_streams, group, tmp_idx, tmp_prob;
-- int tmp_tp = 0;
--
-- if (!mi->sta->deflink.ht_cap.ht_supported)
-- return;
--
-- group = MI_RATE_GROUP(mi->max_tp_rate[0]);
-- tmp_max_streams = minstrel_mcs_groups[group].streams;
-- for (group = 0; group < ARRAY_SIZE(minstrel_mcs_groups); group++) {
-- mg = &mi->groups[group];
-- if (!mi->supported[group] || group == MINSTREL_CCK_GROUP)
-- continue;
--
-- tmp_idx = MI_RATE_IDX(mg->max_group_prob_rate);
-- 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)) {
-- mi->max_prob_rate = mg->max_group_prob_rate;
-- tmp_tp = minstrel_ht_get_tp_avg(mi, group,
-- tmp_idx,
-- tmp_prob);
-- }
-- }
--}
--
- static u16
- __minstrel_ht_get_sample_rate(struct minstrel_ht_sta *mi,
- enum minstrel_sample_type type)
-@@ -1176,8 +1145,6 @@ minstrel_ht_update_stats(struct minstrel
-
- mi->max_prob_rate = tmp_max_prob_rate;
-
-- /* Try to increase robustness of max_prob_rate*/
-- minstrel_ht_prob_rate_reduce_streams(mi);
- minstrel_ht_refill_sample_rates(mi);
-
- #ifdef CPTCFG_MAC80211_DEBUGFS
-@@ -1256,7 +1223,7 @@ minstrel_ht_ri_txstat_valid(struct minst
- }
-
- static void
--minstrel_downgrade_rate(struct minstrel_ht_sta *mi, u16 *idx, bool primary)
-+minstrel_downgrade_prob_rate(struct minstrel_ht_sta *mi, u16 *idx)
- {
- int group, orig_group;
-
-@@ -1271,11 +1238,7 @@ minstrel_downgrade_rate(struct minstrel_
- minstrel_mcs_groups[orig_group].streams)
- continue;
-
-- if (primary)
-- *idx = mi->groups[group].max_group_tp_rate[0];
-- else
-- *idx = mi->groups[group].max_group_tp_rate[1];
-- break;
-+ *idx = mi->groups[group].max_group_prob_rate;
- }
- }
-
-@@ -1286,7 +1249,7 @@ minstrel_ht_tx_status(void *priv, struct
- struct ieee80211_tx_info *info = st->info;
- struct minstrel_ht_sta *mi = priv_sta;
- struct ieee80211_tx_rate *ar = info->status.rates;
-- struct minstrel_rate_stats *rate, *rate2;
-+ struct minstrel_rate_stats *rate;
- struct minstrel_priv *mp = priv;
- u32 update_interval = mp->update_interval;
- bool last, update = false;
-@@ -1354,18 +1317,13 @@ minstrel_ht_tx_status(void *priv, struct
- /*
- * check for sudden death of spatial multiplexing,
- * downgrade to a lower number of streams if necessary.
-+ * only do this for the max_prob_rate to prevent spurious
-+ * rate fluctuations when the link changes suddenly
- */
-- rate = minstrel_get_ratestats(mi, mi->max_tp_rate[0]);
-+ rate = minstrel_get_ratestats(mi, mi->max_prob_rate);
- if (rate->attempts > 30 &&
- 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 &&
-- rate2->success < rate2->attempts / 4) {
-- minstrel_downgrade_rate(mi, &mi->max_tp_rate[1], false);
-+ minstrel_downgrade_prob_rate(mi, &mi->max_prob_rate);
- update = true;
- }
- }
diff --git a/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/305-mac80211-increase-quantum-for-airtime-scheduler.patch b/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/305-mac80211-increase-quantum-for-airtime-scheduler.patch
deleted file mode 100644
index e4575ca..0000000
--- a/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/305-mac80211-increase-quantum-for-airtime-scheduler.patch
+++ /dev/null
@@ -1,53 +0,0 @@
-From: Felix Fietkau <nbd@nbd.name>
-Date: Sun, 26 Jun 2022 11:43:25 +0200
-Subject: [PATCH] mac80211: increase quantum for airtime scheduler
-
-Given the typical AQL budget and queue length, a quantum of 256 with the
-default station weight often requires iterating over all queues frequently,
-until one of them becomes eligible.
-Improve performance by using 8 times station weight as scheduler quantum
-
-Signed-off-by: Felix Fietkau <nbd@nbd.name>
----
-
---- a/net/mac80211/ieee80211_i.h
-+++ b/net/mac80211/ieee80211_i.h
-@@ -92,6 +92,8 @@ extern const u8 ieee80211_ac_to_qos_mask
- */
- #define AIRTIME_ACTIVE_DURATION (HZ / 10)
-
-+#define AIRTIME_QUANTUM_SHIFT 3
-+
- struct ieee80211_bss {
- u32 device_ts_beacon, device_ts_presp;
-
---- a/net/mac80211/tx.c
-+++ b/net/mac80211/tx.c
-@@ -4060,7 +4060,7 @@ struct ieee80211_txq *ieee80211_next_txq
-
- if (deficit < 0)
- sta->airtime[txqi->txq.ac].deficit +=
-- sta->airtime_weight;
-+ sta->airtime_weight << AIRTIME_QUANTUM_SHIFT;
-
- if (deficit < 0 || !aql_check) {
- list_move_tail(&txqi->schedule_order,
-@@ -4203,7 +4203,8 @@ bool ieee80211_txq_may_transmit(struct i
- }
- sta = container_of(iter->txq.sta, struct sta_info, sta);
- if (ieee80211_sta_deficit(sta, ac) < 0)
-- sta->airtime[ac].deficit += sta->airtime_weight;
-+ sta->airtime[ac].deficit += sta->airtime_weight <<
-+ AIRTIME_QUANTUM_SHIFT;
- list_move_tail(&iter->schedule_order, &local->active_txqs[ac]);
- }
-
-@@ -4211,7 +4212,7 @@ bool ieee80211_txq_may_transmit(struct i
- if (sta->airtime[ac].deficit >= 0)
- goto out;
-
-- sta->airtime[ac].deficit += sta->airtime_weight;
-+ sta->airtime[ac].deficit += sta->airtime_weight << AIRTIME_QUANTUM_SHIFT;
- list_move_tail(&txqi->schedule_order, &local->active_txqs[ac]);
- spin_unlock_bh(&local->active_txq_lock[ac]);
-
diff --git a/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/310-mac80211-split-mesh-fast-tx-cache-into-local-proxied.patch b/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/310-mac80211-split-mesh-fast-tx-cache-into-local-proxied.patch
deleted file mode 100644
index 4853cef..0000000
--- a/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/310-mac80211-split-mesh-fast-tx-cache-into-local-proxied.patch
+++ /dev/null
@@ -1,219 +0,0 @@
-From: Felix Fietkau <nbd@nbd.name>
-Date: Fri, 30 Jun 2023 13:11:51 +0200
-Subject: [PATCH] mac80211: split mesh fast tx cache into
- local/proxied/forwarded
-
-Depending on the origin of the packets (and their SA), 802.11 + mesh headers
-could be filled in differently. In order to properly deal with that, add a
-new field to the lookup key, indicating the type (local, proxied or
-forwarded). This can fix spurious packet drop issues that depend on the order
-in which nodes/hosts communicate with each other.
-
-Signed-off-by: Felix Fietkau <nbd@nbd.name>
----
-
---- a/net/mac80211/mesh.c
-+++ b/net/mac80211/mesh.c
-@@ -765,6 +765,9 @@ bool ieee80211_mesh_xmit_fast(struct iee
- struct sk_buff *skb, u32 ctrl_flags)
- {
- struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
-+ struct ieee80211_mesh_fast_tx_key key = {
-+ .type = MESH_FAST_TX_TYPE_LOCAL
-+ };
- struct ieee80211_mesh_fast_tx *entry;
- struct ieee80211s_hdr *meshhdr;
- u8 sa[ETH_ALEN] __aligned(2);
-@@ -800,7 +803,10 @@ bool ieee80211_mesh_xmit_fast(struct iee
- return false;
- }
-
-- entry = mesh_fast_tx_get(sdata, skb->data);
-+ ether_addr_copy(key.addr, skb->data);
-+ if (!ether_addr_equal(skb->data + ETH_ALEN, sdata->vif.addr))
-+ key.type = MESH_FAST_TX_TYPE_PROXIED;
-+ entry = mesh_fast_tx_get(sdata, &key);
- if (!entry)
- return false;
-
---- a/net/mac80211/mesh.h
-+++ b/net/mac80211/mesh.h
-@@ -134,9 +134,33 @@ struct mesh_path {
- #define MESH_FAST_TX_CACHE_TIMEOUT 8000 /* msecs */
-
- /**
-+ * enum ieee80211_mesh_fast_tx_type - cached mesh fast tx entry type
-+ *
-+ * @MESH_FAST_TX_TYPE_LOCAL: tx from the local vif address as SA
-+ * @MESH_FAST_TX_TYPE_PROXIED: local tx with a different SA (e.g. bridged)
-+ * @MESH_FAST_TX_TYPE_FORWARDED: forwarded from a different mesh point
-+ */
-+enum ieee80211_mesh_fast_tx_type {
-+ MESH_FAST_TX_TYPE_LOCAL,
-+ MESH_FAST_TX_TYPE_PROXIED,
-+ MESH_FAST_TX_TYPE_FORWARDED,
-+};
-+
-+/**
-+ * struct ieee80211_mesh_fast_tx_key - cached mesh fast tx entry key
-+ *
-+ * @addr: The Ethernet DA for this entry
-+ * @type: cache entry type
-+ */
-+struct ieee80211_mesh_fast_tx_key {
-+ u8 addr[ETH_ALEN] __aligned(2);
-+ enum ieee80211_mesh_fast_tx_type type;
-+};
-+
-+/**
- * struct ieee80211_mesh_fast_tx - cached mesh fast tx entry
- * @rhash: rhashtable pointer
-- * @addr_key: The Ethernet DA which is the key for this entry
-+ * @key: the lookup key for this cache entry
- * @fast_tx: base fast_tx data
- * @hdr: cached mesh and rfc1042 headers
- * @hdrlen: length of mesh + rfc1042
-@@ -147,7 +171,7 @@ struct mesh_path {
- */
- struct ieee80211_mesh_fast_tx {
- struct rhash_head rhash;
-- u8 addr_key[ETH_ALEN] __aligned(2);
-+ struct ieee80211_mesh_fast_tx_key key;
-
- struct ieee80211_fast_tx fast_tx;
- u8 hdr[sizeof(struct ieee80211s_hdr) + sizeof(rfc1042_header)];
-@@ -333,7 +357,8 @@ void mesh_path_tx_root_frame(struct ieee
-
- bool mesh_action_is_path_sel(struct ieee80211_mgmt *mgmt);
- struct ieee80211_mesh_fast_tx *
--mesh_fast_tx_get(struct ieee80211_sub_if_data *sdata, const u8 *addr);
-+mesh_fast_tx_get(struct ieee80211_sub_if_data *sdata,
-+ struct ieee80211_mesh_fast_tx_key *key);
- bool ieee80211_mesh_xmit_fast(struct ieee80211_sub_if_data *sdata,
- struct sk_buff *skb, u32 ctrl_flags);
- void mesh_fast_tx_cache(struct ieee80211_sub_if_data *sdata,
---- a/net/mac80211/mesh_pathtbl.c
-+++ b/net/mac80211/mesh_pathtbl.c
-@@ -36,8 +36,8 @@ static const struct rhashtable_params me
- static const struct rhashtable_params fast_tx_rht_params = {
- .nelem_hint = 10,
- .automatic_shrinking = true,
-- .key_len = ETH_ALEN,
-- .key_offset = offsetof(struct ieee80211_mesh_fast_tx, addr_key),
-+ .key_len = sizeof(struct ieee80211_mesh_fast_tx_key),
-+ .key_offset = offsetof(struct ieee80211_mesh_fast_tx, key),
- .head_offset = offsetof(struct ieee80211_mesh_fast_tx, rhash),
- .hashfn = mesh_table_hash,
- };
-@@ -426,20 +426,21 @@ static void mesh_fast_tx_entry_free(stru
- }
-
- struct ieee80211_mesh_fast_tx *
--mesh_fast_tx_get(struct ieee80211_sub_if_data *sdata, const u8 *addr)
-+mesh_fast_tx_get(struct ieee80211_sub_if_data *sdata,
-+ struct ieee80211_mesh_fast_tx_key *key)
- {
- struct ieee80211_mesh_fast_tx *entry;
- struct mesh_tx_cache *cache;
-
- cache = &sdata->u.mesh.tx_cache;
-- entry = rhashtable_lookup(&cache->rht, addr, fast_tx_rht_params);
-+ entry = rhashtable_lookup(&cache->rht, key, fast_tx_rht_params);
- if (!entry)
- return NULL;
-
- if (!(entry->mpath->flags & MESH_PATH_ACTIVE) ||
- mpath_expired(entry->mpath)) {
- spin_lock_bh(&cache->walk_lock);
-- entry = rhashtable_lookup(&cache->rht, addr, fast_tx_rht_params);
-+ entry = rhashtable_lookup(&cache->rht, key, fast_tx_rht_params);
- if (entry)
- mesh_fast_tx_entry_free(cache, entry);
- spin_unlock_bh(&cache->walk_lock);
-@@ -484,18 +485,24 @@ void mesh_fast_tx_cache(struct ieee80211
- if (!sta)
- return;
-
-+ build.key.type = MESH_FAST_TX_TYPE_LOCAL;
- if ((meshhdr->flags & MESH_FLAGS_AE) == MESH_FLAGS_AE_A5_A6) {
- /* This is required to keep the mppath alive */
- mppath = mpp_path_lookup(sdata, meshhdr->eaddr1);
- if (!mppath)
- return;
- build.mppath = mppath;
-+ if (!ether_addr_equal(meshhdr->eaddr2, sdata->vif.addr))
-+ build.key.type = MESH_FAST_TX_TYPE_PROXIED;
- } else if (ieee80211_has_a4(hdr->frame_control)) {
- mppath = mpath;
- } else {
- return;
- }
-
-+ if (!ether_addr_equal(hdr->addr4, sdata->vif.addr))
-+ build.key.type = MESH_FAST_TX_TYPE_FORWARDED;
-+
- /* rate limit, in case fast xmit can't be enabled */
- if (mppath->fast_tx_check == jiffies)
- return;
-@@ -542,7 +549,7 @@ void mesh_fast_tx_cache(struct ieee80211
- }
- }
-
-- memcpy(build.addr_key, mppath->dst, ETH_ALEN);
-+ memcpy(build.key.addr, mppath->dst, ETH_ALEN);
- build.timestamp = jiffies;
- build.fast_tx.band = info->band;
- build.fast_tx.da_offs = offsetof(struct ieee80211_hdr, addr3);
-@@ -644,13 +651,19 @@ void mesh_fast_tx_flush_addr(struct ieee
- const u8 *addr)
- {
- struct mesh_tx_cache *cache = &sdata->u.mesh.tx_cache;
-+ struct ieee80211_mesh_fast_tx_key key = {};
- struct ieee80211_mesh_fast_tx *entry;
-+ int i;
-
-+ ether_addr_copy(key.addr, addr);
- cache = &sdata->u.mesh.tx_cache;
- spin_lock_bh(&cache->walk_lock);
-- entry = rhashtable_lookup_fast(&cache->rht, addr, fast_tx_rht_params);
-- if (entry)
-- mesh_fast_tx_entry_free(cache, entry);
-+ for (i = MESH_FAST_TX_TYPE_LOCAL; i < MESH_FAST_TX_TYPE_FORWARDED; i++) {
-+ key.type = i;
-+ entry = rhashtable_lookup_fast(&cache->rht, &key, fast_tx_rht_params);
-+ if (entry)
-+ mesh_fast_tx_entry_free(cache, entry);
-+ }
- spin_unlock_bh(&cache->walk_lock);
- }
-
---- a/net/mac80211/rx.c
-+++ b/net/mac80211/rx.c
-@@ -2726,7 +2726,10 @@ ieee80211_rx_mesh_fast_forward(struct ie
- struct sk_buff *skb, int hdrlen)
- {
- struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
-- struct ieee80211_mesh_fast_tx *entry = NULL;
-+ struct ieee80211_mesh_fast_tx_key key = {
-+ .type = MESH_FAST_TX_TYPE_FORWARDED
-+ };
-+ struct ieee80211_mesh_fast_tx *entry;
- struct ieee80211s_hdr *mesh_hdr;
- struct tid_ampdu_tx *tid_tx;
- struct sta_info *sta;
-@@ -2735,9 +2738,13 @@ ieee80211_rx_mesh_fast_forward(struct ie
-
- mesh_hdr = (struct ieee80211s_hdr *)(skb->data + sizeof(eth));
- if ((mesh_hdr->flags & MESH_FLAGS_AE) == MESH_FLAGS_AE_A5_A6)
-- entry = mesh_fast_tx_get(sdata, mesh_hdr->eaddr1);
-+ ether_addr_copy(key.addr, mesh_hdr->eaddr1);
- else if (!(mesh_hdr->flags & MESH_FLAGS_AE))
-- entry = mesh_fast_tx_get(sdata, skb->data);
-+ ether_addr_copy(key.addr, skb->data);
-+ else
-+ return false;
-+
-+ entry = mesh_fast_tx_get(sdata, &key);
- if (!entry)
- return false;
-
diff --git a/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/312-wifi-cfg80211-annotate-iftype_data-pointer-with-spar.patch b/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/312-wifi-cfg80211-annotate-iftype_data-pointer-with-spar.patch
deleted file mode 100644
index 91ebfc6..0000000
--- a/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/312-wifi-cfg80211-annotate-iftype_data-pointer-with-spar.patch
+++ /dev/null
@@ -1,467 +0,0 @@
-From: Johannes Berg <johannes.berg@intel.com>
-Date: Mon, 28 Aug 2023 09:54:39 +0200
-Subject: [PATCH] wifi: cfg80211: annotate iftype_data pointer with sparse
-
-There were are a number of cases in mac80211 and iwlwifi (at
-least) that used the sband->iftype_data pointer directly,
-instead of using the accessors to find the right array entry
-to use.
-
-Make sparse warn when such a thing is done.
-
-To not have a lot of casts, add two helper functions/macros
-
- - ieee80211_set_sband_iftype_data()
- - for_each_sband_iftype_data()
-
-Signed-off-by: Johannes Berg <johannes.berg@intel.com>
----
-
---- a/drivers/net/wireless/ath/ath11k/mac.c
-+++ b/drivers/net/wireless/ath/ath11k/mac.c
-@@ -5893,8 +5893,9 @@ static void ath11k_mac_setup_he_cap(stru
- ar->mac.iftype[NL80211_BAND_2GHZ],
- NL80211_BAND_2GHZ);
- band = &ar->mac.sbands[NL80211_BAND_2GHZ];
-- band->iftype_data = ar->mac.iftype[NL80211_BAND_2GHZ];
-- band->n_iftype_data = count;
-+ _ieee80211_set_sband_iftype_data(band,
-+ ar->mac.iftype[NL80211_BAND_2GHZ],
-+ count);
- }
-
- if (cap->supported_bands & WMI_HOST_WLAN_5G_CAP) {
-@@ -5902,8 +5903,9 @@ static void ath11k_mac_setup_he_cap(stru
- ar->mac.iftype[NL80211_BAND_5GHZ],
- NL80211_BAND_5GHZ);
- band = &ar->mac.sbands[NL80211_BAND_5GHZ];
-- band->iftype_data = ar->mac.iftype[NL80211_BAND_5GHZ];
-- band->n_iftype_data = count;
-+ _ieee80211_set_sband_iftype_data(band,
-+ ar->mac.iftype[NL80211_BAND_5GHZ],
-+ count);
- }
-
- if (cap->supported_bands & WMI_HOST_WLAN_5G_CAP &&
-@@ -5912,8 +5914,9 @@ static void ath11k_mac_setup_he_cap(stru
- ar->mac.iftype[NL80211_BAND_6GHZ],
- NL80211_BAND_6GHZ);
- band = &ar->mac.sbands[NL80211_BAND_6GHZ];
-- band->iftype_data = ar->mac.iftype[NL80211_BAND_6GHZ];
-- band->n_iftype_data = count;
-+ _ieee80211_set_sband_iftype_data(band,
-+ ar->mac.iftype[NL80211_BAND_6GHZ],
-+ count);
- }
- }
-
---- a/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c
-+++ b/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c
-@@ -1078,8 +1078,8 @@ static void iwl_init_he_hw_capab(struct
-
- memcpy(iftype_data, iwl_he_eht_capa, sizeof(iwl_he_eht_capa));
-
-- sband->iftype_data = iftype_data;
-- sband->n_iftype_data = ARRAY_SIZE(iwl_he_eht_capa);
-+ _ieee80211_set_sband_iftype_data(sband, iftype_data,
-+ ARRAY_SIZE(iwl_he_eht_capa));
-
- for (i = 0; i < sband->n_iftype_data; i++)
- iwl_nvm_fixup_sband_iftd(trans, data, sband, &iftype_data[i],
---- a/drivers/net/wireless/mediatek/mt76/mt7915/init.c
-+++ b/drivers/net/wireless/mediatek/mt76/mt7915/init.c
-@@ -1127,8 +1127,7 @@ void mt7915_set_stream_he_caps(struct mt
- n = mt7915_init_he_caps(phy, NL80211_BAND_2GHZ, data);
-
- band = &phy->mt76->sband_2g.sband;
-- band->iftype_data = data;
-- band->n_iftype_data = n;
-+ _ieee80211_set_sband_iftype_data(band, data, n);
- }
-
- if (phy->mt76->cap.has_5ghz) {
-@@ -1136,8 +1135,7 @@ void mt7915_set_stream_he_caps(struct mt
- n = mt7915_init_he_caps(phy, NL80211_BAND_5GHZ, data);
-
- band = &phy->mt76->sband_5g.sband;
-- band->iftype_data = data;
-- band->n_iftype_data = n;
-+ _ieee80211_set_sband_iftype_data(band, data, n);
- }
-
- if (phy->mt76->cap.has_6ghz) {
-@@ -1145,8 +1143,7 @@ void mt7915_set_stream_he_caps(struct mt
- n = mt7915_init_he_caps(phy, NL80211_BAND_6GHZ, data);
-
- band = &phy->mt76->sband_6g.sband;
-- band->iftype_data = data;
-- band->n_iftype_data = n;
-+ _ieee80211_set_sband_iftype_data(band, data, n);
- }
- }
-
---- a/drivers/net/wireless/mediatek/mt76/mt7921/main.c
-+++ b/drivers/net/wireless/mediatek/mt76/mt7921/main.c
-@@ -196,8 +196,7 @@ void mt7921_set_stream_he_caps(struct mt
- n = mt7921_init_he_caps(phy, NL80211_BAND_2GHZ, data);
-
- band = &phy->mt76->sband_2g.sband;
-- band->iftype_data = data;
-- band->n_iftype_data = n;
-+ _ieee80211_set_sband_iftype_data(band, data, n);
- }
-
- if (phy->mt76->cap.has_5ghz) {
-@@ -205,16 +204,14 @@ void mt7921_set_stream_he_caps(struct mt
- n = mt7921_init_he_caps(phy, NL80211_BAND_5GHZ, data);
-
- band = &phy->mt76->sband_5g.sband;
-- band->iftype_data = data;
-- band->n_iftype_data = n;
-+ _ieee80211_set_sband_iftype_data(band, data, n);
-
- if (phy->mt76->cap.has_6ghz) {
- data = phy->iftype[NL80211_BAND_6GHZ];
- n = mt7921_init_he_caps(phy, NL80211_BAND_6GHZ, data);
-
- band = &phy->mt76->sband_6g.sband;
-- band->iftype_data = data;
-- band->n_iftype_data = n;
-+ _ieee80211_set_sband_iftype_data(band, data, n);
- }
- }
- }
---- a/drivers/net/wireless/mediatek/mt76/mt7996/init.c
-+++ b/drivers/net/wireless/mediatek/mt76/mt7996/init.c
-@@ -828,8 +828,7 @@ __mt7996_set_stream_he_eht_caps(struct m
- n++;
- }
-
-- sband->iftype_data = data;
-- sband->n_iftype_data = n;
-+ _ieee80211_set_sband_iftype_data(sband, data, n);
- }
-
- void mt7996_set_stream_he_eht_caps(struct mt7996_phy *phy)
---- a/drivers/net/wireless/quantenna/qtnfmac/commands.c
-+++ b/drivers/net/wireless/quantenna/qtnfmac/commands.c
-@@ -1335,7 +1335,7 @@ static int qtnf_cmd_band_fill_iftype(con
- return -EINVAL;
- }
-
-- kfree(band->iftype_data);
-+ kfree((__force void *)band->iftype_data);
- band->iftype_data = NULL;
- band->n_iftype_data = tlv->n_iftype_data;
- if (band->n_iftype_data == 0)
-@@ -1347,7 +1347,8 @@ static int qtnf_cmd_band_fill_iftype(con
- band->n_iftype_data = 0;
- return -ENOMEM;
- }
-- band->iftype_data = iftype_data;
-+
-+ _ieee80211_set_sband_iftype_data(band, iftype_data, tlv->n_iftype_data);
-
- for (i = 0; i < band->n_iftype_data; i++)
- qtnf_cmd_conv_iftype(iftype_data++, &tlv->iftype_data[i]);
---- a/drivers/net/wireless/quantenna/qtnfmac/core.c
-+++ b/drivers/net/wireless/quantenna/qtnfmac/core.c
-@@ -549,7 +549,7 @@ static void qtnf_core_mac_detach(struct
- if (!wiphy->bands[band])
- continue;
-
-- kfree(wiphy->bands[band]->iftype_data);
-+ kfree((__force void *)wiphy->bands[band]->iftype_data);
- wiphy->bands[band]->n_iftype_data = 0;
-
- kfree(wiphy->bands[band]->channels);
---- a/drivers/net/wireless/realtek/rtw89/core.c
-+++ b/drivers/net/wireless/realtek/rtw89/core.c
-@@ -3359,8 +3359,7 @@ static void rtw89_init_he_cap(struct rtw
- idx++;
- }
-
-- sband->iftype_data = iftype_data;
-- sband->n_iftype_data = idx;
-+ _ieee80211_set_sband_iftype_data(sband, iftype_data, idx);
- }
-
- static int rtw89_core_set_supported_band(struct rtw89_dev *rtwdev)
-@@ -3405,11 +3404,11 @@ err:
- hw->wiphy->bands[NL80211_BAND_5GHZ] = NULL;
- hw->wiphy->bands[NL80211_BAND_6GHZ] = NULL;
- if (sband_2ghz)
-- kfree(sband_2ghz->iftype_data);
-+ kfree((__force void *)sband_2ghz->iftype_data);
- if (sband_5ghz)
-- kfree(sband_5ghz->iftype_data);
-+ kfree((__force void *)sband_5ghz->iftype_data);
- if (sband_6ghz)
-- kfree(sband_6ghz->iftype_data);
-+ kfree((__force void *)sband_6ghz->iftype_data);
- kfree(sband_2ghz);
- kfree(sband_5ghz);
- kfree(sband_6ghz);
-@@ -3421,11 +3420,11 @@ static void rtw89_core_clr_supported_ban
- struct ieee80211_hw *hw = rtwdev->hw;
-
- if (hw->wiphy->bands[NL80211_BAND_2GHZ])
-- kfree(hw->wiphy->bands[NL80211_BAND_2GHZ]->iftype_data);
-+ kfree((__force void *)hw->wiphy->bands[NL80211_BAND_2GHZ]->iftype_data);
- if (hw->wiphy->bands[NL80211_BAND_5GHZ])
-- kfree(hw->wiphy->bands[NL80211_BAND_5GHZ]->iftype_data);
-+ kfree((__force void *)hw->wiphy->bands[NL80211_BAND_5GHZ]->iftype_data);
- if (hw->wiphy->bands[NL80211_BAND_6GHZ])
-- kfree(hw->wiphy->bands[NL80211_BAND_6GHZ]->iftype_data);
-+ kfree((__force void *)hw->wiphy->bands[NL80211_BAND_6GHZ]->iftype_data);
- kfree(hw->wiphy->bands[NL80211_BAND_2GHZ]);
- kfree(hw->wiphy->bands[NL80211_BAND_5GHZ]);
- kfree(hw->wiphy->bands[NL80211_BAND_6GHZ]);
---- a/drivers/net/wireless/realtek/rtw89/regd.c
-+++ b/drivers/net/wireless/realtek/rtw89/regd.c
-@@ -377,7 +377,7 @@ bottom:
- return;
-
- wiphy->bands[NL80211_BAND_6GHZ] = NULL;
-- kfree(sband->iftype_data);
-+ kfree((__force void *)sband->iftype_data);
- kfree(sband);
- }
-
---- a/drivers/net/wireless/virtual/mac80211_hwsim.c
-+++ b/drivers/net/wireless/virtual/mac80211_hwsim.c
-@@ -4899,25 +4899,19 @@ static const struct ieee80211_sband_ifty
-
- static void mac80211_hwsim_sband_capab(struct ieee80211_supported_band *sband)
- {
-- u16 n_iftype_data;
--
-- if (sband->band == NL80211_BAND_2GHZ) {
-- n_iftype_data = ARRAY_SIZE(sband_capa_2ghz);
-- sband->iftype_data =
-- (struct ieee80211_sband_iftype_data *)sband_capa_2ghz;
-- } else if (sband->band == NL80211_BAND_5GHZ) {
-- n_iftype_data = ARRAY_SIZE(sband_capa_5ghz);
-- sband->iftype_data =
-- (struct ieee80211_sband_iftype_data *)sband_capa_5ghz;
-- } else if (sband->band == NL80211_BAND_6GHZ) {
-- n_iftype_data = ARRAY_SIZE(sband_capa_6ghz);
-- sband->iftype_data =
-- (struct ieee80211_sband_iftype_data *)sband_capa_6ghz;
-- } else {
-- return;
-+ switch (sband->band) {
-+ case NL80211_BAND_2GHZ:
-+ ieee80211_set_sband_iftype_data(sband, sband_capa_2ghz);
-+ break;
-+ case NL80211_BAND_5GHZ:
-+ ieee80211_set_sband_iftype_data(sband, sband_capa_5ghz);
-+ break;
-+ case NL80211_BAND_6GHZ:
-+ ieee80211_set_sband_iftype_data(sband, sband_capa_6ghz);
-+ break;
-+ default:
-+ break;
- }
--
-- sband->n_iftype_data = n_iftype_data;
- }
-
- #ifdef CPTCFG_MAC80211_MESH
---- a/include/net/cfg80211.h
-+++ b/include/net/cfg80211.h
-@@ -415,6 +415,19 @@ struct ieee80211_sta_eht_cap {
- u8 eht_ppe_thres[IEEE80211_EHT_PPE_THRES_MAX_LEN];
- };
-
-+/* sparse defines __CHECKER__; see Documentation/dev-tools/sparse.rst */
-+#ifdef __CHECKER__
-+/*
-+ * This is used to mark the sband->iftype_data pointer which is supposed
-+ * to be an array with special access semantics (per iftype), but a lot
-+ * of code got it wrong in the past, so with this marking sparse will be
-+ * noisy when the pointer is used directly.
-+ */
-+# define __iftd __attribute__((noderef, address_space(__iftype_data)))
-+#else
-+# define __iftd
-+#endif /* __CHECKER__ */
-+
- /**
- * struct ieee80211_sband_iftype_data - sband data per interface type
- *
-@@ -548,10 +561,48 @@ struct ieee80211_supported_band {
- struct ieee80211_sta_s1g_cap s1g_cap;
- struct ieee80211_edmg edmg_cap;
- u16 n_iftype_data;
-- const struct ieee80211_sband_iftype_data *iftype_data;
-+ const struct ieee80211_sband_iftype_data __iftd *iftype_data;
- };
-
- /**
-+ * _ieee80211_set_sband_iftype_data - set sband iftype data array
-+ * @sband: the sband to initialize
-+ * @iftd: the iftype data array pointer
-+ * @n_iftd: the length of the iftype data array
-+ *
-+ * Set the sband iftype data array; use this where the length cannot
-+ * be derived from the ARRAY_SIZE() of the argument, but prefer
-+ * ieee80211_set_sband_iftype_data() where it can be used.
-+ */
-+static inline void
-+_ieee80211_set_sband_iftype_data(struct ieee80211_supported_band *sband,
-+ const struct ieee80211_sband_iftype_data *iftd,
-+ u16 n_iftd)
-+{
-+ sband->iftype_data = (const void __iftd __force *)iftd;
-+ sband->n_iftype_data = n_iftd;
-+}
-+
-+/**
-+ * ieee80211_set_sband_iftype_data - set sband iftype data array
-+ * @sband: the sband to initialize
-+ * @iftd: the iftype data array
-+ */
-+#define ieee80211_set_sband_iftype_data(sband, iftd) \
-+ _ieee80211_set_sband_iftype_data(sband, iftd, ARRAY_SIZE(iftd))
-+
-+/**
-+ * for_each_sband_iftype_data - iterate sband iftype data entries
-+ * @sband: the sband whose iftype_data array to iterate
-+ * @i: iterator counter
-+ * @iftd: iftype data pointer to set
-+ */
-+#define for_each_sband_iftype_data(sband, i, iftd) \
-+ for (i = 0, iftd = (const void __force *)&(sband)->iftype_data[i]; \
-+ i < (sband)->n_iftype_data; \
-+ i++, iftd = (const void __force *)&(sband)->iftype_data[i])
-+
-+/**
- * ieee80211_get_sband_iftype_data - return sband data for a given iftype
- * @sband: the sband to search for the STA on
- * @iftype: enum nl80211_iftype
-@@ -562,6 +613,7 @@ static inline const struct ieee80211_sba
- ieee80211_get_sband_iftype_data(const struct ieee80211_supported_band *sband,
- u8 iftype)
- {
-+ const struct ieee80211_sband_iftype_data *data;
- int i;
-
- if (WARN_ON(iftype >= NL80211_IFTYPE_MAX))
-@@ -570,10 +622,7 @@ ieee80211_get_sband_iftype_data(const st
- if (iftype == NL80211_IFTYPE_AP_VLAN)
- iftype = NL80211_IFTYPE_AP;
-
-- for (i = 0; i < sband->n_iftype_data; i++) {
-- const struct ieee80211_sband_iftype_data *data =
-- &sband->iftype_data[i];
--
-+ for_each_sband_iftype_data(sband, i, data) {
- if (data->types_mask & BIT(iftype))
- return data;
- }
---- a/net/mac80211/main.c
-+++ b/net/mac80211/main.c
-@@ -1052,6 +1052,7 @@ int ieee80211_register_hw(struct ieee802
- supp_he = false;
- supp_eht = false;
- for (band = 0; band < NUM_NL80211_BANDS; band++) {
-+ const struct ieee80211_sband_iftype_data *iftd;
- struct ieee80211_supported_band *sband;
-
- sband = local->hw.wiphy->bands[band];
-@@ -1098,11 +1099,7 @@ int ieee80211_register_hw(struct ieee802
- supp_ht = supp_ht || sband->ht_cap.ht_supported;
- supp_vht = supp_vht || sband->vht_cap.vht_supported;
-
-- for (i = 0; i < sband->n_iftype_data; i++) {
-- const struct ieee80211_sband_iftype_data *iftd;
--
-- iftd = &sband->iftype_data[i];
--
-+ for_each_sband_iftype_data(sband, i, iftd) {
- supp_he = supp_he || iftd->he_cap.has_he;
- supp_eht = supp_eht || iftd->eht_cap.has_eht;
- }
---- a/net/wireless/chan.c
-+++ b/net/wireless/chan.c
-@@ -6,7 +6,7 @@
- *
- * Copyright 2009 Johannes Berg <johannes@sipsolutions.net>
- * Copyright 2013-2014 Intel Mobile Communications GmbH
-- * Copyright 2018-2022 Intel Corporation
-+ * Copyright 2018-2023 Intel Corporation
- */
-
- #include <linux/export.h>
-@@ -1162,8 +1162,7 @@ bool cfg80211_chandef_usable(struct wiph
- if (!sband)
- return false;
-
-- for (i = 0; i < sband->n_iftype_data; i++) {
-- iftd = &sband->iftype_data[i];
-+ for_each_sband_iftype_data(sband, i, iftd) {
- if (!iftd->eht_cap.has_eht)
- continue;
-
---- a/net/wireless/core.c
-+++ b/net/wireless/core.c
-@@ -5,7 +5,7 @@
- * Copyright 2006-2010 Johannes Berg <johannes@sipsolutions.net>
- * Copyright 2013-2014 Intel Mobile Communications GmbH
- * Copyright 2015-2017 Intel Deutschland GmbH
-- * Copyright (C) 2018-2022 Intel Corporation
-+ * Copyright (C) 2018-2023 Intel Corporation
- */
-
- #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-@@ -819,6 +819,7 @@ int wiphy_register(struct wiphy *wiphy)
-
- /* sanity check supported bands/channels */
- for (band = 0; band < NUM_NL80211_BANDS; band++) {
-+ const struct ieee80211_sband_iftype_data *iftd;
- u16 types = 0;
- bool have_he = false;
-
-@@ -875,14 +876,11 @@ int wiphy_register(struct wiphy *wiphy)
- return -EINVAL;
- }
-
-- for (i = 0; i < sband->n_iftype_data; i++) {
-- const struct ieee80211_sband_iftype_data *iftd;
-+ for_each_sband_iftype_data(sband, i, iftd) {
- bool has_ap, has_non_ap;
- u32 ap_bits = BIT(NL80211_IFTYPE_AP) |
- BIT(NL80211_IFTYPE_P2P_GO);
-
-- iftd = &sband->iftype_data[i];
--
- if (WARN_ON(!iftd->types_mask))
- return -EINVAL;
- if (WARN_ON(types & iftd->types_mask))
---- a/net/wireless/nl80211.c
-+++ b/net/wireless/nl80211.c
-@@ -1907,20 +1907,20 @@ static int nl80211_send_band_rateinfo(st
- struct nlattr *nl_iftype_data =
- nla_nest_start_noflag(msg,
- NL80211_BAND_ATTR_IFTYPE_DATA);
-+ const struct ieee80211_sband_iftype_data *iftd;
- int err;
-
- if (!nl_iftype_data)
- return -ENOBUFS;
-
-- for (i = 0; i < sband->n_iftype_data; i++) {
-+ for_each_sband_iftype_data(sband, i, iftd) {
- struct nlattr *iftdata;
-
- iftdata = nla_nest_start_noflag(msg, i + 1);
- if (!iftdata)
- return -ENOBUFS;
-
-- err = nl80211_send_iftype_data(msg, sband,
-- &sband->iftype_data[i]);
-+ err = nl80211_send_iftype_data(msg, sband, iftd);
- if (err)
- return err;
-
diff --git a/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/313-wifi-cfg80211-export-DFS-CAC-time-and-usable-state-h.patch b/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/313-wifi-cfg80211-export-DFS-CAC-time-and-usable-state-h.patch
deleted file mode 100644
index a41a906..0000000
--- a/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/313-wifi-cfg80211-export-DFS-CAC-time-and-usable-state-h.patch
+++ /dev/null
@@ -1,111 +0,0 @@
-From 30ca8b0c4d6c9fb1d76e5894b1e8bf7c6a12224d Mon Sep 17 00:00:00 2001
-From: Aditya Kumar Singh <quic_adisi@quicinc.com>
-Date: Tue, 12 Sep 2023 10:48:55 +0530
-Subject: [PATCH] wifi: cfg80211: export DFS CAC time and usable state helper
- functions
-
-cfg80211 has cfg80211_chandef_dfs_usable() function to know whether
-at least one channel in the chandef is in usable state or not. Also,
-cfg80211_chandef_dfs_cac_time() function is there which tells the CAC
-time required for the given chandef.
-
-Make these two functions visible to drivers by exporting their symbol
-to global list of kernel symbols.
-
-Lower level drivers can make use of these two functions to be aware
-if CAC is required on the given chandef and for how long. For example
-drivers which maintains the CAC state internally can make use of these.
-
-Signed-off-by: Aditya Kumar Singh <quic_adisi@quicinc.com>
-Reviewed-by: Jeff Johnson <quic_jjohnson@quicinc.com>
-Link: https://lore.kernel.org/r/20230912051857.2284-2-quic_adisi@quicinc.com
-Signed-off-by: Johannes Berg <johannes.berg@intel.com>
----
- include/net/cfg80211.h | 24 ++++++++++++++++++++++++
- net/wireless/chan.c | 2 ++
- net/wireless/core.h | 17 -----------------
- 3 files changed, 26 insertions(+), 17 deletions(-)
-
---- a/include/net/cfg80211.h
-+++ b/include/net/cfg80211.h
-@@ -1008,6 +1008,30 @@ int cfg80211_chandef_dfs_required(struct
- enum nl80211_iftype iftype);
-
- /**
-+ * cfg80211_chandef_dfs_usable - checks if chandef is DFS usable and we
-+ * can/need start CAC on such channel
-+ * @wiphy: the wiphy to validate against
-+ * @chandef: the channel definition to check
-+ *
-+ * Return: true if all channels available and at least
-+ * one channel requires CAC (NL80211_DFS_USABLE)
-+ */
-+bool cfg80211_chandef_dfs_usable(struct wiphy *wiphy,
-+ const struct cfg80211_chan_def *chandef);
-+
-+/**
-+ * cfg80211_chandef_dfs_cac_time - get the DFS CAC time (in ms) for given
-+ * channel definition
-+ * @wiphy: the wiphy to validate against
-+ * @chandef: the channel definition to check
-+ *
-+ * Returns: DFS CAC time (in ms) which applies for this channel definition
-+ */
-+unsigned int
-+cfg80211_chandef_dfs_cac_time(struct wiphy *wiphy,
-+ const struct cfg80211_chan_def *chandef);
-+
-+/**
- * nl80211_send_chandef - sends the channel definition.
- * @msg: the msg to send channel definition
- * @chandef: the channel definition to check
---- a/net/wireless/chan.c
-+++ b/net/wireless/chan.c
-@@ -666,6 +666,7 @@ bool cfg80211_chandef_dfs_usable(struct
-
- return (r1 + r2 > 0);
- }
-+EXPORT_SYMBOL(cfg80211_chandef_dfs_usable);
-
- /*
- * Checks if center frequency of chan falls with in the bandwidth
-@@ -965,6 +966,7 @@ cfg80211_chandef_dfs_cac_time(struct wip
-
- return max(t1, t2);
- }
-+EXPORT_SYMBOL(cfg80211_chandef_dfs_cac_time);
-
- static bool cfg80211_secondary_chans_ok(struct wiphy *wiphy,
- u32 center_freq, u32 bandwidth,
---- a/net/wireless/core.h
-+++ b/net/wireless/core.h
-@@ -476,29 +476,12 @@ int cfg80211_scan(struct cfg80211_regist
-
- extern struct work_struct cfg80211_disconnect_work;
-
--/**
-- * cfg80211_chandef_dfs_usable - checks if chandef is DFS usable
-- * @wiphy: the wiphy to validate against
-- * @chandef: the channel definition to check
-- *
-- * Checks if chandef is usable and we can/need start CAC on such channel.
-- *
-- * Return: true if all channels available and at least
-- * one channel requires CAC (NL80211_DFS_USABLE)
-- */
--bool cfg80211_chandef_dfs_usable(struct wiphy *wiphy,
-- const struct cfg80211_chan_def *chandef);
--
- void cfg80211_set_dfs_state(struct wiphy *wiphy,
- const struct cfg80211_chan_def *chandef,
- enum nl80211_dfs_state dfs_state);
-
- void cfg80211_dfs_channels_update_work(struct work_struct *work);
-
--unsigned int
--cfg80211_chandef_dfs_cac_time(struct wiphy *wiphy,
-- const struct cfg80211_chan_def *chandef);
--
- void cfg80211_sched_dfs_chan_update(struct cfg80211_registered_device *rdev);
-
- int
diff --git a/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/314-wifi-mac80211-fix-race-condition-on-enabling-fast-xm.patch b/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/314-wifi-mac80211-fix-race-condition-on-enabling-fast-xm.patch
deleted file mode 100644
index 12ed214..0000000
--- a/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/314-wifi-mac80211-fix-race-condition-on-enabling-fast-xm.patch
+++ /dev/null
@@ -1,34 +0,0 @@
-From: Felix Fietkau <nbd@nbd.name>
-Date: Wed, 3 Jan 2024 15:10:18 +0100
-Subject: [PATCH] wifi: mac80211: fix race condition on enabling fast-xmit
-
-fast-xmit must only be enabled after the sta has been uploaded to the driver,
-otherwise it could end up passing the not-yet-uploaded sta via drv_tx calls
-to the driver, leading to potential crashes because of uninitialized drv_priv
-data.
-Add a missing sta->uploaded check and re-check fast xmit after inserting a sta.
-
-Signed-off-by: Felix Fietkau <nbd@nbd.name>
----
-
---- a/net/mac80211/sta_info.c
-+++ b/net/mac80211/sta_info.c
-@@ -914,6 +914,7 @@ static int sta_info_insert_finish(struct
-
- if (ieee80211_vif_is_mesh(&sdata->vif))
- mesh_accept_plinks_update(sdata);
-+ ieee80211_check_fast_xmit(sta);
-
- return 0;
- out_remove:
---- a/net/mac80211/tx.c
-+++ b/net/mac80211/tx.c
-@@ -3034,7 +3034,7 @@ void ieee80211_check_fast_xmit(struct st
- sdata->vif.type == NL80211_IFTYPE_STATION)
- goto out;
-
-- if (!test_sta_flag(sta, WLAN_STA_AUTHORIZED))
-+ if (!test_sta_flag(sta, WLAN_STA_AUTHORIZED) || !sta->uploaded)
- goto out;
-
- if (test_sta_flag(sta, WLAN_STA_PS_STA) ||
diff --git a/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/320-cfg80211-allow-grace-period-for-DFS-available-after-.patch b/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/320-cfg80211-allow-grace-period-for-DFS-available-after-.patch
deleted file mode 100644
index ec38130..0000000
--- a/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/320-cfg80211-allow-grace-period-for-DFS-available-after-.patch
+++ /dev/null
@@ -1,149 +0,0 @@
-From: Felix Fietkau <nbd@nbd.name>
-Date: Thu, 14 Sep 2023 13:17:16 +0200
-Subject: [PATCH] cfg80211: allow grace period for DFS available after beacon
- shutdown
-
-Fixes reconfiguring an AP on a DFS channel in non-ETSI regdomain
-
-Fixes: b35a51c7dd25 ("cfg80211: Make pre-CAC results valid only for ETSI domain")
-Signed-off-by: Felix Fietkau <nbd@nbd.name>
----
-
---- a/include/net/cfg80211.h
-+++ b/include/net/cfg80211.h
-@@ -175,6 +175,8 @@ enum ieee80211_channel_flags {
- * @dfs_state: current state of this channel. Only relevant if radar is required
- * on this channel.
- * @dfs_state_entered: timestamp (jiffies) when the dfs state was entered.
-+ * @dfs_state_last_available: timestamp (jiffies) of the last time when the
-+ * channel was available.
- * @dfs_cac_ms: DFS CAC time in milliseconds, this is valid for DFS channels.
- */
- struct ieee80211_channel {
-@@ -191,6 +193,7 @@ struct ieee80211_channel {
- int orig_mag, orig_mpwr;
- enum nl80211_dfs_state dfs_state;
- unsigned long dfs_state_entered;
-+ unsigned long dfs_state_last_available;
- unsigned int dfs_cac_ms;
- };
-
---- a/net/wireless/ap.c
-+++ b/net/wireless/ap.c
-@@ -30,6 +30,9 @@ static int ___cfg80211_stop_ap(struct cf
- if (!wdev->links[link_id].ap.beacon_interval)
- return -ENOENT;
-
-+ cfg80211_update_last_available(wdev->wiphy,
-+ &wdev->links[link_id].ap.chandef);
-+
- err = rdev_stop_ap(rdev, dev, link_id);
- if (!err) {
- wdev->conn_owner_nlportid = 0;
-@@ -41,9 +44,6 @@ static int ___cfg80211_stop_ap(struct cf
- if (notify)
- nl80211_send_ap_stopped(wdev, link_id);
-
-- /* Should we apply the grace period during beaconing interface
-- * shutdown also?
-- */
- cfg80211_sched_dfs_chan_update(rdev);
- }
-
---- a/net/wireless/chan.c
-+++ b/net/wireless/chan.c
-@@ -461,6 +461,8 @@ static void cfg80211_set_chans_dfs_state
-
- c->dfs_state = dfs_state;
- c->dfs_state_entered = jiffies;
-+ if (dfs_state == NL80211_DFS_AVAILABLE)
-+ c->dfs_state_last_available = jiffies;
- }
- }
-
-@@ -874,6 +876,49 @@ static bool cfg80211_get_chans_dfs_avail
- return true;
- }
-
-+static void
-+__cfg80211_update_last_available(struct wiphy *wiphy,
-+ u32 center_freq,
-+ u32 bandwidth)
-+{
-+ struct ieee80211_channel *c;
-+ u32 freq, start_freq, end_freq;
-+
-+ start_freq = cfg80211_get_start_freq(center_freq, bandwidth);
-+ end_freq = cfg80211_get_end_freq(center_freq, bandwidth);
-+
-+ /*
-+ * Check entire range of channels for the bandwidth.
-+ * If any channel in between is disabled or has not
-+ * had gone through CAC return false
-+ */
-+ for (freq = start_freq; freq <= end_freq; freq += MHZ_TO_KHZ(20)) {
-+ c = ieee80211_get_channel_khz(wiphy, freq);
-+ if (!c)
-+ return;
-+
-+ c->dfs_state_last_available = jiffies;
-+ }
-+}
-+
-+void cfg80211_update_last_available(struct wiphy *wiphy,
-+ const struct cfg80211_chan_def *chandef)
-+{
-+ int width;
-+
-+ width = cfg80211_chandef_get_width(chandef);
-+ if (width < 0)
-+ return;
-+
-+ __cfg80211_update_last_available(wiphy, MHZ_TO_KHZ(chandef->center_freq1),
-+ width);
-+ if (chandef->width != NL80211_CHAN_WIDTH_80P80)
-+ return;
-+
-+ __cfg80211_update_last_available(wiphy, MHZ_TO_KHZ(chandef->center_freq2),
-+ width);
-+}
-+
- static bool cfg80211_chandef_dfs_available(struct wiphy *wiphy,
- const struct cfg80211_chan_def *chandef)
- {
---- a/net/wireless/core.h
-+++ b/net/wireless/core.h
-@@ -481,6 +481,8 @@ void cfg80211_set_dfs_state(struct wiphy
- enum nl80211_dfs_state dfs_state);
-
- void cfg80211_dfs_channels_update_work(struct work_struct *work);
-+void cfg80211_update_last_available(struct wiphy *wiphy,
-+ const struct cfg80211_chan_def *chandef);
-
- void cfg80211_sched_dfs_chan_update(struct cfg80211_registered_device *rdev);
-
---- a/net/wireless/mlme.c
-+++ b/net/wireless/mlme.c
-@@ -930,6 +930,8 @@ void cfg80211_dfs_channels_update_work(s
- if (c->dfs_state == NL80211_DFS_UNAVAILABLE) {
- time_dfs_update = IEEE80211_DFS_MIN_NOP_TIME_MS;
- radar_event = NL80211_RADAR_NOP_FINISHED;
-+ timeout = c->dfs_state_entered +
-+ msecs_to_jiffies(time_dfs_update);
- } else {
- if (regulatory_pre_cac_allowed(wiphy) ||
- cfg80211_any_wiphy_oper_chan(wiphy, c))
-@@ -937,11 +939,10 @@ void cfg80211_dfs_channels_update_work(s
-
- time_dfs_update = REG_PRE_CAC_EXPIRY_GRACE_MS;
- radar_event = NL80211_RADAR_PRE_CAC_EXPIRED;
-+ timeout = c->dfs_state_last_available +
-+ msecs_to_jiffies(time_dfs_update);
- }
-
-- timeout = c->dfs_state_entered +
-- msecs_to_jiffies(time_dfs_update);
--
- if (time_after_eq(jiffies, timeout)) {
- c->dfs_state = NL80211_DFS_USABLE;
- c->dfs_state_entered = jiffies;
diff --git a/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/330-mac80211-add-AQL-support-for-broadcast-packets.patch b/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/330-mac80211-add-AQL-support-for-broadcast-packets.patch
deleted file mode 100644
index d53afcf..0000000
--- a/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/330-mac80211-add-AQL-support-for-broadcast-packets.patch
+++ /dev/null
@@ -1,302 +0,0 @@
-From: Felix Fietkau <nbd@nbd.name>
-Date: Fri, 9 Feb 2024 19:43:40 +0100
-Subject: [PATCH] mac80211: add AQL support for broadcast packets
-
-Excessive broadcast traffic with little competing unicast traffic can easily
-flood hardware queues, leading to throughput issues. Additionally, filling
-the hardware queues with too many packets breaks FQ for broadcast data.
-Fix this by enabling AQL for broadcast packets.
-
-Signed-off-by: Felix Fietkau <nbd@nbd.name>
----
-
---- a/include/net/cfg80211.h
-+++ b/include/net/cfg80211.h
-@@ -3324,6 +3324,7 @@ enum wiphy_params_flags {
- /* The per TXQ device queue limit in airtime */
- #define IEEE80211_DEFAULT_AQL_TXQ_LIMIT_L 5000
- #define IEEE80211_DEFAULT_AQL_TXQ_LIMIT_H 12000
-+#define IEEE80211_DEFAULT_AQL_TXQ_LIMIT_BC 50000
-
- /* The per interface airtime threshold to switch to lower queue limit */
- #define IEEE80211_AQL_THRESHOLD 24000
---- a/net/mac80211/debugfs.c
-+++ b/net/mac80211/debugfs.c
-@@ -215,11 +215,13 @@ static ssize_t aql_pending_read(struct f
- "VI %u us\n"
- "BE %u us\n"
- "BK %u us\n"
-+ "BC/MC %u us\n"
- "total %u us\n",
- atomic_read(&local->aql_ac_pending_airtime[IEEE80211_AC_VO]),
- atomic_read(&local->aql_ac_pending_airtime[IEEE80211_AC_VI]),
- atomic_read(&local->aql_ac_pending_airtime[IEEE80211_AC_BE]),
- atomic_read(&local->aql_ac_pending_airtime[IEEE80211_AC_BK]),
-+ atomic_read(&local->aql_bc_pending_airtime),
- atomic_read(&local->aql_total_pending_airtime));
- return simple_read_from_buffer(user_buf, count, ppos,
- buf, len);
-@@ -245,7 +247,8 @@ static ssize_t aql_txq_limit_read(struct
- "VO %u %u\n"
- "VI %u %u\n"
- "BE %u %u\n"
-- "BK %u %u\n",
-+ "BK %u %u\n"
-+ "BC/MC %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],
-@@ -253,7 +256,8 @@ static ssize_t aql_txq_limit_read(struct
- 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]);
-+ local->aql_txq_limit_high[IEEE80211_AC_BK],
-+ local->aql_txq_limit_bc);
- return simple_read_from_buffer(user_buf, count, ppos,
- buf, len);
- }
-@@ -279,6 +283,11 @@ static ssize_t aql_txq_limit_write(struc
- else
- buf[count] = '\0';
-
-+ if (sscanf(buf, "mcast %u", &q_limit_low) == 1) {
-+ local->aql_txq_limit_bc = q_limit_low;
-+ return count;
-+ }
-+
- if (sscanf(buf, "%u %u %u", &ac, &q_limit_low, &q_limit_high) != 3)
- return -EINVAL;
-
---- a/net/mac80211/ieee80211_i.h
-+++ b/net/mac80211/ieee80211_i.h
-@@ -1328,10 +1328,12 @@ struct ieee80211_local {
- spinlock_t handle_wake_tx_queue_lock;
-
- u16 airtime_flags;
-+ u32 aql_txq_limit_bc;
- 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;
-+ atomic_t aql_bc_pending_airtime;
- atomic_t aql_ac_pending_airtime[IEEE80211_NUM_ACS];
-
- const struct ieee80211_ops *ops;
---- a/net/mac80211/main.c
-+++ b/net/mac80211/main.c
-@@ -788,6 +788,7 @@ struct ieee80211_hw *ieee80211_alloc_hw_
- spin_lock_init(&local->rx_path_lock);
- spin_lock_init(&local->queue_stop_reason_lock);
-
-+ local->aql_txq_limit_bc = IEEE80211_DEFAULT_AQL_TXQ_LIMIT_BC;
- for (i = 0; i < IEEE80211_NUM_ACS; i++) {
- INIT_LIST_HEAD(&local->active_txqs[i]);
- spin_lock_init(&local->active_txq_lock[i]);
---- a/net/mac80211/sta_info.c
-+++ b/net/mac80211/sta_info.c
-@@ -2343,13 +2343,28 @@ EXPORT_SYMBOL(ieee80211_sta_recalc_aggre
-
- void ieee80211_sta_update_pending_airtime(struct ieee80211_local *local,
- struct sta_info *sta, u8 ac,
-- u16 tx_airtime, bool tx_completed)
-+ u16 tx_airtime, bool tx_completed,
-+ bool mcast)
- {
- int tx_pending;
-
- if (!wiphy_ext_feature_isset(local->hw.wiphy, NL80211_EXT_FEATURE_AQL))
- return;
-
-+ if (mcast) {
-+ if (!tx_completed) {
-+ atomic_add(tx_airtime, &local->aql_bc_pending_airtime);
-+ return;
-+ }
-+
-+ tx_pending = atomic_sub_return(tx_airtime,
-+ &local->aql_bc_pending_airtime);
-+ if (tx_pending < 0)
-+ atomic_cmpxchg(&local->aql_bc_pending_airtime,
-+ tx_pending, 0);
-+ return;
-+ }
-+
- if (!tx_completed) {
- if (sta)
- atomic_add(tx_airtime,
---- a/net/mac80211/tx.c
-+++ b/net/mac80211/tx.c
-@@ -2536,7 +2536,7 @@ static u16 ieee80211_store_ack_skb(struc
-
- spin_lock_irqsave(&local->ack_status_lock, flags);
- id = idr_alloc(&local->ack_status_frames, ack_skb,
-- 1, 0x2000, GFP_ATOMIC);
-+ 1, 0x1000, GFP_ATOMIC);
- spin_unlock_irqrestore(&local->ack_status_lock, flags);
-
- if (id >= 0) {
-@@ -3958,20 +3958,20 @@ begin:
- encap_out:
- IEEE80211_SKB_CB(skb)->control.vif = vif;
-
-- if (tx.sta &&
-- wiphy_ext_feature_isset(local->hw.wiphy, NL80211_EXT_FEATURE_AQL)) {
-- bool ampdu = txq->ac != IEEE80211_AC_VO;
-+ if (wiphy_ext_feature_isset(local->hw.wiphy, NL80211_EXT_FEATURE_AQL)) {
-+ bool ampdu = txq->sta && txq->ac != IEEE80211_AC_VO;
- u32 airtime;
-
- airtime = ieee80211_calc_expected_tx_airtime(hw, vif, txq->sta,
- skb->len, ampdu);
-- if (airtime) {
-- airtime = ieee80211_info_set_tx_time_est(info, airtime);
-- ieee80211_sta_update_pending_airtime(local, tx.sta,
-- txq->ac,
-- airtime,
-- false);
-- }
-+ if (!airtime)
-+ return skb;
-+
-+ airtime = ieee80211_info_set_tx_time_est(info, airtime);
-+ info->tx_time_mc = !tx.sta;
-+ ieee80211_sta_update_pending_airtime(local, tx.sta, txq->ac,
-+ airtime, false,
-+ info->tx_time_mc);
- }
-
- return skb;
-@@ -4026,6 +4026,7 @@ struct ieee80211_txq *ieee80211_next_txq
- struct ieee80211_txq *ret = NULL;
- struct txq_info *txqi = NULL, *head = NULL;
- bool found_eligible_txq = false;
-+ bool aql_check;
-
- spin_lock_bh(&local->active_txq_lock[ac]);
-
-@@ -4049,26 +4050,26 @@ struct ieee80211_txq *ieee80211_next_txq
- if (!head)
- head = txqi;
-
-+ aql_check = ieee80211_txq_airtime_check(hw, &txqi->txq);
-+ if (aql_check)
-+ found_eligible_txq = true;
-+
- if (txqi->txq.sta) {
- struct sta_info *sta = container_of(txqi->txq.sta,
- struct sta_info, sta);
-- bool aql_check = ieee80211_txq_airtime_check(hw, &txqi->txq);
-- s32 deficit = ieee80211_sta_deficit(sta, txqi->txq.ac);
--
-- if (aql_check)
-- found_eligible_txq = true;
--
-- if (deficit < 0)
-+ if (ieee80211_sta_deficit(sta, txqi->txq.ac) < 0) {
- sta->airtime[txqi->txq.ac].deficit +=
- sta->airtime_weight << AIRTIME_QUANTUM_SHIFT;
--
-- if (deficit < 0 || !aql_check) {
-- list_move_tail(&txqi->schedule_order,
-- &local->active_txqs[txqi->txq.ac]);
-- goto begin;
-+ aql_check = false;
- }
- }
-
-+ if (!aql_check) {
-+ list_move_tail(&txqi->schedule_order,
-+ &local->active_txqs[txqi->txq.ac]);
-+ goto begin;
-+ }
-+
- if (txqi->schedule_round == local->schedule_round[ac])
- goto out;
-
-@@ -4133,7 +4134,8 @@ bool ieee80211_txq_airtime_check(struct
- return true;
-
- if (!txq->sta)
-- return true;
-+ return atomic_read(&local->aql_bc_pending_airtime) <
-+ local->aql_txq_limit_bc;
-
- if (unlikely(txq->tid == IEEE80211_NUM_TIDS))
- return true;
-@@ -4182,15 +4184,15 @@ bool ieee80211_txq_may_transmit(struct i
-
- spin_lock_bh(&local->active_txq_lock[ac]);
-
-- if (!txqi->txq.sta)
-- goto out;
--
- if (list_empty(&txqi->schedule_order))
- goto out;
-
- if (!ieee80211_txq_schedule_airtime_check(local, ac))
- goto out;
-
-+ if (!txqi->txq.sta)
-+ goto out;
-+
- list_for_each_entry_safe(iter, tmp, &local->active_txqs[ac],
- schedule_order) {
- if (iter == txqi)
---- a/include/net/mac80211.h
-+++ b/include/net/mac80211.h
-@@ -1116,6 +1116,7 @@ ieee80211_rate_get_vht_nss(const struct
- * link the frame will be transmitted on
- * @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_mc: TX time is for a multicast packet
- * @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
-@@ -1155,8 +1156,9 @@ struct ieee80211_tx_info {
- /* common information */
- u32 flags;
- u32 band:3,
-- ack_frame_id:13,
-+ ack_frame_id:12,
- hw_queue:4,
-+ tx_time_mc:1,
- tx_time_est:10;
- /* 2 free bits */
-
---- a/net/mac80211/sta_info.h
-+++ b/net/mac80211/sta_info.h
-@@ -147,7 +147,8 @@ struct airtime_info {
-
- void ieee80211_sta_update_pending_airtime(struct ieee80211_local *local,
- struct sta_info *sta, u8 ac,
-- u16 tx_airtime, bool tx_completed);
-+ u16 tx_airtime, bool tx_completed,
-+ bool mcast);
-
- struct sta_info;
-
---- a/net/mac80211/status.c
-+++ b/net/mac80211/status.c
-@@ -716,7 +716,7 @@ static void ieee80211_report_used_skb(st
- ieee80211_sta_update_pending_airtime(local, sta,
- skb_get_queue_mapping(skb),
- tx_time_est,
-- true);
-+ true, info->tx_time_mc);
- rcu_read_unlock();
- }
-
-@@ -1127,10 +1127,11 @@ void ieee80211_tx_status_ext(struct ieee
- /* Do this here to avoid the expensive lookup of the sta
- * in ieee80211_report_used_skb().
- */
-+ bool mcast = IEEE80211_SKB_CB(skb)->tx_time_mc;
- ieee80211_sta_update_pending_airtime(local, sta,
- skb_get_queue_mapping(skb),
- tx_time_est,
-- true);
-+ true, mcast);
- ieee80211_info_set_tx_time_est(IEEE80211_SKB_CB(skb), 0);
- }
-
diff --git a/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/331-wifi-mac80211-only-call-drv_sta_rc_update-for-upload.patch b/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/331-wifi-mac80211-only-call-drv_sta_rc_update-for-upload.patch
deleted file mode 100644
index 167b9e3..0000000
--- a/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/331-wifi-mac80211-only-call-drv_sta_rc_update-for-upload.patch
+++ /dev/null
@@ -1,25 +0,0 @@
-From: Felix Fietkau <nbd@nbd.name>
-Date: Wed, 21 Feb 2024 14:41:40 +0100
-Subject: [PATCH] wifi: mac80211: only call drv_sta_rc_update for uploaded
- stations
-
-When a station has not been uploaded yet, receiving SMPS or channel width
-notification action frames can lead to rate_control_rate_update calling
-drv_sta_rc_update with uninitialized driver private data.
-Fix this by adding a missing check for sta->uploaded.
-
-Signed-off-by: Felix Fietkau <nbd@nbd.name>
----
-
---- a/net/mac80211/rate.c
-+++ b/net/mac80211/rate.c
-@@ -119,7 +119,8 @@ void rate_control_rate_update(struct iee
- rcu_read_unlock();
- }
-
-- drv_sta_rc_update(local, sta->sdata, &sta->sta, changed);
-+ if (sta->uploaded)
-+ drv_sta_rc_update(local, sta->sdata, &sta->sta, changed);
- }
-
- int ieee80211_rate_control_register(const struct rate_control_ops *ops)
diff --git a/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/332-wifi-mac80211-check-clear-fast-rx-for-non-4addr-sta-.patch b/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/332-wifi-mac80211-check-clear-fast-rx-for-non-4addr-sta-.patch
deleted file mode 100644
index 02b4345..0000000
--- a/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/332-wifi-mac80211-check-clear-fast-rx-for-non-4addr-sta-.patch
+++ /dev/null
@@ -1,35 +0,0 @@
-From: Felix Fietkau <nbd@nbd.name>
-Date: Sat, 16 Mar 2024 08:37:21 +0100
-Subject: [PATCH] wifi: mac80211: check/clear fast rx for non-4addr sta VLAN
- changes
-
-When moving a station out of a VLAN and deleting the VLAN afterwards, the
-fast_rx entry still holds a pointer to the VLAN's netdev, which can cause
-use-after-free bugs. Fix this by immediately calling ieee80211_check_fast_rx
-after the VLAN change.
-
-Cc: stable@vger.kernel.org
-Reported-by: ranygh@riseup.net
-Signed-off-by: Felix Fietkau <nbd@nbd.name>
----
-
---- a/net/mac80211/cfg.c
-+++ b/net/mac80211/cfg.c
-@@ -2184,15 +2184,14 @@ static int ieee80211_change_station(stru
- }
-
- if (sta->sdata->vif.type == NL80211_IFTYPE_AP_VLAN &&
-- sta->sdata->u.vlan.sta) {
-- ieee80211_clear_fast_rx(sta);
-+ sta->sdata->u.vlan.sta)
- RCU_INIT_POINTER(sta->sdata->u.vlan.sta, NULL);
-- }
-
- if (test_sta_flag(sta, WLAN_STA_AUTHORIZED))
- ieee80211_vif_dec_num_mcast(sta->sdata);
-
- sta->sdata = vlansdata;
-+ ieee80211_check_fast_rx(sta);
- ieee80211_check_fast_xmit(sta);
-
- if (test_sta_flag(sta, WLAN_STA_AUTHORIZED)) {
diff --git a/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/400-allow-ibss-mixed.patch b/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/400-allow-ibss-mixed.patch
deleted file mode 100644
index 7a96f9f..0000000
--- a/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/400-allow-ibss-mixed.patch
+++ /dev/null
@@ -1,40 +0,0 @@
-From: Hauke Mehrtens <hauke@hauke-m.de>
-Date: Mon, 24 Feb 2020 00:00:00 +0100
-Subject: [PATCH] mac80211: Allow IBSS mode and different beacon intervals
-
-ath10k-ct supports the combination to select IBSS (ADHOC) mode and
-different beacon intervals together. mac80211 does not like this
-combination, but Ben says this is ok, so remove this check.
-
-ath10k-ct starting with version 5.2 allows the combination of
-NL80211_IFTYPE_ADHOC and beacon_int_min_gcd in ath10k_10x_ct_if_comb
-which triggers this warning. Ben told me that this is not a big problem
-and we should ignore this.
----
- net/wireless/core.c | 15 ---------------
- 1 file changed, 15 deletions(-)
-
---- a/net/wireless/core.c
-+++ b/net/wireless/core.c
-@@ -651,21 +651,6 @@ static int wiphy_verify_combinations(str
- c->limits[j].max > 1))
- return -EINVAL;
-
-- /*
-- * This isn't well-defined right now. If you have an
-- * IBSS interface, then its beacon interval may change
-- * by joining other networks, and nothing prevents it
-- * from doing that.
-- * So technically we probably shouldn't even allow AP
-- * and IBSS in the same interface, but it seems that
-- * some drivers support that, possibly only with fixed
-- * beacon intervals for IBSS.
-- */
-- if (WARN_ON(types & BIT(NL80211_IFTYPE_ADHOC) &&
-- c->beacon_int_min_gcd)) {
-- return -EINVAL;
-- }
--
- cnt += c->limits[j].max;
- /*
- * Don't advertise an unsupported type
diff --git a/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/780-avoid-crashing-missing-band.patch b/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/780-avoid-crashing-missing-band.patch
deleted file mode 100644
index 35fa961..0000000
--- a/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/780-avoid-crashing-missing-band.patch
+++ /dev/null
@@ -1,34 +0,0 @@
-From: David Bauer <mail@david-bauer.net>
-Date: Thu, 30 Nov 2023 07:32:52 +0100
-Subject: [PATCH] mac80211: avoid crashing on invalid band info
-
-Frequent crashes have been observed on MT7916 based platforms. While the
-root of these crashes are currently unknown, they happen when decoding
-rate information of connected STAs in AP mode. The rate-information is
-associated with a band which is not available on the PHY.
-
-Check for this condition in order to avoid crashing the whole system.
-This patch should be removed once the roout cause has been found and
-fixed.
-
-Link: https://github.com/freifunk-gluon/gluon/issues/2980
-
-Signed-off-by: David Bauer <mail@david-bauer.net>
----
-
---- a/net/mac80211/sta_info.c
-+++ b/net/mac80211/sta_info.c
-@@ -2445,6 +2445,13 @@ static void sta_stats_decode_rate(struct
-
- sband = local->hw.wiphy->bands[band];
-
-+ if (!sband) {
-+ wiphy_warn(local->hw.wiphy,
-+ "Invalid band %d\n",
-+ band);
-+ break;
-+ }
-+
- if (WARN_ON_ONCE(!sband->bitrates))
- break;
-
diff --git a/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/782-net-next-1-of-net-pass-the-dst-buffer-to-of_get_mac_address.patch b/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/782-net-next-1-of-net-pass-the-dst-buffer-to-of_get_mac_address.patch
deleted file mode 100644
index 26af6a2..0000000
--- a/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/782-net-next-1-of-net-pass-the-dst-buffer-to-of_get_mac_address.patch
+++ /dev/null
@@ -1,29 +0,0 @@
---- a/backport-include/linux/of_net.h
-+++ /dev/null
-@@ -1,26 +0,0 @@
--#ifndef _BP_OF_NET_H
--#define _BP_OF_NET_H
--#include_next <linux/of_net.h>
--#include <linux/version.h>
--#include <linux/etherdevice.h>
--
--/* The behavior of of_get_mac_address() changed in kernel 5.2, it now
-- * returns an error code and not NULL in case of an error.
-- */
--#if LINUX_VERSION_IS_LESS(5,13,0)
--static inline int backport_of_get_mac_address(struct device_node *np, u8 *mac_out)
--{
-- const void *mac = of_get_mac_address(np);
--
-- if (!mac)
-- return -ENODEV;
-- if (IS_ERR(mac))
-- return PTR_ERR(mac);
-- ether_addr_copy(mac_out, mac);
--
-- return 0;
--}
--#define of_get_mac_address LINUX_BACKPORT(of_get_mac_address)
--#endif /* < 5.2 */
--
--#endif /* _BP_OF_NET_H */
diff --git a/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/bp-0001-backports-add-SKB_DROP_REASON-and-kfree_skb_reason-b.patch b/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/bp-0001-backports-add-SKB_DROP_REASON-and-kfree_skb_reason-b.patch
deleted file mode 100644
index 46f1c4d..0000000
--- a/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/bp-0001-backports-add-SKB_DROP_REASON-and-kfree_skb_reason-b.patch
+++ /dev/null
@@ -1,48 +0,0 @@
-From 0d65414c2ec0772539b728d075aab23b026b553b Mon Sep 17 00:00:00 2001
-From: Evelyn Tsai <evelyn.tsai@mediatek.com>
-Date: Fri, 23 Feb 2024 09:10:09 +0800
-Subject: [PATCH 1/3] backports: add SKB_DROP_REASON and kfree_skb_reason
- backport on Kernel 5.4
-
----
- backport-include/linux/skbuff.h | 8 ++++++++
- backport-include/net/dropreason-core.h | 6 ++++++
- 2 files changed, 14 insertions(+)
-
-diff --git a/backport-include/linux/skbuff.h b/backport-include/linux/skbuff.h
-index c1592c2..9e23251 100644
---- a/backport-include/linux/skbuff.h
-+++ b/backport-include/linux/skbuff.h
-@@ -144,4 +144,12 @@ static inline u64 skb_get_kcov_handle(struct sk_buff *skb)
- #define napi_build_skb build_skb
- #endif
-
-+#if LINUX_VERSION_IS_LESS(6,0,0)
-+#define kfree_skb_reason LINUX_BACKPORT(kfree_skb_reason)
-+static inline void kfree_skb_reason(struct sk_buff *skb, int reason)
-+{
-+ return kfree_skb(skb);
-+}
-+#endif
-+
- #endif /* __BACKPORT_SKBUFF_H */
-diff --git a/backport-include/net/dropreason-core.h b/backport-include/net/dropreason-core.h
-index ab8532e..31c60b9 100644
---- a/backport-include/net/dropreason-core.h
-+++ b/backport-include/net/dropreason-core.h
-@@ -13,6 +13,12 @@
-
- #include <linux/version.h>
-
-+/* backport for 5.4 */
-+#if LINUX_VERSION_IS_LESS(5,5,0)
-+#define SKB_DROP_REASON_NOT_SPECIFIED 2
-+#define SKB_DROP_REASON_MAX 69
-+#endif
-+
- #if LINUX_VERSION_IS_LESS(5,18,0)
- #define SKB_NOT_DROPPED_YET SKB_DROP_REASON_MAX
- #endif
---
-2.18.0
-
diff --git a/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/bp-0003-backports-Revert-cfg80211-allow-grace-period-for-DFS.patch b/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/bp-0003-backports-Revert-cfg80211-allow-grace-period-for-DFS.patch
deleted file mode 100644
index ad5ef2e..0000000
--- a/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/bp-0003-backports-Revert-cfg80211-allow-grace-period-for-DFS.patch
+++ /dev/null
@@ -1,177 +0,0 @@
-From 23681abf649eaf1eda27dcfd3d17b80e1edeb951 Mon Sep 17 00:00:00 2001
-From: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
-Date: Thu, 19 Oct 2023 09:59:24 +0800
-Subject: [PATCH 3/3] backports: Revert cfg80211: allow grace period for DFS
- available after beacon shutdown
-
-revert 320-cfg80211-allow-grace-period-for-DFS-available-after-.patch
-This patch will lead to channel switch fail when background radar is
-enabled.
-When AP channel switch to USABLE DFS channel,
-1. AP will restart, and the DFS state of the previously operated DFS channel
- will not be cleared immediately if this patch is applied.
-2. Background radar will perform CAC on the specified DFS channel for AP.
-3. AP will choose an AVAILABLE channel to operate on.
-Therefore, AP might select those DFS channels whose DFS state would be
-cleared after the grace period, resulting in channel switch failure.
-
-Signed-off-by: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
----
- include/net/cfg80211.h | 3 ---
- net/wireless/ap.c | 6 +++---
- net/wireless/chan.c | 45 ------------------------------------------
- net/wireless/core.h | 2 --
- net/wireless/mlme.c | 7 +++----
- 5 files changed, 6 insertions(+), 57 deletions(-)
-
-diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
-index a77e8a5..0a825af 100644
---- a/include/net/cfg80211.h
-+++ b/include/net/cfg80211.h
-@@ -175,8 +175,6 @@ enum ieee80211_channel_flags {
- * @dfs_state: current state of this channel. Only relevant if radar is required
- * on this channel.
- * @dfs_state_entered: timestamp (jiffies) when the dfs state was entered.
-- * @dfs_state_last_available: timestamp (jiffies) of the last time when the
-- * channel was available.
- * @dfs_cac_ms: DFS CAC time in milliseconds, this is valid for DFS channels.
- */
- struct ieee80211_channel {
-@@ -193,7 +191,6 @@ struct ieee80211_channel {
- int orig_mag, orig_mpwr;
- enum nl80211_dfs_state dfs_state;
- unsigned long dfs_state_entered;
-- unsigned long dfs_state_last_available;
- unsigned int dfs_cac_ms;
- };
-
-diff --git a/net/wireless/ap.c b/net/wireless/ap.c
-index 63641aa..0962770 100644
---- a/net/wireless/ap.c
-+++ b/net/wireless/ap.c
-@@ -30,9 +30,6 @@ static int ___cfg80211_stop_ap(struct cfg80211_registered_device *rdev,
- if (!wdev->links[link_id].ap.beacon_interval)
- return -ENOENT;
-
-- cfg80211_update_last_available(wdev->wiphy,
-- &wdev->links[link_id].ap.chandef);
--
- err = rdev_stop_ap(rdev, dev, link_id);
- if (!err) {
- wdev->conn_owner_nlportid = 0;
-@@ -44,6 +41,9 @@ static int ___cfg80211_stop_ap(struct cfg80211_registered_device *rdev,
- if (notify)
- nl80211_send_ap_stopped(wdev, link_id);
-
-+ /* Should we apply the grace period during beaconing interface
-+ * shutdown also?
-+ */
- cfg80211_sched_dfs_chan_update(rdev);
- }
-
-diff --git a/net/wireless/chan.c b/net/wireless/chan.c
-index f8348bc..510079f 100644
---- a/net/wireless/chan.c
-+++ b/net/wireless/chan.c
-@@ -461,8 +461,6 @@ static void cfg80211_set_chans_dfs_state(struct wiphy *wiphy, u32 center_freq,
-
- c->dfs_state = dfs_state;
- c->dfs_state_entered = jiffies;
-- if (dfs_state == NL80211_DFS_AVAILABLE)
-- c->dfs_state_last_available = jiffies;
- }
- }
-
-@@ -876,49 +874,6 @@ static bool cfg80211_get_chans_dfs_available(struct wiphy *wiphy,
- return true;
- }
-
--static void
--__cfg80211_update_last_available(struct wiphy *wiphy,
-- u32 center_freq,
-- u32 bandwidth)
--{
-- struct ieee80211_channel *c;
-- u32 freq, start_freq, end_freq;
--
-- start_freq = cfg80211_get_start_freq(center_freq, bandwidth);
-- end_freq = cfg80211_get_end_freq(center_freq, bandwidth);
--
-- /*
-- * Check entire range of channels for the bandwidth.
-- * If any channel in between is disabled or has not
-- * had gone through CAC return false
-- */
-- for (freq = start_freq; freq <= end_freq; freq += MHZ_TO_KHZ(20)) {
-- c = ieee80211_get_channel_khz(wiphy, freq);
-- if (!c)
-- return;
--
-- c->dfs_state_last_available = jiffies;
-- }
--}
--
--void cfg80211_update_last_available(struct wiphy *wiphy,
-- const struct cfg80211_chan_def *chandef)
--{
-- int width;
--
-- width = cfg80211_chandef_get_width(chandef);
-- if (width < 0)
-- return;
--
-- __cfg80211_update_last_available(wiphy, MHZ_TO_KHZ(chandef->center_freq1),
-- width);
-- if (chandef->width != NL80211_CHAN_WIDTH_80P80)
-- return;
--
-- __cfg80211_update_last_available(wiphy, MHZ_TO_KHZ(chandef->center_freq2),
-- width);
--}
--
- static bool cfg80211_chandef_dfs_available(struct wiphy *wiphy,
- const struct cfg80211_chan_def *chandef)
- {
-diff --git a/net/wireless/core.h b/net/wireless/core.h
-index 9aef18e..46aa2a0 100644
---- a/net/wireless/core.h
-+++ b/net/wireless/core.h
-@@ -481,8 +481,6 @@ void cfg80211_set_dfs_state(struct wiphy *wiphy,
- enum nl80211_dfs_state dfs_state);
-
- void cfg80211_dfs_channels_update_work(struct work_struct *work);
--void cfg80211_update_last_available(struct wiphy *wiphy,
-- const struct cfg80211_chan_def *chandef);
-
- void cfg80211_sched_dfs_chan_update(struct cfg80211_registered_device *rdev);
-
-diff --git a/net/wireless/mlme.c b/net/wireless/mlme.c
-index 0002464..3cdfbd2 100644
---- a/net/wireless/mlme.c
-+++ b/net/wireless/mlme.c
-@@ -930,8 +930,6 @@ void cfg80211_dfs_channels_update_work(struct work_struct *work)
- if (c->dfs_state == NL80211_DFS_UNAVAILABLE) {
- time_dfs_update = IEEE80211_DFS_MIN_NOP_TIME_MS;
- radar_event = NL80211_RADAR_NOP_FINISHED;
-- timeout = c->dfs_state_entered +
-- msecs_to_jiffies(time_dfs_update);
- } else {
- if (regulatory_pre_cac_allowed(wiphy) ||
- cfg80211_any_wiphy_oper_chan(wiphy, c))
-@@ -939,10 +937,11 @@ void cfg80211_dfs_channels_update_work(struct work_struct *work)
-
- time_dfs_update = REG_PRE_CAC_EXPIRY_GRACE_MS;
- radar_event = NL80211_RADAR_PRE_CAC_EXPIRED;
-- timeout = c->dfs_state_last_available +
-- msecs_to_jiffies(time_dfs_update);
- }
-
-+ timeout = c->dfs_state_entered +
-+ msecs_to_jiffies(time_dfs_update);
-+
- if (time_after_eq(jiffies, timeout)) {
- c->dfs_state = NL80211_DFS_USABLE;
- c->dfs_state_entered = jiffies;
---
-2.18.0
-
diff --git a/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/mtk-0004-mtk-mac80211-add-support-for-runtime-set-inband-disc.patch b/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/mtk-0004-mtk-mac80211-add-support-for-runtime-set-inband-disc.patch
deleted file mode 100644
index 5644758..0000000
--- a/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/mtk-0004-mtk-mac80211-add-support-for-runtime-set-inband-disc.patch
+++ /dev/null
@@ -1,183 +0,0 @@
-From 1cc0213bb5d4152c41cd6dd00eef4a613a5a0a99 Mon Sep 17 00:00:00 2001
-From: MeiChia Chiu <meichia.chiu@mediatek.com>
-Date: Wed, 19 Oct 2022 13:45:42 +0800
-Subject: [PATCH 04/37] mtk: mac80211: add support for runtime set inband
- discovery
-
-Signed-off-by: MeiChia Chiu <meichia.chiu@mediatek.com>
----
- include/net/cfg80211.h | 1 +
- include/net/mac80211.h | 1 +
- include/uapi/linux/nl80211.h | 1 +
- net/mac80211/cfg.c | 30 +++++++++++++++++++++++++++++-
- net/wireless/nl80211.c | 33 ++++++++++++++++++++++++++++-----
- 5 files changed, 60 insertions(+), 6 deletions(-)
-
-diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
-index 25f15d0..5b2e242 100644
---- a/include/net/cfg80211.h
-+++ b/include/net/cfg80211.h
-@@ -1379,6 +1379,7 @@ struct cfg80211_fils_discovery {
- u32 max_interval;
- size_t tmpl_len;
- const u8 *tmpl;
-+ u8 disable;
- };
-
- /**
-diff --git a/include/net/mac80211.h b/include/net/mac80211.h
-index 231abd1..4eac89a 100644
---- a/include/net/mac80211.h
-+++ b/include/net/mac80211.h
-@@ -526,6 +526,7 @@ struct ieee80211_ftm_responder_params {
- struct ieee80211_fils_discovery {
- u32 min_interval;
- u32 max_interval;
-+ u8 disable;
- };
-
- /**
-diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h
-index 88eb85c..72ef4d9 100644
---- a/include/uapi/linux/nl80211.h
-+++ b/include/uapi/linux/nl80211.h
-@@ -7619,6 +7619,7 @@ enum nl80211_fils_discovery_attributes {
- NL80211_FILS_DISCOVERY_ATTR_INT_MIN,
- NL80211_FILS_DISCOVERY_ATTR_INT_MAX,
- NL80211_FILS_DISCOVERY_ATTR_TMPL,
-+ NL80211_UNSOL_BCAST_PROBE_RESP_ATTR_INTE,
-
- /* keep last */
- __NL80211_FILS_DISCOVERY_ATTR_LAST,
-diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
-index 6b62644..3c07357 100644
---- a/net/mac80211/cfg.c
-+++ b/net/mac80211/cfg.c
-@@ -993,6 +993,7 @@ static int ieee80211_set_fils_discovery(struct ieee80211_sub_if_data *sdata,
- fd = &link_conf->fils_discovery;
- fd->min_interval = params->min_interval;
- fd->max_interval = params->max_interval;
-+ fd->disable = params->disable;
-
- old = sdata_dereference(link->u.ap.fils_discovery, sdata);
- new = kzalloc(sizeof(*new) + params->tmpl_len, GFP_KERNEL);
-@@ -1516,9 +1517,11 @@ static int ieee80211_change_beacon(struct wiphy *wiphy, struct net_device *dev,
- struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
- struct ieee80211_link_data *link;
- struct beacon_data *old;
-+ struct cfg80211_ap_settings *ap_params;
-+ struct ieee80211_supported_band *sband;
-+ u64 changed = 0;
- int err;
- struct ieee80211_bss_conf *link_conf;
-- u64 changed = 0;
-
- sdata_assert_lock(sdata);
-
-@@ -1549,6 +1552,31 @@ static int ieee80211_change_beacon(struct wiphy *wiphy, struct net_device *dev,
- changed |= BSS_CHANGED_HE_BSS_COLOR;
- }
-
-+ sband = ieee80211_get_sband(sdata);
-+ if (!sband)
-+ return -EINVAL;
-+
-+ if (sband->band == NL80211_BAND_6GHZ) {
-+ ap_params = container_of(params, struct cfg80211_ap_settings, beacon);
-+
-+ if(ap_params->unsol_bcast_probe_resp.interval) {
-+ err = ieee80211_set_unsol_bcast_probe_resp(sdata,
-+ &ap_params->unsol_bcast_probe_resp,
-+ link, link_conf);
-+ if (err < 0)
-+ return err;
-+ changed |= BSS_CHANGED_UNSOL_BCAST_PROBE_RESP;
-+ } else {
-+ err = ieee80211_set_fils_discovery(sdata,
-+ &ap_params->fils_discovery,
-+ link, link_conf);
-+
-+ if (err < 0)
-+ return err;
-+ changed |= BSS_CHANGED_FILS_DISCOVERY;
-+ }
-+ }
-+
- ieee80211_link_info_change_notify(sdata, link, changed);
- return 0;
- }
-diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
-index 508edc1..abb9585 100644
---- a/net/wireless/nl80211.c
-+++ b/net/wireless/nl80211.c
-@@ -424,6 +424,7 @@ nl80211_fils_discovery_policy[NL80211_FILS_DISCOVERY_ATTR_MAX + 1] = {
- [NL80211_FILS_DISCOVERY_ATTR_INT_MAX] = NLA_POLICY_MAX(NLA_U32, 10000),
- [NL80211_FILS_DISCOVERY_ATTR_TMPL] =
- NLA_POLICY_BINARY_RANGE(NL80211_FILS_DISCOVERY_TMPL_MIN_LEN, IEEE80211_MAX_DATA_LEN),
-+ [NL80211_UNSOL_BCAST_PROBE_RESP_ATTR_INTE] = NLA_POLICY_MAX(NLA_U32, 20),
- };
-
- static const struct nla_policy
-@@ -5692,6 +5693,8 @@ static int nl80211_parse_fils_discovery(struct cfg80211_registered_device *rdev,
- fd->tmpl = nla_data(tb[NL80211_FILS_DISCOVERY_ATTR_TMPL]);
- fd->min_interval = nla_get_u32(tb[NL80211_FILS_DISCOVERY_ATTR_INT_MIN]);
- fd->max_interval = nla_get_u32(tb[NL80211_FILS_DISCOVERY_ATTR_INT_MAX]);
-+ fd->disable = !(fd->max_interval ||
-+ nla_get_u32(tb[NL80211_UNSOL_BCAST_PROBE_RESP_ATTR_INTE]));
-
- return 0;
- }
-@@ -6243,7 +6246,8 @@ static int nl80211_set_beacon(struct sk_buff *skb, struct genl_info *info)
- unsigned int link_id = nl80211_link_id(info->attrs);
- struct net_device *dev = info->user_ptr[1];
- struct wireless_dev *wdev = dev->ieee80211_ptr;
-- struct cfg80211_beacon_data params;
-+ struct cfg80211_ap_settings ap_params;
-+ struct cfg80211_beacon_data *params;
- int err;
-
- if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP &&
-@@ -6256,17 +6260,36 @@ static int nl80211_set_beacon(struct sk_buff *skb, struct genl_info *info)
- if (!wdev->links[link_id].ap.beacon_interval)
- return -EINVAL;
-
-- err = nl80211_parse_beacon(rdev, info->attrs, ¶ms, info->extack);
-+ memset(&ap_params, 0, sizeof(ap_params));
-+ params = &ap_params.beacon;
-+
-+ err = nl80211_parse_beacon(rdev, info->attrs, params, info->extack);
- if (err)
- goto out;
-
-+ if (info->attrs[NL80211_ATTR_FILS_DISCOVERY]) {
-+ err = nl80211_parse_fils_discovery(rdev,
-+ info->attrs[NL80211_ATTR_FILS_DISCOVERY],
-+ &ap_params);
-+ if (err)
-+ goto out;
-+ }
-+
-+ if (info->attrs[NL80211_ATTR_UNSOL_BCAST_PROBE_RESP]) {
-+ err = nl80211_parse_unsol_bcast_probe_resp(rdev,
-+ info->attrs[NL80211_ATTR_UNSOL_BCAST_PROBE_RESP],
-+ &ap_params);
-+ if (err)
-+ goto out;
-+ }
-+
- wdev_lock(wdev);
-- err = rdev_change_beacon(rdev, dev, ¶ms);
-+ err = rdev_change_beacon(rdev, dev, params);
- wdev_unlock(wdev);
-
- out:
-- kfree(params.mbssid_ies);
-- kfree(params.rnr_ies);
-+ kfree(params->mbssid_ies);
-+ kfree(params->rnr_ies);
- return err;
- }
-
---
-2.18.0
-
diff --git a/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/mtk-0007-mtk-mac80211-check-the-control-channel-before-downgr.patch b/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/mtk-0007-mtk-mac80211-check-the-control-channel-before-downgr.patch
deleted file mode 100644
index ce63f41..0000000
--- a/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/mtk-0007-mtk-mac80211-check-the-control-channel-before-downgr.patch
+++ /dev/null
@@ -1,54 +0,0 @@
-From a2cb7d582c92644990fb3833b70ea3f18a539a02 Mon Sep 17 00:00:00 2001
-From: Evelyn Tsai <evelyn.tsai@mediatek.com>
-Date: Fri, 16 Dec 2022 03:31:06 +0800
-Subject: [PATCH 07/37] mtk: mac80211: check the control channel before
- downgrading the bandwidth
-
----
- net/mac80211/mlme.c | 23 +++++++++++++++++++++++
- 1 file changed, 23 insertions(+)
-
-diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
-index 73f8df0..24d34d4 100644
---- a/net/mac80211/mlme.c
-+++ b/net/mac80211/mlme.c
-@@ -4814,6 +4814,26 @@ ieee80211_verify_sta_eht_mcs_support(struct ieee80211_sub_if_data *sdata,
- return true;
- }
-
-+static bool ieee80211_check_same_ctrl_channel(struct ieee80211_sub_if_data *sdata,
-+ const struct cfg80211_chan_def *chandef)
-+{
-+ struct ieee80211_local *local = sdata->local;
-+ struct ieee80211_chanctx *ctx;
-+
-+ mutex_lock(&local->chanctx_mtx);
-+ list_for_each_entry(ctx, &local->chanctx_list, list) {
-+ if (ctx->replace_state == IEEE80211_CHANCTX_WILL_BE_REPLACED)
-+ continue;
-+ if (ctx->mode == IEEE80211_CHANCTX_EXCLUSIVE)
-+ continue;
-+ if (chandef->chan == ctx->conf.def.chan)
-+ return true;
-+ }
-+
-+ mutex_unlock(&local->chanctx_mtx);
-+ return false;
-+}
-+
- static int ieee80211_prep_channel(struct ieee80211_sub_if_data *sdata,
- struct ieee80211_link_data *link,
- struct cfg80211_bss *cbss,
-@@ -5056,6 +5076,9 @@ static int ieee80211_prep_channel(struct ieee80211_sub_if_data *sdata,
- chandef.width == NL80211_CHAN_WIDTH_10)
- goto out;
-
-+ if (!ret || !ieee80211_check_same_ctrl_channel(sdata, &chandef))
-+ goto out;
-+
- while (ret && chandef.width != NL80211_CHAN_WIDTH_20_NOHT) {
- *conn_flags |=
- ieee80211_chandef_downgrade(&chandef);
---
-2.18.0
-
diff --git a/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/mtk-0010-mtk-mac80211-fix-build-error-on-Linux-Kernel-5.4.patch b/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/mtk-0010-mtk-mac80211-fix-build-error-on-Linux-Kernel-5.4.patch
deleted file mode 100644
index f37dcf9..0000000
--- a/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/mtk-0010-mtk-mac80211-fix-build-error-on-Linux-Kernel-5.4.patch
+++ /dev/null
@@ -1,119 +0,0 @@
-From d878da2558d32ce7ec97dad083a38392e653e54e Mon Sep 17 00:00:00 2001
-From: Evelyn Tsai <evelyn.tsai@mediatek.com>
-Date: Tue, 13 Dec 2022 09:04:49 +0800
-Subject: [PATCH 10/37] mtk: mac80211: fix build error on Linux Kernel 5.4
-
----
- include/linux/ieee80211.h | 8 +++-----
- net/mac80211/rc80211_minstrel_ht.c | 2 ++
- net/mac80211/wpa.c | 4 ++--
- net/wireless/nl80211.c | 12 +++++-------
- 4 files changed, 12 insertions(+), 14 deletions(-)
-
-diff --git a/include/linux/ieee80211.h b/include/linux/ieee80211.h
-index 2fa1862..e53b73e 100644
---- a/include/linux/ieee80211.h
-+++ b/include/linux/ieee80211.h
-@@ -310,11 +310,9 @@ static inline u16 ieee80211_sn_sub(u16 sn1, u16 sn2)
- struct ieee80211_hdr {
- __le16 frame_control;
- __le16 duration_id;
-- struct_group(addrs,
-- u8 addr1[ETH_ALEN];
-- u8 addr2[ETH_ALEN];
-- u8 addr3[ETH_ALEN];
-- );
-+ u8 addr1[ETH_ALEN];
-+ u8 addr2[ETH_ALEN];
-+ u8 addr3[ETH_ALEN];
- __le16 seq_ctrl;
- u8 addr4[ETH_ALEN];
- } __packed __aligned(2);
-diff --git a/net/mac80211/rc80211_minstrel_ht.c b/net/mac80211/rc80211_minstrel_ht.c
-index 3562903..3768947 100644
---- a/net/mac80211/rc80211_minstrel_ht.c
-+++ b/net/mac80211/rc80211_minstrel_ht.c
-@@ -10,7 +10,9 @@
- #include <linux/random.h>
- #include <linux/moduleparam.h>
- #include <linux/ieee80211.h>
-+#if LINUX_VERSION_IS_GEQ(5,10,0)
- #include <linux/minmax.h>
-+#endif
- #include <net/mac80211.h>
- #include "rate.h"
- #include "sta_info.h"
-diff --git a/net/mac80211/wpa.c b/net/mac80211/wpa.c
-index 2d8e38b..0bb3907 100644
---- a/net/mac80211/wpa.c
-+++ b/net/mac80211/wpa.c
-@@ -351,7 +351,7 @@ static u8 ccmp_gcmp_aad(struct sk_buff *skb, u8 *aad)
- * FC | A1 | A2 | A3 | SC | [A4] | [QC] */
- put_unaligned_be16(len_a, &aad[0]);
- put_unaligned(mask_fc, (__le16 *)&aad[2]);
-- memcpy(&aad[4], &hdr->addrs, 3 * ETH_ALEN);
-+ memcpy(&aad[4], &hdr->addr1, 3 * ETH_ALEN);
-
- /* Mask Seq#, leave Frag# */
- aad[22] = *((u8 *) &hdr->seq_ctrl) & 0x0f;
-@@ -792,7 +792,7 @@ static void bip_aad(struct sk_buff *skb, u8 *aad)
- IEEE80211_FCTL_MOREDATA);
- put_unaligned(mask_fc, (__le16 *) &aad[0]);
- /* A1 || A2 || A3 */
-- memcpy(aad + 2, &hdr->addrs, 3 * ETH_ALEN);
-+ memcpy(aad + 2, &hdr->addr1, 3 * ETH_ALEN);
- }
-
-
-diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
-index abb9585..c652a01 100644
---- a/net/wireless/nl80211.c
-+++ b/net/wireless/nl80211.c
-@@ -462,11 +462,6 @@ nl80211_sta_wme_policy[NL80211_STA_WME_MAX + 1] = {
- [NL80211_STA_WME_MAX_SP] = { .type = NLA_U8 },
- };
-
--static struct netlink_range_validation nl80211_punct_bitmap_range = {
-- .min = 0,
-- .max = 0xffff,
--};
--
- static const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = {
- [0] = { .strict_start_type = NL80211_ATTR_HE_OBSS_PD },
- [NL80211_ATTR_WIPHY] = { .type = NLA_U32 },
-@@ -806,8 +801,7 @@ static const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = {
- [NL80211_ATTR_MLD_ADDR] = NLA_POLICY_EXACT_LEN(ETH_ALEN),
- [NL80211_ATTR_MLO_SUPPORT] = { .type = NLA_FLAG },
- [NL80211_ATTR_MAX_NUM_AKM_SUITES] = { .type = NLA_REJECT },
-- [NL80211_ATTR_PUNCT_BITMAP] =
-- NLA_POLICY_FULL_RANGE(NLA_U32, &nl80211_punct_bitmap_range),
-+ [NL80211_ATTR_PUNCT_BITMAP] = NLA_POLICY_RANGE(NLA_U8, 0, 0xffff),
-
- [NL80211_ATTR_MAX_HW_TIMESTAMP_PEERS] = { .type = NLA_U16 },
- [NL80211_ATTR_HW_TIMESTAMP_ENABLED] = { .type = NLA_FLAG },
-@@ -16729,9 +16723,11 @@ static const struct genl_ops nl80211_ops[] = {
- /* can be retrieved by unprivileged users */
- .internal_flags = IFLAGS(NL80211_FLAG_NEED_WIPHY),
- },
-+#if LINUX_VERSION_IS_GEQ(5,10,0)
- };
-
- static const struct genl_small_ops nl80211_small_ops[] = {
-+#endif
- {
- .cmd = NL80211_CMD_SET_WIPHY,
- .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
-@@ -17576,8 +17572,10 @@ static struct genl_family nl80211_fam __genl_ro_after_init = {
- .module = THIS_MODULE,
- .ops = nl80211_ops,
- .n_ops = ARRAY_SIZE(nl80211_ops),
-+#if LINUX_VERSION_IS_GEQ(5,10,0)
- .small_ops = nl80211_small_ops,
- .n_small_ops = ARRAY_SIZE(nl80211_small_ops),
-+#endif
- #if LINUX_VERSION_IS_GEQ(6,1,0)
- .resv_start_op = NL80211_CMD_REMOVE_LINK_STA + 1,
- #endif
---
-2.18.0
-
diff --git a/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/mtk-0012-mtk-mac80211-ageout-color-bitmap.patch b/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/mtk-0012-mtk-mac80211-ageout-color-bitmap.patch
deleted file mode 100644
index 4d838c8..0000000
--- a/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/mtk-0012-mtk-mac80211-ageout-color-bitmap.patch
+++ /dev/null
@@ -1,146 +0,0 @@
-From 999bc7e5454349e1d43e7eaedccbbf291446a0fd Mon Sep 17 00:00:00 2001
-From: Yi-Chia Hsieh <yi-chia.hsieh@mediatek.com>
-Date: Mon, 13 Mar 2023 05:36:59 +0800
-Subject: [PATCH 12/37] mtk: mac80211: ageout color bitmap
-
-Adding a periodic work which runs once per second to check BSS color.
-OBSS BSS Color will be ageout if not seen for 10 seconds.
----
- include/net/mac80211.h | 1 +
- net/mac80211/cfg.c | 30 ++++++++++++++++++++++++++++++
- net/mac80211/ieee80211_i.h | 5 +++++
- net/mac80211/iface.c | 5 +++++
- net/mac80211/link.c | 2 ++
- net/mac80211/rx.c | 1 +
- 6 files changed, 44 insertions(+)
-
-diff --git a/include/net/mac80211.h b/include/net/mac80211.h
-index 1a13d47..361fe92 100644
---- a/include/net/mac80211.h
-+++ b/include/net/mac80211.h
-@@ -745,6 +745,7 @@ struct ieee80211_bss_conf {
- struct ieee80211_he_obss_pd he_obss_pd;
- struct cfg80211_he_bss_color he_bss_color;
- u64 used_color_bitmap;
-+ u64 color_last_seen[64];
- struct ieee80211_fils_discovery fils_discovery;
- u32 unsol_bcast_probe_resp_interval;
- struct cfg80211_bitrate_mask beacon_tx_rate;
-diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
-index af284d2..de3d181 100644
---- a/net/mac80211/cfg.c
-+++ b/net/mac80211/cfg.c
-@@ -4889,6 +4889,36 @@ out:
- return err;
- }
-
-+void
-+ieee80211_color_aging_work(struct work_struct *work)
-+{
-+ struct ieee80211_sub_if_data *sdata =
-+ container_of(work, struct ieee80211_sub_if_data,
-+ deflink.color_aging_work.work);
-+ struct ieee80211_bss_conf *bss_conf = &sdata->vif.bss_conf;
-+ int i = 0;
-+
-+ sdata_lock(sdata);
-+
-+ if (!ieee80211_sdata_running(sdata))
-+ goto unlock;
-+
-+ for (i = 0; i < IEEE80211_BSS_COLOR_MAX; i++) {
-+ /* ageout if not seen for a period */
-+ if ((bss_conf->used_color_bitmap & BIT_ULL(i)) &&
-+ time_before(bss_conf->color_last_seen[i],
-+ jiffies - IEEE80211_BSS_COLOR_AGEOUT_TIME * HZ)) {
-+ bss_conf->used_color_bitmap &= ~BIT_ULL(i);
-+ }
-+ }
-+
-+ ieee80211_queue_delayed_work(&sdata->local->hw,
-+ &sdata->deflink.color_aging_work, HZ);
-+
-+unlock:
-+ sdata_unlock(sdata);
-+}
-+
- static int
- ieee80211_set_radar_background(struct wiphy *wiphy,
- struct cfg80211_chan_def *chandef)
-diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
-index aecc401..6b0b149 100644
---- a/net/mac80211/ieee80211_i.h
-+++ b/net/mac80211/ieee80211_i.h
-@@ -992,6 +992,7 @@ struct ieee80211_link_data {
-
- struct work_struct color_change_finalize_work;
- struct delayed_work color_collision_detect_work;
-+ struct delayed_work color_aging_work;
- u64 color_bitmap;
-
- /* context reservation -- protected with chanctx_mtx */
-@@ -1991,9 +1992,13 @@ void ieee80211_csa_finalize_work(struct work_struct *work);
- int ieee80211_channel_switch(struct wiphy *wiphy, struct net_device *dev,
- struct cfg80211_csa_settings *params);
-
-+#define IEEE80211_BSS_COLOR_AGEOUT_TIME 10
-+#define IEEE80211_BSS_COLOR_MAX 64
-+
- /* color change handling */
- void ieee80211_color_change_finalize_work(struct work_struct *work);
- void ieee80211_color_collision_detection_work(struct work_struct *work);
-+void ieee80211_color_aging_work(struct work_struct *work);
-
- /* interface handling */
- #define MAC80211_SUPPORTED_FEATURES_TX (NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | \
-diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c
-index 4de8d3d..b3de593 100644
---- a/net/mac80211/iface.c
-+++ b/net/mac80211/iface.c
-@@ -541,6 +541,7 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, bool going_do
- cancel_work_sync(&sdata->deflink.color_change_finalize_work);
-
- cancel_delayed_work_sync(&sdata->deflink.dfs_cac_timer_work);
-+ cancel_delayed_work_sync(&sdata->deflink.color_aging_work);
-
- if (sdata->wdev.cac_started) {
- chandef = sdata->vif.bss_conf.chandef;
-@@ -1474,6 +1475,10 @@ int ieee80211_do_open(struct wireless_dev *wdev, bool coming_up)
-
- set_bit(SDATA_STATE_RUNNING, &sdata->state);
-
-+ if (sdata->vif.type == NL80211_IFTYPE_AP)
-+ ieee80211_queue_delayed_work(&sdata->local->hw,
-+ &sdata->deflink.color_aging_work, HZ);
-+
- return 0;
- err_del_interface:
- drv_remove_interface(local, sdata);
-diff --git a/net/mac80211/link.c b/net/mac80211/link.c
-index 16cbaea..116100a 100644
---- a/net/mac80211/link.c
-+++ b/net/mac80211/link.c
-@@ -47,6 +47,8 @@ void ieee80211_link_init(struct ieee80211_sub_if_data *sdata,
- INIT_LIST_HEAD(&link->reserved_chanctx_list);
- INIT_DELAYED_WORK(&link->dfs_cac_timer_work,
- ieee80211_dfs_cac_timer_work);
-+ INIT_DELAYED_WORK(&link->color_aging_work,
-+ ieee80211_color_aging_work);
-
- if (!deflink) {
- switch (sdata->vif.type) {
-diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
-index 2df16de..fead07e 100644
---- a/net/mac80211/rx.c
-+++ b/net/mac80211/rx.c
-@@ -3357,6 +3357,7 @@ ieee80211_rx_check_bss_color_collision(struct ieee80211_rx_data *rx)
- IEEE80211_HE_OPERATION_BSS_COLOR_MASK);
-
- bss_conf->used_color_bitmap |= BIT_ULL(color);
-+ bss_conf->color_last_seen[color] = jiffies;
-
- // trace_bss_color_bitmap(color, bss_conf->used_color_bitmap);
- if (color == bss_conf->he_bss_color.color)
---
-2.18.0
-
diff --git a/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/mtk-0021-mtk-mac80211-Add-utilities-for-converting-op_class.patch b/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/mtk-0021-mtk-mac80211-Add-utilities-for-converting-op_class.patch
deleted file mode 100644
index 124ac8e..0000000
--- a/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/mtk-0021-mtk-mac80211-Add-utilities-for-converting-op_class.patch
+++ /dev/null
@@ -1,201 +0,0 @@
-From 3012337540e2bfdf708cdd113c25c2501bf63da7 Mon Sep 17 00:00:00 2001
-From: Michael-CY Lee <michael-cy.lee@mediatek.com>
-Date: Mon, 14 Aug 2023 18:03:29 +0800
-Subject: [PATCH 21/37] mtk: mac80211: Add utilities for converting op_class
-
-These utilities include converting op_class to nl80211 channel width and
-center frequency.
-
-Signed-off-by: Michael-CY Lee <michael-cy.lee@mediatek.com>
----
- include/net/cfg80211.h | 25 ++++++++
- net/wireless/util.c | 130 ++++++++++++++++++++++++++++++++++++++++-
- 2 files changed, 154 insertions(+), 1 deletion(-)
-
-diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
-index 0b5a4e6..19c8abe 100644
---- a/include/net/cfg80211.h
-+++ b/include/net/cfg80211.h
-@@ -8723,6 +8723,31 @@ void cfg80211_ch_switch_started_notify(struct net_device *dev,
- bool ieee80211_operating_class_to_band(u8 operating_class,
- enum nl80211_band *band);
-
-+/**
-+ * ieee80211_operating_class_to_center_freq - convert operating class to
-+ * center frequency
-+ *
-+ * @operating_class: the operating class to convert
-+ * @chan: the ieee80211_channel to convert
-+ * @center_freq1: cneter frequency 1 pointer to fill
-+ * @center_freq2: cneter frequency 2 pointer to fill
-+ *
-+ * Returns %true if the conversion was successful, %false otherwise.
-+ */
-+bool ieee80211_operating_class_to_center_freq(u8 operating_class,
-+ struct ieee80211_channel *chan,
-+ u32 *center_freq1,
-+ u32 *center_freq2);
-+
-+/**
-+ * ieee80211_operating_class_to_chan_width - convert operating class to
-+ * nl80211 channel width
-+ *
-+ * @operating_class: the operating class to convert
-+ */
-+enum nl80211_chan_width
-+ieee80211_operating_class_to_chan_width(u8 operating_class);
-+
- /**
- * ieee80211_chandef_to_operating_class - convert chandef to operation class
- *
-diff --git a/net/wireless/util.c b/net/wireless/util.c
-index 1783ab9..13cb986 100644
---- a/net/wireless/util.c
-+++ b/net/wireless/util.c
-@@ -1981,7 +1981,7 @@ bool ieee80211_operating_class_to_band(u8 operating_class,
- case 128 ... 130:
- *band = NL80211_BAND_5GHZ;
- return true;
-- case 131 ... 135:
-+ case 131 ... 137:
- *band = NL80211_BAND_6GHZ;
- return true;
- case 81:
-@@ -1999,6 +1999,134 @@ bool ieee80211_operating_class_to_band(u8 operating_class,
- }
- EXPORT_SYMBOL(ieee80211_operating_class_to_band);
-
-+bool ieee80211_operating_class_to_center_freq(u8 operating_class,
-+ struct ieee80211_channel *chan,
-+ u32 *center_freq1,
-+ u32 *center_freq2)
-+{
-+ u32 control_freq, offset;
-+ enum nl80211_band band;
-+
-+ control_freq = chan->center_freq;
-+ if (!ieee80211_operating_class_to_band(operating_class, &band))
-+ return false;
-+
-+ if (band != chan->band)
-+ return false;
-+
-+ if (control_freq >= 5955)
-+ offset = control_freq - 5955;
-+ else if (control_freq >= 5745)
-+ offset = control_freq - 5745;
-+ else if (control_freq >= 5180)
-+ offset = control_freq - 5180;
-+ offset /= 20;
-+
-+ *center_freq2 = 0;
-+ switch (operating_class) {
-+ case 81: /* 2 GHz band; 20 MHz; channels 1..13 */
-+ case 82: /* 2 GHz band; 20 MHz; channel 14 */
-+ case 115: /* 5 GHz band; 20 MHz; channels 36,40,44,48 */
-+ case 118: /* 5 GHz band; 20 MHz; channels 52,56,60,64 */
-+ case 121: /* 5 GHz band; 20 MHz; channels 100..144 */
-+ case 124: /* 5 GHz band; 20 MHz; channels 149,153,157,161 */
-+ case 125: /* 5 GHz band; 20 MHz; channels 149..177 */
-+ case 131: /* 6 GHz band; 20 MHz; channels 1..233*/
-+ case 136: /* 6 GHz band; 20 MHz; channel 2 */
-+ *center_freq1 = control_freq;
-+ return true;
-+ case 83: /* 2 GHz band; 40 MHz; channels 1..9 */
-+ case 116: /* 5 GHz band; 40 MHz; channels 36,44 */
-+ case 119: /* 5 GHz band; 40 MHz; channels 52,60 */
-+ case 122: /* 5 GHz band; 40 MHz; channels 100,108,116,124,132,140 */
-+ case 126: /* 5 GHz band; 40 MHz; channels 149,157,165,173 */
-+ *center_freq1 = control_freq + 10;
-+ return true;
-+ case 84: /* 2 GHz band; 40 MHz; channels 5..13 */
-+ case 117: /* 5 GHz band; 40 MHz; channels 40,48 */
-+ case 120: /* 5 GHz band; 40 MHz; channels 56,64 */
-+ case 123: /* 5 GHz band; 40 MHz; channels 104,112,120,128,136,144 */
-+ case 127: /* 5 GHz band; 40 MHz; channels 153,161,169,177 */
-+ *center_freq1 = control_freq - 10;
-+ return true;
-+ case 132: /* 6 GHz band; 40 MHz; channels 1,5,..,229*/
-+ *center_freq1 = control_freq + 10 - (offset & 1) * 20;
-+ return true;
-+ case 128: /* 5 GHz band; 80 MHz; channels 36..64,100..144,149..177 */
-+ *center_freq1 = control_freq + 30 - (offset & 3) * 20;
-+ return true;
-+ case 130: /* 5 GHz band; 80+80 MHz; channels 36..64,100..144,149..177 */
-+ /* TODO How to know the center_freq2 of 80+80 MHz?*/
-+ *center_freq1 = 0;
-+ return false;
-+ case 133: /* 6 GHz band; 80 MHz; channels 1,5,..,229 */
-+ *center_freq1 = control_freq + 30 - (offset & 3) * 20;
-+ return true;
-+ case 129: /* 5 GHz band; 160 MHz; channels 36..64,100..144,149..177 */
-+ *center_freq1 = control_freq + 70 - (offset & 7) * 20;
-+ return true;
-+ case 134: /* 6 GHz band; 160 MHz; channels 1,5,..,229 */
-+ *center_freq1 = control_freq + 70 - (offset & 7) * 20;
-+ return true;
-+ case 135: /* 6 GHz band; 80+80 MHz; channels 1,5,..,229 */
-+ /* TODO How to know the center_freq2 of 80+80 MHz?*/
-+ *center_freq1 = 0;
-+ return false;
-+ case 137: /* 6 GHz band; 320 MHz; channels 1,5,..,229 */
-+ /* TODO it's 320-1 or 320-2 channelization? */
-+ /* Currently convert to 320-1 */
-+ *center_freq1 = control_freq + 150 - (offset & 15) * 20;
-+ return true;
-+ default:
-+ return false;
-+ }
-+}
-+EXPORT_SYMBOL(ieee80211_operating_class_to_center_freq);
-+
-+enum nl80211_chan_width
-+ieee80211_operating_class_to_chan_width(u8 operating_class)
-+{
-+ switch (operating_class) {
-+ case 81: /* 2 GHz band; 20 MHz; channels 1..13 */
-+ case 82: /* 2 GHz band; 20 MHz; channel 14 */
-+ case 115: /* 5 GHz band; 20 MHz; channels 36,40,44,48 */
-+ case 118: /* 5 GHz band; 20 MHz; channels 52,56,60,64 */
-+ case 121: /* 5 GHz band; 20 MHz; channels 100..144 */
-+ case 124: /* 5 GHz band; 20 MHz; channels 149,153,157,161 */
-+ case 125: /* 5 GHz band; 20 MHz; channels 149..177 */
-+ case 131: /* 6 GHz band; 20 MHz; channels 1..233*/
-+ case 136: /* 6 GHz band; 20 MHz; channel 2 */
-+ return NL80211_CHAN_WIDTH_20;
-+ case 83: /* 2 GHz band; 40 MHz; channels 1..9 */
-+ case 84: /* 2 GHz band; 40 MHz; channels 5..13 */
-+ case 116: /* 5 GHz band; 40 MHz; channels 36,44 */
-+ case 117: /* 5 GHz band; 40 MHz; channels 40,48 */
-+ case 119: /* 5 GHz band; 40 MHz; channels 52,60 */
-+ case 120: /* 5 GHz band; 40 MHz; channels 56,64 */
-+ case 122: /* 5 GHz band; 40 MHz; channels 100,108,116,124,132,140 */
-+ case 123: /* 5 GHz band; 40 MHz; channels 104,112,120,128,136,144 */
-+ case 126: /* 5 GHz band; 40 MHz; channels 149,157,165,173 */
-+ case 127: /* 5 GHz band; 40 MHz; channels 153,161,169,177 */
-+ case 132: /* 6 GHz band; 40 MHz; channels 1,5,..,229*/
-+ return NL80211_CHAN_WIDTH_40;
-+ case 128: /* 5 GHz band; 80 MHz; channels 36..64,100..144,149..177 */
-+ case 133: /* 6 GHz band; 80 MHz; channels 1,5,..,229 */
-+ return NL80211_CHAN_WIDTH_80;
-+ case 130: /* 5 GHz band; 80+80 MHz; channels 36..64,100..144,149..177 */
-+ case 135: /* 6 GHz band; 80+80 MHz; channels 1,5,..,229 */
-+ return NL80211_CHAN_WIDTH_80P80;
-+ case 129: /* 5 GHz band; 160 MHz; channels 36..64,100..144,149..177 */
-+ case 134: /* 6 GHz band; 160 MHz; channels 1,5,..,229 */
-+ return NL80211_CHAN_WIDTH_160;
-+ case 137: /* 6 GHz band; 320 MHz; channels 1,5,..,229 */
-+ return NL80211_CHAN_WIDTH_320;
-+ default:
-+ WARN_ON(1);
-+ return NL80211_CHAN_WIDTH_20_NOHT;
-+ }
-+}
-+EXPORT_SYMBOL(ieee80211_operating_class_to_chan_width);
-+
- bool ieee80211_chandef_to_operating_class(struct cfg80211_chan_def *chandef,
- u8 *op_class)
- {
---
-2.18.0
-
diff --git a/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/mtk-0022-mtk-mac80211-refactor-STA-CSA-parsing-flows.patch b/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/mtk-0022-mtk-mac80211-refactor-STA-CSA-parsing-flows.patch
deleted file mode 100644
index af8fb94..0000000
--- a/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/mtk-0022-mtk-mac80211-refactor-STA-CSA-parsing-flows.patch
+++ /dev/null
@@ -1,598 +0,0 @@
-From 8ecaec9854b8449c824f77a5b3b6c6bba6720b9d Mon Sep 17 00:00:00 2001
-From: Michael-CY Lee <michael-cy.lee@mediatek.com>
-Date: Thu, 28 Sep 2023 09:28:50 +0800
-Subject: [PATCH 22/37] mtk: mac80211: refactor STA CSA parsing flows
-
-This patch changes the flows when STA parses csa IE:
-
-1. If Extended CSA IE is presented, this patch uses the subfield op_class
- to build the VHT and HE operation in 5 GHz and 6 GHz, respectively.
-2. If Extended CSA IE is NOT presented but the Wide Bandwidth Channel
- Switch IE is presented, the new channel width is at least 40 MHz.
- Therefore this patch first prepares a 40 MHz chandef, then build the
- VHT and HE operation in 5 GHz and 6 GHz, respectively.
- Note that in a 6 GHz BSS, the subfield of Wide Bandwidth Channel Switch
- IE might be the VHT, deprecated VHT or HE operation, so this patch
- checks the combination of new channel width, ccfs0 and ccfs1 to build
- the correct HE operation.
-3. From the HE/VHT operation created in step 1 or 2, this patch then
- creates the chandef and assigns it to csa_ie.
-
-Signed-off-by: Michael-CY Lee <michael-cy.lee@mediatek.com>
----
- net/mac80211/spectmgmt.c | 508 ++++++++++++++++++++++++++++++++++-----
- 1 file changed, 454 insertions(+), 54 deletions(-)
-
-diff --git a/net/mac80211/spectmgmt.c b/net/mac80211/spectmgmt.c
-index 871cdac..dee7a60 100644
---- a/net/mac80211/spectmgmt.c
-+++ b/net/mac80211/spectmgmt.c
-@@ -19,6 +19,332 @@
- #include "sta_info.h"
- #include "wme.h"
-
-+static inline void
-+op_class_to_6ghz_he_eht_oper(u8 op_class, struct ieee80211_channel *chan,
-+ struct ieee80211_he_operation *he_oper,
-+ struct ieee80211_eht_operation *eht_oper)
-+{
-+ u8 new_chan_width;
-+ u32 he_oper_params, center_freq1 = 0, center_freq2 = 0;
-+ struct ieee80211_he_6ghz_oper *he_6ghz_oper;
-+ struct ieee80211_eht_operation_info *eht_oper_info;
-+
-+ new_chan_width = ieee80211_operating_class_to_chan_width(op_class);
-+ if (!ieee80211_operating_class_to_center_freq(op_class, chan,
-+ ¢er_freq1,
-+ ¢er_freq2)) {
-+ new_chan_width = NL80211_CHAN_WIDTH_20;
-+ center_freq1 = chan->center_freq;
-+ }
-+
-+ he_oper_params =
-+ u32_encode_bits(1, IEEE80211_HE_OPERATION_6GHZ_OP_INFO);
-+ he_oper->he_oper_params = cpu_to_le32(he_oper_params);
-+
-+ he_6ghz_oper = (struct ieee80211_he_6ghz_oper *)he_oper->optional;
-+ he_6ghz_oper->primary =
-+ ieee80211_frequency_to_channel(chan->center_freq);
-+ he_6ghz_oper->ccfs0 = ieee80211_frequency_to_channel(center_freq1);
-+ he_6ghz_oper->ccfs1 = center_freq2 ?
-+ ieee80211_frequency_to_channel(center_freq2) : 0;
-+
-+ switch (new_chan_width) {
-+ case NL80211_CHAN_WIDTH_320:
-+ /* Cannot derive center frequency for 320 MHZ from op_class
-+ * since it might be 320-1 or 320-2
-+ */
-+ WARN_ON(1);
-+ break;
-+ case NL80211_CHAN_WIDTH_160:
-+ he_6ghz_oper->ccfs1 = he_6ghz_oper->ccfs0;
-+ he_6ghz_oper->ccfs0 += chan->center_freq < center_freq1 ? -8 : 8;
-+ fallthrough;
-+ case NL80211_CHAN_WIDTH_80P80:
-+ he_6ghz_oper->control =
-+ IEEE80211_HE_6GHZ_OPER_CTRL_CHANWIDTH_160MHZ;
-+ break;
-+ case NL80211_CHAN_WIDTH_80:
-+ he_6ghz_oper->control =
-+ IEEE80211_HE_6GHZ_OPER_CTRL_CHANWIDTH_80MHZ;
-+ break;
-+ case NL80211_CHAN_WIDTH_40:
-+ he_6ghz_oper->control =
-+ IEEE80211_HE_6GHZ_OPER_CTRL_CHANWIDTH_40MHZ;
-+ break;
-+ default:
-+ he_6ghz_oper->control =
-+ IEEE80211_HE_6GHZ_OPER_CTRL_CHANWIDTH_20MHZ;
-+ break;
-+ }
-+
-+ eht_oper->params = IEEE80211_EHT_OPER_INFO_PRESENT;
-+
-+ eht_oper_info =
-+ (struct ieee80211_eht_operation_info *)eht_oper->optional;
-+ eht_oper_info->control = he_6ghz_oper->control;
-+ eht_oper_info->ccfs0 = he_6ghz_oper->ccfs0;
-+ eht_oper_info->ccfs1 = he_6ghz_oper->ccfs1;
-+}
-+
-+static inline void
-+wbcs_ie_to_6ghz_he_eht_oper(const struct ieee80211_wide_bw_chansw_ie *wbcs_ie,
-+ u8 new_chan_no,
-+ struct ieee80211_he_operation *he_oper,
-+ struct ieee80211_eht_operation *eht_oper)
-+{
-+ u32 he_oper_params;
-+ struct ieee80211_he_6ghz_oper *he_6ghz_oper;
-+ struct ieee80211_eht_operation_info *eht_oper_info;
-+ bool fallback_20mhz;
-+ u8 ccfs_diff;
-+
-+ he_oper_params =
-+ u32_encode_bits(1, IEEE80211_HE_OPERATION_6GHZ_OP_INFO);
-+ he_oper->he_oper_params = cpu_to_le32(he_oper_params);
-+
-+ he_6ghz_oper = (struct ieee80211_he_6ghz_oper *)he_oper->optional;
-+ he_6ghz_oper->primary = new_chan_no;
-+
-+ /* The Wide Bandwidth Channel Switch IE in a 6 GHz BSS migth be
-+ * deprecated VHT operation, VHT operation (IEEE 802.11-2020 9.4.2.160)
-+ * or HE operation (IEEE P80211be D3.2 9.4.2.159).
-+ * Check the combination of width, ccfs0 and ccfs1 to build the correct
-+ * HE/EHT operation.
-+ */
-+ he_6ghz_oper->ccfs0 = wbcs_ie->new_center_freq_seg0;
-+ he_6ghz_oper->ccfs1 = wbcs_ie->new_center_freq_seg1;
-+ switch (wbcs_ie->new_channel_width) {
-+ case 0:
-+ /* Must be [deprecated] VHT operation with 40 MHz bandwidth */
-+ he_6ghz_oper->control =
-+ IEEE80211_HE_6GHZ_OPER_CTRL_CHANWIDTH_40MHZ;
-+ break;
-+ case 1:
-+ if (he_6ghz_oper->ccfs1) {
-+ /* VHT operation with 160/80P80 MHz bandwidth */
-+ he_6ghz_oper->control =
-+ IEEE80211_HE_6GHZ_OPER_CTRL_CHANWIDTH_160MHZ;
-+ } else if ((he_6ghz_oper->ccfs0 - 7) % 16 == 0) {
-+ /* [deprecated] VHT operation with 80 MHz bandwidth */
-+ he_6ghz_oper->control =
-+ IEEE80211_HE_6GHZ_OPER_CTRL_CHANWIDTH_80MHZ;
-+ } else {
-+ /* HE operation with 40 MHz bandwidth */
-+ he_6ghz_oper->control =
-+ IEEE80211_HE_6GHZ_OPER_CTRL_CHANWIDTH_40MHZ;
-+ }
-+ break;
-+ case 2:
-+ if ((he_6ghz_oper->ccfs0 - 15) % 32 == 0) {
-+ /* deprecated VHT operation with 160 MHz bandwidth */
-+ he_6ghz_oper->control =
-+ IEEE80211_HE_6GHZ_OPER_CTRL_CHANWIDTH_160MHZ;
-+ he_6ghz_oper->ccfs1 = he_6ghz_oper->ccfs0;
-+ he_6ghz_oper->ccfs0 +=
-+ new_chan_no < he_6ghz_oper->ccfs0 ? -8 : 8;
-+ } else {
-+ /* HE operation with 80 MHz bandwidth */
-+ he_6ghz_oper->control =
-+ IEEE80211_HE_6GHZ_OPER_CTRL_CHANWIDTH_80MHZ;
-+ }
-+ break;
-+ case 3:
-+ /* Can be
-+ * 1. deprecated VHT operation with 80P80 MHz bandwidth
-+ * 2. HE operation with 160/80P80 MHz bandwidth
-+ */
-+ he_6ghz_oper->control =
-+ IEEE80211_HE_6GHZ_OPER_CTRL_CHANWIDTH_160MHZ;
-+ break;
-+ case 4:
-+ /* 320 MHz bandwidth
-+ * TODO channel switch to 320 MHz bandwidth should be indiated
-+ * by Bandwidth Indication IE (IEEE P80211be D3.2 9.4.2.159)
-+ */
-+ he_6ghz_oper->control = IEEE80211_EHT_OPER_CHAN_WIDTH_320MHZ;
-+ break;
-+ default:
-+ /* Ignore invalid width */
-+ break;
-+ }
-+
-+ /* Validate the relationship between new channel width and center frequency
-+ * segments, and fallback to 20 MHz if the relationship is wrong.
-+ */
-+ fallback_20mhz = false;
-+ switch (he_6ghz_oper->control) {
-+ case IEEE80211_HE_6GHZ_OPER_CTRL_CHANWIDTH_40MHZ:
-+ if ((he_6ghz_oper->ccfs0 - 3) % 8 != 0)
-+ fallback_20mhz = true;
-+ break;
-+ case IEEE80211_HE_6GHZ_OPER_CTRL_CHANWIDTH_80MHZ:
-+ if ((he_6ghz_oper->ccfs0 - 7) % 16 != 0)
-+ fallback_20mhz = true;
-+ break;
-+ case IEEE80211_HE_6GHZ_OPER_CTRL_CHANWIDTH_160MHZ:
-+ ccfs_diff = abs(he_6ghz_oper->ccfs1 - he_6ghz_oper->ccfs0);
-+ if ((ccfs_diff == 8 && (he_6ghz_oper->ccfs1 - 15) % 32 != 0) ||
-+ (ccfs_diff > 16 && ((he_6ghz_oper->ccfs0 - 7) % 16 != 0 ||
-+ (he_6ghz_oper->ccfs1 - 7) % 16 != 0)))
-+ fallback_20mhz = true;
-+ break;
-+ case IEEE80211_EHT_OPER_CHAN_WIDTH_320MHZ:
-+ if ((he_6ghz_oper->ccfs1 - 31) % 32 != 0)
-+ fallback_20mhz = true;
-+ break;
-+ }
-+
-+ if (fallback_20mhz) {
-+ he_6ghz_oper->control =
-+ IEEE80211_HE_6GHZ_OPER_CTRL_CHANWIDTH_20MHZ;
-+ he_6ghz_oper->ccfs0 = he_6ghz_oper->primary;
-+ he_6ghz_oper->ccfs1 = 0;
-+ }
-+
-+ eht_oper->params = IEEE80211_EHT_OPER_INFO_PRESENT;
-+ eht_oper_info =
-+ (struct ieee80211_eht_operation_info *)eht_oper->optional;
-+ eht_oper_info->control = he_6ghz_oper->control;
-+ eht_oper_info->ccfs0 = he_6ghz_oper->ccfs0;
-+ eht_oper_info->ccfs1 = he_6ghz_oper->ccfs1;
-+}
-+
-+static inline void
-+op_class_to_ht_vht_oper(u8 op_class, struct ieee80211_channel *chan,
-+ struct ieee80211_ht_operation *ht_oper,
-+ struct ieee80211_vht_operation *vht_oper)
-+{
-+ u8 new_chan_width;
-+ u32 center_freq1 = 0, center_freq2 = 0;
-+
-+ new_chan_width = ieee80211_operating_class_to_chan_width(op_class);
-+ if (!ieee80211_operating_class_to_center_freq(op_class, chan,
-+ ¢er_freq1,
-+ ¢er_freq2)) {
-+ new_chan_width = NL80211_CHAN_WIDTH_20;
-+ center_freq1 = chan->center_freq;
-+ }
-+
-+ vht_oper->center_freq_seg0_idx =
-+ ieee80211_frequency_to_channel(center_freq1);
-+ vht_oper->center_freq_seg1_idx = center_freq2 ?
-+ ieee80211_frequency_to_channel(center_freq2) : 0;
-+
-+ ht_oper->ht_param = (chan->center_freq / 20) & 1 ?
-+ IEEE80211_HT_PARAM_CHA_SEC_ABOVE :
-+ IEEE80211_HT_PARAM_CHA_SEC_BELOW;
-+
-+ switch (new_chan_width) {
-+ case NL80211_CHAN_WIDTH_320:
-+ WARN_ON(1);
-+ break;
-+ case NL80211_CHAN_WIDTH_160:
-+ vht_oper->chan_width = IEEE80211_VHT_CHANWIDTH_80MHZ;
-+ vht_oper->center_freq_seg1_idx = vht_oper->center_freq_seg0_idx;
-+ vht_oper->center_freq_seg0_idx +=
-+ chan->center_freq < center_freq1 ? -8 : 8;
-+ break;
-+ case NL80211_CHAN_WIDTH_80P80:
-+ vht_oper->chan_width = IEEE80211_VHT_CHANWIDTH_80MHZ;
-+ break;
-+ case NL80211_CHAN_WIDTH_80:
-+ vht_oper->chan_width = IEEE80211_VHT_CHANWIDTH_80MHZ;
-+ break;
-+ default:
-+ vht_oper->chan_width = IEEE80211_VHT_CHANWIDTH_USE_HT;
-+ if (chan->center_freq != center_freq1)
-+ ht_oper->ht_param = chan->center_freq > center_freq1 ?
-+ IEEE80211_HT_PARAM_CHA_SEC_BELOW :
-+ IEEE80211_HT_PARAM_CHA_SEC_ABOVE;
-+ else
-+ ht_oper->ht_param = IEEE80211_HT_PARAM_CHA_SEC_NONE;
-+ }
-+
-+ ht_oper->operation_mode =
-+ cpu_to_le16(vht_oper->center_freq_seg1_idx <<
-+ IEEE80211_HT_OP_MODE_CCFS2_SHIFT);
-+}
-+
-+static inline void
-+wbcs_ie_to_ht_vht_oper(struct ieee80211_channel *chan,
-+ const struct ieee80211_wide_bw_chansw_ie *wbcs_ie,
-+ struct ieee80211_ht_operation *ht_oper,
-+ struct ieee80211_vht_operation *vht_oper)
-+{
-+ u8 new_chan_width, new_ccfs0, new_ccfs1;
-+ bool fallback_20mhz;
-+
-+ new_chan_width = wbcs_ie->new_channel_width;
-+ new_ccfs0 = wbcs_ie->new_center_freq_seg0;
-+ new_ccfs1 = wbcs_ie->new_center_freq_seg1;
-+
-+ /* Validate the relationship between new channel width and center frequency
-+ * segments, and fallback to 20 MHz if the relationship is wrong.
-+ */
-+ fallback_20mhz = false;
-+ switch (new_chan_width) {
-+ case IEEE80211_VHT_CHANWIDTH_USE_HT:
-+ /* If the wide bandwidth channel switch IE is presented,
-+ * the new channel width is at least 40 MHz.
-+ */
-+ if (!new_ccfs1) {
-+ new_ccfs0 -= (new_ccfs0 >= 149) ? 151 : 38;
-+ if (new_ccfs0 % 8 != 0)
-+ fallback_20mhz = true;
-+ } else {
-+ fallback_20mhz = true;
-+ }
-+ break;
-+ case IEEE80211_VHT_CHANWIDTH_80MHZ:
-+ if (!new_ccfs1) {
-+ new_ccfs0 -= (new_ccfs0 >= 149) ? 155 : 42;
-+ if (new_ccfs0 % 16 != 0)
-+ fallback_20mhz = true;
-+ break;
-+ } else if (abs(new_ccfs1 - new_ccfs0) == 8) {
-+ new_ccfs0 = new_ccfs1;
-+ new_ccfs1 = 0;
-+ }
-+ fallthrough;
-+ case IEEE80211_VHT_CHANWIDTH_160MHZ:
-+ if (!new_ccfs1) {
-+ if (new_ccfs0 != 50 && new_ccfs0 != 114 && new_ccfs0 != 163)
-+ fallback_20mhz = true;
-+ break;
-+ }
-+ fallthrough;
-+ case IEEE80211_VHT_CHANWIDTH_80P80MHZ:
-+ new_ccfs0 -= (new_ccfs0 >= 149) ? 155 : 42;
-+ new_ccfs1 -= (new_ccfs1 >= 149) ? 155 : 42;
-+ if (new_ccfs0 % 16 != 0 || new_ccfs1 % 16 != 0)
-+ fallback_20mhz = true;
-+ break;
-+ default:
-+ fallback_20mhz = true;
-+ }
-+
-+ if (fallback_20mhz) {
-+ ht_oper->ht_param = IEEE80211_HT_PARAM_CHA_SEC_NONE;
-+
-+ vht_oper->chan_width = IEEE80211_VHT_CHANWIDTH_USE_HT;
-+ vht_oper->center_freq_seg0_idx =
-+ ieee80211_frequency_to_channel(chan->center_freq);
-+ vht_oper->center_freq_seg1_idx = 0;
-+
-+ } else {
-+ ht_oper->ht_param = (chan->center_freq / 20) & 1 ?
-+ IEEE80211_HT_PARAM_CHA_SEC_ABOVE :
-+ IEEE80211_HT_PARAM_CHA_SEC_BELOW;
-+
-+ vht_oper->chan_width = new_chan_width;
-+ vht_oper->center_freq_seg0_idx = wbcs_ie->new_center_freq_seg0;
-+ vht_oper->center_freq_seg1_idx = wbcs_ie->new_center_freq_seg1;
-+ }
-+
-+ ht_oper->operation_mode = cpu_to_le16(vht_oper->center_freq_seg1_idx <<
-+ IEEE80211_HT_OP_MODE_CCFS2_SHIFT);
-+}
-+
- int ieee80211_parse_ch_switch_ie(struct ieee80211_sub_if_data *sdata,
- struct ieee802_11_elems *elems,
- enum nl80211_band current_band,
-@@ -26,19 +352,27 @@ int ieee80211_parse_ch_switch_ie(struct ieee80211_sub_if_data *sdata,
- ieee80211_conn_flags_t conn_flags, u8 *bssid,
- struct ieee80211_csa_ie *csa_ie)
- {
-+ struct ieee80211_supported_band *sband;
- enum nl80211_band new_band = current_band;
-- int new_freq;
-- u8 new_chan_no;
-+ int new_freq, size;
-+ u8 new_chan_no = 0, new_op_class = 0;
- struct ieee80211_channel *new_chan;
-- struct cfg80211_chan_def new_vht_chandef = {};
-+ struct cfg80211_chan_def new_chandef = {};
- const struct ieee80211_sec_chan_offs_ie *sec_chan_offs;
- const struct ieee80211_wide_bw_chansw_ie *wide_bw_chansw_ie;
-+ const struct ieee80211_ext_chansw_ie *ext_chansw_ie;
-+ struct ieee80211_ht_operation *ht_oper;
-+ struct ieee80211_vht_operation *vht_oper;
-+ struct ieee80211_he_operation *he_oper;
-+ struct ieee80211_eht_operation *eht_oper;
-+ struct ieee80211_sta_ht_cap sta_ht_cap;
- int secondary_channel_offset = -1;
-
- memset(csa_ie, 0, sizeof(*csa_ie));
-
- sec_chan_offs = elems->sec_chan_offs;
- wide_bw_chansw_ie = elems->wide_bw_chansw_ie;
-+ ext_chansw_ie = elems->ext_chansw_ie;
-
- if (conn_flags & (IEEE80211_CONN_DISABLE_HT |
- IEEE80211_CONN_DISABLE_40MHZ)) {
-@@ -46,29 +380,30 @@ int ieee80211_parse_ch_switch_ie(struct ieee80211_sub_if_data *sdata,
- wide_bw_chansw_ie = NULL;
- }
-
-- if (conn_flags & IEEE80211_CONN_DISABLE_VHT)
-- wide_bw_chansw_ie = NULL;
--
-- if (elems->ext_chansw_ie) {
-- if (!ieee80211_operating_class_to_band(
-- elems->ext_chansw_ie->new_operating_class,
-- &new_band)) {
-- sdata_info(sdata,
-- "cannot understand ECSA IE operating class, %d, ignoring\n",
-- elems->ext_chansw_ie->new_operating_class);
-+ if (ext_chansw_ie) {
-+ new_op_class = ext_chansw_ie->new_operating_class;
-+ if (!ieee80211_operating_class_to_band(new_op_class, &new_band)) {
-+ new_op_class = 0;
-+ sdata_info(sdata, "cannot understand ECSA IE "
-+ "operating class, %d, ignoring\n",
-+ ext_chansw_ie->new_operating_class);
-+ } else {
-+ new_chan_no = ext_chansw_ie->new_ch_num;
-+ csa_ie->count = ext_chansw_ie->count;
-+ csa_ie->mode = ext_chansw_ie->mode;
- }
-- new_chan_no = elems->ext_chansw_ie->new_ch_num;
-- csa_ie->count = elems->ext_chansw_ie->count;
-- csa_ie->mode = elems->ext_chansw_ie->mode;
-- } else if (elems->ch_switch_ie) {
-+ }
-+
-+ if (!new_op_class && elems->ch_switch_ie) {
- new_chan_no = elems->ch_switch_ie->new_ch_num;
- csa_ie->count = elems->ch_switch_ie->count;
- csa_ie->mode = elems->ch_switch_ie->mode;
-- } else {
-- /* nothing here we understand */
-- return 1;
- }
-
-+ /* nothing here we understand */
-+ if (!new_chan_no)
-+ return 1;
-+
- /* Mesh Channel Switch Parameters Element */
- if (elems->mesh_chansw_params_ie) {
- csa_ie->ttl = elems->mesh_chansw_params_ie->mesh_ttl;
-@@ -132,54 +467,119 @@ int ieee80211_parse_ch_switch_ie(struct ieee80211_sub_if_data *sdata,
- break;
- }
-
-- if (wide_bw_chansw_ie) {
-- u8 new_seg1 = wide_bw_chansw_ie->new_center_freq_seg1;
-- struct ieee80211_vht_operation vht_oper = {
-- .chan_width =
-- wide_bw_chansw_ie->new_channel_width,
-- .center_freq_seg0_idx =
-- wide_bw_chansw_ie->new_center_freq_seg0,
-- .center_freq_seg1_idx = new_seg1,
-- /* .basic_mcs_set doesn't matter */
-- };
-- struct ieee80211_ht_operation ht_oper = {
-- .operation_mode =
-- cpu_to_le16(new_seg1 <<
-- IEEE80211_HT_OP_MODE_CCFS2_SHIFT),
-- };
--
-- /* default, for the case of IEEE80211_VHT_CHANWIDTH_USE_HT,
-- * to the previously parsed chandef
-- */
-- new_vht_chandef = csa_ie->chandef;
-+ if (new_band == NL80211_BAND_6GHZ) {
-+ size = sizeof(struct ieee80211_he_operation) +
-+ sizeof(struct ieee80211_he_6ghz_oper);
-+ he_oper = kzalloc(size, GFP_KERNEL);
-+ if (!he_oper)
-+ return -ENOMEM;
-+
-+ size = sizeof(struct ieee80211_eht_operation) +
-+ sizeof(struct ieee80211_eht_operation_info);
-+ eht_oper = kzalloc(size, GFP_KERNEL);
-+ if (!eht_oper) {
-+ kfree(he_oper);
-+ return -ENOMEM;
-+ }
-+
-+ if (new_op_class && new_op_class != 135 && new_op_class != 137) {
-+ /* There is no way to tell the ccfs1 for op_class 135
-+ * (80P80 MHz) and 137 (320 MHz).
-+ */
-+ op_class_to_6ghz_he_eht_oper(new_op_class, new_chan,
-+ he_oper, eht_oper);
-+ } else if (wide_bw_chansw_ie) {
-+ wbcs_ie_to_6ghz_he_eht_oper(wide_bw_chansw_ie,
-+ new_chan_no, he_oper,
-+ eht_oper);
-+ }
-+
-+ new_chandef = csa_ie->chandef;
-
- /* ignore if parsing fails */
-- if (!ieee80211_chandef_vht_oper(&sdata->local->hw,
-- vht_cap_info,
-- &vht_oper, &ht_oper,
-- &new_vht_chandef))
-- new_vht_chandef.chan = NULL;
-+ if (!ieee80211_chandef_he_6ghz_oper(sdata, he_oper, eht_oper,
-+ &new_chandef))
-+ new_chandef.chan = NULL;
-+
-+ kfree(he_oper);
-+ kfree(eht_oper);
-+ } else {
-+ sband = sdata->local->hw.wiphy->bands[new_band];
-+ memcpy(&sta_ht_cap, &sband->ht_cap, sizeof(sta_ht_cap));
-+ ieee80211_apply_htcap_overrides(sdata, &sta_ht_cap);
-+
-+ if (!sta_ht_cap.ht_supported ||
-+ !(sta_ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40))
-+ goto out;
-+
-+ ht_oper = kzalloc(sizeof(*ht_oper), GFP_KERNEL);
-+ if (!ht_oper)
-+ return -ENOMEM;
-+
-+ vht_oper = kzalloc(sizeof(*vht_oper), GFP_KERNEL);
-+ if (!vht_oper) {
-+ kfree(ht_oper);
-+ return -ENOMEM;
-+ }
-+
-+ if (new_op_class && new_op_class != 130) {
-+ /* There is no way to tell the ccfs1 for op_class 130
-+ * (80P80 MHz).
-+ */
-+ op_class_to_ht_vht_oper(new_op_class, new_chan, ht_oper,
-+ vht_oper);
-+ } else if (wide_bw_chansw_ie && new_band == NL80211_BAND_5GHZ &&
-+ sband->vht_cap.vht_supported) {
-+ /* It is assumed that there is no WBCS IE in the beacon
-+ * from a 2 GHz BSS during a channel switch.
-+ */
-+ wbcs_ie_to_ht_vht_oper(new_chan, wide_bw_chansw_ie,
-+ ht_oper, vht_oper);
-+ } else {
-+ kfree(ht_oper);
-+ kfree(vht_oper);
-+ goto out;
-+ }
-+
-+ new_chandef = csa_ie->chandef;
-+
-+ ieee80211_chandef_ht_oper(ht_oper, &new_chandef);
-+
-+ /* ignore if parsing fails */
-+ if (sband->vht_cap.vht_supported &&
-+ !ieee80211_chandef_vht_oper(&sdata->local->hw, vht_cap_info,
-+ vht_oper, ht_oper, &new_chandef))
-+ new_chandef.chan = NULL;
-+
-+ kfree(ht_oper);
-+ kfree(vht_oper);
-+ }
-+
-+ if (new_chandef.chan) {
-+ if (conn_flags & IEEE80211_CONN_DISABLE_320MHZ &&
-+ new_chandef.width == NL80211_CHAN_WIDTH_320)
-+ ieee80211_chandef_downgrade(&new_chandef);
-
- if (conn_flags & IEEE80211_CONN_DISABLE_80P80MHZ &&
-- new_vht_chandef.width == NL80211_CHAN_WIDTH_80P80)
-- ieee80211_chandef_downgrade(&new_vht_chandef);
-+ new_chandef.width == NL80211_CHAN_WIDTH_80P80)
-+ ieee80211_chandef_downgrade(&new_chandef);
-+
- if (conn_flags & IEEE80211_CONN_DISABLE_160MHZ &&
-- new_vht_chandef.width == NL80211_CHAN_WIDTH_160)
-- ieee80211_chandef_downgrade(&new_vht_chandef);
-- }
-+ new_chandef.width == NL80211_CHAN_WIDTH_160)
-+ ieee80211_chandef_downgrade(&new_chandef);
-
-- /* if VHT data is there validate & use it */
-- if (new_vht_chandef.chan) {
-- if (!cfg80211_chandef_compatible(&new_vht_chandef,
-+ if (!cfg80211_chandef_compatible(&new_chandef,
- &csa_ie->chandef)) {
- sdata_info(sdata,
- "BSS %pM: CSA has inconsistent channel data, disconnecting\n",
- bssid);
- return -EINVAL;
- }
-- csa_ie->chandef = new_vht_chandef;
-+
-+ csa_ie->chandef = new_chandef;
- }
-
-+out:
- if (elems->max_channel_switch_time)
- csa_ie->max_switch_time =
- (elems->max_channel_switch_time[0] << 0) |
---
-2.18.0
-
diff --git a/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/mtk-0036-mtk-mac80211-Add-CSA-action-frame-tx-when-channel-sw.patch b/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/mtk-0036-mtk-mac80211-Add-CSA-action-frame-tx-when-channel-sw.patch
deleted file mode 100644
index a5cf569..0000000
--- a/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/mtk-0036-mtk-mac80211-Add-CSA-action-frame-tx-when-channel-sw.patch
+++ /dev/null
@@ -1,117 +0,0 @@
-From 2bb34cb05062f9f53252c5a15304a75141e02660 Mon Sep 17 00:00:00 2001
-From: "fancy.liu" <fancy.liu@mediatek.com>
-Date: Thu, 30 Nov 2023 16:42:59 +0800
-Subject: [PATCH 36/37] mtk: mac80211: Add CSA action frame tx when channel
- switch on AP
-
-Description:
-To meet spec requirement.
-
-802.11-2020
-11.8.8.2 Selecting and advertising a new channel in a non-DMG infrastructure BSS
-11.8.8.6 Selecting and advertising a new channel in a DMG BSS
--
-An AP shall inform associated STAs that the AP is moving to a new channel and shall maintain the association by advertising the switch using Channel Switch Announcement elements in Beacon frames, Probe Response frames, and Channel Switch Announcement frames until the intended channel switch time.
-
-Signed-off-by: fancy.liu <fancy.liu@mediatek.com>
----
- net/mac80211/cfg.c | 28 ++++++++++++++--------------
- net/mac80211/util.c | 10 +++++++---
- 2 files changed, 21 insertions(+), 17 deletions(-)
-
-diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
-index cf694bc..a2d1688 100644
---- a/net/mac80211/cfg.c
-+++ b/net/mac80211/cfg.c
-@@ -3798,15 +3798,7 @@ static int ieee80211_set_csa_beacon(struct ieee80211_sub_if_data *sdata,
- * immediately too. If we would delay the switch
- * until the next TBTT, we would have to set the probe
- * response here.
-- *
-- * TODO: A channel switch with count <= 1 without
-- * sending a CSA action frame is kind of useless,
-- * because the clients won't know we're changing
-- * channels. The action frame must be implemented
-- * either here or in the userspace.
- */
-- if (params->count <= 1)
-- break;
-
- if ((params->n_counter_offsets_beacon >
- IEEE80211_MAX_CNTDWN_COUNTERS_NUM) ||
-@@ -3822,14 +3814,20 @@ static int ieee80211_set_csa_beacon(struct ieee80211_sub_if_data *sdata,
- csa.n_counter_offsets_presp = params->n_counter_offsets_presp;
- csa.count = params->count;
-
-- err = ieee80211_assign_beacon(sdata, &sdata->deflink,
-- ¶ms->beacon_csa, &csa,
-- NULL, changed);
-- if (err < 0) {
-- ieee80211_free_next_beacon(&sdata->deflink);
-- return err;
-+ /* see comments in the NL80211_IFTYPE_AP block */
-+ if (params->count > 1) {
-+ err = ieee80211_assign_beacon(sdata, &sdata->deflink,
-+ ¶ms->beacon_csa, &csa,
-+ NULL, changed);
-+
-+ if (err < 0) {
-+ ieee80211_free_next_beacon(&sdata->deflink);
-+ return err;
-+ }
- }
-
-+ ieee80211_send_action_csa(sdata, params);
-+
- break;
- case NL80211_IFTYPE_ADHOC:
- if (!sdata->vif.cfg.ibss_joined)
-@@ -3901,6 +3899,7 @@ static int ieee80211_set_csa_beacon(struct ieee80211_sub_if_data *sdata,
- }
- #endif
- default:
-+ sdata_info(sdata, "Won't send CSA for vif.type:%d.\n", sdata->vif.type);
- return -EOPNOTSUPP;
- }
-
-@@ -3990,6 +3989,7 @@ __ieee80211_channel_switch(struct wiphy *wiphy, struct net_device *dev,
-
- err = ieee80211_set_csa_beacon(sdata, params, &changed);
- if (err) {
-+ sdata_info(sdata, "failed to set csa in beacon.\n");
- ieee80211_link_unreserve_chanctx(&sdata->deflink);
- goto out;
- }
-diff --git a/net/mac80211/util.c b/net/mac80211/util.c
-index f0bb4e8..00a20a6 100644
---- a/net/mac80211/util.c
-+++ b/net/mac80211/util.c
-@@ -4514,8 +4514,11 @@ int ieee80211_send_action_csa(struct ieee80211_sub_if_data *sdata,
- u8 *pos;
-
- if (sdata->vif.type != NL80211_IFTYPE_ADHOC &&
-- sdata->vif.type != NL80211_IFTYPE_MESH_POINT)
-+ sdata->vif.type != NL80211_IFTYPE_MESH_POINT &&
-+ sdata->vif.type != NL80211_IFTYPE_AP) {
-+ sdata_info(sdata, "Not allow csa action on vif.type:%d.\n", sdata->vif.type);
- return -EOPNOTSUPP;
-+ }
-
- skb = dev_alloc_skb(local->tx_headroom + hdr_len +
- 5 + /* channel switch announcement element */
-@@ -4532,9 +4535,10 @@ int ieee80211_send_action_csa(struct ieee80211_sub_if_data *sdata,
-
- eth_broadcast_addr(mgmt->da);
- memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN);
-- if (ieee80211_vif_is_mesh(&sdata->vif)) {
-+ if (sdata->vif.type == NL80211_IFTYPE_AP ||
-+ sdata->vif.type == NL80211_IFTYPE_MESH_POINT) {
- memcpy(mgmt->bssid, sdata->vif.addr, ETH_ALEN);
-- } else {
-+ } else if (sdata->vif.type == NL80211_IFTYPE_ADHOC) {
- struct ieee80211_if_ibss *ifibss = &sdata->u.ibss;
- memcpy(mgmt->bssid, ifibss->bssid, ETH_ALEN);
- }
---
-2.18.0
-
diff --git a/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/subsys.inc b/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/subsys.inc
index 8a4fb66..9bb2504 100644
--- a/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/subsys.inc
+++ b/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/subsys.inc
@@ -1,63 +1,64 @@
#patch subsys (come from openwrt/lede/target/linux/mediatek)
SRC_URI_append = " \
- file://110-mac80211_keep_keys_on_stop_ap.patch \
- file://120-cfg80211_allow_perm_addr_change.patch \
- file://130-disable_auto_vif.patch \
- file://210-ap_scan.patch \
- file://301-mac80211-sta-randomize-BA-session-dialog-token-alloc.patch \
- file://302-mac80211-minstrel_ht-fix-MINSTREL_FRAC-macro.patch \
- file://303-mac80211-minstrel_ht-reduce-fluctuations-in-rate-pro.patch \
- file://304-mac80211-minstrel_ht-rework-rate-downgrade-code-and-.patch \
- file://305-mac80211-increase-quantum-for-airtime-scheduler.patch \
- file://310-mac80211-split-mesh-fast-tx-cache-into-local-proxied.patch \
- file://312-wifi-cfg80211-annotate-iftype_data-pointer-with-spar.patch \
- file://313-wifi-cfg80211-export-DFS-CAC-time-and-usable-state-h.patch \
- file://314-wifi-mac80211-fix-race-condition-on-enabling-fast-xm.patch \
- file://320-cfg80211-allow-grace-period-for-DFS-available-after-.patch \
- file://330-mac80211-add-AQL-support-for-broadcast-packets.patch \
- file://331-wifi-mac80211-only-call-drv_sta_rc_update-for-upload.patch \
- file://332-wifi-mac80211-check-clear-fast-rx-for-non-4addr-sta-.patch \
- file://400-allow-ibss-mixed.patch \
- file://780-avoid-crashing-missing-band.patch \
- file://782-net-next-1-of-net-pass-the-dst-buffer-to-of_get_mac_address.patch \
- file://bp-0001-backports-add-SKB_DROP_REASON-and-kfree_skb_reason-b.patch \
- file://bp-0002-backports-update-kernel-version-check-for-eth_hw_add.patch \
- file://bp-0003-backports-Revert-cfg80211-allow-grace-period-for-DFS.patch \
- file://mtk-0001-mtk-mac80211-do-not-setup-twt-when-twt-responder-is-.patch \
- file://mtk-0002-mtk-cfg80211-extend-CAC-time-for-weather-radar-chann.patch \
- file://mtk-0003-mtk-mac80211-it-s-invalid-case-when-frag_threshold-i.patch \
- file://mtk-0004-mtk-mac80211-add-support-for-runtime-set-inband-disc.patch \
- file://mtk-0005-mtk-cfg80211-implement-DFS-status-show-cac-and-nop-s.patch \
- file://mtk-0006-mtk-mac80211-Set-TWT-Information-Frame-Disabled-bit-.patch \
- file://mtk-0007-mtk-mac80211-check-the-control-channel-before-downgr.patch \
- file://mtk-0008-mtk-mac80211-fix-tx-amsdu-aggregation.patch \
- file://mtk-0009-mtk-mac80211-add-fill-receive-path-ops-to-get-wed-id.patch \
- file://mtk-0010-mtk-mac80211-fix-build-error-on-Linux-Kernel-5.4.patch \
- file://mtk-0011-mtk-mac80211-track-obss-color-bitmap.patch \
- file://mtk-0012-mtk-mac80211-ageout-color-bitmap.patch \
- file://mtk-0013-mtk-mac80211-update-max_bssid_indicator-based-on-rea.patch \
- file://mtk-0014-mtk-mac80211-support-configurable-addba-resp-time.patch \
- file://mtk-0015-mtk-mac80211-add-sta-assisted-DFS-state-update-mecha.patch \
- file://mtk-0016-mtk-nl80211-Mark-DFS-channel-as-available-for-CSA.patch \
- file://mtk-0017-mtk-cfg80211-fix-early-return-in-cfg80211_stop_backg.patch \
- file://mtk-0018-mtk-cfg80211-add-background-radar-stop-when-backgrou.patch \
- file://mtk-0019-mtk-mac80211-avoid-kernel-warning-of-check_flush_dep.patch \
- file://mtk-0020-mtk-mac80211-avoid-calling-switch_vif_chanctx-when-u.patch \
- file://mtk-0021-mtk-mac80211-Add-utilities-for-converting-op_class.patch \
- file://mtk-0022-mtk-mac80211-refactor-STA-CSA-parsing-flows.patch \
- file://mtk-0023-mtk-mac80211-add-EHT-BA1024-support.patch \
- file://mtk-0024-mtk-mac80211-add-rate-duration-for-EHT-rate.patch \
- file://mtk-0025-mtk-mac80211-add-send-bar-action-when-recieve-addba-.patch \
- file://mtk-0026-mtk-mac80211-inrease-beacon-loss-count.patch \
- file://mtk-0027-mtk-cfg80211-add-support-for-updating-background-cha.patch \
- file://mtk-0028-mtk-mac80211-Allow-STA-interface-to-set-TX-queue-par.patch \
- file://mtk-0029-mtk-mac80211-export-ieee80211_tpt_led_trig_tx-rx-for.patch \
- file://mtk-0030-mtk-mac80211-add-packet-count-input-for-dev_sw_netst.patch \
- file://mtk-0031-mtk-mac80211-add-per-bss-flag-to-support-vendors-cou.patch \
- file://mtk-0032-mtk-mac80211-set-eht_support-to-false-when-AP-is-not.patch \
- file://mtk-0033-mtk-mac80211-Add-cert-mode-to-disable-ba-timeout.patch \
- file://mtk-0034-mtk-mac80211-ACS-channel-time-is-reset-by-ch_restore.patch \
- file://mtk-0035-mtk-mac80211-Fix-SMPS-action-frame-cap-check.patch \
- file://mtk-0036-mtk-mac80211-Add-CSA-action-frame-tx-when-channel-sw.patch \
- file://mtk-0037-mtk-mac80211-fix-AP-mgmt-not-encrypted-in-WDS-mode-w.patch \
+ file://0001-sync-backports-patches-build.patch \
+ file://0002-sync-backports-patches-ath.patch \
+ file://0003-sync-backports-patches-ath5k.patch \
+ file://0004-sync-backports-patches-ath9k.patch \
+ file://0005-sync-backports-patches-ath10k.patch \
+ file://0006-sync-backports-patches-rt2x00.patch \
+ file://0007-sync-backports-patches-subsys.patch \
+ file://0008-mtk-mac80211-do-not-setup-twt-when-twt-responder-is-.patch \
+ file://0009-mtk-cfg80211-extend-CAC-time-for-weather-radar-chann.patch \
+ file://0010-mtk-mac80211-it-s-invalid-case-when-frag_threshold-i.patch \
+ file://0011-mtk-cfg80211-implement-DFS-status-show-cac-and-nop-s.patch \
+ file://0012-mtk-mac80211-Set-TWT-Information-Frame-Disabled-bit-.patch \
+ file://0013-mtk-mac80211-check-the-control-channel-before-downgr.patch \
+ file://0014-mtk-mac80211-fix-tx-amsdu-aggregation.patch \
+ file://0015-mtk-mac80211-add-fill-receive-path-ops-to-get-wed-id.patch \
+ file://0016-mtk-mac80211-track-obss-color-bitmap.patch \
+ file://0017-mtk-mac80211-update-max_bssid_indicator-based-on-rea.patch \
+ file://0018-mtk-mac80211-support-configurable-addba-resp-time.patch \
+ file://0019-mtk-mac80211-add-sta-assisted-DFS-state-update-mecha.patch \
+ file://0020-mtk-nl80211-Mark-DFS-channel-as-available-for-CSA.patch \
+ file://0021-mtk-cfg80211-fix-early-return-in-cfg80211_stop_backg.patch \
+ file://0022-mtk-cfg80211-add-background-radar-stop-when-backgrou.patch \
+ file://0023-mtk-mac80211-avoid-kernel-warning-of-check_flush_dep.patch \
+ file://0024-mtk-mac80211-avoid-calling-switch_vif_chanctx-when-u.patch \
+ file://0025-mtk-mac80211-add-EHT-BA1024-support.patch \
+ file://0026-mtk-mac80211-add-rate-duration-for-EHT-rate.patch \
+ file://0027-mtk-mac80211-add-send-bar-action-when-recieve-addba-.patch \
+ file://0028-mtk-mac80211-inrease-beacon-loss-count.patch \
+ file://0029-mtk-cfg80211-add-support-for-updating-background-cha.patch \
+ file://0030-mtk-mac80211-Allow-STA-interface-to-set-TX-queue-par.patch \
+ file://0031-mtk-mac80211-export-ieee80211_tpt_led_trig_tx-rx-for.patch \
+ file://0032-mtk-mac80211-add-packet-count-input-for-dev_sw_netst.patch \
+ file://0033-mtk-mac80211-add-per-bss-flag-to-support-vendors-cou.patch \
+ file://0034-mtk-mac80211-set-eht_support-to-false-when-AP-is-not.patch \
+ file://0035-mtk-mac80211-Add-cert-mode-to-disable-ba-timeout.patch \
+ file://0036-backports-update-kernel-version-check-for-eth_hw_add.patch \
+ file://0037-mac80211-mtk-ACS-channel-time-is-reset-by-ch_restore.patch \
+ file://0038-mtk-mac80211-Fix-SMPS-action-frame-cap-check.patch \
+ file://0039-mtk-mac80211-allow-multiple-links-for-STA-vif.patch \
+ file://0040-mtk-mac80211-increase-association-timeout-time.patch \
+ file://0041-mtk-mac80211-fix-crash-when-starting-tx-ba-session.patch \
+ file://0042-mtk-mac80211-use-link-address-for-eapol-source-in-ie.patch \
+ file://0043-cfg80211-mtk-implement-DFS-radar-detect-for-MLO.patch \
+ file://0044-mtk-wifi-mac80211-add-wds-mlo-support.patch \
+ file://0045-mtk-mac80211-fix-ieee80211_probe_client-warning.patch \
+ file://0046-mtk-mac80211-remove-link-0-warn-on-in-rate_control_r.patch \
+ file://0047-mtk-mac80211-fix-radar-required-of-link-issue-in-res.patch \
+ file://0048-mtk-cfg80211-rework-cac-started-cac-start-time-for-m.patch \
+ file://0049-mtk-mac80211-remove-links-when-removing-AP_VLAN-inte.patch \
+ file://0050-mtk-mac80211-fix-AP-mgmt-not-encrypted-in-WDS-mode-w.patch \
+ file://0051-mtk-mac80211-fix-ieee80211_ht_cap_ie_to_sta_ht_cap-w.patch \
+ file://0052-mtk-mac80211-fix-mac-address-to-support-hw-path-in-s.patch \
+ file://0053-mtk-mac80211-workaround-for-configuring-txpower-in-m.patch \
+ file://0054-mtk-mac80211-send-broadcast-multicast-mgmt.-via-all-.patch \
+ file://0055-mtk-mac80211-fix-mlo-BW-160-channel-switch-issue.patch \
+ file://0056-mtk-mac80211-extend-IEEE80211_KEY_FLAG_GENERATE_MMIE.patch \
+ file://0057-mtk-wifi-mt76-mt7996-not-to-check-need_offchan-for-M.patch \
+ file://0058-mtk-wifi-mt76-mt7996-assign-link-address-to-the-head.patch \
+ file://0059-mtk-wifi-mt76-mt7996-Do-MLD-address-translation-befo.patch \
+ file://0060-mtk-wifi-mac80211-defer-enabling-beacon-for-MLD-AP.patch \
+ file://0061-mtk-wifi-mac80211-fix-radar-trigger-issue-due-to-ref.patch \
"