From 91881f45dc4b8302bf90644b70ddd9f5152f48aa Mon Sep 17 00:00:00 2001
From: Matthias Schiffer <mschiffer@universe-factory.net>
Date: Tue, 19 Jul 2016 18:58:37 +0200
Subject: [PATCH] mac80211: update to LEDE
 6c2651566cce8f5b3a3d3b976439dee2bac5e07e

Also switch to kmod-ath10k-ct, so we can drop our AP+IBSS patch.
---
 ...fine-wmac-reset-function-for-QCA955x.patch |   85 +
 ...11-ath10k-allow-simultaneous-AP-IBSS.patch |   42 -
 ...1566cce8f5b3a3d3b976439dee2bac5e07e.patch} | 6525 ++++++++++++-----
 ...0105-mt76-fix-build-with-kernel-3.18.patch |    2 +-
 targets/ar71xx-generic/profiles.mk            |   10 +-
 5 files changed, 4911 insertions(+), 1753 deletions(-)
 create mode 100644 patches/openwrt/0006-ar71xx-define-wmac-reset-function-for-QCA955x.patch
 delete mode 100644 patches/openwrt/0007-mac80211-ath10k-allow-simultaneous-AP-IBSS.patch
 rename patches/openwrt/{0006-mac80211-update-to-LEDE-0a0caa2656c8db73518a1783743ede772e3ac40f.patch => 0007-mac80211-update-to-LEDE-6c2651566cce8f5b3a3d3b976439dee2bac5e07e.patch} (65%)

diff --git a/patches/openwrt/0006-ar71xx-define-wmac-reset-function-for-QCA955x.patch b/patches/openwrt/0006-ar71xx-define-wmac-reset-function-for-QCA955x.patch
new file mode 100644
index 000000000..81d95a9af
--- /dev/null
+++ b/patches/openwrt/0006-ar71xx-define-wmac-reset-function-for-QCA955x.patch
@@ -0,0 +1,85 @@
+From: Matthias Schiffer <mschiffer@universe-factory.net>
+Date: Tue, 19 Jul 2016 17:48:53 +0200
+Subject: ar71xx: define wmac reset function for QCA955x
+
+Signed-off-by: Felix Fietkau <nbd@nbd.name>
+
+Backport of LEDE a176168a85477caa44eef7e979567d1d52868fde
+
+diff --git a/target/linux/ar71xx/patches-3.18/640-MIPS-ath79-add-QCA955x-wmac-reset.patch b/target/linux/ar71xx/patches-3.18/640-MIPS-ath79-add-QCA955x-wmac-reset.patch
+new file mode 100644
+index 0000000..4ac5acd
+--- /dev/null
++++ b/target/linux/ar71xx/patches-3.18/640-MIPS-ath79-add-QCA955x-wmac-reset.patch
+@@ -0,0 +1,71 @@
++--- a/arch/mips/ath79/common.h
+++++ b/arch/mips/ath79/common.h
++@@ -19,6 +19,8 @@
++ #define ATH79_MEM_SIZE_MIN	(2 * 1024 * 1024)
++ #define ATH79_MEM_SIZE_MAX	(128 * 1024 * 1024)
++ 
+++extern void __iomem *ath79_ddr_base;
+++
++ void ath79_clocks_init(void);
++ unsigned long ath79_get_sys_clk_rate(const char *id);
++ 
++--- a/arch/mips/ath79/dev-wmac.c
+++++ b/arch/mips/ath79/dev-wmac.c
++@@ -149,6 +149,27 @@ static void ar934x_wmac_setup(void)
++ 		ath79_wmac_data.is_clk_25mhz = true;
++ }
++ 
+++static int ar955x_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;
+++}
+++
++ static void qca955x_wmac_setup(void)
++ {
++ 	u32 t;
++@@ -165,6 +186,8 @@ static void qca955x_wmac_setup(void)
++ 		ath79_wmac_data.is_clk_25mhz = false;
++ 	else
++ 		ath79_wmac_data.is_clk_25mhz = true;
+++
+++	ath79_wmac_data.external_reset = ar955x_wmac_reset;
++ }
++ 
++ static bool __init
++--- a/arch/mips/include/asm/mach-ath79/ar71xx_regs.h
+++++ b/arch/mips/include/asm/mach-ath79/ar71xx_regs.h
++@@ -32,7 +32,7 @@
++ #define AR71XX_SPI_SIZE		0x01000000
++ 
++ #define AR71XX_DDR_CTRL_BASE	(AR71XX_APB_BASE + 0x00000000)
++-#define AR71XX_DDR_CTRL_SIZE	0x100
+++#define AR71XX_DDR_CTRL_SIZE	0x200
++ #define AR71XX_UART_BASE	(AR71XX_APB_BASE + 0x00020000)
++ #define AR71XX_UART_SIZE	0x100
++ #define AR71XX_USB_CTRL_BASE	(AR71XX_APB_BASE + 0x00030000)
++@@ -173,6 +173,9 @@
++ #define AR934X_DDR_REG_FLUSH_PCIE	0xa8
++ #define AR934X_DDR_REG_FLUSH_WMAC	0xac
++ 
+++#define QCA955X_DDR_CTL_CONFIG		0x108
+++#define QCA955X_DDR_CTL_CONFIG_ACT_WMAC	BIT(23)
+++
++ /*
++  * PLL block
++  */
diff --git a/patches/openwrt/0007-mac80211-ath10k-allow-simultaneous-AP-IBSS.patch b/patches/openwrt/0007-mac80211-ath10k-allow-simultaneous-AP-IBSS.patch
deleted file mode 100644
index 4d5e1b86d..000000000
--- a/patches/openwrt/0007-mac80211-ath10k-allow-simultaneous-AP-IBSS.patch
+++ /dev/null
@@ -1,42 +0,0 @@
-From: Matthias Schiffer <mschiffer@universe-factory.net>
-Date: Wed, 20 May 2015 23:10:36 +0200
-Subject: mac80211: ath10k: allow simultaneous AP+IBSS
-
-diff --git a/package/kernel/mac80211/patches/950-ath10k_AP_IBSS.patch b/package/kernel/mac80211/patches/950-ath10k_AP_IBSS.patch
-new file mode 100644
-index 0000000..956c3fd
---- /dev/null
-+++ b/package/kernel/mac80211/patches/950-ath10k_AP_IBSS.patch
-@@ -0,0 +1,32 @@
-+--- a/drivers/net/wireless/ath/ath10k/mac.c
-++++ b/drivers/net/wireless/ath/ath10k/mac.c
-+@@ -7521,6 +7521,10 @@ static const struct ieee80211_iface_limi
-+ 			| BIT(NL80211_IFTYPE_MESH_POINT)
-+ #endif
-+ 	},
-++	{
-++	.max    = 1,
-++	.types  = BIT(NL80211_IFTYPE_ADHOC)
-++	},
-+ };
-+ 
-+ static const struct ieee80211_iface_limit ath10k_10x_if_limits[] = {
-+@@ -7535,6 +7539,10 @@ static const struct ieee80211_iface_limi
-+ 		.max	= 1,
-+ 		.types	= BIT(NL80211_IFTYPE_STATION)
-+ 	},
-++	{
-++	.max    = 1,
-++	.types  = BIT(NL80211_IFTYPE_ADHOC)
-++	},
-+ };
-+ 
-+ static const struct ieee80211_iface_combination ath10k_if_comb[] = {
-+@@ -7920,6 +7928,7 @@ int ath10k_mac_register(struct ath10k *a
-+ 		ar->hw->wiphy->iface_combinations = ath10k_10x_if_comb;
-+ 		ar->hw->wiphy->n_iface_combinations =
-+ 			ARRAY_SIZE(ath10k_10x_if_comb);
-++		ar->hw->wiphy->interface_modes |= BIT(NL80211_IFTYPE_ADHOC);
-+ 		break;
-+ 	case ATH10K_FW_WMI_OP_VERSION_10_4:
-+ 		ar->hw->wiphy->iface_combinations = ath10k_10_4_if_comb;
diff --git a/patches/openwrt/0006-mac80211-update-to-LEDE-0a0caa2656c8db73518a1783743ede772e3ac40f.patch b/patches/openwrt/0007-mac80211-update-to-LEDE-6c2651566cce8f5b3a3d3b976439dee2bac5e07e.patch
similarity index 65%
rename from patches/openwrt/0006-mac80211-update-to-LEDE-0a0caa2656c8db73518a1783743ede772e3ac40f.patch
rename to patches/openwrt/0007-mac80211-update-to-LEDE-6c2651566cce8f5b3a3d3b976439dee2bac5e07e.patch
index 26bd06095..85b2157af 100644
--- a/patches/openwrt/0006-mac80211-update-to-LEDE-0a0caa2656c8db73518a1783743ede772e3ac40f.patch
+++ b/patches/openwrt/0007-mac80211-update-to-LEDE-6c2651566cce8f5b3a3d3b976439dee2bac5e07e.patch
@@ -1,9 +1,9 @@
 From: Matthias Schiffer <mschiffer@universe-factory.net>
 Date: Tue, 7 Jun 2016 14:06:23 +0200
-Subject: mac80211: update to LEDE 0a0caa2656c8db73518a1783743ede772e3ac40f
+Subject: mac80211: update to LEDE 6c2651566cce8f5b3a3d3b976439dee2bac5e07e
 
 diff --git a/package/firmware/ath10k-firmware/Makefile b/package/firmware/ath10k-firmware/Makefile
-index b03d644..4f63cdd 100644
+index b03d644..170a6c9 100644
 --- a/package/firmware/ath10k-firmware/Makefile
 +++ b/package/firmware/ath10k-firmware/Makefile
 @@ -8,7 +8,7 @@
@@ -28,7 +28,7 @@ index b03d644..4f63cdd 100644
    CATEGORY:=Kernel modules
    SUBMENU:=$(WMENU)
    URL:=$(PKG_SOURCE_URL)
-+  DEPENDS:=kmod-ath10k
++  DEPENDS:=
  endef
  
  define Package/ath10k-firmware-qca988x
@@ -135,7 +135,7 @@ index b03d644..4f63cdd 100644
  define Package/ath10k-firmware-qca6174/install
  	$(INSTALL_DIR) $(1)/lib/firmware/ath10k
  	$(CP) $(PKG_BUILD_DIR)/QCA6174 $(1)/lib/firmware/ath10k/
-@@ -97,6 +163,33 @@ define Package/ath10k-firmware-qca99x0/install
+@@ -97,6 +163,36 @@ define Package/ath10k-firmware-qca99x0/install
  		$(1)/lib/firmware/ath10k/QCA99X0/hw2.0/firmware-5.bin
  endef
  
@@ -154,6 +154,9 @@ index b03d644..4f63cdd 100644
 +
 +define Package/ath10k-firmware-qca9984/install
 +	$(INSTALL_DIR) $(1)/lib/firmware/ath10k/QCA9984/hw1.0
++	ln -s \
++		../../cal-pci-0000:01:00.0.bin \
++		$(1)/lib/firmware/ath10k/QCA9984/hw1.0/board.bin
 +	$(INSTALL_DATA) \
 +		$(PKG_BUILD_DIR)/QCA9984/hw1.0/board-2.bin \
 +		$(1)/lib/firmware/ath10k/QCA9984/hw1.0/board-2.bin
@@ -526,8 +529,94 @@ index 0000000..94d6135
 + 
 + 	adev->channel = channel;
 + 
+diff --git a/package/kernel/ath10k-ct/Makefile b/package/kernel/ath10k-ct/Makefile
+new file mode 100644
+index 0000000..adda03c
+--- /dev/null
++++ b/package/kernel/ath10k-ct/Makefile
+@@ -0,0 +1,80 @@
++include $(TOPDIR)/rules.mk
++
++PKG_NAME:=ath10k-ct
++PKG_VERSION:=2016-07-09
++PKG_RELEASE=1
++
++PKG_LICENSE:=GPLv2
++PKG_LICENSE_FILES:=
++
++PKG_SOURCE_URL:=https://github.com/greearb/ath10k-ct.git
++PKG_SOURCE_PROTO:=git
++PKG_SOURCE_SUBDIR:=$(PKG_NAME)-$(PKG_VERSION)
++PKG_SOURCE_VERSION:=0241aa1d2797ef564bf36fa67888e62289d71e8f
++PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION)-$(PKG_SOURCE_VERSION).tar.xz
++
++PKG_MAINTAINER:=Ben Greear <greearb@candelatech.com>
++PKG_BUILD_PARALLEL:=1
++
++STAMP_CONFIGURED_DEPENDS := $(STAGING_DIR)/usr/include/mac80211-backport/backport/autoconf.h
++
++include $(INCLUDE_DIR)/kernel.mk
++include $(INCLUDE_DIR)/package.mk
++
++define KernelPackage/ath10k-ct
++  SUBMENU:=Wireless Drivers
++  TITLE:=ath10k-ct driver optimized for CT ath10k firmware
++  DEPENDS:=+kmod-mac80211 +kmod-ath +@DRIVER_11N_SUPPORT @PCI_SUPPORT
++  FILES:=\
++	$(PKG_BUILD_DIR)/ath10k/ath10k_pci.ko \
++	$(PKG_BUILD_DIR)/ath10k/ath10k_core.ko
++  AUTOLOAD:=$(call AutoLoad,50,mac80211 ath ath10k_core ath10k_pci)
++endef
++
++NOSTDINC_FLAGS = \
++	-I$(PKG_BUILD_DIR) \
++	-I$(STAGING_DIR)/usr/include/mac80211-backport/uapi \
++	-I$(STAGING_DIR)/usr/include/mac80211-backport \
++	-I$(STAGING_DIR)/usr/include/mac80211/uapi \
++	-I$(STAGING_DIR)/usr/include/mac80211 \
++	-include backport/autoconf.h \
++	-include backport/backport.h
++
++ifdef CONFIG_PACKAGE_MAC80211_MESH
++  NOSTDINC_FLAGS += -DCONFIG_MAC80211_MESH
++endif
++
++CT_MAKEDEFS += CONFIG_ATH10K=m CONFIG_ATH10K_PCI=m
++# No AHB support enabled yet.  Could conditionally enable it later.
++#CT_MAKEDEFS += CONFIG_ATH10K_AHB=y
++#NOSTDINC_FLAGS += -DCONFIG_ATH10K_AHB
++NOSTDINC_FLAGS += -DSTANDALONE_CT
++
++ifdef CONFIG_PACKAGE_MAC80211_DEBUGFS
++  CT_MAKEDEFS += CONFIG_ATH10K_DEBUGFS=y CONFIG_MAC80211_DEBUGFS=y
++  NOSTDINC_FLAGS += -DCONFIG_MAC80211_DEBUGFS
++  NOSTDINC_FLAGS += -DCONFIG_ATH10K_DEBUGFS
++endif
++
++ifdef CONFIG_PACKAGE_ATH_DEBUG
++  NOSTDINC_FLAGS += -DCONFIG_ATH10K_DEBUG
++endif
++
++define Build/Configure
++	cp $(STAGING_DIR)/usr/include/mac80211/ath/*.h $(PKG_BUILD_DIR)
++endef
++
++ifneq ($(findstring c,$(OPENWRT_VERBOSE)),)
++  CT_MAKEDEFS += V=1
++endif
++
++define Build/Compile
++	+$(MAKE) $(CT_MAKEDEFS) $(PKG_JOBS) -C "$(LINUX_DIR)" \
++		ARCH="$(LINUX_KARCH)" \
++		CROSS_COMPILE="$(TARGET_CROSS)" \
++		SUBDIRS="$(PKG_BUILD_DIR)/ath10k" \
++		NOSTDINC_FLAGS="$(NOSTDINC_FLAGS)" \
++		modules
++endef
++
++$(eval $(call KernelPackage,ath10k-ct))
 diff --git a/package/kernel/mac80211/Makefile b/package/kernel/mac80211/Makefile
-index 30da1cf..bee0723 100644
+index 30da1cf..f2839cd 100644
 --- a/package/kernel/mac80211/Makefile
 +++ b/package/kernel/mac80211/Makefile
 @@ -10,20 +10,21 @@ include $(INCLUDE_DIR)/kernel.mk
@@ -535,12 +624,12 @@ index 30da1cf..bee0723 100644
  PKG_NAME:=mac80211
  
 -PKG_VERSION:=2016-01-10
-+PKG_VERSION:=2016-05-12
++PKG_VERSION:=2016-06-20
  PKG_RELEASE:=1
  PKG_SOURCE_URL:=http://mirror2.openwrt.org/sources
  PKG_BACKPORT_VERSION:=
 -PKG_MD5SUM:=be5fae2e8d6f7490f9b073374fb895ba
-+PKG_MD5SUM:=2142cf38509896dca108624e7c193611
++PKG_MD5SUM:=29c79bdc3928ef5113b17042ebda9237
  
  PKG_SOURCE:=compat-wireless-$(PKG_VERSION)$(PKG_BACKPORT_VERSION).tar.bz2
  PKG_BUILD_DIR:=$(KERNEL_BUILD_DIR)/compat-wireless-$(PKG_VERSION)
@@ -618,7 +707,15 @@ index 30da1cf..bee0723 100644
  		help
  		  Atheros' idea of regulatory handling is that the EEPROM of the card defines
  		  the regulatory limits and the user is only allowed to restrict the settings
-@@ -226,6 +246,10 @@ define KernelPackage/ath9k/config
+@@ -199,6 +219,7 @@ define KernelPackage/ath9k-common
+   $(call KernelPackage/mac80211/Default)
+   TITLE:=Atheros 802.11n wireless devices (common code for ath9k and ath9k_htc)
+   URL:=https://wireless.wiki.kernel.org/en/users/drivers/ath9k
++  HIDDEN:=1
+   DEPENDS+= @PCI_SUPPORT||USB_SUPPORT||TARGET_ar71xx +kmod-ath +@DRIVER_11N_SUPPORT +@DRIVER_11W_SUPPORT +@KERNEL_RELAY
+   FILES:= \
+ 	$(PKG_BUILD_DIR)/drivers/net/wireless/ath/ath9k/ath9k_common.ko \
+@@ -226,6 +247,10 @@ define KernelPackage/ath9k/config
  		bool "Support chips used in PC OEM cards"
  		depends on PACKAGE_kmod-ath9k
  
@@ -629,7 +726,7 @@ index 30da1cf..bee0723 100644
  endef
  
  define KernelPackage/ath9k-htc
-@@ -247,7 +271,7 @@ define KernelPackage/ath10k
+@@ -247,7 +272,7 @@ define KernelPackage/ath10k
    $(call KernelPackage/mac80211/Default)
    TITLE:=Atheros 802.11ac wireless cards support
    URL:=https://wireless.wiki.kernel.org/en/users/Drivers/ath10k
@@ -638,7 +735,7 @@ index 30da1cf..bee0723 100644
    FILES:= \
  	$(PKG_BUILD_DIR)/drivers/net/wireless/ath/ath10k/ath10k_core.ko \
  	$(PKG_BUILD_DIR)/drivers/net/wireless/ath/ath10k/ath10k_pci.ko
-@@ -673,6 +697,7 @@ define KernelPackage/brcmfmac/config
+@@ -673,6 +698,7 @@ define KernelPackage/brcmfmac/config
  
  	config BRCMFMAC_SDIO
  		bool "Enable SDIO bus interface support"
@@ -646,7 +743,7 @@ index 30da1cf..bee0723 100644
  		default n
  		help
  		  Enable support for cards attached to an SDIO bus.
-@@ -761,7 +786,7 @@ endef
+@@ -761,7 +787,7 @@ endef
  
  define KernelPackage/iwlwifi
    $(call KernelPackage/mac80211/Default)
@@ -655,7 +752,7 @@ index 30da1cf..bee0723 100644
    TITLE:=Intel AGN Wireless support
    FILES:= \
  	$(PKG_BUILD_DIR)/drivers/net/wireless/intel/iwlwifi/iwlwifi.ko \
-@@ -870,7 +895,7 @@ endef
+@@ -870,7 +896,7 @@ endef
  define KernelPackage/lib80211
    $(call KernelPackage/mac80211/Default)
    TITLE:=802.11 Networking stack
@@ -664,7 +761,7 @@ index 30da1cf..bee0723 100644
    FILES:= \
  	$(PKG_BUILD_DIR)/net/wireless/lib80211.ko \
  	$(PKG_BUILD_DIR)/net/wireless/lib80211_crypt_wep.ko \
-@@ -897,7 +922,7 @@ endef
+@@ -897,7 +923,7 @@ endef
  define KernelPackage/libipw
    $(call KernelPackage/mac80211/Default)
    TITLE:=libipw for ipw2100 and ipw2200
@@ -673,7 +770,7 @@ index 30da1cf..bee0723 100644
    FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/intel/ipw2x00/libipw.ko
    AUTOLOAD:=$(call AutoProbe,libipw)
  endef
-@@ -978,7 +1003,7 @@ endef
+@@ -978,7 +1004,7 @@ endef
  define KernelPackage/libertas-spi
    $(call KernelPackage/mac80211/Default)
    SUBMENU:=Wireless Drivers
@@ -682,7 +779,68 @@ index 30da1cf..bee0723 100644
    KCONFIG := \
  	CONFIG_SPI=y \
  	CONFIG_SPI_MASTER=y
-@@ -1453,6 +1478,7 @@ config-y:= \
+@@ -1036,33 +1062,6 @@ define KernelPackage/mwifiex-pcie/description
+  Kernel modules for Marvell 802.11n/802.11ac PCIe Wireless cards
+ endef
+ 
+-
+-# Prism54 drivers
+-P54PCIFW:=2.13.12.0.arm
+-P54USBFW:=2.13.24.0.lm87.arm
+-P54SPIFW:=2.13.0.0.a.13.14.arm
+-
+-define Download/p54usb
+-  FILE:=$(P54USBFW)
+-  URL:=http://daemonizer.de/prism54/prism54-fw/fw-usb
+-  MD5SUM:=8e8ab005a4f8f0123bcdc51bc25b47f6
+-endef
+-$(eval $(call Download,p54usb))
+-
+-define Download/p54pci
+-  FILE:=$(P54PCIFW)
+-  URL:=http://daemonizer.de/prism54/prism54-fw/fw-softmac
+-  MD5SUM:=ff7536af2092b1c4b21315bd103ef4c4
+-endef
+-$(eval $(call Download,p54pci))
+-
+-define Download/p54spi
+-  FILE:=$(P54SPIFW)
+-  URL:=http://daemonizer.de/prism54/prism54-fw/stlc4560
+-  MD5SUM:=42661f8ecbadd88012807493f596081d
+-endef
+-$(eval $(call Download,p54spi))
+-
+ define KernelPackage/p54/Default
+   $(call KernelPackage/mac80211/Default)
+   TITLE:=Prism54 Drivers
+@@ -1082,7 +1081,7 @@ endef
+ define KernelPackage/p54-pci
+   $(call KernelPackage/p54/Default)
+   TITLE+= (PCI)
+-  DEPENDS+= @PCI_SUPPORT +kmod-p54-common
++  DEPENDS+= @PCI_SUPPORT +kmod-p54-common +p54-pci-firmware
+   FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/intersil/p54/p54pci.ko
+   AUTOLOAD:=$(call AutoProbe,p54pci)
+ endef
+@@ -1090,7 +1089,7 @@ endef
+ define KernelPackage/p54-usb
+   $(call KernelPackage/p54/Default)
+   TITLE+= (USB)
+-  DEPENDS+= @USB_SUPPORT +kmod-usb-core +kmod-p54-common
++  DEPENDS+= @USB_SUPPORT +kmod-usb-core +kmod-p54-common +p54-usb-firmware
+   FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/intersil/p54/p54usb.ko
+   AUTOLOAD:=$(call AutoProbe,p54usb)
+ endef
+@@ -1098,7 +1097,7 @@ endef
+ define KernelPackage/p54-spi
+   $(call KernelPackage/p54/Default)
+   TITLE+= (SPI)
+-  DEPENDS+= @TARGET_omap24xx +kmod-p54-common
++  DEPENDS+= @TARGET_omap24xx +kmod-p54-common +p54-spi-firmware
+   FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/intersil/p54/p54spi.ko
+   AUTOLOAD:=$(call AutoProbe,p54spi)
+ endef
+@@ -1453,6 +1452,7 @@ config-y:= \
  	WLAN_VENDOR_ATH \
  	WLAN_VENDOR_ATMEL \
  	WLAN_VENDOR_BROADCOM \
@@ -690,7 +848,7 @@ index 30da1cf..bee0723 100644
  	WLAN_VENDOR_INTEL \
  	WLAN_VENDOR_INTERSIL \
  	WLAN_VENDOR_MARVELL \
-@@ -1491,6 +1517,8 @@ endif
+@@ -1491,6 +1491,8 @@ endif
  
  config-$(call config_package,lib80211) += LIB80211 LIB80211_CRYPT_WEP LIB80211_CRYPT_CCMP LIB80211_CRYPT_TKIP
  
@@ -699,7 +857,7 @@ index 30da1cf..bee0723 100644
  config-$(call config_package,ath) += ATH_CARDS ATH_COMMON
  config-$(CONFIG_PACKAGE_ATH_DEBUG) += ATH_DEBUG ATH10K_DEBUG
  config-$(CONFIG_PACKAGE_ATH_DFS) += ATH9K_DFS_CERTIFIED ATH10K_DFS_CERTIFIED
-@@ -1501,6 +1529,7 @@ config-$(CONFIG_TARGET_ar71xx) += ATH9K_AHB
+@@ -1501,6 +1503,7 @@ config-$(CONFIG_TARGET_ar71xx) += ATH9K_AHB
  config-$(CONFIG_PCI) += ATH9K_PCI
  config-$(CONFIG_ATH_USER_REGD) += ATH_USER_REGD
  config-$(CONFIG_ATH9K_SUPPORT_PCOEM) += ATH9K_PCOEM
@@ -707,7 +865,29 @@ index 30da1cf..bee0723 100644
  
  config-$(call config_package,ath9k-htc) += ATH9K_HTC
  config-$(call config_package,ath10k) += ATH10K ATH10K_PCI
-@@ -1764,6 +1793,7 @@ endef
+@@ -1742,21 +1745,6 @@ define KernelPackage/ipw2200/install
+ 	$(INSTALL_DATA) $(PKG_BUILD_DIR)/$(IPW2200_NAME)-$(IPW2200_VERSION)/ipw2200*.fw $(1)/lib/firmware
+ endef
+ 
+-define KernelPackage/p54-pci/install
+-	$(INSTALL_DIR) $(1)/lib/firmware
+-	$(INSTALL_DATA) $(DL_DIR)/$(P54PCIFW) $(1)/lib/firmware/isl3886pci
+-endef
+-
+-define KernelPackage/p54-usb/install
+-	$(INSTALL_DIR) $(1)/lib/firmware
+-	$(INSTALL_DATA) $(DL_DIR)/$(P54USBFW) $(1)/lib/firmware/isl3887usb
+-endef
+-
+-define KernelPackage/p54-spi/install
+-	$(INSTALL_DIR) $(1)/lib/firmware
+-	$(INSTALL_DATA) $(DL_DIR)/$(P54SPIFW) $(1)/lib/firmware/3826.arm
+-endef
+-
+ define KernelPackage/zd1211rw/install
+ 	$(INSTALL_DIR) $(1)/lib/firmware/zd1211
+ 	$(INSTALL_DATA) $(PKG_BUILD_DIR)/$(ZD1211FW_NAME)/zd1211* $(1)/lib/firmware/zd1211
+@@ -1764,6 +1752,7 @@ endef
  
  
  $(eval $(call KernelPackage,adm8211))
@@ -901,33 +1081,51 @@ index 9adfd8f..0000000
 -+#endif
 -+
 - #endif /* __BACKPORT_SKBUFF_H */
-diff --git a/package/kernel/mac80211/patches/004-header-backport-GENL_UNS_ADMIN_PERM.patch b/package/kernel/mac80211/patches/004-header-backport-GENL_UNS_ADMIN_PERM.patch
+diff --git a/package/kernel/mac80211/patches/004-fix_duplicate_skcipher_backport.patch b/package/kernel/mac80211/patches/004-fix_duplicate_skcipher_backport.patch
 new file mode 100644
-index 0000000..38d655f
+index 0000000..38b3179
 --- /dev/null
-+++ b/package/kernel/mac80211/patches/004-header-backport-GENL_UNS_ADMIN_PERM.patch
-@@ -0,0 +1,21 @@
-+From: Felix Fietkau <nbd@nbd.name>
-+Date: Sat, 14 May 2016 16:39:35 +0200
-+Subject: [PATCH] header: backport GENL_UNS_ADMIN_PERM
-+
-+Signed-off-by: Felix Fietkau <nbd@nbd.name>
-+---
-+ create mode 100644 backport-include/uapi/linux/genetlink.h
-+
-+--- /dev/null
-++++ b/backport-include/uapi/linux/genetlink.h
-+@@ -0,0 +1,10 @@
-++#ifndef __COMPAT_UAPI_LINUX_GENETLINK_H
-++#define __COMPAT_UAPI_LINUX_GENETLINK_H
++++ b/package/kernel/mac80211/patches/004-fix_duplicate_skcipher_backport.patch
+@@ -0,0 +1,11 @@
++--- a/compat/Makefile
+++++ b/compat/Makefile
++@@ -35,8 +35,6 @@ compat-$(CPTCFG_KERNEL_4_6) += backport-
++ 
++ compat-$(CPTCFG_BPAUTO_BUILD_CRYPTO_CCM) += crypto-ccm.o
++ compat-$(CPTCFG_BPAUTO_CRYPTO_SKCIPHER) += crypto-skcipher.o
++-skcipher-objs += crypto-skcipher.o
++-obj-$(CPTCFG_BPAUTO_CRYPTO_SKCIPHER) += skcipher.o
++ compat-$(CPTCFG_BPAUTO_BUILD_WANT_DEV_COREDUMP) += drivers-base-devcoredump.o
++ compat-$(CPTCFG_BPAUTO_RHASHTABLE) += lib-rhashtable.o
++ cordic-objs += lib-cordic.o
+diff --git a/package/kernel/mac80211/patches/005-backport_skb_get_hash_perturb.patch b/package/kernel/mac80211/patches/005-backport_skb_get_hash_perturb.patch
+new file mode 100644
+index 0000000..29bccc1
+--- /dev/null
++++ b/package/kernel/mac80211/patches/005-backport_skb_get_hash_perturb.patch
+@@ -0,0 +1,22 @@
++--- a/backport-include/linux/skbuff.h
+++++ b/backport-include/linux/skbuff.h
++@@ -305,6 +305,19 @@ static inline void skb_free_frag(void *d
++ {
++ 	put_page(virt_to_head_page(data));
++ }
 ++
-++#include_next <uapi/linux/genetlink.h>
+++#include <net/flow_keys.h>
+++#include <linux/jhash.h>
 ++
-++#ifndef GENL_UNS_ADMIN_PERM
-++#define GENL_UNS_ADMIN_PERM GENL_ADMIN_PERM
-++#endif
+++static inline u32 skb_get_hash_perturb(struct sk_buff *skb, u32 key)
+++{
+++	struct flow_keys keys;
 ++
-++#endif
+++	skb_flow_dissect(skb, &keys);
+++	return jhash_3words((__force u32)keys.dst,
+++			    (__force u32)keys.src ^ keys.ip_proto,
+++			    (__force u32)keys.ports, key);
+++}
++ #endif
++ 
++ #endif /* __BACKPORT_SKBUFF_H */
 diff --git a/package/kernel/mac80211/patches/005-backports-add-napi_alloc_frag.patch b/package/kernel/mac80211/patches/005-backports-add-napi_alloc_frag.patch
 deleted file mode 100644
 index 9b672a8..0000000
@@ -954,213 +1152,8 @@ index 9b672a8..0000000
 - /*
 -  * Complicated way of saying: We only backport netdev_rss_key stuff on kernels
 -  * that either already have net_get_random_once() (>= 3.13) or where we've been
-diff --git a/package/kernel/mac80211/patches/005-header-backport-nla_put_u64_64bit-and-nla_put_64bit.patch b/package/kernel/mac80211/patches/005-header-backport-nla_put_u64_64bit-and-nla_put_64bit.patch
-new file mode 100644
-index 0000000..e20d87a
---- /dev/null
-+++ b/package/kernel/mac80211/patches/005-header-backport-nla_put_u64_64bit-and-nla_put_64bit.patch
-@@ -0,0 +1,158 @@
-+From: Felix Fietkau <nbd@nbd.name>
-+Date: Sat, 14 May 2016 16:40:16 +0200
-+Subject: [PATCH] header: backport nla_put_u64_64bit and nla_put_64bit
-+
-+Signed-off-by: Felix Fietkau <nbd@nbd.name>
-+---
-+
-+--- a/backport-include/net/netlink.h
-++++ b/backport-include/net/netlink.h
-+@@ -189,4 +189,148 @@ static inline __le64 nla_get_le64(const
-+ }
-+ #endif /* < 4.4 */
-+ 
-++
-++#if LINUX_VERSION_CODE < KERNEL_VERSION(4,7,0)
-++
-++/**
-++ * nla_need_padding_for_64bit - test 64-bit alignment of the next attribute
-++ * @skb: socket buffer the message is stored in
-++ *
-++ * Return true if padding is needed to align the next attribute (nla_data()) to
-++ * a 64-bit aligned area.
-++ */
-++static inline bool nla_need_padding_for_64bit(struct sk_buff *skb)
-++{
-++#ifndef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS
-++	/* The nlattr header is 4 bytes in size, that's why we test
-++	 * if the skb->data _is_ aligned.  A NOP attribute, plus
-++	 * nlattr header for next attribute, will make nla_data()
-++	 * 8-byte aligned.
-++	 */
-++	if (IS_ALIGNED((unsigned long)skb_tail_pointer(skb), 8))
-++		return true;
-++#endif
-++	return false;
-++}
-++
-++/**
-++ * nla_align_64bit - 64-bit align the nla_data() of next attribute
-++ * @skb: socket buffer the message is stored in
-++ * @padattr: attribute type for the padding
-++ *
-++ * Conditionally emit a padding netlink attribute in order to make
-++ * the next attribute we emit have a 64-bit aligned nla_data() area.
-++ * This will only be done in architectures which do not have
-++ * CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS defined.
-++ *
-++ * Returns zero on success or a negative error code.
-++ */
-++static inline int nla_align_64bit(struct sk_buff *skb, int padattr)
-++{
-++	if (nla_need_padding_for_64bit(skb) &&
-++	    !nla_reserve(skb, padattr, 0))
-++		return -EMSGSIZE;
-++
-++	return 0;
-++}
-++
-++/**
-++ * __nla_reserve_64bit - reserve room for attribute on the skb and align it
-++ * @skb: socket buffer to reserve room on
-++ * @attrtype: attribute type
-++ * @attrlen: length of attribute payload
-++ * @padattr: attribute type for the padding
-++ *
-++ * Adds a netlink attribute header to a socket buffer and reserves
-++ * room for the payload but does not copy it. It also ensure that this
-++ * attribute will have a 64-bit aligned nla_data() area.
-++ *
-++ * The caller is responsible to ensure that the skb provides enough
-++ * tailroom for the attribute header and payload.
-++ */
-++static inline struct nlattr *__nla_reserve_64bit(struct sk_buff *skb, int attrtype,
-++						 int attrlen, int padattr)
-++{
-++	if (nla_need_padding_for_64bit(skb))
-++		nla_align_64bit(skb, padattr);
-++
-++	return __nla_reserve(skb, attrtype, attrlen);
-++}
-++
-++/**
-++ * __nla_put_64bit - Add a netlink attribute to a socket buffer and align it
-++ * @skb: socket buffer to add attribute to
-++ * @attrtype: attribute type
-++ * @attrlen: length of attribute payload
-++ * @data: head of attribute payload
-++ * @padattr: attribute type for the padding
-++ *
-++ * The caller is responsible to ensure that the skb provides enough
-++ * tailroom for the attribute header and payload.
-++ */
-++static inline void __nla_put_64bit(struct sk_buff *skb, int attrtype, int attrlen,
-++				   const void *data, int padattr)
-++{
-++	struct nlattr *nla;
-++
-++	nla = __nla_reserve_64bit(skb, attrtype, attrlen, padattr);
-++	memcpy(nla_data(nla), data, attrlen);
-++}
-++
-++/**
-++ * nla_total_size_64bit - total length of attribute including padding
-++ * @payload: length of payload
-++ */
-++static inline int nla_total_size_64bit(int payload)
-++{
-++	return NLA_ALIGN(nla_attr_size(payload))
-++#ifndef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS
-++		+ NLA_ALIGN(nla_attr_size(0))
-++#endif
-++		;
-++}
-++
-++/**
-++ * nla_put_64bit - Add a netlink attribute to a socket buffer and align it
-++ * @skb: socket buffer to add attribute to
-++ * @attrtype: attribute type
-++ * @attrlen: length of attribute payload
-++ * @data: head of attribute payload
-++ * @padattr: attribute type for the padding
-++ *
-++ * Returns -EMSGSIZE if the tailroom of the skb is insufficient to store
-++ * the attribute header and payload.
-++ */
-++static inline int nla_put_64bit(struct sk_buff *skb, int attrtype, int attrlen,
-++				const void *data, int padattr)
-++{
-++	size_t len;
-++
-++	if (nla_need_padding_for_64bit(skb))
-++		len = nla_total_size_64bit(attrlen);
-++	else
-++		len = nla_total_size(attrlen);
-++	if (unlikely(skb_tailroom(skb) < len))
-++		return -EMSGSIZE;
-++
-++	__nla_put_64bit(skb, attrtype, attrlen, data, padattr);
-++	return 0;
-++}
-++
-++/**
-++ * nla_put_u64_64bit - Add a u64 netlink attribute to a skb and align it
-++ * @skb: socket buffer to add attribute to
-++ * @attrtype: attribute type
-++ * @value: numeric value
-++ * @padattr: attribute type for the padding
-++ */
-++static inline int nla_put_u64_64bit(struct sk_buff *skb, int attrtype,
-++				    u64 value, int padattr)
-++{
-++	return nla_put_64bit(skb, attrtype, sizeof(u64), &value, padattr);
-++}
-++
-++
-++#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(4,7,0) */
-++
-+ #endif /* __BACKPORT_NET_NETLINK_H */
-diff --git a/package/kernel/mac80211/patches/006-compat-bump-rhashtable-backport-version-due-to-API-c.patch b/package/kernel/mac80211/patches/006-compat-bump-rhashtable-backport-version-due-to-API-c.patch
-new file mode 100644
-index 0000000..1fdad3c
---- /dev/null
-+++ b/package/kernel/mac80211/patches/006-compat-bump-rhashtable-backport-version-due-to-API-c.patch
-@@ -0,0 +1,18 @@
-+From: Felix Fietkau <nbd@nbd.name>
-+Date: Sat, 14 May 2016 16:44:57 +0200
-+Subject: [PATCH] compat: bump rhashtable backport version due to API changes
-+
-+Signed-off-by: Felix Fietkau <nbd@nbd.name>
-+---
-+
-+--- a/compat/Kconfig
-++++ b/compat/Kconfig
-+@@ -139,7 +139,7 @@ config BPAUTO_BUILD_WANT_DEV_COREDUMP
-+ config BPAUTO_RHASHTABLE
-+ 	bool
-+ 	# current API of rhashtable was introduced in version 4.1
-+-	depends on KERNEL_4_1
-++	depends on KERNEL_4_7
-+ 	# not very nice - but better than always having it
-+ 	default y if MAC80211
-+ 	#h-file linux/rhashtable.h
-diff --git a/package/kernel/mac80211/patches/007-fix_duplicate_skcipher_backport.patch b/package/kernel/mac80211/patches/007-fix_duplicate_skcipher_backport.patch
-new file mode 100644
-index 0000000..38b3179
---- /dev/null
-+++ b/package/kernel/mac80211/patches/007-fix_duplicate_skcipher_backport.patch
-@@ -0,0 +1,11 @@
-+--- a/compat/Makefile
-++++ b/compat/Makefile
-+@@ -35,8 +35,6 @@ compat-$(CPTCFG_KERNEL_4_6) += backport-
-+ 
-+ compat-$(CPTCFG_BPAUTO_BUILD_CRYPTO_CCM) += crypto-ccm.o
-+ compat-$(CPTCFG_BPAUTO_CRYPTO_SKCIPHER) += crypto-skcipher.o
-+-skcipher-objs += crypto-skcipher.o
-+-obj-$(CPTCFG_BPAUTO_CRYPTO_SKCIPHER) += skcipher.o
-+ compat-$(CPTCFG_BPAUTO_BUILD_WANT_DEV_COREDUMP) += drivers-base-devcoredump.o
-+ compat-$(CPTCFG_BPAUTO_RHASHTABLE) += lib-rhashtable.o
-+ cordic-objs += lib-cordic.o
 diff --git a/package/kernel/mac80211/patches/060-no_local_ssb_bcma.patch b/package/kernel/mac80211/patches/060-no_local_ssb_bcma.patch
-index fd1e1cf..e9a140c 100644
+index fd1e1cf..8be5fa1 100644
 --- a/package/kernel/mac80211/patches/060-no_local_ssb_bcma.patch
 +++ b/package/kernel/mac80211/patches/060-no_local_ssb_bcma.patch
 @@ -1,6 +1,6 @@
@@ -1184,7 +1177,7 @@ index fd1e1cf..e9a140c 100644
   #else
   	return bus->chipco.dev;
 -@@ -4903,7 +4903,7 @@ static int b43_wireless_core_init(struct
-+@@ -4901,7 +4901,7 @@ static int b43_wireless_core_init(struct
++@@ -4883,7 +4883,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. */
@@ -1215,180 +1208,10 @@ index 3765591..0000000
 --EXPORT_SYMBOL_GPL(clk_disable);
 --#endif
 diff --git a/package/kernel/mac80211/patches/100-remove-cryptoapi-dependencies.patch b/package/kernel/mac80211/patches/100-remove-cryptoapi-dependencies.patch
-index 02f46c7..b65b0bd 100644
+index 02f46c7..fbe22e5 100644
 --- a/package/kernel/mac80211/patches/100-remove-cryptoapi-dependencies.patch
 +++ b/package/kernel/mac80211/patches/100-remove-cryptoapi-dependencies.patch
-@@ -34,12 +34,9 @@
-  #include "aes_ccm.h"
-  
- -void ieee80211_aes_ccm_encrypt(struct crypto_aead *tfm, u8 *b_0, u8 *aad,
---			       u8 *data, size_t data_len, u8 *mic,
---			       size_t mic_len)
- +static void aes_ccm_prepare(struct crypto_cipher *tfm, u8 *b_0, u8 *aad, u8 *s_0,
- +			    u8 *a, u8 *b)
-- {
---	struct scatterlist sg[3];
-++{
- +	int i;
- +
- +	crypto_cipher_encrypt_one(tfm, b, b_0);
-@@ -54,55 +51,56 @@
- +	for (i = 0; i < AES_BLOCK_SIZE; i++)
- +		aad[i] ^= b[i];
- +	crypto_cipher_encrypt_one(tfm, a, aad);
-- 
---	char aead_req_data[sizeof(struct aead_request) +
---			   crypto_aead_reqsize(tfm)]
---		__aligned(__alignof__(struct aead_request));
---	struct aead_request *aead_req = (void *) aead_req_data;
-++
- +	/* Mask out bits from auth-only-b_0 */
- +	b_0[0] &= 0x07;
-- 
---	memset(aead_req, 0, sizeof(aead_req_data));
-++
- +	/* S_0 is used to encrypt T (= MIC) */
- +	b_0[14] = 0;
- +	b_0[15] = 0;
- +	crypto_cipher_encrypt_one(tfm, s_0, b_0);
- +}
-- 
---	sg_init_table(sg, 3);
---	sg_set_buf(&sg[0], &aad[2], be16_to_cpup((__be16 *)aad));
---	sg_set_buf(&sg[1], data, data_len);
---	sg_set_buf(&sg[2], mic, mic_len);
-- 
---	aead_request_set_tfm(aead_req, tfm);
---	aead_request_set_crypt(aead_req, sg, sg, data_len, b_0);
---	aead_request_set_ad(aead_req, sg[0].length);
-++
-++
- +void ieee80211_aes_ccm_encrypt(struct crypto_cipher *tfm, u8 *b_0, u8 *aad,
--+			       u8 *data, size_t data_len, u8 *mic,
--+			       size_t mic_len)
--+{
-+ 			       u8 *data, size_t data_len, u8 *mic,
-+ 			       size_t mic_len)
-+ {
-+-	struct scatterlist sg[3];
- +	int i, j, last_len, num_blocks;
- +	u8 b[AES_BLOCK_SIZE];
- +	u8 s_0[AES_BLOCK_SIZE];
- +	u8 e[AES_BLOCK_SIZE];
- +	u8 *pos, *cpos;
--+
-+ 
-+-	char aead_req_data[sizeof(struct aead_request) +
-+-			   crypto_aead_reqsize(tfm)]
-+-		__aligned(__alignof__(struct aead_request));
-+-	struct aead_request *aead_req = (void *) aead_req_data;
- +	num_blocks = DIV_ROUND_UP(data_len, AES_BLOCK_SIZE);
- +	last_len = data_len % AES_BLOCK_SIZE;
- +	aes_ccm_prepare(tfm, b_0, aad, s_0, b, b);
--+
-+ 
-+-	memset(aead_req, 0, sizeof(aead_req_data));
- +	/* Process payload blocks */
- +	pos = data;
- +	cpos = data;
- +	for (j = 1; j <= num_blocks; j++) {
- +		int blen = (j == num_blocks && last_len) ?
- +			last_len : AES_BLOCK_SIZE;
--+
-+ 
-+-	sg_init_table(sg, 3);
-+-	sg_set_buf(&sg[0], &aad[2], be16_to_cpup((__be16 *)aad));
-+-	sg_set_buf(&sg[1], data, data_len);
-+-	sg_set_buf(&sg[2], mic, mic_len);
- +		/* Authentication followed by encryption */
- +		for (i = 0; i < blen; i++)
- +			b[i] ^= pos[i];
- +		crypto_cipher_encrypt_one(tfm, b, b);
--+
-+ 
-+-	aead_request_set_tfm(aead_req, tfm);
-+-	aead_request_set_crypt(aead_req, sg, sg, data_len, b_0);
-+-	aead_request_set_ad(aead_req, sg[0].length);
- +		b_0[14] = (j >> 8) & 0xff;
- +		b_0[15] = j & 0xff;
- +		crypto_cipher_encrypt_one(tfm, e, b_0);
-@@ -125,37 +123,30 @@
- -			   crypto_aead_reqsize(tfm)]
- -		__aligned(__alignof__(struct aead_request));
- -	struct aead_request *aead_req = (void *) aead_req_data;
---
---	if (data_len == 0)
---		return -EINVAL;
---
---	memset(aead_req, 0, sizeof(aead_req_data));
---
---	sg_init_table(sg, 3);
---	sg_set_buf(&sg[0], &aad[2], be16_to_cpup((__be16 *)aad));
---	sg_set_buf(&sg[1], data, data_len);
---	sg_set_buf(&sg[2], mic, mic_len);
---
---	aead_request_set_tfm(aead_req, tfm);
---	aead_request_set_crypt(aead_req, sg, sg, data_len + mic_len, b_0);
---	aead_request_set_ad(aead_req, sg[0].length);
- +	int i, j, last_len, num_blocks;
- +	u8 *pos, *cpos;
- +	u8 a[AES_BLOCK_SIZE];
- +	u8 b[AES_BLOCK_SIZE];
- +	u8 s_0[AES_BLOCK_SIZE];
--+
-+ 
-+-	if (data_len == 0)
-+-		return -EINVAL;
- +	num_blocks = DIV_ROUND_UP(data_len, AES_BLOCK_SIZE);
- +	last_len = data_len % AES_BLOCK_SIZE;
- +	aes_ccm_prepare(tfm, b_0, aad, s_0, a, b);
--+
-+ 
-+-	memset(aead_req, 0, sizeof(aead_req_data));
- +	/* Process payload blocks */
- +	cpos = data;
- +	pos = data;
- +	for (j = 1; j <= num_blocks; j++) {
- +		int blen = (j == num_blocks && last_len) ?
- +			last_len : AES_BLOCK_SIZE;
--+
-+ 
-+-	sg_init_table(sg, 3);
-+-	sg_set_buf(&sg[0], &aad[2], be16_to_cpup((__be16 *)aad));
-+-	sg_set_buf(&sg[1], data, data_len);
-+-	sg_set_buf(&sg[2], mic, mic_len);
- +		/* Decryption followed by authentication */
- +		b_0[14] = (j >> 8) & 0xff;
- +		b_0[15] = j & 0xff;
-@@ -166,7 +157,10 @@
- +		}
- +		crypto_cipher_encrypt_one(tfm, a, a);
- +	}
--+
-+ 
-+-	aead_request_set_tfm(aead_req, tfm);
-+-	aead_request_set_crypt(aead_req, sg, sg, data_len + mic_len, b_0);
-+-	aead_request_set_ad(aead_req, sg[0].length);
- +	for (i = 0; i < mic_len; i++) {
- +		if ((mic[i] ^ s_0[i]) != a[i])
- +			return -1;
-@@ -185,12 +179,12 @@
-  {
- -	struct crypto_aead *tfm;
- -	int err;
--+	struct crypto_cipher *tfm;
-- 
-+-
- -	tfm = crypto_alloc_aead("ccm(aes)", 0, CRYPTO_ALG_ASYNC);
- -	if (IS_ERR(tfm))
- -		return tfm;
---
-++	struct crypto_cipher *tfm;
-+ 
- -	err = crypto_aead_setkey(tfm, key, key_len);
- -	if (err)
- -		goto free_aead;
-@@ -309,7 +303,7 @@
+@@ -309,7 +309,7 @@
   #endif /* AES_GMAC_H */
  --- a/net/mac80211/key.h
  +++ b/net/mac80211/key.h
@@ -1397,7 +1220,7 @@ index 02f46c7..b65b0bd 100644
   			 * Management frames.
   			 */
   			u8 rx_pn[IEEE80211_NUM_TIDS + 1][IEEE80211_CCMP_PN_LEN];
-@@ -320,7 +314,7 @@
+@@ -320,7 +320,7 @@
   		struct {
  --- a/net/mac80211/wpa.c
  +++ b/net/mac80211/wpa.c
@@ -1406,7 +1229,7 @@ index 02f46c7..b65b0bd 100644
   }
   
   
-@@ -330,7 +324,7 @@
+@@ -330,7 +330,7 @@
   {
   	__le16 mask_fc;
   	int a4_included, mgmt;
@@ -1415,7 +1238,7 @@ index 02f46c7..b65b0bd 100644
   	else
   		qos_tid = 0;
   
-@@ -347,7 +341,7 @@
+@@ -347,7 +347,7 @@
   
   	/* Nonce: Nonce Flags | A2 | PN
   	 * Nonce Flags: Priority (b0..b3) | Management (b4) | Reserved (b5..b7)
@@ -1424,7 +1247,7 @@ index 02f46c7..b65b0bd 100644
   	b_0[1] = qos_tid | (mgmt << 4);
   	memcpy(&b_0[2], hdr->addr2, ETH_ALEN);
   	memcpy(&b_0[8], pn, IEEE80211_CCMP_PN_LEN);
-@@ -356,7 +350,7 @@
+@@ -356,7 +356,7 @@
   
   	/* AAD (extra authenticate-only data) / masked 802.11 header
   	 * FC | A1 | A2 | A3 | SC | [A4] | [QC] */
@@ -1433,7 +1256,7 @@ index 02f46c7..b65b0bd 100644
   		return 0;
   
   	pos += IEEE80211_CCMP_HDR_LEN;
-@@ -365,7 +359,7 @@
+@@ -365,7 +365,7 @@
   	ieee80211_aes_ccm_encrypt(key->u.ccmp.tfm, b_0, aad, pos, len,
   				  skb_put(skb, mic_len), mic_len);
   
@@ -1456,33 +1279,39 @@ index d1d9fbd..3ca166f 100644
   
   	__sta_info_flush(sdata, true);
 diff --git a/package/kernel/mac80211/patches/150-disable_addr_notifier.patch b/package/kernel/mac80211/patches/150-disable_addr_notifier.patch
-index 2855a88..3029598 100644
+index 2855a88..16fab84 100644
 --- a/package/kernel/mac80211/patches/150-disable_addr_notifier.patch
 +++ b/package/kernel/mac80211/patches/150-disable_addr_notifier.patch
-@@ -18,7 +18,7 @@
+@@ -18,9 +18,9 @@
   static int ieee80211_ifa6_changed(struct notifier_block *nb,
   				  unsigned long data, void *arg)
   {
 -@@ -1087,14 +1087,14 @@ int ieee80211_register_hw(struct ieee802
-+@@ -1089,14 +1089,14 @@ int ieee80211_register_hw(struct ieee802
-  
-  	rtnl_unlock();
+- 
+- 	rtnl_unlock();
++@@ -1090,14 +1090,14 @@ int ieee80211_register_hw(struct ieee802
++ 	if (result)
++ 		goto fail_flows;
   
+ -#ifdef CONFIG_INET
+ +#ifdef __disabled__CONFIG_INET
 @@ -35,7 +35,7 @@
   	local->ifa6_notifier.notifier_call = ieee80211_ifa6_changed;
   	result = register_inet6addr_notifier(&local->ifa6_notifier);
   	if (result)
 -@@ -1103,13 +1103,13 @@ int ieee80211_register_hw(struct ieee802
-+@@ -1105,13 +1105,13 @@ int ieee80211_register_hw(struct ieee802
++@@ -1106,13 +1106,13 @@ int ieee80211_register_hw(struct ieee802
   
   	return 0;
   
-@@ -52,7 +52,7 @@
+@@ -51,8 +51,8 @@
+ +#if defined(__disabled__CONFIG_INET) || defined(__disabled__CONFIG_IPV6)
    fail_ifa:
   #endif
-  	rtnl_lock();
+- 	rtnl_lock();
 -@@ -1137,10 +1137,10 @@ void ieee80211_unregister_hw(struct ieee
-+@@ -1139,10 +1139,10 @@ void ieee80211_unregister_hw(struct ieee
++ 	ieee80211_txq_teardown_flows(local);
++@@ -1142,10 +1142,10 @@ void ieee80211_unregister_hw(struct ieee
   	tasklet_kill(&local->tx_pending_tasklet);
   	tasklet_kill(&local->tasklet);
   
@@ -1498,14 +1327,32 @@ index a99cbd2..29f05c4 100644
   		 * the  frames sent while scanning on other channel will be
   		 * lost)
   		 */
+diff --git a/package/kernel/mac80211/patches/220-fq_disable_hack.patch b/package/kernel/mac80211/patches/220-fq_disable_hack.patch
+new file mode 100644
+index 0000000..7f420be
+--- /dev/null
++++ b/package/kernel/mac80211/patches/220-fq_disable_hack.patch
+@@ -0,0 +1,15 @@
++mac80211 fq has been found to cause a regression in multi-stream TCP
++performance. Disable it until the cause has been found and fixed
++
++--- a/include/net/fq_impl.h
+++++ b/include/net/fq_impl.h
++@@ -104,6 +104,9 @@ static struct fq_flow *fq_flow_classify(
++ 
++ 	lockdep_assert_held(&fq->lock);
++ 
+++	/* HACK: disable fq for now until TCP issues are fixed */
+++	return get_default_func(fq, tin, 0, skb);
+++
++ 	hash = skb_get_hash_perturb(skb, fq->perturbation);
++ 	idx = reciprocal_scale(hash, fq->flows_cnt);
++ 	flow = &fq->flows[idx];
 diff --git a/package/kernel/mac80211/patches/300-ath9k-force-rx_clear-when-disabling-rx.patch b/package/kernel/mac80211/patches/300-ath9k-force-rx_clear-when-disabling-rx.patch
-index bddb15a..8f7e893 100644
+index bddb15a..098bda7 100644
 --- a/package/kernel/mac80211/patches/300-ath9k-force-rx_clear-when-disabling-rx.patch
 +++ b/package/kernel/mac80211/patches/300-ath9k-force-rx_clear-when-disabling-rx.patch
-@@ -1,17 +1,18 @@
--From: Felix Fietkau <nbd@openwrt.org>
-+From: Felix Fietkau <nbd@nbd.name>
- Date: Sun, 7 Jun 2015 13:53:35 +0200
+@@ -3,15 +3,16 @@ Date: Sun, 7 Jun 2015 13:53:35 +0200
  Subject: [PATCH] ath9k: force rx_clear when disabling rx
  
  This makes stopping Rx more reliable and should reduce the frequency of
@@ -1539,25 +1386,6 @@ index bddb15a..8f7e893 100644
   
   	ath9k_hw_disable_mib_counters(ah);
   }
-diff --git a/package/kernel/mac80211/patches/301-ath9k-limit-retries-for-powersave-response-frames.patch b/package/kernel/mac80211/patches/301-ath9k-limit-retries-for-powersave-response-frames.patch
-index a160dc4..358d028 100644
---- a/package/kernel/mac80211/patches/301-ath9k-limit-retries-for-powersave-response-frames.patch
-+++ b/package/kernel/mac80211/patches/301-ath9k-limit-retries-for-powersave-response-frames.patch
-@@ -1,4 +1,4 @@
--From: Felix Fietkau <nbd@openwrt.org>
-+From: Felix Fietkau <nbd@nbd.name>
- Date: Thu, 2 Jul 2015 15:20:56 +0200
- Subject: [PATCH] ath9k: limit retries for powersave response frames
- 
-@@ -8,7 +8,7 @@ gone to sleep. To avoid wasting too much airtime on this, limit the
- number of retries on such frames and ensure that no sample rate gets
- used.
- 
--Signed-off-by: Felix Fietkau <nbd@openwrt.org>
-+Signed-off-by: Felix Fietkau <nbd@nbd.name>
- ---
- 
- --- a/drivers/net/wireless/ath/ath9k/xmit.c
 diff --git a/package/kernel/mac80211/patches/302-Revert-ath9k-interpret-requested-txpower-in-EIRP-dom.patch b/package/kernel/mac80211/patches/302-Revert-ath9k-interpret-requested-txpower-in-EIRP-dom.patch
 new file mode 100644
 index 0000000..7caa9be
@@ -1702,158 +1530,33 @@ index 22b987a..0000000
 - static const u32 qca953x_2p0_baseband_core[][2] = {
 - 	/* Addr      allmodes  */
 - 	{0x00009800, 0xafe68e30},
-diff --git a/package/kernel/mac80211/patches/303-mac80211-mesh-flush-mesh-paths-unconditionally.patch b/package/kernel/mac80211/patches/303-mac80211-mesh-flush-mesh-paths-unconditionally.patch
+diff --git a/package/kernel/mac80211/patches/303-ath10k-Ensure-txrx-compl-task-is-stopped-when-cleani.patch b/package/kernel/mac80211/patches/303-ath10k-Ensure-txrx-compl-task-is-stopped-when-cleani.patch
 new file mode 100644
-index 0000000..518d0a3
+index 0000000..73accd8
 --- /dev/null
-+++ b/package/kernel/mac80211/patches/303-mac80211-mesh-flush-mesh-paths-unconditionally.patch
-@@ -0,0 +1,146 @@
-+From: Bob Copeland <me@bobcopeland.com>
-+Date: Sun, 15 May 2016 13:19:16 -0400
-+Subject: [PATCH] mac80211: mesh: flush mesh paths unconditionally
-+
-+Currently, the mesh paths associated with a nexthop station are cleaned
-+up in the following code path:
-+
-+    __sta_info_destroy_part1
-+    synchronize_net()
-+    __sta_info_destroy_part2
-+     -> cleanup_single_sta
-+       -> mesh_sta_cleanup
-+         -> mesh_plink_deactivate
-+           -> mesh_path_flush_by_nexthop
-+
-+However, there are a couple of problems here:
-+
-+1) the paths aren't flushed at all if the MPM is running in userspace
-+   (e.g. when using wpa_supplicant or authsae)
-+
-+2) there is no synchronize_rcu between removing the path and readers
-+   accessing the nexthop, which means the following race is possible:
-+
-+CPU0                            CPU1
-+~~~~                            ~~~~
-+                                sta_info_destroy_part1()
-+                                synchronize_net()
-+rcu_read_lock()
-+mesh_nexthop_resolve()
-+  mpath = mesh_path_lookup()
-+                                [...] -> mesh_path_flush_by_nexthop()
-+  sta = rcu_dereference(
-+    mpath->next_hop)
-+                                kfree(sta)
-+  access sta <-- CRASH
-+
-+Fix both of these by unconditionally flushing paths before destroying
-+the sta, and by adding a synchronize_net() after path flush to ensure
-+no active readers can still dereference the sta.
-+
-+Fixes this crash:
-+
-+[  348.529295] BUG: unable to handle kernel paging request at 00020040
-+[  348.530014] IP: [<f929245d>] ieee80211_mps_set_frame_flags+0x40/0xaa [mac80211]
-+[  348.530014] *pde = 00000000
-+[  348.530014] Oops: 0000 [#1] PREEMPT
-+[  348.530014] Modules linked in: drbg ansi_cprng ctr ccm ppp_generic slhc ipt_MASQUERADE nf_nat_masquerade_ipv4 8021q ]
-+[  348.530014] CPU: 0 PID: 20597 Comm: wget Tainted: G           O 4.6.0-rc5-wt=V1 #1
-+[  348.530014] Hardware name: To Be Filled By O.E.M./To be filled by O.E.M., BIOS 080016  11/07/2014
-+[  348.530014] task: f64fa280 ti: f4f9c000 task.ti: f4f9c000
-+[  348.530014] EIP: 0060:[<f929245d>] EFLAGS: 00010246 CPU: 0
-+[  348.530014] EIP is at ieee80211_mps_set_frame_flags+0x40/0xaa [mac80211]
-+[  348.530014] EAX: f4ce63e0 EBX: 00000088 ECX: f3788416 EDX: 00020008
-+[  348.530014] ESI: 00000000 EDI: 00000088 EBP: f6409a4c ESP: f6409a40
-+[  348.530014]  DS: 007b ES: 007b FS: 0000 GS: 0033 SS: 0068
-+[  348.530014] CR0: 80050033 CR2: 00020040 CR3: 33190000 CR4: 00000690
-+[  348.530014] Stack:
-+[  348.530014]  00000000 f4ce63e0 f5f9bd80 f6409a64 f9291d80 0000ce67 f5d51e00 f4ce63e0
-+[  348.530014]  f3788416 f6409a80 f9291dc1 f4ce8320 f4ce63e0 f5d51e00 f4ce63e0 f4ce8320
-+[  348.530014]  f6409a98 f9277f6f 00000000 00000000 0000007c 00000000 f6409b2c f9278dd1
-+[  348.530014] Call Trace:
-+[  348.530014]  [<f9291d80>] mesh_nexthop_lookup+0xbb/0xc8 [mac80211]
-+[  348.530014]  [<f9291dc1>] mesh_nexthop_resolve+0x34/0xd8 [mac80211]
-+[  348.530014]  [<f9277f6f>] ieee80211_xmit+0x92/0xc1 [mac80211]
-+[  348.530014]  [<f9278dd1>] __ieee80211_subif_start_xmit+0x807/0x83c [mac80211]
-+[  348.530014]  [<c04df012>] ? sch_direct_xmit+0xd7/0x1b3
-+[  348.530014]  [<c022a8c6>] ? __local_bh_enable_ip+0x5d/0x7b
-+[  348.530014]  [<f956870c>] ? nf_nat_ipv4_out+0x4c/0xd0 [nf_nat_ipv4]
-+[  348.530014]  [<f957e036>] ? iptable_nat_ipv4_fn+0xf/0xf [iptable_nat]
-+[  348.530014]  [<c04c6f45>] ? netif_skb_features+0x14d/0x30a
-+[  348.530014]  [<f9278e10>] ieee80211_subif_start_xmit+0xa/0xe [mac80211]
-+[  348.530014]  [<c04c769c>] dev_hard_start_xmit+0x1f8/0x267
-+[  348.530014]  [<c04c7261>] ?  validate_xmit_skb.isra.120.part.121+0x10/0x253
-+[  348.530014]  [<c04defc6>] sch_direct_xmit+0x8b/0x1b3
-+[  348.530014]  [<c04c7a9c>] __dev_queue_xmit+0x2c8/0x513
-+[  348.530014]  [<c04c7cfb>] dev_queue_xmit+0xa/0xc
-+[  348.530014]  [<f91bfc7a>] batadv_send_skb_packet+0xd6/0xec [batman_adv]
-+[  348.530014]  [<f91bfdc4>] batadv_send_unicast_skb+0x15/0x4a [batman_adv]
-+[  348.530014]  [<f91b5938>] batadv_dat_send_data+0x27e/0x310 [batman_adv]
-+[  348.530014]  [<f91c30b5>] ? batadv_tt_global_hash_find.isra.11+0x8/0xa [batman_adv]
-+[  348.530014]  [<f91b63f3>] batadv_dat_snoop_outgoing_arp_request+0x208/0x23d [batman_adv]
-+[  348.530014]  [<f91c0cd9>] batadv_interface_tx+0x206/0x385 [batman_adv]
-+[  348.530014]  [<c04c769c>] dev_hard_start_xmit+0x1f8/0x267
-+[  348.530014]  [<c04c7261>] ?  validate_xmit_skb.isra.120.part.121+0x10/0x253
-+[  348.530014]  [<c04defc6>] sch_direct_xmit+0x8b/0x1b3
-+[  348.530014]  [<c04c7a9c>] __dev_queue_xmit+0x2c8/0x513
-+[  348.530014]  [<f80cbd2a>] ? igb_xmit_frame+0x57/0x72 [igb]
-+[  348.530014]  [<c04c7cfb>] dev_queue_xmit+0xa/0xc
-+[  348.530014]  [<f843a326>] br_dev_queue_push_xmit+0xeb/0xfb [bridge]
-+[  348.530014]  [<f843a35f>] br_forward_finish+0x29/0x74 [bridge]
-+[  348.530014]  [<f843a23b>] ? deliver_clone+0x3b/0x3b [bridge]
-+[  348.530014]  [<f843a714>] __br_forward+0x89/0xe7 [bridge]
-+[  348.530014]  [<f843a336>] ? br_dev_queue_push_xmit+0xfb/0xfb [bridge]
-+[  348.530014]  [<f843a234>] deliver_clone+0x34/0x3b [bridge]
-+[  348.530014]  [<f843a68b>] ? br_flood+0x95/0x95 [bridge]
-+[  348.530014]  [<f843a66d>] br_flood+0x77/0x95 [bridge]
-+[  348.530014]  [<f843a809>] br_flood_forward+0x13/0x1a [bridge]
-+[  348.530014]  [<f843a68b>] ? br_flood+0x95/0x95 [bridge]
-+[  348.530014]  [<f843b877>] br_handle_frame_finish+0x392/0x3db [bridge]
-+[  348.530014]  [<c04e9b2b>] ? nf_iterate+0x2b/0x6b
-+[  348.530014]  [<f843baa6>] br_handle_frame+0x1e6/0x240 [bridge]
-+[  348.530014]  [<f843b4e5>] ? br_handle_local_finish+0x6a/0x6a [bridge]
-+[  348.530014]  [<c04c4ba0>] __netif_receive_skb_core+0x43a/0x66b
-+[  348.530014]  [<f843b8c0>] ? br_handle_frame_finish+0x3db/0x3db [bridge]
-+[  348.530014]  [<c023cea4>] ? resched_curr+0x19/0x37
-+[  348.530014]  [<c0240707>] ? check_preempt_wakeup+0xbf/0xfe
-+[  348.530014]  [<c0255dec>] ? ktime_get_with_offset+0x5c/0xfc
-+[  348.530014]  [<c04c4fc1>] __netif_receive_skb+0x47/0x55
-+[  348.530014]  [<c04c57ba>] netif_receive_skb_internal+0x40/0x5a
-+[  348.530014]  [<c04c61ef>] napi_gro_receive+0x3a/0x94
-+[  348.530014]  [<f80ce8d5>] igb_poll+0x6fd/0x9ad [igb]
-+[  348.530014]  [<c0242bd8>] ? swake_up_locked+0x14/0x26
-+[  348.530014]  [<c04c5d29>] net_rx_action+0xde/0x250
-+[  348.530014]  [<c022a743>] __do_softirq+0x8a/0x163
-+[  348.530014]  [<c022a6b9>] ? __hrtimer_tasklet_trampoline+0x19/0x19
-+[  348.530014]  [<c021100f>] do_softirq_own_stack+0x26/0x2c
-+[  348.530014]  <IRQ>
-+[  348.530014]  [<c022a957>] irq_exit+0x31/0x6f
-+[  348.530014]  [<c0210eb2>] do_IRQ+0x8d/0xa0
-+[  348.530014]  [<c058152c>] common_interrupt+0x2c/0x40
-+[  348.530014] Code: e7 8c 00 66 81 ff 88 00 75 12 85 d2 75 0e b2 c3 b8 83 e9 29 f9 e8 a7 5f f9 c6 eb 74 66 81 e3 8c 005
-+[  348.530014] EIP: [<f929245d>] ieee80211_mps_set_frame_flags+0x40/0xaa [mac80211] SS:ESP 0068:f6409a40
-+[  348.530014] CR2: 0000000000020040
-+[  348.530014] ---[ end trace 48556ac26779732e ]---
-+[  348.530014] Kernel panic - not syncing: Fatal exception in interrupt
-+[  348.530014] Kernel Offset: disabled
++++ b/package/kernel/mac80211/patches/303-ath10k-Ensure-txrx-compl-task-is-stopped-when-cleani.patch
+@@ -0,0 +1,21 @@
++From: Ben Greear <greearb@candelatech.com>
++Date: Fri, 1 Apr 2016 14:12:08 -0700
++Subject: [PATCH] ath10k: Ensure txrx-compl-task is stopped when cleaning
++ htt-tx.
 +
-+Cc: stable@vger.kernel.org
-+Reported-by: Fred Veldini <fred.veldini@gmail.com>
-+Tested-by: Fred Veldini <fred.veldini@gmail.com>
-+Signed-off-by: Bob Copeland <me@bobcopeland.com>
++Otherwise, the txrx-compl-task may access some bad memory?
++
++Signed-off-by: Ben Greear <greearb@candelatech.com>
 +---
 +
-+--- a/net/mac80211/mesh.c
-++++ b/net/mac80211/mesh.c
-+@@ -161,6 +161,10 @@ void mesh_sta_cleanup(struct sta_info *s
-+ 		del_timer_sync(&sta->mesh->plink_timer);
-+ 	}
++--- a/drivers/net/wireless/ath/ath10k/htt_tx.c
+++++ b/drivers/net/wireless/ath/ath10k/htt_tx.c
++@@ -388,6 +388,8 @@ void ath10k_htt_tx_free(struct ath10k_ht
++ {
++ 	int size;
 + 
-++	/* make sure no readers can access nexthop sta from here on */
-++	mesh_path_flush_by_nexthop(sta);
-++	synchronize_net();
+++	tasklet_kill(&htt->txrx_compl_task);
 ++
-+ 	if (changed)
-+ 		ieee80211_mbss_info_change_notify(sdata, changed);
-+ }
++ 	idr_for_each(&htt->pending_tx, ath10k_htt_tx_clean_up_pending, htt->ar);
++ 	idr_destroy(&htt->pending_tx);
++ 
 diff --git a/package/kernel/mac80211/patches/303-rt2x00-fix-monitor-mode-regression.patch b/package/kernel/mac80211/patches/303-rt2x00-fix-monitor-mode-regression.patch
 deleted file mode 100644
 index 7bb7435..0000000
@@ -2016,102 +1719,148 @@ index 7bb7435..0000000
 - 			   !rt2x00dev->intf_ap_count);
 - 	rt2x00_set_field32(&reg, TXRX_CSR0_DROP_VERSION_ERROR, 1);
 - 	rt2x00_set_field32(&reg, TXRX_CSR0_DROP_MULTICAST,
-diff --git a/package/kernel/mac80211/patches/304-ath9k-avoid-ANI-restart-if-no-trigger.patch b/package/kernel/mac80211/patches/304-ath9k-avoid-ANI-restart-if-no-trigger.patch
-deleted file mode 100644
-index 049059a..0000000
---- a/package/kernel/mac80211/patches/304-ath9k-avoid-ANI-restart-if-no-trigger.patch
-+++ /dev/null
-@@ -1,32 +0,0 @@
--From: Miaoqing Pan <miaoqing@codeaurora.org>
--Date: Fri, 15 Jan 2016 18:17:17 +0800
--Subject: [PATCH] ath9k: avoid ANI restart if no trigger
--
--Fixes commit 54da20d83f0e ("ath9k_hw: improve ANI processing and rx desensitizing parameters")
--
--Call ath9k_ani_restart() only when the phy error rate reach the
--ANI immunity threshold. Sync the logic with internal code base.
--
--Signed-off-by: Miaoqing Pan <miaoqing@codeaurora.org>
-----
--
----- a/drivers/net/wireless/ath/ath9k/ani.c
--+++ b/drivers/net/wireless/ath/ath9k/ani.c
--@@ -444,14 +444,16 @@ void ath9k_hw_ani_monitor(struct ath_hw
-- 		    ofdmPhyErrRate < ah->config.ofdm_trig_low) {
-- 			ath9k_hw_ani_lower_immunity(ah);
-- 			aniState->ofdmsTurn = !aniState->ofdmsTurn;
--+			ath9k_ani_restart(ah);
-- 		} else if (ofdmPhyErrRate > ah->config.ofdm_trig_high) {
-- 			ath9k_hw_ani_ofdm_err_trigger(ah);
-- 			aniState->ofdmsTurn = false;
--+			ath9k_ani_restart(ah);
-- 		} else if (cckPhyErrRate > ah->config.cck_trig_high) {
-- 			ath9k_hw_ani_cck_err_trigger(ah);
-- 			aniState->ofdmsTurn = true;
--+			ath9k_ani_restart(ah);
-- 		}
---		ath9k_ani_restart(ah);
-- 	}
-- }
-- EXPORT_SYMBOL(ath9k_hw_ani_monitor);
-diff --git a/package/kernel/mac80211/patches/304-mac80211-fix-fast_tx-header-alignment.patch b/package/kernel/mac80211/patches/304-mac80211-fix-fast_tx-header-alignment.patch
+diff --git a/package/kernel/mac80211/patches/304-ath10k-Ensure-peer_map-references-are-cleaned-up.patch b/package/kernel/mac80211/patches/304-ath10k-Ensure-peer_map-references-are-cleaned-up.patch
 new file mode 100644
-index 0000000..6316d81
+index 0000000..7dec1fb
 --- /dev/null
-+++ b/package/kernel/mac80211/patches/304-mac80211-fix-fast_tx-header-alignment.patch
-@@ -0,0 +1,25 @@
-+From: Felix Fietkau <nbd@nbd.name>
-+Date: Thu, 19 May 2016 17:32:13 +0200
-+Subject: [PATCH] mac80211: fix fast_tx header alignment
++++ b/package/kernel/mac80211/patches/304-ath10k-Ensure-peer_map-references-are-cleaned-up.patch
+@@ -0,0 +1,60 @@
++From: Ben Greear <greearb@candelatech.com>
++Date: Fri, 1 Apr 2016 14:12:09 -0700
++Subject: [PATCH] ath10k: Ensure peer_map references are cleaned up.
 +
-+The header field is defined as u8[] but also accessed as struct
-+ieee80211_hdr. Enforce an alignment of 2 to prevent unnecessary
-+unaligned accesses, which can be very harmful for performance on many
-+platforms.
++While debugging OS crashes due to firmware crashes, I enabled
++kasan, and it noticed that peer objects were being used-after-freed.
 +
-+Fixes: e495c24731a2 ("mac80211: extend fast-xmit for more ciphers")
-+Cc: stable@vger.kernel.org
-+Signed-off-by: Felix Fietkau <nbd@nbd.name>
++Looks like there are two places we could be leaving stale references
++in the peer-map, so clean that up.
++
++Signed-off-by: Ben Greear <greearb@candelatech.com>
 +---
 +
-+--- a/net/mac80211/sta_info.h
-++++ b/net/mac80211/sta_info.h
-+@@ -280,7 +280,7 @@ struct ieee80211_fast_tx {
-+ 	u8 sa_offs, da_offs, pn_offs;
-+ 	u8 band;
-+ 	u8 hdr[30 + 2 + IEEE80211_FAST_XMIT_MAX_IV +
-+-	       sizeof(rfc1042_header)];
-++	       sizeof(rfc1042_header)] __aligned(2);
++--- a/drivers/net/wireless/ath/ath10k/mac.c
+++++ b/drivers/net/wireless/ath/ath10k/mac.c
++@@ -802,6 +802,7 @@ static void ath10k_peer_cleanup(struct a
++ {
++ 	struct ath10k_peer *peer, *tmp;
++ 	int peer_id;
+++	int i;
 + 
-+ 	struct rcu_head rcu_head;
-+ };
-diff --git a/package/kernel/mac80211/patches/305-ath10k-Ensure-txrx-compl-task-is-stopped-when-cleani.patch b/package/kernel/mac80211/patches/305-ath10k-Ensure-txrx-compl-task-is-stopped-when-cleani.patch
++ 	lockdep_assert_held(&ar->conf_mutex);
++ 
++@@ -818,6 +819,17 @@ static void ath10k_peer_cleanup(struct a
++ 			ar->peer_map[peer_id] = NULL;
++ 		}
++ 
+++		/* Double check that peer is properly un-referenced from
+++		 * the peer_map
+++		 */
+++		for (i = 0; i < ARRAY_SIZE(ar->peer_map); i++) {
+++			if (ar->peer_map[i] == peer) {
+++				ath10k_warn(ar, "removing stale peer_map entry for %pM (ptr %p idx %d)\n",
+++					    peer->addr, peer, i);
+++				ar->peer_map[i] = NULL;
+++			}
+++		}
+++
++ 		list_del(&peer->list);
++ 		kfree(peer);
++ 		ar->num_peers--;
++@@ -828,6 +840,7 @@ static void ath10k_peer_cleanup(struct a
++ static void ath10k_peer_cleanup_all(struct ath10k *ar)
++ {
++ 	struct ath10k_peer *peer, *tmp;
+++	int i;
++ 
++ 	lockdep_assert_held(&ar->conf_mutex);
++ 
++@@ -836,6 +849,10 @@ static void ath10k_peer_cleanup_all(stru
++ 		list_del(&peer->list);
++ 		kfree(peer);
++ 	}
+++
+++	for (i = 0; i < ARRAY_SIZE(ar->peer_map); i++)
+++		ar->peer_map[i] = NULL;
+++
++ 	spin_unlock_bh(&ar->data_lock);
++ 
++ 	ar->num_peers = 0;
+diff --git a/package/kernel/mac80211/patches/304-ath9k-avoid-ANI-restart-if-no-trigger.patch b/package/kernel/mac80211/patches/304-ath9k-avoid-ANI-restart-if-no-trigger.patch
+deleted file mode 100644
+index 049059a..0000000
+--- a/package/kernel/mac80211/patches/304-ath9k-avoid-ANI-restart-if-no-trigger.patch
++++ /dev/null
+@@ -1,32 +0,0 @@
+-From: Miaoqing Pan <miaoqing@codeaurora.org>
+-Date: Fri, 15 Jan 2016 18:17:17 +0800
+-Subject: [PATCH] ath9k: avoid ANI restart if no trigger
+-
+-Fixes commit 54da20d83f0e ("ath9k_hw: improve ANI processing and rx desensitizing parameters")
+-
+-Call ath9k_ani_restart() only when the phy error rate reach the
+-ANI immunity threshold. Sync the logic with internal code base.
+-
+-Signed-off-by: Miaoqing Pan <miaoqing@codeaurora.org>
+----
+-
+---- a/drivers/net/wireless/ath/ath9k/ani.c
+-+++ b/drivers/net/wireless/ath/ath9k/ani.c
+-@@ -444,14 +444,16 @@ void ath9k_hw_ani_monitor(struct ath_hw
+- 		    ofdmPhyErrRate < ah->config.ofdm_trig_low) {
+- 			ath9k_hw_ani_lower_immunity(ah);
+- 			aniState->ofdmsTurn = !aniState->ofdmsTurn;
+-+			ath9k_ani_restart(ah);
+- 		} else if (ofdmPhyErrRate > ah->config.ofdm_trig_high) {
+- 			ath9k_hw_ani_ofdm_err_trigger(ah);
+- 			aniState->ofdmsTurn = false;
+-+			ath9k_ani_restart(ah);
+- 		} else if (cckPhyErrRate > ah->config.cck_trig_high) {
+- 			ath9k_hw_ani_cck_err_trigger(ah);
+- 			aniState->ofdmsTurn = true;
+-+			ath9k_ani_restart(ah);
+- 		}
+--		ath9k_ani_restart(ah);
+- 	}
+- }
+- EXPORT_SYMBOL(ath9k_hw_ani_monitor);
+diff --git a/package/kernel/mac80211/patches/305-ath10k-Clean-up-peer-when-sta-goes-away.patch b/package/kernel/mac80211/patches/305-ath10k-Clean-up-peer-when-sta-goes-away.patch
 new file mode 100644
-index 0000000..73accd8
+index 0000000..7248a8c
 --- /dev/null
-+++ b/package/kernel/mac80211/patches/305-ath10k-Ensure-txrx-compl-task-is-stopped-when-cleani.patch
-@@ -0,0 +1,21 @@
++++ b/package/kernel/mac80211/patches/305-ath10k-Clean-up-peer-when-sta-goes-away.patch
+@@ -0,0 +1,32 @@
 +From: Ben Greear <greearb@candelatech.com>
-+Date: Fri, 1 Apr 2016 14:12:08 -0700
-+Subject: [PATCH] ath10k: Ensure txrx-compl-task is stopped when cleaning
-+ htt-tx.
++Date: Fri, 1 Apr 2016 14:12:11 -0700
++Subject: [PATCH] ath10k: Clean up peer when sta goes away.
 +
-+Otherwise, the txrx-compl-task may access some bad memory?
++If WMI and/or firmware has issues removing the peer object,
++then we still need to clean up the peer object in the driver.
 +
 +Signed-off-by: Ben Greear <greearb@candelatech.com>
 +---
 +
-+--- a/drivers/net/wireless/ath/ath10k/htt_tx.c
-++++ b/drivers/net/wireless/ath/ath10k/htt_tx.c
-+@@ -388,6 +388,8 @@ void ath10k_htt_tx_free(struct ath10k_ht
-+ {
-+ 	int size;
++--- a/drivers/net/wireless/ath/ath10k/mac.c
+++++ b/drivers/net/wireless/ath/ath10k/mac.c
++@@ -5992,9 +5992,17 @@ static int ath10k_sta_state(struct ieee8
++ 				continue;
 + 
-++	tasklet_kill(&htt->txrx_compl_task);
++ 			if (peer->sta == sta) {
++-				ath10k_warn(ar, "found sta peer %pM entry on vdev %i after it was supposedly removed\n",
++-					    sta->addr, arvif->vdev_id);
+++				ath10k_warn(ar, "found sta peer %pM (ptr %p id %d) entry on vdev %i after it was supposedly removed\n",
+++					    sta->addr, peer, i, arvif->vdev_id);
++ 				peer->sta = NULL;
 ++
-+ 	idr_for_each(&htt->pending_tx, ath10k_htt_tx_clean_up_pending, htt->ar);
-+ 	idr_destroy(&htt->pending_tx);
-+ 
+++				/* Clean up the peer object as well since we
+++				 * must have failed to do this above.
+++				 */
+++				list_del(&peer->list);
+++				ar->peer_map[i] = NULL;
+++				kfree(peer);
+++				ar->num_peers--;
++ 			}
++ 		}
++ 		spin_unlock_bh(&ar->data_lock);
 diff --git a/package/kernel/mac80211/patches/305-ath9k-clean-up-ANI-per-channel-pointer-checking.patch b/package/kernel/mac80211/patches/305-ath9k-clean-up-ANI-per-channel-pointer-checking.patch
 deleted file mode 100644
 index a1ac67c..0000000
@@ -2209,72 +1958,6 @@ index a1ac67c..0000000
 - 	if (!ath9k_hw_ani_read_counters(ah))
 - 		return;
 - 
-diff --git a/package/kernel/mac80211/patches/306-ath10k-Ensure-peer_map-references-are-cleaned-up.patch b/package/kernel/mac80211/patches/306-ath10k-Ensure-peer_map-references-are-cleaned-up.patch
-new file mode 100644
-index 0000000..2979b4b
---- /dev/null
-+++ b/package/kernel/mac80211/patches/306-ath10k-Ensure-peer_map-references-are-cleaned-up.patch
-@@ -0,0 +1,60 @@
-+From: Ben Greear <greearb@candelatech.com>
-+Date: Fri, 1 Apr 2016 14:12:09 -0700
-+Subject: [PATCH] ath10k: Ensure peer_map references are cleaned up.
-+
-+While debugging OS crashes due to firmware crashes, I enabled
-+kasan, and it noticed that peer objects were being used-after-freed.
-+
-+Looks like there are two places we could be leaving stale references
-+in the peer-map, so clean that up.
-+
-+Signed-off-by: Ben Greear <greearb@candelatech.com>
-+---
-+
-+--- a/drivers/net/wireless/ath/ath10k/mac.c
-++++ b/drivers/net/wireless/ath/ath10k/mac.c
-+@@ -773,6 +773,7 @@ static void ath10k_peer_cleanup(struct a
-+ {
-+ 	struct ath10k_peer *peer, *tmp;
-+ 	int peer_id;
-++	int i;
-+ 
-+ 	lockdep_assert_held(&ar->conf_mutex);
-+ 
-+@@ -789,6 +790,17 @@ static void ath10k_peer_cleanup(struct a
-+ 			ar->peer_map[peer_id] = NULL;
-+ 		}
-+ 
-++		/* Double check that peer is properly un-referenced from
-++		 * the peer_map
-++		 */
-++		for (i = 0; i < ARRAY_SIZE(ar->peer_map); i++) {
-++			if (ar->peer_map[i] == peer) {
-++				ath10k_warn(ar, "removing stale peer_map entry for %pM (ptr %p idx %d)\n",
-++					    peer->addr, peer, i);
-++				ar->peer_map[i] = NULL;
-++			}
-++		}
-++
-+ 		list_del(&peer->list);
-+ 		kfree(peer);
-+ 		ar->num_peers--;
-+@@ -799,6 +811,7 @@ static void ath10k_peer_cleanup(struct a
-+ static void ath10k_peer_cleanup_all(struct ath10k *ar)
-+ {
-+ 	struct ath10k_peer *peer, *tmp;
-++	int i;
-+ 
-+ 	lockdep_assert_held(&ar->conf_mutex);
-+ 
-+@@ -807,6 +820,10 @@ static void ath10k_peer_cleanup_all(stru
-+ 		list_del(&peer->list);
-+ 		kfree(peer);
-+ 	}
-++
-++	for (i = 0; i < ARRAY_SIZE(ar->peer_map); i++)
-++		ar->peer_map[i] = NULL;
-++
-+ 	spin_unlock_bh(&ar->data_lock);
-+ 
-+ 	ar->num_peers = 0;
 diff --git a/package/kernel/mac80211/patches/306-ath9k-do-not-reset-while-BB-panic-0x4000409-on-ar956.patch b/package/kernel/mac80211/patches/306-ath9k-do-not-reset-while-BB-panic-0x4000409-on-ar956.patch
 deleted file mode 100644
 index cf8194a..0000000
@@ -2312,44 +1995,215 @@ index cf8194a..0000000
 - 			return false;
 - 		else
 - 			return true;
-diff --git a/package/kernel/mac80211/patches/307-ath10k-Clean-up-peer-when-sta-goes-away.patch b/package/kernel/mac80211/patches/307-ath10k-Clean-up-peer-when-sta-goes-away.patch
+diff --git a/package/kernel/mac80211/patches/306-mac80211-add-hdrlen-to-ieee80211_tx_data.patch b/package/kernel/mac80211/patches/306-mac80211-add-hdrlen-to-ieee80211_tx_data.patch
 new file mode 100644
-index 0000000..f814ae7
+index 0000000..4a8f143
 --- /dev/null
-+++ b/package/kernel/mac80211/patches/307-ath10k-Clean-up-peer-when-sta-goes-away.patch
-@@ -0,0 +1,32 @@
-+From: Ben Greear <greearb@candelatech.com>
-+Date: Fri, 1 Apr 2016 14:12:11 -0700
-+Subject: [PATCH] ath10k: Clean up peer when sta goes away.
++++ b/package/kernel/mac80211/patches/306-mac80211-add-hdrlen-to-ieee80211_tx_data.patch
+@@ -0,0 +1,203 @@
++From: Janusz Dziedzic <janusz.dziedzic@tieto.com>
++Date: Fri, 19 Feb 2016 11:01:49 +0100
++Subject: [PATCH] mac80211: add hdrlen to ieee80211_tx_data
 +
-+If WMI and/or firmware has issues removing the peer object,
-+then we still need to clean up the peer object in the driver.
++Add hdrlen to ieee80211_tx_data and use this
++when wep/ccmd/tkip. This is preparation for
++aligned4 code.
 +
-+Signed-off-by: Ben Greear <greearb@candelatech.com>
++Signed-off-by: Janusz Dziedzic <janusz.dziedzic@tieto.com>
 +---
 +
-+--- a/drivers/net/wireless/ath/ath10k/mac.c
-++++ b/drivers/net/wireless/ath/ath10k/mac.c
-+@@ -5949,9 +5949,17 @@ static int ath10k_sta_state(struct ieee8
-+ 				continue;
++--- a/net/mac80211/ieee80211_i.h
+++++ b/net/mac80211/ieee80211_i.h
++@@ -173,6 +173,7 @@ struct ieee80211_tx_data {
++ 	struct ieee80211_tx_rate rate;
 + 
-+ 			if (peer->sta == sta) {
-+-				ath10k_warn(ar, "found sta peer %pM entry on vdev %i after it was supposedly removed\n",
-+-					    sta->addr, arvif->vdev_id);
-++				ath10k_warn(ar, "found sta peer %pM (ptr %p id %d) entry on vdev %i after it was supposedly removed\n",
-++					    sta->addr, peer, i, arvif->vdev_id);
-+ 				peer->sta = NULL;
++ 	unsigned int flags;
+++	unsigned int hdrlen;
++ };
++ 
++ 
++--- a/net/mac80211/tx.c
+++++ b/net/mac80211/tx.c
++@@ -922,7 +922,7 @@ ieee80211_tx_h_fragment(struct ieee80211
++ 	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
++ 	struct ieee80211_hdr *hdr = (void *)skb->data;
++ 	int frag_threshold = tx->local->hw.wiphy->frag_threshold;
++-	int hdrlen;
+++	int hdrlen = tx->hdrlen;
++ 	int fragnum;
++ 
++ 	/* no matter what happens, tx->skb moves to tx->skbs */
++@@ -943,8 +943,6 @@ ieee80211_tx_h_fragment(struct ieee80211
++ 	if (WARN_ON(info->flags & IEEE80211_TX_CTL_AMPDU))
++ 		return TX_DROP;
++ 
++-	hdrlen = ieee80211_hdrlen(hdr->frame_control);
++-
++ 	/* internal error, why isn't DONTFRAG set? */
++ 	if (WARN_ON(skb->len + FCS_LEN <= frag_threshold))
++ 		return TX_DROP;
++@@ -1176,6 +1174,8 @@ ieee80211_tx_prepare(struct ieee80211_su
++ 
++ 	hdr = (struct ieee80211_hdr *) skb->data;
++ 
+++	tx->hdrlen = ieee80211_hdrlen(hdr->frame_control);
 ++
-++				/* Clean up the peer object as well since we
-++				 * must have failed to do this above.
-++				 */
-++				list_del(&peer->list);
-++				ar->peer_map[i] = NULL;
-++				kfree(peer);
-++				ar->num_peers--;
-+ 			}
-+ 		}
-+ 		spin_unlock_bh(&ar->data_lock);
++ 	if (likely(sta)) {
++ 		if (!IS_ERR(sta))
++ 			tx->sta = sta;
++--- a/net/mac80211/util.c
+++++ b/net/mac80211/util.c
++@@ -1226,6 +1226,7 @@ void ieee80211_send_auth(struct ieee8021
++ 	struct ieee80211_local *local = sdata->local;
++ 	struct sk_buff *skb;
++ 	struct ieee80211_mgmt *mgmt;
+++	unsigned int hdrlen;
++ 	int err;
++ 
++ 	/* 24 + 6 = header + auth_algo + auth_transaction + status_code */
++@@ -1250,8 +1251,10 @@ void ieee80211_send_auth(struct ieee8021
++ 		memcpy(skb_put(skb, extra_len), extra, extra_len);
++ 
++ 	if (auth_alg == WLAN_AUTH_SHARED_KEY && transaction == 3) {
+++		hdrlen = ieee80211_hdrlen(mgmt->frame_control);
++ 		mgmt->frame_control |= cpu_to_le16(IEEE80211_FCTL_PROTECTED);
++-		err = ieee80211_wep_encrypt(local, skb, key, key_len, key_idx);
+++		err = ieee80211_wep_encrypt(local, skb, hdrlen, key,
+++					    key_len, key_idx);
++ 		WARN_ON(err);
++ 	}
++ 
++--- a/net/mac80211/wep.c
+++++ b/net/mac80211/wep.c
++@@ -89,11 +89,11 @@ static void ieee80211_wep_get_iv(struct
++ 
++ static u8 *ieee80211_wep_add_iv(struct ieee80211_local *local,
++ 				struct sk_buff *skb,
+++				unsigned int hdrlen,
++ 				int keylen, int keyidx)
++ {
++ 	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
++ 	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
++-	unsigned int hdrlen;
++ 	u8 *newhdr;
++ 
++ 	hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_PROTECTED);
++@@ -101,7 +101,6 @@ static u8 *ieee80211_wep_add_iv(struct i
++ 	if (WARN_ON(skb_headroom(skb) < IEEE80211_WEP_IV_LEN))
++ 		return NULL;
++ 
++-	hdrlen = ieee80211_hdrlen(hdr->frame_control);
++ 	newhdr = skb_push(skb, IEEE80211_WEP_IV_LEN);
++ 	memmove(newhdr, newhdr + IEEE80211_WEP_IV_LEN, hdrlen);
++ 
++@@ -160,6 +159,7 @@ int ieee80211_wep_encrypt_data(struct cr
++  */
++ int ieee80211_wep_encrypt(struct ieee80211_local *local,
++ 			  struct sk_buff *skb,
+++			  unsigned int hdrlen,
++ 			  const u8 *key, int keylen, int keyidx)
++ {
++ 	u8 *iv;
++@@ -169,7 +169,7 @@ int ieee80211_wep_encrypt(struct ieee802
++ 	if (WARN_ON(skb_tailroom(skb) < IEEE80211_WEP_ICV_LEN))
++ 		return -1;
++ 
++-	iv = ieee80211_wep_add_iv(local, skb, keylen, keyidx);
+++	iv = ieee80211_wep_add_iv(local, skb, hdrlen, keylen, keyidx);
++ 	if (!iv)
++ 		return -1;
++ 
++@@ -306,13 +306,14 @@ static int wep_encrypt_skb(struct ieee80
++ 	struct ieee80211_key_conf *hw_key = info->control.hw_key;
++ 
++ 	if (!hw_key) {
++-		if (ieee80211_wep_encrypt(tx->local, skb, tx->key->conf.key,
+++		if (ieee80211_wep_encrypt(tx->local, skb, tx->hdrlen,
+++					  tx->key->conf.key,
++ 					  tx->key->conf.keylen,
++ 					  tx->key->conf.keyidx))
++ 			return -1;
++ 	} else if ((hw_key->flags & IEEE80211_KEY_FLAG_GENERATE_IV) ||
++ 		   (hw_key->flags & IEEE80211_KEY_FLAG_PUT_IV_SPACE)) {
++-		if (!ieee80211_wep_add_iv(tx->local, skb,
+++		if (!ieee80211_wep_add_iv(tx->local, skb, tx->hdrlen,
++ 					  tx->key->conf.keylen,
++ 					  tx->key->conf.keyidx))
++ 			return -1;
++--- a/net/mac80211/wep.h
+++++ b/net/mac80211/wep.h
++@@ -22,6 +22,7 @@ int ieee80211_wep_encrypt_data(struct cr
++ 				size_t klen, u8 *data, size_t data_len);
++ int ieee80211_wep_encrypt(struct ieee80211_local *local,
++ 			  struct sk_buff *skb,
+++			  unsigned int hdrlen,
++ 			  const u8 *key, int keylen, int keyidx);
++ int ieee80211_wep_decrypt_data(struct crypto_cipher *tfm, u8 *rc4key,
++ 			       size_t klen, u8 *data, size_t data_len);
++--- a/net/mac80211/wpa.c
+++++ b/net/mac80211/wpa.c
++@@ -43,7 +43,7 @@ ieee80211_tx_h_michael_mic_add(struct ie
++ 	    skb->len < 24 || !ieee80211_is_data_present(hdr->frame_control))
++ 		return TX_CONTINUE;
++ 
++-	hdrlen = ieee80211_hdrlen(hdr->frame_control);
+++	hdrlen = tx->hdrlen;
++ 	if (skb->len < hdrlen)
++ 		return TX_DROP;
++ 
++@@ -186,7 +186,6 @@ mic_fail_no_key:
++ 
++ static int tkip_encrypt_skb(struct ieee80211_tx_data *tx, struct sk_buff *skb)
++ {
++-	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
++ 	struct ieee80211_key *key = tx->key;
++ 	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
++ 	unsigned int hdrlen;
++@@ -201,7 +200,7 @@ static int tkip_encrypt_skb(struct ieee8
++ 		return 0;
++ 	}
++ 
++-	hdrlen = ieee80211_hdrlen(hdr->frame_control);
+++	hdrlen = tx->hdrlen;
++ 	len = skb->len - hdrlen;
++ 
++ 	if (info->control.hw_key)
++@@ -418,7 +417,7 @@ static int ccmp_encrypt_skb(struct ieee8
++ 		return 0;
++ 	}
++ 
++-	hdrlen = ieee80211_hdrlen(hdr->frame_control);
+++	hdrlen = tx->hdrlen;
++ 	len = skb->len - hdrlen;
++ 
++ 	if (info->control.hw_key)
++@@ -651,7 +650,7 @@ static int gcmp_encrypt_skb(struct ieee8
++ 		return 0;
++ 	}
++ 
++-	hdrlen = ieee80211_hdrlen(hdr->frame_control);
+++	hdrlen = tx->hdrlen;
++ 	len = skb->len - hdrlen;
++ 
++ 	if (info->control.hw_key)
++@@ -791,7 +790,6 @@ static ieee80211_tx_result
++ ieee80211_crypto_cs_encrypt(struct ieee80211_tx_data *tx,
++ 			    struct sk_buff *skb)
++ {
++-	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
++ 	struct ieee80211_key *key = tx->key;
++ 	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
++ 	int hdrlen;
++@@ -807,8 +805,7 @@ ieee80211_crypto_cs_encrypt(struct ieee8
++ 		     pskb_expand_head(skb, iv_len, 0, GFP_ATOMIC)))
++ 		return TX_DROP;
++ 
++-	hdrlen = ieee80211_hdrlen(hdr->frame_control);
++-
+++	hdrlen = tx->hdrlen;
++ 	pos = skb_push(skb, iv_len);
++ 	memmove(pos, pos + iv_len, hdrlen);
++ 
 diff --git a/package/kernel/mac80211/patches/307-ath9k-fix-inconsistent-use-of-tab-and-space-in-inden.patch b/package/kernel/mac80211/patches/307-ath9k-fix-inconsistent-use-of-tab-and-space-in-inden.patch
 deleted file mode 100644
 index 80b781c..0000000
@@ -2383,78 +2237,325 @@ index 80b781c..0000000
 - 		else
 - 			return MS(le32_to_cpu(eep->modalHeader5G.papdRateMaskHt40),
 - 				  AR9300_PAPRD_SCALE_1);
-diff --git a/package/kernel/mac80211/patches/308-ath10k-remove-duplicate-and-unused-rx-rate-flags.patch b/package/kernel/mac80211/patches/308-ath10k-remove-duplicate-and-unused-rx-rate-flags.patch
+diff --git a/package/kernel/mac80211/patches/307-mac80211-add-NEED_ALIGNED4_SKBS-hw-flag.patch b/package/kernel/mac80211/patches/307-mac80211-add-NEED_ALIGNED4_SKBS-hw-flag.patch
 new file mode 100644
-index 0000000..7c5c5be
+index 0000000..eeb881e
 --- /dev/null
-+++ b/package/kernel/mac80211/patches/308-ath10k-remove-duplicate-and-unused-rx-rate-flags.patch
-@@ -0,0 +1,66 @@
-+From: Mohammed Shafi Shajakhan <mohammed@qti.qualcomm.com>
-+Date: Thu, 2 Jun 2016 19:54:41 +0530
-+Subject: [PATCH] ath10k: remove duplicate and unused rx rate flags
++++ b/package/kernel/mac80211/patches/307-mac80211-add-NEED_ALIGNED4_SKBS-hw-flag.patch
+@@ -0,0 +1,235 @@
++From: Janusz Dziedzic <janusz.dziedzic@tieto.com>
++Date: Fri, 19 Feb 2016 11:01:50 +0100
++Subject: [PATCH] mac80211: add NEED_ALIGNED4_SKBS hw flag
 +
-+All these flags are not used and their use is completely
-+covered by 'ath10k_hw_rate_ofdm', 'ath10k_hw_rate_cck',
-+and RX_PPDU_START_RATE_FLAG
++HW/driver should set NEED_ALIGNED4_SKBS flag in case
++require aligned skbs to four-byte boundaries.
++This affect only TX direction.
 +
-+Signed-off-by: Mohammed Shafi Shajakhan <mohammed@qti.qualcomm.com>
++Padding is added after ieee80211_hdr, before IV/LLC.
++
++Before we have to do memmove(hdrlen) twice in the
++dirver. Once before we pass this to HW and next
++in tx completion (to be sure monitor will report
++this tx frame correctly).
++
++With this patch we can skip this memmove() and save CPU.
++
++Currently this was tested with ath9k, both hw/sw crypt for
++wep/tkip/ccmp.
++
++Signed-off-by: Janusz Dziedzic <janusz.dziedzic@tieto.com>
 +---
 +
-+--- a/drivers/net/wireless/ath/ath10k/rx_desc.h
-++++ b/drivers/net/wireless/ath/ath10k/rx_desc.h
-+@@ -656,26 +656,6 @@ struct rx_msdu_end {
-+  *		Reserved: HW should fill with zero.  FW should ignore.
++--- a/include/net/mac80211.h
+++++ b/include/net/mac80211.h
++@@ -2014,6 +2014,9 @@ struct ieee80211_txq {
++  * @IEEE80211_HW_TX_FRAG_LIST: Hardware (or driver) supports sending frag_list
++  *	skbs, needed for zero-copy software A-MSDU.
++  *
+++ * @IEEE80211_HW_NEEDS_ALIGNED4_SKBS: Driver need aligned skbs to four-byte.
+++ *	Padding will be added after ieee80211_hdr, before IV/LLC.
+++ *
++  * @NUM_IEEE80211_HW_FLAGS: number of hardware flags, used for sizing arrays
 +  */
++ enum ieee80211_hw_flags {
++@@ -2054,6 +2057,7 @@ enum ieee80211_hw_flags {
++ 	IEEE80211_HW_USES_RSS,
++ 	IEEE80211_HW_TX_AMSDU,
++ 	IEEE80211_HW_TX_FRAG_LIST,
+++	IEEE80211_HW_NEEDS_ALIGNED4_SKBS,
++ 
++ 	/* keep last, obviously */
++ 	NUM_IEEE80211_HW_FLAGS
++--- a/net/mac80211/debugfs.c
+++++ b/net/mac80211/debugfs.c
++@@ -302,6 +302,7 @@ static const char *hw_flag_names[] = {
++ 	FLAG(USES_RSS),
++ 	FLAG(TX_AMSDU),
++ 	FLAG(TX_FRAG_LIST),
+++	FLAG(NEEDS_ALIGNED4_SKBS),
++ #undef FLAG
++ };
 + 
-+-#define RX_PPDU_START_SIG_RATE_SELECT_OFDM 0
-+-#define RX_PPDU_START_SIG_RATE_SELECT_CCK  1
-+-
-+-#define RX_PPDU_START_SIG_RATE_OFDM_48 0
-+-#define RX_PPDU_START_SIG_RATE_OFDM_24 1
-+-#define RX_PPDU_START_SIG_RATE_OFDM_12 2
-+-#define RX_PPDU_START_SIG_RATE_OFDM_6  3
-+-#define RX_PPDU_START_SIG_RATE_OFDM_54 4
-+-#define RX_PPDU_START_SIG_RATE_OFDM_36 5
-+-#define RX_PPDU_START_SIG_RATE_OFDM_18 6
-+-#define RX_PPDU_START_SIG_RATE_OFDM_9  7
-+-
-+-#define RX_PPDU_START_SIG_RATE_CCK_LP_11  0
-+-#define RX_PPDU_START_SIG_RATE_CCK_LP_5_5 1
-+-#define RX_PPDU_START_SIG_RATE_CCK_LP_2   2
-+-#define RX_PPDU_START_SIG_RATE_CCK_LP_1   3
-+-#define RX_PPDU_START_SIG_RATE_CCK_SP_11  4
-+-#define RX_PPDU_START_SIG_RATE_CCK_SP_5_5 5
-+-#define RX_PPDU_START_SIG_RATE_CCK_SP_2   6
-+-
-+ #define HTT_RX_PPDU_START_PREAMBLE_LEGACY        0x04
-+ #define HTT_RX_PPDU_START_PREAMBLE_HT            0x08
-+ #define HTT_RX_PPDU_START_PREAMBLE_HT_WITH_TXBF  0x09
-+@@ -711,25 +691,6 @@ struct rx_msdu_end {
-+ /* No idea what this flag means. It seems to be always set in rate. */
-+ #define RX_PPDU_START_RATE_FLAG BIT(3)
-+ 
-+-enum rx_ppdu_start_rate {
-+-	RX_PPDU_START_RATE_OFDM_48M = RX_PPDU_START_RATE_FLAG | ATH10K_HW_RATE_OFDM_48M,
-+-	RX_PPDU_START_RATE_OFDM_24M = RX_PPDU_START_RATE_FLAG | ATH10K_HW_RATE_OFDM_24M,
-+-	RX_PPDU_START_RATE_OFDM_12M = RX_PPDU_START_RATE_FLAG | ATH10K_HW_RATE_OFDM_12M,
-+-	RX_PPDU_START_RATE_OFDM_6M  = RX_PPDU_START_RATE_FLAG | ATH10K_HW_RATE_OFDM_6M,
-+-	RX_PPDU_START_RATE_OFDM_54M = RX_PPDU_START_RATE_FLAG | ATH10K_HW_RATE_OFDM_54M,
-+-	RX_PPDU_START_RATE_OFDM_36M = RX_PPDU_START_RATE_FLAG | ATH10K_HW_RATE_OFDM_36M,
-+-	RX_PPDU_START_RATE_OFDM_18M = RX_PPDU_START_RATE_FLAG | ATH10K_HW_RATE_OFDM_18M,
-+-	RX_PPDU_START_RATE_OFDM_9M  = RX_PPDU_START_RATE_FLAG | ATH10K_HW_RATE_OFDM_9M,
-+-
-+-	RX_PPDU_START_RATE_CCK_LP_11M  = RX_PPDU_START_RATE_FLAG | ATH10K_HW_RATE_CCK_LP_11M,
-+-	RX_PPDU_START_RATE_CCK_LP_5_5M = RX_PPDU_START_RATE_FLAG | ATH10K_HW_RATE_CCK_LP_5_5M,
-+-	RX_PPDU_START_RATE_CCK_LP_2M   = RX_PPDU_START_RATE_FLAG | ATH10K_HW_RATE_CCK_LP_2M,
-+-	RX_PPDU_START_RATE_CCK_LP_1M   = RX_PPDU_START_RATE_FLAG | ATH10K_HW_RATE_CCK_LP_1M,
-+-	RX_PPDU_START_RATE_CCK_SP_11M  = RX_PPDU_START_RATE_FLAG | ATH10K_HW_RATE_CCK_SP_11M,
-+-	RX_PPDU_START_RATE_CCK_SP_5_5M = RX_PPDU_START_RATE_FLAG | ATH10K_HW_RATE_CCK_SP_5_5M,
-+-	RX_PPDU_START_RATE_CCK_SP_2M   = RX_PPDU_START_RATE_FLAG | ATH10K_HW_RATE_CCK_SP_2M,
-+-};
++--- a/net/mac80211/ieee80211_i.h
+++++ b/net/mac80211/ieee80211_i.h
++@@ -1497,6 +1497,29 @@ ieee80211_have_rx_timestamp(struct ieee8
++ 	return false;
++ }
++ 
+++static inline unsigned int
+++ieee80211_hdr_padsize(struct ieee80211_hw *hw, unsigned int hdrlen)
+++{
+++	/*
+++	 * While hdrlen is already aligned to two-byte boundaries,
+++	 * simple check with & 2 will return correct padsize.
+++	 */
+++	if (ieee80211_hw_check(hw, NEEDS_ALIGNED4_SKBS))
+++		return hdrlen & 2;
+++	return 0;
+++}
+++
+++static inline unsigned int
+++ieee80211_padded_hdrlen(struct ieee80211_hw *hw, __le16 fc)
+++{
+++	unsigned int hdrlen;
+++
+++	hdrlen = ieee80211_hdrlen(fc);
+++	hdrlen += ieee80211_hdr_padsize(hw, hdrlen);
+++
+++	return hdrlen;
+++}
+++
++ u64 ieee80211_calculate_rx_timestamp(struct ieee80211_local *local,
++ 				     struct ieee80211_rx_status *status,
++ 				     unsigned int mpdu_len,
++--- a/net/mac80211/sta_info.h
+++++ b/net/mac80211/sta_info.h
++@@ -279,7 +279,7 @@ struct ieee80211_fast_tx {
++ 	u8 hdr_len;
++ 	u8 sa_offs, da_offs, pn_offs;
++ 	u8 band;
++-	u8 hdr[30 + 2 + IEEE80211_FAST_XMIT_MAX_IV +
+++	u8 hdr[30 + 2 + 2 + IEEE80211_FAST_XMIT_MAX_IV +
++ 	       sizeof(rfc1042_header)] __aligned(2);
++ 
++ 	struct rcu_head rcu_head;
++--- a/net/mac80211/status.c
+++++ b/net/mac80211/status.c
++@@ -683,9 +683,22 @@ void ieee80211_tx_monitor(struct ieee802
++ 	struct sk_buff *skb2;
++ 	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
++ 	struct ieee80211_sub_if_data *sdata;
+++	struct ieee80211_hdr *hdr = (void *)skb->data;
++ 	struct net_device *prev_dev = NULL;
+++	unsigned int hdrlen, padsize;
++ 	int rtap_len;
++ 
+++	/* Remove padding if was added */
+++	if (ieee80211_hw_check(&local->hw, NEEDS_ALIGNED4_SKBS)) {
+++		hdrlen = ieee80211_hdrlen(hdr->frame_control);
+++		padsize = ieee80211_hdr_padsize(&local->hw, hdrlen);
+++
+++		if (padsize && skb->len > hdrlen + padsize) {
+++			memmove(skb->data + padsize, skb->data, hdrlen);
+++			skb_pull(skb, padsize);
+++		}
+++	}
+++
++ 	/* send frame to monitor interfaces now */
++ 	rtap_len = ieee80211_tx_radiotap_len(info);
++ 	if (WARN_ON_ONCE(skb_headroom(skb) < rtap_len)) {
++--- a/net/mac80211/tkip.c
+++++ b/net/mac80211/tkip.c
++@@ -201,10 +201,12 @@ void ieee80211_get_tkip_p2k(struct ieee8
++ {
++ 	struct ieee80211_key *key = (struct ieee80211_key *)
++ 			container_of(keyconf, struct ieee80211_key, conf);
+++	struct ieee80211_hw *hw = &key->local->hw;
++ 	const u8 *tk = &key->conf.key[NL80211_TKIP_DATA_OFFSET_ENCR_KEY];
++ 	struct tkip_ctx *ctx = &key->u.tkip.tx;
++ 	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
++-	const u8 *data = (u8 *)hdr + ieee80211_hdrlen(hdr->frame_control);
+++	const u8 *data = (u8 *)hdr + ieee80211_padded_hdrlen(hw,
+++							hdr->frame_control);
++ 	u32 iv32 = get_unaligned_le32(&data[4]);
++ 	u16 iv16 = data[2] | (data[0] << 8);
++ 
++--- a/net/mac80211/tx.c
+++++ b/net/mac80211/tx.c
++@@ -1173,8 +1173,7 @@ ieee80211_tx_prepare(struct ieee80211_su
++ 	info->flags &= ~IEEE80211_TX_INTFL_NEED_TXPROCESSING;
++ 
++ 	hdr = (struct ieee80211_hdr *) skb->data;
 +-
-+ struct rx_ppdu_start {
-+ 	struct {
-+ 		u8 pri20_mhz;
++-	tx->hdrlen = ieee80211_hdrlen(hdr->frame_control);
+++	tx->hdrlen = ieee80211_padded_hdrlen(&local->hw, hdr->frame_control);
++ 
++ 	if (likely(sta)) {
++ 		if (!IS_ERR(sta))
++@@ -2108,7 +2107,7 @@ netdev_tx_t ieee80211_monitor_start_xmit
++ 		goto fail;
++ 
++ 	hdr = (struct ieee80211_hdr *)(skb->data + len_rthdr);
++-	hdrlen = ieee80211_hdrlen(hdr->frame_control);
+++	hdrlen = ieee80211_padded_hdrlen(&local->hw, hdr->frame_control);
++ 
++ 	if (skb->len < len_rthdr + hdrlen)
++ 		goto fail;
++@@ -2334,7 +2333,7 @@ static struct sk_buff *ieee80211_build_h
++ 	struct ieee80211_chanctx_conf *chanctx_conf;
++ 	struct ieee80211_sub_if_data *ap_sdata;
++ 	enum nl80211_band band;
++-	int ret;
+++	int padsize, ret;
++ 
++ 	if (IS_ERR(sta))
++ 		sta = NULL;
++@@ -2554,6 +2553,9 @@ static struct sk_buff *ieee80211_build_h
++ 		hdrlen += 2;
++ 	}
++ 
+++	/* Check aligned4 skb required */
+++	padsize = ieee80211_hdr_padsize(&sdata->local->hw, hdrlen);
+++
++ 	/*
++ 	 * Drop unicast frames to unauthorised stations unless they are
++ 	 * EAPOL frames from the local station.
++@@ -2640,6 +2642,7 @@ static struct sk_buff *ieee80211_build_h
++ 	h_pos -= skip_header_bytes;
++ 
++ 	head_need = hdrlen + encaps_len + meshhdrlen - skb_headroom(skb);
+++	head_need += padsize;
++ 
++ 	/*
++ 	 * So we need to modify the skb header and hence need a copy of
++@@ -2678,6 +2681,9 @@ static struct sk_buff *ieee80211_build_h
++ 	}
++ #endif
++ 
+++	if (padsize)
+++		memset(skb_push(skb, padsize), 0, padsize);
+++
++ 	if (ieee80211_is_data_qos(fc)) {
++ 		__le16 *qos_control;
++ 
++@@ -2691,8 +2697,8 @@ static struct sk_buff *ieee80211_build_h
++ 	} else
++ 		memcpy(skb_push(skb, hdrlen), &hdr, hdrlen);
++ 
++-	nh_pos += hdrlen;
++-	h_pos += hdrlen;
+++	nh_pos += hdrlen + padsize;
+++	h_pos += hdrlen + padsize;
++ 
++ 	/* Update skb pointers to various headers since this modified frame
++ 	 * is going to go through Linux networking code that may potentially
++@@ -2861,6 +2867,9 @@ void ieee80211_check_fast_xmit(struct st
++ 		fc |= cpu_to_le16(IEEE80211_STYPE_QOS_DATA);
++ 	}
++ 
+++	/* Check aligned4 skb required */
+++	build.hdr_len += ieee80211_hdr_padsize(&local->hw, build.hdr_len);
+++
++ 	/* We store the key here so there's no point in using rcu_dereference()
++ 	 * but that's fine because the code that changes the pointers will call
++ 	 * this function after doing so. For a single CPU that would be enough,
++--- a/net/mac80211/util.c
+++++ b/net/mac80211/util.c
++@@ -1224,6 +1224,7 @@ void ieee80211_send_auth(struct ieee8021
++ 			 u32 tx_flags)
++ {
++ 	struct ieee80211_local *local = sdata->local;
+++	struct ieee80211_hw *hw = &local->hw;
++ 	struct sk_buff *skb;
++ 	struct ieee80211_mgmt *mgmt;
++ 	unsigned int hdrlen;
++@@ -1251,7 +1252,7 @@ void ieee80211_send_auth(struct ieee8021
++ 		memcpy(skb_put(skb, extra_len), extra, extra_len);
++ 
++ 	if (auth_alg == WLAN_AUTH_SHARED_KEY && transaction == 3) {
++-		hdrlen = ieee80211_hdrlen(mgmt->frame_control);
+++		hdrlen = ieee80211_padded_hdrlen(hw, mgmt->frame_control);
++ 		mgmt->frame_control |= cpu_to_le16(IEEE80211_FCTL_PROTECTED);
++ 		err = ieee80211_wep_encrypt(local, skb, hdrlen, key,
++ 					    key_len, key_idx);
+diff --git a/package/kernel/mac80211/patches/308-ath10k-Fix-sending-NULL-Qos-NULL-data-frames-for-QCA.patch b/package/kernel/mac80211/patches/308-ath10k-Fix-sending-NULL-Qos-NULL-data-frames-for-QCA.patch
+new file mode 100644
+index 0000000..8590aad
+--- /dev/null
++++ b/package/kernel/mac80211/patches/308-ath10k-Fix-sending-NULL-Qos-NULL-data-frames-for-QCA.patch
+@@ -0,0 +1,72 @@
++From: Mohammed Shafi Shajakhan <mohammed@qti.qualcomm.com>
++Date: Thu, 23 Jun 2016 22:10:01 +0530
++Subject: [PATCH] ath10k: Fix sending NULL/ Qos NULL data frames for
++ QCA99X0 and later
++
++For chipsets like QCA99X0, IPQ4019 and later we are not getting proper
++NULL func status (always acked/successs !!) when hostapd does a
++PROBE_CLIENT via nullfunc frames when the station is powered off
++abruptly (inactive timer probes client via null func after the inactive
++time reaches beyond the threshold). Fix this by disabling the workaround
++(getting the ACK status of NULL func frames by sending via HTT mgmt-tx
++ path) introduced by the change ("ath10k: fix beacon loss handling ")
++for QCA99X0 and later chipsets. The normal tx path provides the proper
++ACK status for NULL data frames. As of now disable this workaround for
++chipsets QCA99X0 and later, once the 10.1 firmware is obselete we can
++completely get rid of this workaround for all the chipsets
++
++Signed-off-by: Tamizh chelvam <c_traja@qti.qualcomm.com>
++Signed-off-by: Mohammed Shafi Shajakhan <mohammed@qti.qualcomm.com>
++---
++
++--- a/drivers/net/wireless/ath/ath10k/core.c
+++++ b/drivers/net/wireless/ath/ath10k/core.c
++@@ -181,6 +181,7 @@ static const struct ath10k_hw_params ath
++ 			.board = QCA99X0_HW_2_0_BOARD_DATA_FILE,
++ 			.board_size = QCA99X0_BOARD_DATA_SZ,
++ 			.board_ext_size = QCA99X0_BOARD_EXT_DATA_SZ,
+++			.disable_null_func_workaround = true,
++ 		},
++ 	},
++ 	{
++@@ -204,6 +205,7 @@ static const struct ath10k_hw_params ath
++ 			.board = QCA9984_HW_1_0_BOARD_DATA_FILE,
++ 			.board_size = QCA99X0_BOARD_DATA_SZ,
++ 			.board_ext_size = QCA99X0_BOARD_EXT_DATA_SZ,
+++			.disable_null_func_workaround = true,
++ 		},
++ 	},
++ 	{
++@@ -262,6 +264,7 @@ static const struct ath10k_hw_params ath
++ 			.board = QCA4019_HW_1_0_BOARD_DATA_FILE,
++ 			.board_size = QCA4019_BOARD_DATA_SZ,
++ 			.board_ext_size = QCA4019_BOARD_EXT_DATA_SZ,
+++			.disable_null_func_workaround = true,
++ 		},
++ 	},
++ };
++--- a/drivers/net/wireless/ath/ath10k/core.h
+++++ b/drivers/net/wireless/ath/ath10k/core.h
++@@ -750,6 +750,12 @@ struct ath10k {
++ 			const char *board;
++ 			size_t board_size;
++ 			size_t board_ext_size;
+++			/* Workaround of sending NULL data frames via
+++			 * HTT mgmt TX and getting the proper ACK status does
+++			 * not works for chipsets QCA99X0 and later, while
+++			 * Tx data path reports the ACK status properly.
+++			 */
+++			bool disable_null_func_workaround;
++ 		} fw;
++ 	} hw_params;
++ 
++--- a/drivers/net/wireless/ath/ath10k/mac.c
+++++ b/drivers/net/wireless/ath/ath10k/mac.c
++@@ -3253,6 +3253,7 @@ ath10k_mac_tx_h_get_txmode(struct ath10k
++ 	 * mode though because AP don't sleep.
++ 	 */
++ 	if (ar->htt.target_version_major < 3 &&
+++	    !ar->hw_params.fw.disable_null_func_workaround &&
++ 	    (ieee80211_is_nullfunc(fc) || ieee80211_is_qos_nullfunc(fc)) &&
++ 	    !test_bit(ATH10K_FW_FEATURE_HAS_WMI_MGMT_TX,
++ 		      ar->running_fw->fw_file.fw_features))
 diff --git a/package/kernel/mac80211/patches/308-ath9k-fix-data-bus-error-on-ar9300-and-ar9580.patch b/package/kernel/mac80211/patches/308-ath9k-fix-data-bus-error-on-ar9300-and-ar9580.patch
 deleted file mode 100644
 index d408866..0000000
@@ -2675,225 +2776,48 @@ index 711e019..0000000
 - void brcmf_sdiod_change_state(struct brcmf_sdio_dev *sdiodev,
 - 			      enum brcmf_sdiod_state state);
 - #ifdef CONFIG_PM_SLEEP
-diff --git a/package/kernel/mac80211/patches/309-ath10k-fix-CCK-h-w-rates-for-QCA99X0-and-newer-chips.patch b/package/kernel/mac80211/patches/309-ath10k-fix-CCK-h-w-rates-for-QCA99X0-and-newer-chips.patch
+diff --git a/package/kernel/mac80211/patches/309-cfg80211-fix-proto-in-ieee80211_data_to_8023-for-fra.patch b/package/kernel/mac80211/patches/309-cfg80211-fix-proto-in-ieee80211_data_to_8023-for-fra.patch
 new file mode 100644
-index 0000000..50ebfce
+index 0000000..41c27ca
 --- /dev/null
-+++ b/package/kernel/mac80211/patches/309-ath10k-fix-CCK-h-w-rates-for-QCA99X0-and-newer-chips.patch
-@@ -0,0 +1,141 @@
-+From: Mohammed Shafi Shajakhan <mohammed@qti.qualcomm.com>
-+Date: Thu, 2 Jun 2016 19:54:42 +0530
-+Subject: [PATCH] ath10k: fix CCK h/w rates for QCA99X0 and newer chipsets
-+
-+CCK hardware table mapping from QCA99X0 onwards got revised.
-+The CCK hardware rate values are in a proper order wrt. to
-+rate and preamble as below
-+
-+ATH10K_HW_RATE_REV2_CCK_LP_1M = 1,
-+ATH10K_HW_RATE_REV2_CCK_LP_2M = 2,
-+ATH10K_HW_RATE_REV2_CCK_LP_5_5M = 3,
-+ATH10K_HW_RATE_REV2_CCK_LP_11M = 4,
-+ATH10K_HW_RATE_REV2_CCK_SP_2M = 5,
-+ATH10K_HW_RATE_REV2_CCK_SP_5_5M = 6,
-+ATH10K_HW_RATE_REV2_CCK_SP_11M = 7,
-+
-+This results in reporting of rx frames (with CCK rates)
-+totally wrong for QCA99X0, QCA4019. Fix this by having
-+separate CCK rate table for these chipsets with rev2 suffix
-+and registering the correct rate mapping to mac80211 based on
-+the new hw_param (introduced) 'cck_rate_map_rev2' which shall
-+be true for any newchipsets from QCA99X0 onwards
++++ b/package/kernel/mac80211/patches/309-cfg80211-fix-proto-in-ieee80211_data_to_8023-for-fra.patch
+@@ -0,0 +1,37 @@
++From: Felix Fietkau <nbd@nbd.name>
++Date: Wed, 29 Jun 2016 10:02:32 +0200
++Subject: [PATCH] cfg80211: fix proto in ieee80211_data_to_8023 for frames
++ without LLC header
 +
-+Signed-off-by: Mohammed Shafi Shajakhan <mohammed@qti.qualcomm.com>
-+---
++The PDU length of incoming LLC frames is set to the total skb payload size
++in __ieee80211_data_to_8023() of net/wireless/util.c which incorrectly
++includes the length of the IEEE 802.11 header.
 +
-+--- a/drivers/net/wireless/ath/ath10k/core.c
-++++ b/drivers/net/wireless/ath/ath10k/core.c
-+@@ -148,6 +148,8 @@ static const struct ath10k_hw_params ath
-+ 		.uart_pin = 7,
-+ 		.otp_exe_param = 0x00000700,
-+ 		.continuous_frag_desc = true,
-++		.cck_rate_map_rev2 = true,
-++		.cck_rate_map_rev2 = true,
-+ 		.channel_counters_freq_hz = 150000,
-+ 		.max_probe_resp_desc_thres = 24,
-+ 		.hw_4addr_pad = ATH10K_HW_4ADDR_PAD_BEFORE,
-+@@ -205,6 +207,7 @@ static const struct ath10k_hw_params ath
-+ 		.has_shifted_cc_wraparound = true,
-+ 		.otp_exe_param = 0x0010000,
-+ 		.continuous_frag_desc = true,
-++		.cck_rate_map_rev2 = true,
-+ 		.channel_counters_freq_hz = 125000,
-+ 		.max_probe_resp_desc_thres = 24,
-+ 		.hw_4addr_pad = ATH10K_HW_4ADDR_PAD_BEFORE,
-+--- a/drivers/net/wireless/ath/ath10k/core.h
-++++ b/drivers/net/wireless/ath/ath10k/core.h
-+@@ -716,6 +716,12 @@ struct ath10k {
-+ 		 */
-+ 		bool continuous_frag_desc;
-+ 
-++		/* CCK hardware rate table mapping for the newer chipsets
-++		 * like QCA99X0, QCA4019 got revised. The CCK h/w rate values
-++		 * are in a proper order with respect to the rate/preamble
-++		 */
-++		bool cck_rate_map_rev2;
-++
-+ 		u32 channel_counters_freq_hz;
-+ 
-+ 		/* Mgmt tx descriptors threshold for limiting probe response
-+--- a/drivers/net/wireless/ath/ath10k/hw.h
-++++ b/drivers/net/wireless/ath/ath10k/hw.h
-+@@ -315,6 +315,16 @@ enum ath10k_hw_rate_cck {
-+ 	ATH10K_HW_RATE_CCK_SP_2M,
-+ };
-+ 
-++enum ath10k_hw_rate_rev2_cck {
-++	ATH10K_HW_RATE_REV2_CCK_LP_1M = 1,
-++	ATH10K_HW_RATE_REV2_CCK_LP_2M,
-++	ATH10K_HW_RATE_REV2_CCK_LP_5_5M,
-++	ATH10K_HW_RATE_REV2_CCK_LP_11M,
-++	ATH10K_HW_RATE_REV2_CCK_SP_2M,
-++	ATH10K_HW_RATE_REV2_CCK_SP_5_5M,
-++	ATH10K_HW_RATE_REV2_CCK_SP_11M,
-++};
-++
-+ enum ath10k_hw_4addr_pad {
-+ 	ATH10K_HW_4ADDR_PAD_AFTER,
-+ 	ATH10K_HW_4ADDR_PAD_BEFORE,
-+--- a/drivers/net/wireless/ath/ath10k/mac.c
-++++ b/drivers/net/wireless/ath/ath10k/mac.c
-+@@ -62,6 +62,32 @@ static struct ieee80211_rate ath10k_rate
-+ 	{ .bitrate = 540, .hw_value = ATH10K_HW_RATE_OFDM_54M },
-+ };
-+ 
-++static struct ieee80211_rate ath10k_rates_rev2[] = {
-++	{ .bitrate = 10,
-++	  .hw_value = ATH10K_HW_RATE_REV2_CCK_LP_1M },
-++	{ .bitrate = 20,
-++	  .hw_value = ATH10K_HW_RATE_REV2_CCK_LP_2M,
-++	  .hw_value_short = ATH10K_HW_RATE_REV2_CCK_SP_2M,
-++	  .flags = IEEE80211_RATE_SHORT_PREAMBLE },
-++	{ .bitrate = 55,
-++	  .hw_value = ATH10K_HW_RATE_REV2_CCK_LP_5_5M,
-++	  .hw_value_short = ATH10K_HW_RATE_REV2_CCK_SP_5_5M,
-++	  .flags = IEEE80211_RATE_SHORT_PREAMBLE },
-++	{ .bitrate = 110,
-++	  .hw_value = ATH10K_HW_RATE_REV2_CCK_LP_11M,
-++	  .hw_value_short = ATH10K_HW_RATE_REV2_CCK_SP_11M,
-++	  .flags = IEEE80211_RATE_SHORT_PREAMBLE },
-++
-++	{ .bitrate = 60, .hw_value = ATH10K_HW_RATE_OFDM_6M },
-++	{ .bitrate = 90, .hw_value = ATH10K_HW_RATE_OFDM_9M },
-++	{ .bitrate = 120, .hw_value = ATH10K_HW_RATE_OFDM_12M },
-++	{ .bitrate = 180, .hw_value = ATH10K_HW_RATE_OFDM_18M },
-++	{ .bitrate = 240, .hw_value = ATH10K_HW_RATE_OFDM_24M },
-++	{ .bitrate = 360, .hw_value = ATH10K_HW_RATE_OFDM_36M },
-++	{ .bitrate = 480, .hw_value = ATH10K_HW_RATE_OFDM_48M },
-++	{ .bitrate = 540, .hw_value = ATH10K_HW_RATE_OFDM_54M },
-++};
-++
-+ #define ATH10K_MAC_FIRST_OFDM_RATE_IDX 4
-+ 
-+ #define ath10k_a_rates (ath10k_rates + ATH10K_MAC_FIRST_OFDM_RATE_IDX)
-+@@ -70,6 +96,9 @@ static struct ieee80211_rate ath10k_rate
-+ #define ath10k_g_rates (ath10k_rates + 0)
-+ #define ath10k_g_rates_size (ARRAY_SIZE(ath10k_rates))
-+ 
-++#define ath10k_g_rates_rev2 (ath10k_rates_rev2 + 0)
-++#define ath10k_g_rates_rev2_size (ARRAY_SIZE(ath10k_rates_rev2))
-++
-+ static bool ath10k_mac_bitrate_is_cck(int bitrate)
-+ {
-+ 	switch (bitrate) {
-+@@ -7720,8 +7749,14 @@ int ath10k_mac_register(struct ath10k *a
-+ 		band = &ar->mac.sbands[NL80211_BAND_2GHZ];
-+ 		band->n_channels = ARRAY_SIZE(ath10k_2ghz_channels);
-+ 		band->channels = channels;
-+-		band->n_bitrates = ath10k_g_rates_size;
-+-		band->bitrates = ath10k_g_rates;
-++
-++		if (ar->hw_params.cck_rate_map_rev2) {
-++			band->n_bitrates = ath10k_g_rates_rev2_size;
-++			band->bitrates = ath10k_g_rates_rev2;
-++		} else {
-++			band->n_bitrates = ath10k_g_rates_size;
-++			band->bitrates = ath10k_g_rates;
-++		}
-+ 
-+ 		ar->hw->wiphy->bands[NL80211_BAND_2GHZ] = band;
-+ 	}
-diff --git a/package/kernel/mac80211/patches/310-ath10k-improve-tx-scheduling.patch b/package/kernel/mac80211/patches/310-ath10k-improve-tx-scheduling.patch
-new file mode 100644
-index 0000000..81ac2db
---- /dev/null
-+++ b/package/kernel/mac80211/patches/310-ath10k-improve-tx-scheduling.patch
-@@ -0,0 +1,67 @@
-+From: Michal Kazior <michal.kazior@tieto.com>
-+Date: Mon, 23 May 2016 23:12:45 +0300
-+Subject: [PATCH] ath10k: improve tx scheduling
++The resulting LLC frame header has a too large PDU length, causing the
++llc_fixup_skb() function of net/llc/llc_input.c to reject the incoming
++skb, effectively breaking STP.
 +
-+Recent changes revolving around implementing
-+wake_tx_queue support introduced a significant
-+performance regressions on some (slower, uni-proc)
-+systems.
++Solve the problem by properly substracting the IEEE 802.11 frame header size
++from the PDU length, allowing the LLC processor to pick up the incoming
++control messages.
 +
-+Signed-off-by: Michal Kazior <michal.kazior@tieto.com>
-+Signed-off-by: Kalle Valo <kvalo@qca.qualcomm.com>
++Special thanks to Gerry Rozema for tracking down the regression and proposing
++a suitable patch.
++
++Fixes: 2d1c304cb2d5 ("cfg80211: add function for 802.3 conversion with separate output buffer")
++Cc: stable@vger.kernel.org
++Reported-by: Gerry Rozema <gerryr@rozeware.com>
++Signed-off-by: Felix Fietkau <nbd@nbd.name>
 +---
 +
-+--- a/drivers/net/wireless/ath/ath10k/htt_rx.c
-++++ b/drivers/net/wireless/ath/ath10k/htt_rx.c
-+@@ -2291,7 +2291,6 @@ bool ath10k_htt_t2h_msg_handler(struct a
-+ 			ath10k_htt_tx_mgmt_dec_pending(htt);
-+ 			spin_unlock_bh(&htt->tx_lock);
-+ 		}
-+-		ath10k_mac_tx_push_pending(ar);
-+ 		break;
-+ 	}
-+ 	case HTT_T2H_MSG_TYPE_TX_COMPL_IND:
-+@@ -2442,8 +2441,6 @@ static void ath10k_htt_txrx_compl_task(u
-+ 		dev_kfree_skb_any(skb);
-+ 	}
-+ 
-+-	ath10k_mac_tx_push_pending(ar);
-+-
-+ 	num_mpdus = atomic_read(&htt->num_mpdus_ready);
-+ 
-+ 	while (num_mpdus) {
-+--- a/drivers/net/wireless/ath/ath10k/mac.c
-++++ b/drivers/net/wireless/ath/ath10k/mac.c
-+@@ -3827,6 +3827,9 @@ void ath10k_mac_tx_push_pending(struct a
-+ 	int ret;
-+ 	int max;
-+ 
-++	if (ar->htt.num_pending_tx >= (ar->htt.max_num_pending_tx / 2))
-++		return;
-++
-+ 	spin_lock_bh(&ar->txqs_lock);
-+ 	rcu_read_lock();
-+ 
-+@@ -4097,9 +4100,7 @@ static void ath10k_mac_op_wake_tx_queue(
-+ 		list_add_tail(&artxq->list, &ar->txqs);
-+ 	spin_unlock_bh(&ar->txqs_lock);
-+ 
-+-	if (ath10k_mac_tx_can_push(hw, txq))
-+-		tasklet_schedule(&ar->htt.txrx_compl_task);
-+-
-++	ath10k_mac_tx_push_pending(ar);
-+ 	ath10k_htt_tx_txq_update(hw, txq);
-+ }
-+ 
-+--- a/drivers/net/wireless/ath/ath10k/txrx.c
-++++ b/drivers/net/wireless/ath/ath10k/txrx.c
-+@@ -117,6 +117,9 @@ int ath10k_txrx_tx_unref(struct ath10k_h
++--- a/net/wireless/util.c
+++++ b/net/wireless/util.c
++@@ -509,7 +509,7 @@ static int __ieee80211_data_to_8023(stru
++ 		 * replace EtherType */
++ 		hdrlen += ETH_ALEN + 2;
++ 	else
++-		tmp.h_proto = htons(skb->len);
+++		tmp.h_proto = htons(skb->len - hdrlen);
 + 
-+ 	ieee80211_tx_status(htt->ar->hw, msdu);
-+ 	/* we do not own the msdu anymore */
-++
-++	ath10k_mac_tx_push_pending(ar);
-++
-+ 	return 0;
-+ }
++ 	pskb_pull(skb, hdrlen);
 + 
 diff --git a/package/kernel/mac80211/patches/310-ath9k_hw-ignore-eeprom-magic-mismatch-on-flash-based.patch b/package/kernel/mac80211/patches/310-ath9k_hw-ignore-eeprom-magic-mismatch-on-flash-based.patch
 deleted file mode 100644
@@ -2939,71 +2863,172 @@ index 287d6e1..0000000
 - 		ath_err(common,
 - 			"Invalid EEPROM Magic (0x%04x).\n", magic);
 - 		return -EINVAL;
-diff --git a/package/kernel/mac80211/patches/311-ath10k-fix-deadlock-while-processing-rx_in_ord_ind.patch b/package/kernel/mac80211/patches/311-ath10k-fix-deadlock-while-processing-rx_in_ord_ind.patch
+diff --git a/package/kernel/mac80211/patches/310-mac80211-minstrel-Enable-STBC-and-LDPC-for-VHT-Rates.patch b/package/kernel/mac80211/patches/310-mac80211-minstrel-Enable-STBC-and-LDPC-for-VHT-Rates.patch
+new file mode 100644
+index 0000000..25929c9
+--- /dev/null
++++ b/package/kernel/mac80211/patches/310-mac80211-minstrel-Enable-STBC-and-LDPC-for-VHT-Rates.patch
+@@ -0,0 +1,81 @@
++From: Chaitanya T K <chaitanya.mgit@gmail.com>
++Date: Mon, 27 Jun 2016 15:23:26 +0530
++Subject: [PATCH] mac80211: minstrel: Enable STBC and LDPC for VHT Rates
++
++If peer support reception of STBC and LDPC, enable them for better
++performance.
++
++Signed-off-by: Chaitanya TK <chaitanya.mgit@gmail.com>
++---
++
++--- a/include/linux/ieee80211.h
+++++ b/include/linux/ieee80211.h
++@@ -1550,6 +1550,7 @@ struct ieee80211_vht_operation {
++ #define IEEE80211_VHT_CAP_RXSTBC_3				0x00000300
++ #define IEEE80211_VHT_CAP_RXSTBC_4				0x00000400
++ #define IEEE80211_VHT_CAP_RXSTBC_MASK				0x00000700
+++#define IEEE80211_VHT_CAP_RXSTBC_SHIFT				8
++ #define IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE			0x00000800
++ #define IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE			0x00001000
++ #define IEEE80211_VHT_CAP_BEAMFORMEE_STS_SHIFT                  13
++--- a/net/mac80211/rc80211_minstrel_ht.c
+++++ b/net/mac80211/rc80211_minstrel_ht.c
++@@ -1166,13 +1166,14 @@ minstrel_ht_update_caps(void *priv, stru
++ 	struct minstrel_ht_sta_priv *msp = priv_sta;
++ 	struct minstrel_ht_sta *mi = &msp->ht;
++ 	struct ieee80211_mcs_info *mcs = &sta->ht_cap.mcs;
++-	u16 sta_cap = sta->ht_cap.cap;
+++	u16 ht_cap = sta->ht_cap.cap;
++ 	struct ieee80211_sta_vht_cap *vht_cap = &sta->vht_cap;
++ 	int use_vht;
++ 	int n_supported = 0;
++ 	int ack_dur;
++ 	int stbc;
++ 	int i;
+++	bool ldpc = false;
++ 
++ 	/* fall back to the old minstrel for legacy stations */
++ 	if (!sta->ht_cap.ht_supported)
++@@ -1210,16 +1211,24 @@ minstrel_ht_update_caps(void *priv, stru
++ 	}
++ 	mi->sample_tries = 4;
++ 
++-	/* TODO tx_flags for vht - ATM the RC API is not fine-grained enough */
++ 	if (!use_vht) {
++-		stbc = (sta_cap & IEEE80211_HT_CAP_RX_STBC) >>
+++		stbc = (ht_cap & IEEE80211_HT_CAP_RX_STBC) >>
++ 			IEEE80211_HT_CAP_RX_STBC_SHIFT;
++-		mi->tx_flags |= stbc << IEEE80211_TX_CTL_STBC_SHIFT;
++ 
++-		if (sta_cap & IEEE80211_HT_CAP_LDPC_CODING)
++-			mi->tx_flags |= IEEE80211_TX_CTL_LDPC;
+++		if (ht_cap & IEEE80211_HT_CAP_LDPC_CODING)
+++			ldpc = true;
+++	} else {
+++		stbc = (vht_cap->cap & IEEE80211_VHT_CAP_RXSTBC_MASK) >>
+++			IEEE80211_VHT_CAP_RXSTBC_SHIFT;
+++
+++		if (vht_cap->cap & IEEE80211_VHT_CAP_RXLDPC)
+++			ldpc = true;
++ 	}
++ 
+++	mi->tx_flags |= stbc << IEEE80211_TX_CTL_STBC_SHIFT;
+++	if (ldpc)
+++		mi->tx_flags |= IEEE80211_TX_CTL_LDPC;
+++
++ 	for (i = 0; i < ARRAY_SIZE(mi->groups); i++) {
++ 		u32 gflags = minstrel_mcs_groups[i].flags;
++ 		int bw, nss;
++@@ -1232,10 +1241,10 @@ minstrel_ht_update_caps(void *priv, stru
++ 
++ 		if (gflags & IEEE80211_TX_RC_SHORT_GI) {
++ 			if (gflags & IEEE80211_TX_RC_40_MHZ_WIDTH) {
++-				if (!(sta_cap & IEEE80211_HT_CAP_SGI_40))
+++				if (!(ht_cap & IEEE80211_HT_CAP_SGI_40))
++ 					continue;
++ 			} else {
++-				if (!(sta_cap & IEEE80211_HT_CAP_SGI_20))
+++				if (!(ht_cap & IEEE80211_HT_CAP_SGI_20))
++ 					continue;
++ 			}
++ 		}
+diff --git a/package/kernel/mac80211/patches/311-ath10k-disable-wake_tx_queue-for-older-devices.patch b/package/kernel/mac80211/patches/311-ath10k-disable-wake_tx_queue-for-older-devices.patch
 new file mode 100644
-index 0000000..3664d70
+index 0000000..4cf26a6
 --- /dev/null
-+++ b/package/kernel/mac80211/patches/311-ath10k-fix-deadlock-while-processing-rx_in_ord_ind.patch
-@@ -0,0 +1,59 @@
-+From: Rajkumar Manoharan <rmanohar@qti.qualcomm.com>
-+Date: Thu, 9 Jun 2016 11:33:55 +0530
-+Subject: [PATCH] ath10k: fix deadlock while processing rx_in_ord_ind
-+
-+commit 5c86d97bcc1d ("ath10k: combine txrx and replenish task")
-+introduced deadlock while processing rx in order indication message
-+for qca6174 based devices. While merging replenish and txrx tasklets,
-+replenish task should be called out of htt rx ring locking since it
-+is also try to acquire the same lock.
-+
-+Unfortunately this issue is not exposed by other solutions (qca988x,
-+qca99x0 & qca4019), as rx_in_ord_ind message is specific to qca6174
-+based devices. This patch fixes
-+
-+=============================================
-+[ INFO: possible recursive locking detected ]
-+4.7.0-rc2-wt-ath+ #1353 Tainted: G            E
-+---------------------------------------------
-+swapper/3/0 is trying to acquire lock:
-+ (&(&htt->rx_ring.lock)->rlock){+.-...}, at: [<f8d7ef19>]
-+ath10k_htt_rx_msdu_buff_replenish+0x29/0x90 [ath10k_core]
-+
-+but task is already holding lock:
-+ (&(&htt->rx_ring.lock)->rlock){+.-...}, at: [<f8d82cab>]
-+ath10k_htt_txrx_compl_task+0x21b/0x250 [ath10k_core]
-+
-+other info that might help us debug this:
-+ Possible unsafe locking scenario:
-+
-+       CPU0
-+       ----
-+  lock(&(&htt->rx_ring.lock)->rlock);
-+  lock(&(&htt->rx_ring.lock)->rlock);
-+
-+ *** DEADLOCK ***
-+
-+ May be due to missing lock nesting notation
-+
-+1 lock held by swapper/3/0:
-+ #0:  (&(&htt->rx_ring.lock)->rlock){+.-...}, at: [<f8d82cab>]
-+ath10k_htt_txrx_compl_task+0x21b/0x250 [ath10k_core]
-+
-+Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=119151
-+Fixes: 5c86d97bcc1d ("ath10k: combine txrx and replenish task")
-+Reported-by: Mike Lothian <mike@fireburn.co.uk>
-+Signed-off-by: Rajkumar Manoharan <rmanohar@qti.qualcomm.com>
-+Signed-off-by: Kalle Valo <kvalo@qca.qualcomm.com>
++++ b/package/kernel/mac80211/patches/311-ath10k-disable-wake_tx_queue-for-older-devices.patch
+@@ -0,0 +1,73 @@
++From: Michal Kazior <michal.kazior@tieto.com>
++Date: Tue, 17 May 2016 14:47:01 +0200
++Subject: [PATCH] ath10k: disable wake_tx_queue for older devices
++
++Some setups suffer performance regressions with
++current wake_tx_queue implementation.
++
++Signed-off-by: Michal Kazior <michal.kazior@tieto.com>
 +---
 +
-+--- a/drivers/net/wireless/ath/ath10k/htt_rx.c
-++++ b/drivers/net/wireless/ath/ath10k/htt_rx.c
-+@@ -1904,7 +1904,6 @@ static void ath10k_htt_rx_in_ord_ind(str
-+ 			return;
-+ 		}
-+ 	}
-+-	ath10k_htt_rx_msdu_buff_replenish(htt);
++--- a/drivers/net/wireless/ath/ath10k/core.h
+++++ b/drivers/net/wireless/ath/ath10k/core.h
++@@ -667,6 +667,7 @@ struct ath10k_fw_components {
++ struct ath10k {
++ 	struct ath_common ath_common;
++ 	struct ieee80211_hw *hw;
+++	struct ieee80211_ops *ops;
++ 	struct device *dev;
++ 	u8 mac_addr[ETH_ALEN];
++ 
++--- a/drivers/net/wireless/ath/ath10k/mac.c
+++++ b/drivers/net/wireless/ath/ath10k/mac.c
++@@ -7497,21 +7497,32 @@ static const struct ieee80211_channel at
++ struct ath10k *ath10k_mac_create(size_t priv_size)
++ {
++ 	struct ieee80211_hw *hw;
+++	struct ieee80211_ops *ops;
++ 	struct ath10k *ar;
++ 
++-	hw = ieee80211_alloc_hw(sizeof(struct ath10k) + priv_size, &ath10k_ops);
++-	if (!hw)
+++	ops = kmemdup(&ath10k_ops, sizeof(ath10k_ops), GFP_KERNEL);
+++	if (!ops)
+++		return NULL;
+++
+++	hw = ieee80211_alloc_hw(sizeof(struct ath10k) + priv_size, ops);
+++	if (!hw) {
+++		kfree(ops);
++ 		return NULL;
+++	}
++ 
++ 	ar = hw->priv;
++ 	ar->hw = hw;
+++	ar->ops = ops;
++ 
++ 	return ar;
++ }
++ 
++ void ath10k_mac_destroy(struct ath10k *ar)
++ {
+++	struct ieee80211_ops *ops = ar->ops;
+++
++ 	ieee80211_free_hw(ar->hw);
+++	kfree(ops);
 + }
 + 
-+ static void ath10k_htt_rx_tx_fetch_resp_id_confirm(struct ath10k *ar,
++ static const struct ieee80211_iface_limit ath10k_if_limits[] = {
++@@ -7945,6 +7956,15 @@ int ath10k_mac_register(struct ath10k *a
++ 			ath10k_warn(ar, "failed to initialise DFS pattern detector\n");
++ 	}
++ 
+++	/* Current wake_tx_queue implementation imposes a significant
+++	 * performance penalty in some setups. The tx scheduling code needs
+++	 * more work anyway so disable the wake_tx_queue unless firmware
+++	 * supports the pull-push mechanism.
+++	 */
+++	if (!test_bit(ATH10K_FW_FEATURE_PEER_FLOW_CONTROL,
+++		      ar->running_fw->fw_file.fw_features))
+++		ar->ops->wake_tx_queue = NULL;
+++
++ 	ret = ath_regd_init(&ar->ath_common.regulatory, ar->hw->wiphy,
++ 			    ath10k_reg_notifier);
++ 	if (ret) {
 diff --git a/package/kernel/mac80211/patches/311-ath9k-do-not-limit-the-number-of-DFS-interfaces-to-1.patch b/package/kernel/mac80211/patches/311-ath9k-do-not-limit-the-number-of-DFS-interfaces-to-1.patch
 deleted file mode 100644
 index 070efa9..0000000
@@ -3065,6 +3090,57 @@ index 070efa9..0000000
 - };
 - 
 - #ifdef CPTCFG_ATH9K_CHANNEL_CONTEXT
+diff --git a/package/kernel/mac80211/patches/312-ath9k-Correct-TSF-adjustment-to-align-the-beacon-tim.patch b/package/kernel/mac80211/patches/312-ath9k-Correct-TSF-adjustment-to-align-the-beacon-tim.patch
+new file mode 100644
+index 0000000..df43105
+--- /dev/null
++++ b/package/kernel/mac80211/patches/312-ath9k-Correct-TSF-adjustment-to-align-the-beacon-tim.patch
+@@ -0,0 +1,45 @@
++From: Benjamin Berg <benjamin.berg@open-mesh.com>
++Date: Mon, 4 Jul 2016 14:37:20 +0200
++Subject: [PATCH] ath9k: Correct TSF adjustment to align the beacon time
++ correctly
++
++Beacons were not send out at (timestamp % beacon_time == 0) for interfaces
++other than the primary one. To send out beacons with the correct timestamp
++according to 10.1.3.2 of the 802.11 standard the tsf_adjustment has to be
++set to the negative time difference instead of positive. This way the
++later beacons get corrected to have a lower (and similar) timestamp with
++regard to the beacon from slot 0.
++
++I am not aware about any issues that have been caused by this.
++
++Signed-off-by: Benjamin Berg <benjamin.berg@open-mesh.com>
++---
++
++--- a/drivers/net/wireless/ath/ath9k/beacon.c
+++++ b/drivers/net/wireless/ath/ath9k/beacon.c
++@@ -279,17 +279,21 @@ static void ath9k_set_tsfadjust(struct a
++ 	struct ath_common *common = ath9k_hw_common(sc->sc_ah);
++ 	struct ath_vif *avp = (void *)vif->drv_priv;
++ 	struct ath_beacon_config *cur_conf = &avp->chanctx->beacon;
++-	u32 tsfadjust;
+++	s64 tsfadjust;
++ 
++ 	if (avp->av_bslot == 0)
++ 		return;
++ 
+++	/* tsf_adjust is added to the TSF value. We send out the beacon late,
+++	 * so need to adjust the TSF starting point to be later in time (i.e.
+++	 * the theoretical first beacon has a TSF of 0 after correction).
+++	 */
++ 	tsfadjust = cur_conf->beacon_interval * avp->av_bslot;
++-	tsfadjust = TU_TO_USEC(tsfadjust) / ATH_BCBUF;
+++	tsfadjust = -TU_TO_USEC(tsfadjust) / ATH_BCBUF;
++ 	avp->tsf_adjust = cpu_to_le64(tsfadjust);
++ 
++-	ath_dbg(common, CONFIG, "tsfadjust is: %llu for bslot: %d\n",
++-		(unsigned long long)tsfadjust, avp->av_bslot);
+++	ath_dbg(common, CONFIG, "tsfadjust is: %lld for bslot: %d\n",
+++		(signed long long)tsfadjust, avp->av_bslot);
++ }
++ 
++ bool ath9k_csa_is_finished(struct ath_softc *sc, struct ieee80211_vif *vif)
 diff --git a/package/kernel/mac80211/patches/312-mac80211-fix-txq-queue-related-crashes.patch b/package/kernel/mac80211/patches/312-mac80211-fix-txq-queue-related-crashes.patch
 deleted file mode 100644
 index 61cafc7..0000000
@@ -3098,6 +3174,82 @@ index 61cafc7..0000000
 - 		atomic_set(&sdata->txqs_len[txqi->txq.ac], 0);
 - 	}
 - 
+diff --git a/package/kernel/mac80211/patches/313-ath9k-Handle-channel-context-in-get_-set_-reset_tsf.patch b/package/kernel/mac80211/patches/313-ath9k-Handle-channel-context-in-get_-set_-reset_tsf.patch
+new file mode 100644
+index 0000000..ef0afbe
+--- /dev/null
++++ b/package/kernel/mac80211/patches/313-ath9k-Handle-channel-context-in-get_-set_-reset_tsf.patch
+@@ -0,0 +1,70 @@
++From: Benjamin Berg <benjamin.berg@open-mesh.com>
++Date: Mon, 4 Jul 2016 14:37:21 +0200
++Subject: [PATCH] ath9k: Handle channel context in get_/set_/reset_tsf
++
++The ath9k TSF handling routines need to be aware of the channel context that
++is being modified. With this change the TSF related values that are stored
++in each channel context will be correctly tracked and the harware will only
++be updated if the modified context is currently the active one.
++
++Without this change the TSF modifications done using these routines would
++for example be lost during a hardware reset as done by ath_complete_reset.
++
++Signed-off-by: Benjamin Berg <benjamin.berg@open-mesh.com>
++---
++
++--- a/drivers/net/wireless/ath/ath9k/main.c
+++++ b/drivers/net/wireless/ath/ath9k/main.c
++@@ -1823,11 +1823,18 @@ static void ath9k_bss_info_changed(struc
++ static u64 ath9k_get_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
++ {
++ 	struct ath_softc *sc = hw->priv;
+++	struct ath_vif *avp = (void *)vif->drv_priv;
++ 	u64 tsf;
++ 
++ 	mutex_lock(&sc->mutex);
++ 	ath9k_ps_wakeup(sc);
++-	tsf = ath9k_hw_gettsf64(sc->sc_ah);
+++	/* Get current TSF either from HW or kernel time. */
+++	if (sc->cur_chan == avp->chanctx) {
+++		tsf = ath9k_hw_gettsf64(sc->sc_ah);
+++	} else {
+++		tsf = sc->cur_chan->tsf_val +
+++		      ath9k_hw_get_tsf_offset(&sc->cur_chan->tsf_ts, NULL);
+++	}
++ 	ath9k_ps_restore(sc);
++ 	mutex_unlock(&sc->mutex);
++ 
++@@ -1839,10 +1846,14 @@ static void ath9k_set_tsf(struct ieee802
++ 			  u64 tsf)
++ {
++ 	struct ath_softc *sc = hw->priv;
+++	struct ath_vif *avp = (void *)vif->drv_priv;
++ 
++ 	mutex_lock(&sc->mutex);
++ 	ath9k_ps_wakeup(sc);
++-	ath9k_hw_settsf64(sc->sc_ah, tsf);
+++	getrawmonotonic(&avp->chanctx->tsf_ts);
+++	if (sc->cur_chan == avp->chanctx)
+++		ath9k_hw_settsf64(sc->sc_ah, tsf);
+++	avp->chanctx->tsf_val = tsf;
++ 	ath9k_ps_restore(sc);
++ 	mutex_unlock(&sc->mutex);
++ }
++@@ -1850,11 +1861,15 @@ static void ath9k_set_tsf(struct ieee802
++ static void ath9k_reset_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
++ {
++ 	struct ath_softc *sc = hw->priv;
+++	struct ath_vif *avp = (void *)vif->drv_priv;
++ 
++ 	mutex_lock(&sc->mutex);
++ 
++ 	ath9k_ps_wakeup(sc);
++-	ath9k_hw_reset_tsf(sc->sc_ah);
+++	getrawmonotonic(&avp->chanctx->tsf_ts);
+++	if (sc->cur_chan == avp->chanctx)
+++		ath9k_hw_reset_tsf(sc->sc_ah);
+++	avp->chanctx->tsf_val = 0;
++ 	ath9k_ps_restore(sc);
++ 
++ 	mutex_unlock(&sc->mutex);
 diff --git a/package/kernel/mac80211/patches/313-mac80211-fix-unnecessary-frame-drops-in-mesh-fwding.patch b/package/kernel/mac80211/patches/313-mac80211-fix-unnecessary-frame-drops-in-mesh-fwding.patch
 deleted file mode 100644
 index 844d43b..0000000
@@ -3161,6 +3313,77 @@ index 844d43b..0000000
 - 	if (ieee80211_queue_stopped(&local->hw, q)) {
 - 		IEEE80211_IFSTA_MESH_CTR_INC(ifmsh, dropped_frames_congestion);
 - 		return RX_DROP_MONITOR;
+diff --git a/package/kernel/mac80211/patches/314-ath9k-Use-tsf-offset-helper-in-ath9k_hw_reset.patch b/package/kernel/mac80211/patches/314-ath9k-Use-tsf-offset-helper-in-ath9k_hw_reset.patch
+new file mode 100644
+index 0000000..e725a8b
+--- /dev/null
++++ b/package/kernel/mac80211/patches/314-ath9k-Use-tsf-offset-helper-in-ath9k_hw_reset.patch
+@@ -0,0 +1,65 @@
++From: Benjamin Berg <benjamin.berg@open-mesh.com>
++Date: Mon, 4 Jul 2016 14:37:22 +0200
++Subject: [PATCH] ath9k: Use tsf offset helper in ath9k_hw_reset
++
++These changes make ath9k_hw_reset more consistent with other places that
++handle the TSF value by using the same helper routine.
++
++A slight improvement is to not assume that a fixed time of 1.5ms has
++passed for the initval writes when compared to the first write attempt.
++Instead the TSF value is re-calculated which will yield a higher accuracy
++of the restored TSF timer.
++
++Signed-off-by: Benjamin Berg <benjamin.berg@open-mesh.com>
++---
++
++--- a/drivers/net/wireless/ath/ath9k/hw.c
+++++ b/drivers/net/wireless/ath/ath9k/hw.c
++@@ -1832,8 +1832,9 @@ int ath9k_hw_reset(struct ath_hw *ah, st
++ 	u32 saveLedState;
++ 	u32 saveDefAntenna;
++ 	u32 macStaId1;
+++	struct timespec tsf_ts;
+++	u32 tsf_offset;
++ 	u64 tsf = 0;
++-	s64 usec = 0;
++ 	int r;
++ 	bool start_mci_reset = false;
++ 	bool save_fullsleep = ah->chip_fullsleep;
++@@ -1877,8 +1878,8 @@ int ath9k_hw_reset(struct ath_hw *ah, st
++ 	macStaId1 = REG_READ(ah, AR_STA_ID1) & AR_STA_ID1_BASE_RATE_11B;
++ 
++ 	/* Save TSF before chip reset, a cold reset clears it */
+++	getrawmonotonic(&tsf_ts);
++ 	tsf = ath9k_hw_gettsf64(ah);
++-	usec = ktime_to_us(ktime_get_raw());
++ 
++ 	saveLedState = REG_READ(ah, AR_CFG_LED) &
++ 		(AR_CFG_LED_ASSOC_CTL | AR_CFG_LED_MODE_SEL |
++@@ -1911,8 +1912,8 @@ int ath9k_hw_reset(struct ath_hw *ah, st
++ 	}
++ 
++ 	/* Restore TSF */
++-	usec = ktime_to_us(ktime_get_raw()) - usec;
++-	ath9k_hw_settsf64(ah, tsf + usec);
+++	tsf_offset = ath9k_hw_get_tsf_offset(&tsf_ts, NULL);
+++	ath9k_hw_settsf64(ah, tsf + tsf_offset);
++ 
++ 	if (AR_SREV_9280_20_OR_LATER(ah))
++ 		REG_SET_BIT(ah, AR_GPIO_INPUT_EN_VAL, AR_GPIO_JTAG_DISABLE);
++@@ -1932,12 +1933,11 @@ int ath9k_hw_reset(struct ath_hw *ah, st
++ 	/*
++ 	 * Some AR91xx SoC devices frequently fail to accept TSF writes
++ 	 * right after the chip reset. When that happens, write a new
++-	 * value after the initvals have been applied, with an offset
++-	 * based on measured time difference
+++	 * value after the initvals have been applied.
++ 	 */
++ 	if (AR_SREV_9100(ah) && (ath9k_hw_gettsf64(ah) < tsf)) {
++-		tsf += 1500;
++-		ath9k_hw_settsf64(ah, tsf);
+++		tsf_offset = ath9k_hw_get_tsf_offset(&tsf_ts, NULL);
+++		ath9k_hw_settsf64(ah, tsf + tsf_offset);
++ 	}
++ 
++ 	ath9k_hw_init_mfp(ah);
 diff --git a/package/kernel/mac80211/patches/314-mac80211-Requeue-work-after-scan-complete-for-all-VI.patch b/package/kernel/mac80211/patches/314-mac80211-Requeue-work-after-scan-complete-for-all-VI.patch
 deleted file mode 100644
 index 5b3efbd..0000000
@@ -3270,6 +3493,44 @@ index 5b3efbd..0000000
 - 	if (was_scanning)
 - 		ieee80211_start_next_roc(local);
 - }
+diff --git a/package/kernel/mac80211/patches/315-ath9k-Expose-tsf_adjustment-in-mac80211-tsf-getters-.patch b/package/kernel/mac80211/patches/315-ath9k-Expose-tsf_adjustment-in-mac80211-tsf-getters-.patch
+new file mode 100644
+index 0000000..c95ab7e
+--- /dev/null
++++ b/package/kernel/mac80211/patches/315-ath9k-Expose-tsf_adjustment-in-mac80211-tsf-getters-.patch
+@@ -0,0 +1,32 @@
++From: Benjamin Berg <benjamin.berg@open-mesh.com>
++Date: Mon, 4 Jul 2016 14:37:23 +0200
++Subject: [PATCH] ath9k: Expose tsf_adjustment in mac80211 tsf getters and
++ setters.
++
++The ath9k driver modifies the TSF for VIFs for the purpose of sending
++beacons in a staggered fashion. This patch exposes this VIF specific
++adjustment of the TSF value to mac80211. Without the change the TSF
++routines handle the hardware TSF value instead of the actual TSF value as
++seen on the air.
++
++Signed-off-by: Benjamin Berg <benjamin.berg@open-mesh.com>
++---
++
++--- a/drivers/net/wireless/ath/ath9k/main.c
+++++ b/drivers/net/wireless/ath/ath9k/main.c
++@@ -1835,6 +1835,7 @@ static u64 ath9k_get_tsf(struct ieee8021
++ 		tsf = sc->cur_chan->tsf_val +
++ 		      ath9k_hw_get_tsf_offset(&sc->cur_chan->tsf_ts, NULL);
++ 	}
+++	tsf += le64_to_cpu(avp->tsf_adjust);
++ 	ath9k_ps_restore(sc);
++ 	mutex_unlock(&sc->mutex);
++ 
++@@ -1850,6 +1851,7 @@ static void ath9k_set_tsf(struct ieee802
++ 
++ 	mutex_lock(&sc->mutex);
++ 	ath9k_ps_wakeup(sc);
+++	tsf -= le64_to_cpu(avp->tsf_adjust);
++ 	getrawmonotonic(&avp->chanctx->tsf_ts);
++ 	if (sc->cur_chan == avp->chanctx)
++ 		ath9k_hw_settsf64(sc->sc_ah, tsf);
 diff --git a/package/kernel/mac80211/patches/315-mac80211-fix-ibss-scan-parameters.patch b/package/kernel/mac80211/patches/315-mac80211-fix-ibss-scan-parameters.patch
 deleted file mode 100644
 index 52fecb9..0000000
@@ -3333,6 +3594,149 @@ index 52fecb9..0000000
 - 	} else {
 - 		int interval = IEEE80211_SCAN_INTERVAL;
 - 
+diff --git a/package/kernel/mac80211/patches/316-ath9k-Remove-some-defined-constants-to-decrease-verb.patch b/package/kernel/mac80211/patches/316-ath9k-Remove-some-defined-constants-to-decrease-verb.patch
+new file mode 100644
+index 0000000..36aaa10
+--- /dev/null
++++ b/package/kernel/mac80211/patches/316-ath9k-Remove-some-defined-constants-to-decrease-verb.patch
+@@ -0,0 +1,137 @@
++From: Benjamin Berg <benjamin.berg@open-mesh.com>
++Date: Mon, 4 Jul 2016 14:37:24 +0200
++Subject: [PATCH] ath9k: Remove some #defined constants to decrease
++ verbosity
++
++The removed ATH9K_SLOT_TIME_X constants simply map the value in microseconds
++to the same integer. These constants were not used consistently, so fix the
++inconsistency issue by replacing all occurances with the integer equivalent.
++
++Signed-off-by: Benjamin Berg <benjamin.berg@open-mesh.com>
++---
++
++--- a/drivers/net/wireless/ath/ath9k/beacon.c
+++++ b/drivers/net/wireless/ath/ath9k/beacon.c
++@@ -50,7 +50,7 @@ static void ath9k_beaconq_config(struct
++ 		txq = sc->tx.txq_map[IEEE80211_AC_BE];
++ 		ath9k_hw_get_txq_props(ah, txq->axq_qnum, &qi_be);
++ 		qi.tqi_aifs = qi_be.tqi_aifs;
++-		if (ah->slottime == ATH9K_SLOT_TIME_20)
+++		if (ah->slottime == 20)
++ 			qi.tqi_cwmin = 2*qi_be.tqi_cwmin;
++ 		else
++ 			qi.tqi_cwmin = 4*qi_be.tqi_cwmin;
++--- a/drivers/net/wireless/ath/ath9k/dynack.c
+++++ b/drivers/net/wireless/ath/ath9k/dynack.c
++@@ -280,7 +280,7 @@ EXPORT_SYMBOL(ath_dynack_sample_ack_ts);
++ void ath_dynack_node_init(struct ath_hw *ah, struct ath_node *an)
++ {
++ 	/* ackto = slottime + sifs + air delay */
++-	u32 ackto = ATH9K_SLOT_TIME_9 + 16 + 64;
+++	u32 ackto = 9 + 16 + 64;
++ 	struct ath_dynack *da = &ah->dynack;
++ 
++ 	an->ackto = ackto;
++@@ -315,7 +315,7 @@ EXPORT_SYMBOL(ath_dynack_node_deinit);
++ void ath_dynack_reset(struct ath_hw *ah)
++ {
++ 	/* ackto = slottime + sifs + air delay */
++-	u32 ackto = ATH9K_SLOT_TIME_9 + 16 + 64;
+++	u32 ackto = 9 + 16 + 64;
++ 	struct ath_dynack *da = &ah->dynack;
++ 
++ 	da->lto = jiffies;
++--- a/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c
+++++ b/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c
++@@ -45,7 +45,7 @@ void ath9k_htc_beaconq_config(struct ath
++ 		 * Long slot time  : 2x cwmin
++ 		 * Short slot time : 4x cwmin
++ 		 */
++-		if (ah->slottime == ATH9K_SLOT_TIME_20)
+++		if (ah->slottime == 20)
++ 			qi.tqi_cwmin = 2*qi_be.tqi_cwmin;
++ 		else
++ 			qi.tqi_cwmin = 4*qi_be.tqi_cwmin;
++--- a/drivers/net/wireless/ath/ath9k/htc_drv_init.c
+++++ b/drivers/net/wireless/ath/ath9k/htc_drv_init.c
++@@ -678,7 +678,7 @@ static int ath9k_init_priv(struct ath9k_
++ 
++ 	for (i = 0; i < ATH9K_HTC_MAX_BCN_VIF; i++)
++ 		priv->beacon.bslot[i] = NULL;
++-	priv->beacon.slottime = ATH9K_SLOT_TIME_9;
+++	priv->beacon.slottime = 9;
++ 
++ 	ath9k_cmn_init_channels_rates(common);
++ 	ath9k_cmn_init_crypto(ah);
++--- a/drivers/net/wireless/ath/ath9k/hw.c
+++++ b/drivers/net/wireless/ath/ath9k/hw.c
++@@ -454,7 +454,7 @@ static void ath9k_hw_init_defaults(struc
++ 	if (AR_SREV_9100(ah))
++ 		ah->sta_id1_defaults |= AR_STA_ID1_AR9100_BA_FIX;
++ 
++-	ah->slottime = ATH9K_SLOT_TIME_9;
+++	ah->slottime = 9;
++ 	ah->globaltxtimeout = (u32) -1;
++ 	ah->power_mode = ATH9K_PM_UNDEFINED;
++ 	ah->htc_reset_init = true;
++--- a/drivers/net/wireless/ath/ath9k/init.c
+++++ b/drivers/net/wireless/ath/ath9k/init.c
++@@ -372,7 +372,7 @@ static void ath9k_init_misc(struct ath_s
++ 
++ 	common->last_rssi = ATH_RSSI_DUMMY_MARKER;
++ 	memcpy(common->bssidmask, ath_bcast_mac, ETH_ALEN);
++-	sc->beacon.slottime = ATH9K_SLOT_TIME_9;
+++	sc->beacon.slottime = 9;
++ 
++ 	for (i = 0; i < ARRAY_SIZE(sc->beacon.bslot); i++)
++ 		sc->beacon.bslot[i] = NULL;
++--- a/drivers/net/wireless/ath/ath9k/mac.h
+++++ b/drivers/net/wireless/ath/ath9k/mac.h
++@@ -65,10 +65,6 @@
++ #define INIT_SSH_RETRY  32
++ #define INIT_SLG_RETRY  32
++ 
++-#define ATH9K_SLOT_TIME_6 6
++-#define ATH9K_SLOT_TIME_9 9
++-#define ATH9K_SLOT_TIME_20 20
++-
++ #define ATH9K_TXERR_XRETRY         0x01
++ #define ATH9K_TXERR_FILT           0x02
++ #define ATH9K_TXERR_FIFO           0x04
++--- a/drivers/net/wireless/ath/ath9k/main.c
+++++ b/drivers/net/wireless/ath/ath9k/main.c
++@@ -926,7 +926,7 @@ static void ath9k_vif_iter(struct ath9k_
++ 	}
++ 
++ 	if (!vif->bss_conf.use_short_slot)
++-		iter_data->slottime = ATH9K_SLOT_TIME_20;
+++		iter_data->slottime = 20;
++ 
++ 	switch (vif->type) {
++ 	case NL80211_IFTYPE_AP:
++@@ -999,7 +999,7 @@ void ath9k_calculate_iter_data(struct at
++ 	 */
++ 	memset(iter_data, 0, sizeof(*iter_data));
++ 	eth_broadcast_addr(iter_data->mask);
++-	iter_data->slottime = ATH9K_SLOT_TIME_9;
+++	iter_data->slottime = 9;
++ 
++ 	list_for_each_entry(avp, &ctx->vifs, list)
++ 		ath9k_vif_iter(iter_data, avp->vif->addr, avp->vif);
++@@ -1061,7 +1061,7 @@ static void ath9k_set_offchannel_state(s
++ 	ah->opmode = vif->type;
++ 	ah->imask &= ~ATH9K_INT_SWBA;
++ 	ah->imask &= ~ATH9K_INT_TSFOOR;
++-	ah->slottime = ATH9K_SLOT_TIME_9;
+++	ah->slottime = 9;
++ 
++ 	ath_hw_setbssidmask(common);
++ 	ath9k_hw_setopmode(ah);
++@@ -1788,6 +1788,7 @@ static void ath9k_bss_info_changed(struc
++ 			slottime = 9;
++ 		else
++ 			slottime = 20;
+++
++ 		if (vif->type == NL80211_IFTYPE_AP) {
++ 			/*
++ 			 * Defer update, so that connected stations can adjust
 diff --git a/package/kernel/mac80211/patches/316-net-mac80211-agg-rx.c-fix-use-of-uninitialised-value.patch b/package/kernel/mac80211/patches/316-net-mac80211-agg-rx.c-fix-use-of-uninitialised-value.patch
 deleted file mode 100644
 index e78df36..0000000
@@ -3389,6 +3793,556 @@ index e78df36..0000000
 - 	if (!tid_agg_rx)
 - 		goto end;
 - 
+diff --git a/package/kernel/mac80211/patches/317-ath9k-Fix-beacon-configuration-for-addition-removal-.patch b/package/kernel/mac80211/patches/317-ath9k-Fix-beacon-configuration-for-addition-removal-.patch
+new file mode 100644
+index 0000000..360dfbf
+--- /dev/null
++++ b/package/kernel/mac80211/patches/317-ath9k-Fix-beacon-configuration-for-addition-removal-.patch
+@@ -0,0 +1,544 @@
++From: Benjamin Berg <benjamin.berg@open-mesh.com>
++Date: Mon, 4 Jul 2016 14:37:25 +0200
++Subject: [PATCH] ath9k: Fix beacon configuration for addition/removal of
++ interfaces
++
++This patch fixes some issues with interface reconfiguration. It could
++for example happen that an AP interface in beacon slot 0 was removed
++leaving an IBSS station in one of the other slots. When this happens
++the driver never sends out the beacon as it only tries to send a beacon
++from slot 0.
++
++Appart from that the tracking of required changes to the beacon config is
++relatively complicated and prone to errors.
++
++The approach taken here is to solve reconfiguration issues is to
++reconfigure the beacons when any interface changes. This means that
++the complexity of deciding whether an interface change may modify the
++beacon configuration is gone. It also means that the beacon config will
++be reliably updated when an interface is removed.
++
++The issue that a single non-AP interface might not be in beacon
++slot 0 and wouldn't be send out is solved by moving it into the
++first slot. The TSF value in hardware is adjusted accordingly so
++that the timestamp of the beacons stay consistent.
++
++Signed-off-by: Benjamin Berg <benjamin.berg@open-mesh.com>
++---
++
++--- a/drivers/net/wireless/ath/ath9k/ath9k.h
+++++ b/drivers/net/wireless/ath/ath9k/ath9k.h
++@@ -637,6 +637,8 @@ struct ath9k_vif_iter_data {
++ 	int nwds;      /* number of WDS vifs */
++ 	int nadhocs;   /* number of adhoc vifs */
++ 	int nocbs;     /* number of OCB vifs */
+++	int nbcnvifs;  /* number of beaconing vifs */
+++	struct ieee80211_vif *primary_beacon_vif;
++ 	struct ieee80211_vif *primary_sta;
++ };
++ 
++@@ -685,10 +687,11 @@ struct ath_beacon {
++ };
++ 
++ void ath9k_beacon_tasklet(unsigned long data);
++-void ath9k_beacon_config(struct ath_softc *sc, struct ieee80211_vif *vif,
++-			 u32 changed);
+++void ath9k_beacon_config(struct ath_softc *sc, struct ieee80211_vif *main_vif,
+++			 bool beacons);
++ void ath9k_beacon_assign_slot(struct ath_softc *sc, struct ieee80211_vif *vif);
++ void ath9k_beacon_remove_slot(struct ath_softc *sc, struct ieee80211_vif *vif);
+++void ath9k_beacon_ensure_primary_slot(struct ath_softc *sc);
++ void ath9k_set_beacon(struct ath_softc *sc);
++ bool ath9k_csa_is_finished(struct ath_softc *sc, struct ieee80211_vif *vif);
++ void ath9k_csa_update(struct ath_softc *sc);
++--- a/drivers/net/wireless/ath/ath9k/beacon.c
+++++ b/drivers/net/wireless/ath/ath9k/beacon.c
++@@ -209,7 +209,6 @@ void ath9k_beacon_assign_slot(struct ath
++ 	}
++ 
++ 	sc->beacon.bslot[avp->av_bslot] = vif;
++-	sc->nbcnvifs++;
++ 
++ 	ath_dbg(common, CONFIG, "Added interface at beacon slot: %d\n",
++ 		avp->av_bslot);
++@@ -220,15 +219,12 @@ void ath9k_beacon_remove_slot(struct ath
++ 	struct ath_common *common = ath9k_hw_common(sc->sc_ah);
++ 	struct ath_vif *avp = (void *)vif->drv_priv;
++ 	struct ath_buf *bf = avp->av_bcbuf;
++-	struct ath_beacon_config *cur_conf = &sc->cur_chan->beacon;
++ 
++ 	ath_dbg(common, CONFIG, "Removing interface at beacon slot: %d\n",
++ 		avp->av_bslot);
++ 
++ 	tasklet_disable(&sc->bcon_tasklet);
++ 
++-	cur_conf->enable_beacon &= ~BIT(avp->av_bslot);
++-
++ 	if (bf && bf->bf_mpdu) {
++ 		struct sk_buff *skb = bf->bf_mpdu;
++ 		dma_unmap_single(sc->dev, bf->bf_buf_addr,
++@@ -240,12 +236,73 @@ void ath9k_beacon_remove_slot(struct ath
++ 
++ 	avp->av_bcbuf = NULL;
++ 	sc->beacon.bslot[avp->av_bslot] = NULL;
++-	sc->nbcnvifs--;
++ 	list_add_tail(&bf->list, &sc->beacon.bbuf);
++ 
++ 	tasklet_enable(&sc->bcon_tasklet);
++ }
++ 
+++void ath9k_beacon_ensure_primary_slot(struct ath_softc *sc)
+++{
+++	struct ath_common *common = ath9k_hw_common(sc->sc_ah);
+++	struct ieee80211_vif *vif;
+++	struct ath_vif *avp;
+++	s64 tsfadjust;
+++	u32 offset;
+++	int first_slot = ATH_BCBUF;
+++	int slot;
+++
+++	tasklet_disable(&sc->bcon_tasklet);
+++
+++	/* Find first taken slot. */
+++	for (slot = 0; slot < ATH_BCBUF; slot++) {
+++		if (sc->beacon.bslot[slot]) {
+++			first_slot = slot;
+++			break;
+++		}
+++	}
+++	if (first_slot == 0)
+++		goto out;
+++
+++	/* Re-enumarate all slots, moving them forward. */
+++	for (slot = 0; slot < ATH_BCBUF; slot++) {
+++		if (slot + first_slot < ATH_BCBUF) {
+++			vif = sc->beacon.bslot[slot + first_slot];
+++			sc->beacon.bslot[slot] = vif;
+++
+++			if (vif) {
+++				avp = (void *)vif->drv_priv;
+++				avp->av_bslot = slot;
+++			}
+++		} else {
+++			sc->beacon.bslot[slot] = NULL;
+++		}
+++	}
+++
+++	vif = sc->beacon.bslot[0];
+++	if (WARN_ON(!vif))
+++		goto out;
+++
+++	/* Get the tsf_adjust value for the new first slot. */
+++	avp = (void *)vif->drv_priv;
+++	tsfadjust = le64_to_cpu(avp->tsf_adjust);
+++
+++	ath_dbg(common, CONFIG,
+++		"Adjusting global TSF after beacon slot reassignment: %lld\n",
+++		(signed long long)tsfadjust);
+++
+++	/* Modify TSF as required and update the HW. */
+++	avp->chanctx->tsf_val += tsfadjust;
+++	if (sc->cur_chan == avp->chanctx) {
+++		offset = ath9k_hw_get_tsf_offset(&avp->chanctx->tsf_ts, NULL);
+++		ath9k_hw_settsf64(sc->sc_ah, avp->chanctx->tsf_val + offset);
+++	}
+++
+++	/* The slots tsf_adjust will be updated by ath9k_beacon_config later. */
+++
+++out:
+++	tasklet_enable(&sc->bcon_tasklet);
+++}
+++
++ static int ath9k_beacon_choose_slot(struct ath_softc *sc)
++ {
++ 	struct ath_common *common = ath9k_hw_common(sc->sc_ah);
++@@ -274,26 +331,33 @@ static int ath9k_beacon_choose_slot(stru
++ 	return slot;
++ }
++ 
++-static void ath9k_set_tsfadjust(struct ath_softc *sc, struct ieee80211_vif *vif)
+++static void ath9k_set_tsfadjust(struct ath_softc *sc,
+++				struct ath_beacon_config *cur_conf)
++ {
++ 	struct ath_common *common = ath9k_hw_common(sc->sc_ah);
++-	struct ath_vif *avp = (void *)vif->drv_priv;
++-	struct ath_beacon_config *cur_conf = &avp->chanctx->beacon;
++ 	s64 tsfadjust;
+++	int slot;
++ 
++-	if (avp->av_bslot == 0)
++-		return;
+++	for (slot = 0; slot < ATH_BCBUF; slot++) {
+++		struct ath_vif *avp;
++ 
++-	/* tsf_adjust is added to the TSF value. We send out the beacon late,
++-	 * so need to adjust the TSF starting point to be later in time (i.e.
++-	 * the theoretical first beacon has a TSF of 0 after correction).
++-	 */
++-	tsfadjust = cur_conf->beacon_interval * avp->av_bslot;
++-	tsfadjust = -TU_TO_USEC(tsfadjust) / ATH_BCBUF;
++-	avp->tsf_adjust = cpu_to_le64(tsfadjust);
+++		if (!sc->beacon.bslot[slot])
+++			continue;
++ 
++-	ath_dbg(common, CONFIG, "tsfadjust is: %lld for bslot: %d\n",
++-		(signed long long)tsfadjust, avp->av_bslot);
+++		avp = (void *)sc->beacon.bslot[slot]->drv_priv;
+++
+++		/* tsf_adjust is added to the TSF value. We send out the
+++		 * beacon late, so need to adjust the TSF starting point to be
+++		 * later in time (i.e. the theoretical first beacon has a TSF
+++		 * of 0 after correction).
+++		 */
+++		tsfadjust = cur_conf->beacon_interval * avp->av_bslot;
+++		tsfadjust = -TU_TO_USEC(tsfadjust) / ATH_BCBUF;
+++		avp->tsf_adjust = cpu_to_le64(tsfadjust);
+++
+++		ath_dbg(common, CONFIG, "tsfadjust is: %lld for bslot: %d\n",
+++			(signed long long)tsfadjust, avp->av_bslot);
+++	}
++ }
++ 
++ bool ath9k_csa_is_finished(struct ath_softc *sc, struct ieee80211_vif *vif)
++@@ -447,20 +511,28 @@ void ath9k_beacon_tasklet(unsigned long
++  * Both nexttbtt and intval have to be in usecs.
++  */
++ static void ath9k_beacon_init(struct ath_softc *sc, u32 nexttbtt,
++-			      u32 intval, bool reset_tsf)
+++			      u32 intval)
++ {
++ 	struct ath_hw *ah = sc->sc_ah;
++ 
++ 	ath9k_hw_disable_interrupts(ah);
++-	if (reset_tsf)
++-		ath9k_hw_reset_tsf(ah);
++ 	ath9k_beaconq_config(sc);
++ 	ath9k_hw_beaconinit(ah, nexttbtt, intval);
+++	ah->imask |= ATH9K_INT_SWBA;
++ 	sc->beacon.bmisscnt = 0;
++ 	ath9k_hw_set_interrupts(ah);
++ 	ath9k_hw_enable_interrupts(ah);
++ }
++ 
+++static void ath9k_beacon_stop(struct ath_softc *sc)
+++{
+++	ath9k_hw_disable_interrupts(sc->sc_ah);
+++	sc->sc_ah->imask &= ~(ATH9K_INT_SWBA | ATH9K_INT_BMISS);
+++	sc->beacon.bmisscnt = 0;
+++	ath9k_hw_set_interrupts(sc->sc_ah);
+++	ath9k_hw_enable_interrupts(sc->sc_ah);
+++}
+++
++ /*
++  * For multi-bss ap support beacons are either staggered evenly over N slots or
++  * burst together.  For the former arrange for the SWBA to be delivered for each
++@@ -472,7 +544,7 @@ static void ath9k_beacon_config_ap(struc
++ 	struct ath_hw *ah = sc->sc_ah;
++ 
++ 	ath9k_cmn_beacon_config_ap(ah, conf, ATH_BCBUF);
++-	ath9k_beacon_init(sc, conf->nexttbtt, conf->intval, false);
+++	ath9k_beacon_init(sc, conf->nexttbtt, conf->intval);
++ }
++ 
++ static void ath9k_beacon_config_sta(struct ath_hw *ah,
++@@ -501,7 +573,7 @@ static void ath9k_beacon_config_adhoc(st
++ 
++ 	ath9k_cmn_beacon_config_adhoc(ah, conf);
++ 
++-	ath9k_beacon_init(sc, conf->nexttbtt, conf->intval, conf->ibss_creator);
+++	ath9k_beacon_init(sc, conf->nexttbtt, conf->intval);
++ 
++ 	/*
++ 	 * Set the global 'beacon has been configured' flag for the
++@@ -511,44 +583,6 @@ static void ath9k_beacon_config_adhoc(st
++ 		set_bit(ATH_OP_BEACONS, &common->op_flags);
++ }
++ 
++-static bool ath9k_allow_beacon_config(struct ath_softc *sc,
++-				      struct ieee80211_vif *vif)
++-{
++-	struct ath_common *common = ath9k_hw_common(sc->sc_ah);
++-	struct ath_vif *avp = (void *)vif->drv_priv;
++-
++-	if (ath9k_is_chanctx_enabled()) {
++-		/*
++-		 * If the VIF is not present in the current channel context,
++-		 * then we can't do the usual opmode checks. Allow the
++-		 * beacon config for the VIF to be updated in this case and
++-		 * return immediately.
++-		 */
++-		if (sc->cur_chan != avp->chanctx)
++-			return true;
++-	}
++-
++-	if (sc->sc_ah->opmode == NL80211_IFTYPE_AP) {
++-		if (vif->type != NL80211_IFTYPE_AP) {
++-			ath_dbg(common, CONFIG,
++-				"An AP interface is already present !\n");
++-			return false;
++-		}
++-	}
++-
++-	if (sc->sc_ah->opmode == NL80211_IFTYPE_STATION) {
++-		if ((vif->type == NL80211_IFTYPE_STATION) &&
++-		    test_bit(ATH_OP_BEACONS, &common->op_flags) &&
++-		    vif != sc->cur_chan->primary_sta) {
++-			ath_dbg(common, CONFIG,
++-				"Beacon already configured for a station interface\n");
++-			return false;
++-		}
++-	}
++-
++-	return true;
++-}
++-
++ static void ath9k_cache_beacon_config(struct ath_softc *sc,
++ 				      struct ath_chanctx *ctx,
++ 				      struct ieee80211_bss_conf *bss_conf)
++@@ -584,87 +618,79 @@ static void ath9k_cache_beacon_config(st
++ 	if (cur_conf->dtim_period == 0)
++ 		cur_conf->dtim_period = 1;
++ 
+++	ath9k_set_tsfadjust(sc, cur_conf);
++ }
++ 
++-void ath9k_beacon_config(struct ath_softc *sc, struct ieee80211_vif *vif,
++-			 u32 changed)
+++void ath9k_beacon_config(struct ath_softc *sc, struct ieee80211_vif *main_vif,
+++			 bool beacons)
++ {
++-	struct ieee80211_bss_conf *bss_conf = &vif->bss_conf;
++-        struct ath_hw *ah = sc->sc_ah;
++-        struct ath_common *common = ath9k_hw_common(ah);
++-	struct ath_vif *avp = (void *)vif->drv_priv;
++-	struct ath_chanctx *ctx = avp->chanctx;
+++	struct ath_hw *ah = sc->sc_ah;
+++	struct ath_common *common = ath9k_hw_common(ah);
+++	struct ath_vif *avp;
+++	struct ath_chanctx *ctx;
++ 	struct ath_beacon_config *cur_conf;
++ 	unsigned long flags;
+++	bool enabled;
++ 	bool skip_beacon = false;
++ 
++-	if (!ctx)
+++	if (!beacons) {
+++		clear_bit(ATH_OP_BEACONS, &common->op_flags);
+++		ath9k_beacon_stop(sc);
++ 		return;
+++	}
++ 
++-	cur_conf = &avp->chanctx->beacon;
++-	if (vif->type == NL80211_IFTYPE_AP)
++-		ath9k_set_tsfadjust(sc, vif);
++-
++-	if (!ath9k_allow_beacon_config(sc, vif))
+++	if (WARN_ON(!main_vif))
++ 		return;
++ 
++-	if (vif->type == NL80211_IFTYPE_STATION) {
++-		ath9k_cache_beacon_config(sc, ctx, bss_conf);
++-		if (ctx != sc->cur_chan)
++-			return;
+++	avp = (void *)main_vif->drv_priv;
+++	ctx = avp->chanctx;
+++	cur_conf = &ctx->beacon;
+++	enabled = cur_conf->enable_beacon;
+++	cur_conf->enable_beacon = beacons;
+++
+++	if (sc->sc_ah->opmode == NL80211_IFTYPE_STATION) {
+++		ath9k_cache_beacon_config(sc, ctx, &main_vif->bss_conf);
++ 
++ 		ath9k_set_beacon(sc);
++ 		set_bit(ATH_OP_BEACONS, &common->op_flags);
++ 		return;
++ 	}
++ 
++-	/*
++-	 * Take care of multiple interfaces when
++-	 * enabling/disabling SWBA.
++-	 */
++-	if (changed & BSS_CHANGED_BEACON_ENABLED) {
++-		bool enabled = cur_conf->enable_beacon;
++-
++-		if (!bss_conf->enable_beacon) {
++-			cur_conf->enable_beacon &= ~BIT(avp->av_bslot);
++-		} else {
++-			cur_conf->enable_beacon |= BIT(avp->av_bslot);
++-			if (!enabled)
++-				ath9k_cache_beacon_config(sc, ctx, bss_conf);
++-		}
++-	}
++-
++-	if (ctx != sc->cur_chan)
++-		return;
+++	/* Update the beacon configuration. */
+++	ath9k_cache_beacon_config(sc, ctx, &main_vif->bss_conf);
++ 
++ 	/*
++ 	 * Configure the HW beacon registers only when we have a valid
++ 	 * beacon interval.
++ 	 */
++ 	if (cur_conf->beacon_interval) {
++-		/*
++-		 * If we are joining an existing IBSS network, start beaconing
++-		 * only after a TSF-sync has taken place. Ensure that this
++-		 * happens by setting the appropriate flags.
+++		/* Special case to sync the TSF when joining an existing IBSS.
+++		 * This is only done if no AP interface is active.
+++		 * Note that mac80211 always resets the TSF when creating a new
+++		 * IBSS interface.
++ 		 */
++-		if ((changed & BSS_CHANGED_IBSS) && !bss_conf->ibss_creator &&
++-		    bss_conf->enable_beacon) {
+++		if (sc->sc_ah->opmode == NL80211_IFTYPE_ADHOC &&
+++		    !enabled && beacons && !main_vif->bss_conf.ibss_creator) {
++ 			spin_lock_irqsave(&sc->sc_pm_lock, flags);
++ 			sc->ps_flags |= PS_BEACON_SYNC | PS_WAIT_FOR_BEACON;
++ 			spin_unlock_irqrestore(&sc->sc_pm_lock, flags);
++ 			skip_beacon = true;
++-		} else {
++-			ath9k_set_beacon(sc);
++ 		}
++ 
++ 		/*
++ 		 * Do not set the ATH_OP_BEACONS flag for IBSS joiner mode
++ 		 * here, it is done in ath9k_beacon_config_adhoc().
++ 		 */
++-		if (cur_conf->enable_beacon && !skip_beacon)
+++		if (beacons && !skip_beacon) {
++ 			set_bit(ATH_OP_BEACONS, &common->op_flags);
++-		else
+++			ath9k_set_beacon(sc);
+++		} else {
++ 			clear_bit(ATH_OP_BEACONS, &common->op_flags);
+++			ath9k_beacon_stop(sc);
+++		}
+++	} else {
+++		clear_bit(ATH_OP_BEACONS, &common->op_flags);
+++		ath9k_beacon_stop(sc);
++ 	}
++ }
++ 
++--- a/drivers/net/wireless/ath/ath9k/common.h
+++++ b/drivers/net/wireless/ath/ath9k/common.h
++@@ -50,6 +50,7 @@
++ #define IEEE80211_MS_TO_TU(x)   (((x) * 1000) / 1024)
++ 
++ struct ath_beacon_config {
+++	struct ieee80211_vif *main_vif;
++ 	int beacon_interval;
++ 	u16 dtim_period;
++ 	u16 bmiss_timeout;
++--- a/drivers/net/wireless/ath/ath9k/main.c
+++++ b/drivers/net/wireless/ath/ath9k/main.c
++@@ -910,6 +910,22 @@ static bool ath9k_uses_beacons(int type)
++ 	}
++ }
++ 
+++static void ath9k_vif_iter_set_beacon(struct ath9k_vif_iter_data *iter_data,
+++				      struct ieee80211_vif *vif)
+++{
+++	/* Use the first (configured) interface, but prefering AP interfaces. */
+++	if (!iter_data->primary_beacon_vif) {
+++		iter_data->primary_beacon_vif = vif;
+++	} else {
+++		if (iter_data->primary_beacon_vif->type != NL80211_IFTYPE_AP &&
+++		    vif->type == NL80211_IFTYPE_AP)
+++		iter_data->primary_beacon_vif = vif;
+++	}
+++
+++	iter_data->beacons = true;
+++	iter_data->nbcnvifs += 1;
+++}
+++
++ static void ath9k_vif_iter(struct ath9k_vif_iter_data *iter_data,
++ 			   u8 *mac, struct ieee80211_vif *vif)
++ {
++@@ -931,6 +947,8 @@ static void ath9k_vif_iter(struct ath9k_
++ 	switch (vif->type) {
++ 	case NL80211_IFTYPE_AP:
++ 		iter_data->naps++;
+++		if (vif->bss_conf.enable_beacon)
+++			ath9k_vif_iter_set_beacon(iter_data, vif);
++ 		break;
++ 	case NL80211_IFTYPE_STATION:
++ 		iter_data->nstations++;
++@@ -943,12 +961,12 @@ static void ath9k_vif_iter(struct ath9k_
++ 	case NL80211_IFTYPE_ADHOC:
++ 		iter_data->nadhocs++;
++ 		if (vif->bss_conf.enable_beacon)
++-			iter_data->beacons = true;
+++			ath9k_vif_iter_set_beacon(iter_data, vif);
++ 		break;
++ 	case NL80211_IFTYPE_MESH_POINT:
++ 		iter_data->nmeshes++;
++ 		if (vif->bss_conf.enable_beacon)
++-			iter_data->beacons = true;
+++			ath9k_vif_iter_set_beacon(iter_data, vif);
++ 		break;
++ 	case NL80211_IFTYPE_WDS:
++ 		iter_data->nwds++;
++@@ -1081,7 +1099,6 @@ void ath9k_calculate_summary_state(struc
++ 	struct ath_hw *ah = sc->sc_ah;
++ 	struct ath_common *common = ath9k_hw_common(ah);
++ 	struct ath9k_vif_iter_data iter_data;
++-	struct ath_beacon_config *cur_conf;
++ 
++ 	ath_chanctx_check_active(sc, ctx);
++ 
++@@ -1103,13 +1120,12 @@ void ath9k_calculate_summary_state(struc
++ 	ath_hw_setbssidmask(common);
++ 
++ 	if (iter_data.naps > 0) {
++-		cur_conf = &ctx->beacon;
++ 		ath9k_hw_set_tsfadjust(ah, true);
++ 		ah->opmode = NL80211_IFTYPE_AP;
++-		if (cur_conf->enable_beacon)
++-			iter_data.beacons = true;
++ 	} else {
++ 		ath9k_hw_set_tsfadjust(ah, false);
+++		if (iter_data.beacons)
+++			ath9k_beacon_ensure_primary_slot(sc);
++ 
++ 		if (iter_data.nmeshes)
++ 			ah->opmode = NL80211_IFTYPE_MESH_POINT;
++@@ -1134,7 +1150,6 @@ void ath9k_calculate_summary_state(struc
++ 			ctx->switch_after_beacon = true;
++ 	}
++ 
++-	ah->imask &= ~ATH9K_INT_SWBA;
++ 	if (ah->opmode == NL80211_IFTYPE_STATION) {
++ 		bool changed = (iter_data.primary_sta != ctx->primary_sta);
++ 
++@@ -1151,16 +1166,12 @@ void ath9k_calculate_summary_state(struc
++ 			if (ath9k_hw_mci_is_enabled(sc->sc_ah))
++ 				ath9k_mci_update_wlan_channels(sc, true);
++ 		}
++-	} else if (iter_data.beacons) {
++-		ah->imask |= ATH9K_INT_SWBA;
++ 	}
+++	sc->nbcnvifs = iter_data.nbcnvifs;
+++	ath9k_beacon_config(sc, iter_data.primary_beacon_vif,
+++			    iter_data.beacons);
++ 	ath9k_hw_set_interrupts(ah);
++ 
++-	if (iter_data.beacons)
++-		set_bit(ATH_OP_BEACONS, &common->op_flags);
++-	else
++-		clear_bit(ATH_OP_BEACONS, &common->op_flags);
++-
++ 	if (ah->slottime != iter_data.slottime) {
++ 		ah->slottime = iter_data.slottime;
++ 		ath9k_hw_init_global_settings(ah);
++@@ -1777,9 +1788,7 @@ static void ath9k_bss_info_changed(struc
++ 	if ((changed & BSS_CHANGED_BEACON_ENABLED) ||
++ 	    (changed & BSS_CHANGED_BEACON_INT) ||
++ 	    (changed & BSS_CHANGED_BEACON_INFO)) {
++-		ath9k_beacon_config(sc, vif, changed);
++-		if (changed & BSS_CHANGED_BEACON_ENABLED)
++-			ath9k_calculate_summary_state(sc, avp->chanctx);
+++		ath9k_calculate_summary_state(sc, avp->chanctx);
++ 	}
++ 
++ 	if ((avp->chanctx == sc->cur_chan) &&
 diff --git a/package/kernel/mac80211/patches/317-mac80211-minstrel_ht-fix-out-of-bound-in-minstrel_ht.patch b/package/kernel/mac80211/patches/317-mac80211-minstrel_ht-fix-out-of-bound-in-minstrel_ht.patch
 deleted file mode 100644
 index 5bf53b9..0000000
@@ -3440,6 +4394,120 @@ index 5bf53b9..0000000
 - 			mg->max_group_prob_rate = index;
 - 	}
 - }
+diff --git a/package/kernel/mac80211/patches/318-brcmfmac-slightly-simplify-building-interface-combin.patch b/package/kernel/mac80211/patches/318-brcmfmac-slightly-simplify-building-interface-combin.patch
+new file mode 100644
+index 0000000..d946ecc
+--- /dev/null
++++ b/package/kernel/mac80211/patches/318-brcmfmac-slightly-simplify-building-interface-combin.patch
+@@ -0,0 +1,108 @@
++From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <zajec5@gmail.com>
++Date: Tue, 7 Jun 2016 21:10:18 +0200
++Subject: [PATCH] brcmfmac: slightly simplify building interface combinations
++MIME-Version: 1.0
++Content-Type: text/plain; charset=UTF-8
++Content-Transfer-Encoding: 8bit
++
++This change reorders some operations in brcmf_setup_ifmodes in hope to
++make it simpler:
++1) It allocates arrays right before filling them. This way it's easier
++   to follow requested array length as it's immediately followed by
++   code filling it. It's easier to check e.g. why we need 4 entries for
++   P2P. Other than that it deduplicates some checks (e.g. for P2P).
++2) It reorders code to first prepare limits and then define a new combo.
++   Previously this was mixed (e.g. we were setting num of channels
++   before preparing limits).
++3) It modifies mbss code to use i variable just like other combos do.
++
++Signed-off-by: Rafał Miłecki <zajec5@gmail.com>
++Acked-by: Arend van Spriel <arend.vanspriel@broadcom.com>
++Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
++---
++
++--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
+++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
++@@ -6284,29 +6284,15 @@ static int brcmf_setup_ifmodes(struct wi
++ 	if (!combo)
++ 		goto err;
++ 
++-	c0_limits = kcalloc(p2p ? 3 : 2, sizeof(*c0_limits), GFP_KERNEL);
++-	if (!c0_limits)
++-		goto err;
++-
++-	if (p2p) {
++-		p2p_limits = kcalloc(4, sizeof(*p2p_limits), GFP_KERNEL);
++-		if (!p2p_limits)
++-			goto err;
++-	}
++-
++-	if (mbss) {
++-		mbss_limits = kcalloc(1, sizeof(*mbss_limits), GFP_KERNEL);
++-		if (!mbss_limits)
++-			goto err;
++-	}
++-
++ 	wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) |
++ 				 BIT(NL80211_IFTYPE_ADHOC) |
++ 				 BIT(NL80211_IFTYPE_AP);
++ 
++ 	c = 0;
++ 	i = 0;
++-	combo[c].num_different_channels = 1;
+++	c0_limits = kcalloc(p2p ? 3 : 2, sizeof(*c0_limits), GFP_KERNEL);
+++	if (!c0_limits)
+++		goto err;
++ 	c0_limits[i].max = 1;
++ 	c0_limits[i++].types = BIT(NL80211_IFTYPE_STATION);
++ 	if (p2p) {
++@@ -6324,6 +6310,7 @@ static int brcmf_setup_ifmodes(struct wi
++ 		c0_limits[i].max = 1;
++ 		c0_limits[i++].types = BIT(NL80211_IFTYPE_AP);
++ 	}
+++	combo[c].num_different_channels = 1;
++ 	combo[c].max_interfaces = i;
++ 	combo[c].n_limits = i;
++ 	combo[c].limits = c0_limits;
++@@ -6331,7 +6318,9 @@ static int brcmf_setup_ifmodes(struct wi
++ 	if (p2p) {
++ 		c++;
++ 		i = 0;
++-		combo[c].num_different_channels = 1;
+++		p2p_limits = kcalloc(4, sizeof(*p2p_limits), GFP_KERNEL);
+++		if (!p2p_limits)
+++			goto err;
++ 		p2p_limits[i].max = 1;
++ 		p2p_limits[i++].types = BIT(NL80211_IFTYPE_STATION);
++ 		p2p_limits[i].max = 1;
++@@ -6340,6 +6329,7 @@ static int brcmf_setup_ifmodes(struct wi
++ 		p2p_limits[i++].types = BIT(NL80211_IFTYPE_P2P_CLIENT);
++ 		p2p_limits[i].max = 1;
++ 		p2p_limits[i++].types = BIT(NL80211_IFTYPE_P2P_DEVICE);
+++		combo[c].num_different_channels = 1;
++ 		combo[c].max_interfaces = i;
++ 		combo[c].n_limits = i;
++ 		combo[c].limits = p2p_limits;
++@@ -6347,14 +6337,19 @@ static int brcmf_setup_ifmodes(struct wi
++ 
++ 	if (mbss) {
++ 		c++;
+++		i = 0;
+++		mbss_limits = kcalloc(1, sizeof(*mbss_limits), GFP_KERNEL);
+++		if (!mbss_limits)
+++			goto err;
+++		mbss_limits[i].max = 4;
+++		mbss_limits[i++].types = BIT(NL80211_IFTYPE_AP);
++ 		combo[c].beacon_int_infra_match = true;
++ 		combo[c].num_different_channels = 1;
++-		mbss_limits[0].max = 4;
++-		mbss_limits[0].types = BIT(NL80211_IFTYPE_AP);
++ 		combo[c].max_interfaces = 4;
++-		combo[c].n_limits = 1;
+++		combo[c].n_limits = i;
++ 		combo[c].limits = mbss_limits;
++ 	}
+++
++ 	wiphy->n_iface_combinations = n_combos;
++ 	wiphy->iface_combinations = combo;
++ 	return 0;
 diff --git a/package/kernel/mac80211/patches/318-mac80211-move-A-MSDU-skb_linearize-call-to-ieee80211.patch b/package/kernel/mac80211/patches/318-mac80211-move-A-MSDU-skb_linearize-call-to-ieee80211.patch
 deleted file mode 100644
 index 655dc4b..0000000
@@ -3481,6 +4549,455 @@ index 655dc4b..0000000
 - 	if (has_80211_header) {
 - 		err = ieee80211_data_to_8023(skb, addr, iftype);
 - 		if (err)
+diff --git a/package/kernel/mac80211/patches/319-0001-brcmfmac-fix-lockup-when-removing-P2P-interface-afte.patch b/package/kernel/mac80211/patches/319-0001-brcmfmac-fix-lockup-when-removing-P2P-interface-afte.patch
+new file mode 100644
+index 0000000..073d012
+--- /dev/null
++++ b/package/kernel/mac80211/patches/319-0001-brcmfmac-fix-lockup-when-removing-P2P-interface-afte.patch
+@@ -0,0 +1,154 @@
++From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <zajec5@gmail.com>
++Date: Fri, 17 Jun 2016 12:29:21 +0200
++Subject: [PATCH] brcmfmac: fix lockup when removing P2P interface after
++ event timeout
++MIME-Version: 1.0
++Content-Type: text/plain; charset=UTF-8
++Content-Transfer-Encoding: 8bit
++
++Removing P2P interface is handled by sending a proper request to the
++firmware. On success firmware triggers an event and driver's handler
++removes a matching interface.
++
++However on event timeout we remove interface directly from the cfg80211
++callback. Current code doesn't handle this case correctly as it always
++assumes rtnl to be unlocked.
++
++Fix it by adding an extra rtnl_locked parameter to functions and calling
++unregister_netdevice when needed.
++
++Signed-off-by: Rafał Miłecki <zajec5@gmail.com>
++Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
++---
++
++--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
+++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
++@@ -548,12 +548,16 @@ fail:
++ 	return -EBADE;
++ }
++ 
++-static void brcmf_net_detach(struct net_device *ndev)
+++static void brcmf_net_detach(struct net_device *ndev, bool rtnl_locked)
++ {
++-	if (ndev->reg_state == NETREG_REGISTERED)
++-		unregister_netdev(ndev);
++-	else
+++	if (ndev->reg_state == NETREG_REGISTERED) {
+++		if (rtnl_locked)
+++			unregister_netdevice(ndev);
+++		else
+++			unregister_netdev(ndev);
+++	} else {
++ 		brcmf_cfg80211_free_netdev(ndev);
+++	}
++ }
++ 
++ void brcmf_net_setcarrier(struct brcmf_if *ifp, bool on)
++@@ -651,7 +655,7 @@ struct brcmf_if *brcmf_add_if(struct brc
++ 			brcmf_err("ERROR: netdev:%s already exists\n",
++ 				  ifp->ndev->name);
++ 			netif_stop_queue(ifp->ndev);
++-			brcmf_net_detach(ifp->ndev);
+++			brcmf_net_detach(ifp->ndev, false);
++ 			drvr->iflist[bsscfgidx] = NULL;
++ 		} else {
++ 			brcmf_dbg(INFO, "netdev:%s ignore IF event\n",
++@@ -699,7 +703,8 @@ struct brcmf_if *brcmf_add_if(struct brc
++ 	return ifp;
++ }
++ 
++-static void brcmf_del_if(struct brcmf_pub *drvr, s32 bsscfgidx)
+++static void brcmf_del_if(struct brcmf_pub *drvr, s32 bsscfgidx,
+++			 bool rtnl_locked)
++ {
++ 	struct brcmf_if *ifp;
++ 
++@@ -729,7 +734,7 @@ static void brcmf_del_if(struct brcmf_pu
++ 			cancel_work_sync(&ifp->multicast_work);
++ 			cancel_work_sync(&ifp->ndoffload_work);
++ 		}
++-		brcmf_net_detach(ifp->ndev);
+++		brcmf_net_detach(ifp->ndev, rtnl_locked);
++ 	} else {
++ 		/* Only p2p device interfaces which get dynamically created
++ 		 * end up here. In this case the p2p module should be informed
++@@ -743,14 +748,14 @@ static void brcmf_del_if(struct brcmf_pu
++ 	}
++ }
++ 
++-void brcmf_remove_interface(struct brcmf_if *ifp)
+++void brcmf_remove_interface(struct brcmf_if *ifp, bool rtnl_locked)
++ {
++ 	if (!ifp || WARN_ON(ifp->drvr->iflist[ifp->bsscfgidx] != ifp))
++ 		return;
++ 	brcmf_dbg(TRACE, "Enter, bsscfgidx=%d, ifidx=%d\n", ifp->bsscfgidx,
++ 		  ifp->ifidx);
++ 	brcmf_fws_del_interface(ifp);
++-	brcmf_del_if(ifp->drvr, ifp->bsscfgidx);
+++	brcmf_del_if(ifp->drvr, ifp->bsscfgidx, rtnl_locked);
++ }
++ 
++ #ifdef CONFIG_INET
++@@ -1057,9 +1062,9 @@ fail:
++ 		brcmf_fws_deinit(drvr);
++ 	}
++ 	if (ifp)
++-		brcmf_net_detach(ifp->ndev);
+++		brcmf_net_detach(ifp->ndev, false);
++ 	if (p2p_ifp)
++-		brcmf_net_detach(p2p_ifp->ndev);
+++		brcmf_net_detach(p2p_ifp->ndev, false);
++ 	drvr->iflist[0] = NULL;
++ 	drvr->iflist[1] = NULL;
++ 	if (drvr->settings->ignore_probe_fail)
++@@ -1128,7 +1133,7 @@ void brcmf_detach(struct device *dev)
++ 
++ 	/* make sure primary interface removed last */
++ 	for (i = BRCMF_MAX_IFS-1; i > -1; i--)
++-		brcmf_remove_interface(drvr->iflist[i]);
+++		brcmf_remove_interface(drvr->iflist[i], false);
++ 
++ 	brcmf_cfg80211_detach(drvr->config);
++ 
++--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.h
+++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.h
++@@ -216,7 +216,7 @@ struct brcmf_if *brcmf_get_ifp(struct br
++ int brcmf_net_attach(struct brcmf_if *ifp, bool rtnl_locked);
++ struct brcmf_if *brcmf_add_if(struct brcmf_pub *drvr, s32 bsscfgidx, s32 ifidx,
++ 			      bool is_p2pdev, char *name, u8 *mac_addr);
++-void brcmf_remove_interface(struct brcmf_if *ifp);
+++void brcmf_remove_interface(struct brcmf_if *ifp, bool rtnl_locked);
++ void brcmf_txflowblock_if(struct brcmf_if *ifp,
++ 			  enum brcmf_netif_stop_reason reason, bool state);
++ void brcmf_txfinalize(struct brcmf_if *ifp, struct sk_buff *txp, bool success);
++--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fweh.c
+++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fweh.c
++@@ -183,7 +183,7 @@ static void brcmf_fweh_handle_if_event(s
++ 	err = brcmf_fweh_call_event_handler(ifp, emsg->event_code, emsg, data);
++ 
++ 	if (ifp && ifevent->action == BRCMF_E_IF_DEL)
++-		brcmf_remove_interface(ifp);
+++		brcmf_remove_interface(ifp, false);
++ }
++ 
++ /**
++--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/p2p.c
+++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/p2p.c
++@@ -2289,7 +2289,7 @@ int brcmf_p2p_del_vif(struct wiphy *wiph
++ 			err = 0;
++ 	}
++ 	if (err)
++-		brcmf_remove_interface(vif->ifp);
+++		brcmf_remove_interface(vif->ifp, true);
++ 
++ 	brcmf_cfg80211_arm_vif_event(cfg, NULL);
++ 	if (vif->wdev.iftype != NL80211_IFTYPE_P2P_DEVICE)
++@@ -2395,7 +2395,7 @@ void brcmf_p2p_detach(struct brcmf_p2p_i
++ 	if (vif != NULL) {
++ 		brcmf_p2p_cancel_remain_on_channel(vif->ifp);
++ 		brcmf_p2p_deinit_discovery(p2p);
++-		brcmf_remove_interface(vif->ifp);
+++		brcmf_remove_interface(vif->ifp, false);
++ 	}
++ 	/* just set it all to zero */
++ 	memset(p2p, 0, sizeof(*p2p));
+diff --git a/package/kernel/mac80211/patches/319-0002-brcmfmac-use-const-char-for-interface-name-in-brcmf_.patch b/package/kernel/mac80211/patches/319-0002-brcmfmac-use-const-char-for-interface-name-in-brcmf_.patch
+new file mode 100644
+index 0000000..6d3f3c6
+--- /dev/null
++++ b/package/kernel/mac80211/patches/319-0002-brcmfmac-use-const-char-for-interface-name-in-brcmf_.patch
+@@ -0,0 +1,40 @@
++From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <zajec5@gmail.com>
++Date: Fri, 17 Jun 2016 12:48:44 +0200
++Subject: [PATCH] brcmfmac: use const char * for interface name in
++ brcmf_add_if
++MIME-Version: 1.0
++Content-Type: text/plain; charset=UTF-8
++Content-Transfer-Encoding: 8bit
++
++This function can work just fine with const pointer, it only calls
++alloc_netdev which take const as well. Moreover it makes this function
++more flexible as some cfg80211 callback may provide const char * as
++well, e.g. add_virtual_intf. This will be needed for more advanced
++interface management.
++
++Signed-off-by: Rafał Miłecki <zajec5@gmail.com>
++Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
++---
++
++--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
+++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
++@@ -638,7 +638,7 @@ fail:
++ }
++ 
++ struct brcmf_if *brcmf_add_if(struct brcmf_pub *drvr, s32 bsscfgidx, s32 ifidx,
++-			      bool is_p2pdev, char *name, u8 *mac_addr)
+++			      bool is_p2pdev, const char *name, u8 *mac_addr)
++ {
++ 	struct brcmf_if *ifp;
++ 	struct net_device *ndev;
++--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.h
+++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.h
++@@ -215,7 +215,7 @@ char *brcmf_ifname(struct brcmf_if *ifp)
++ struct brcmf_if *brcmf_get_ifp(struct brcmf_pub *drvr, int ifidx);
++ int brcmf_net_attach(struct brcmf_if *ifp, bool rtnl_locked);
++ struct brcmf_if *brcmf_add_if(struct brcmf_pub *drvr, s32 bsscfgidx, s32 ifidx,
++-			      bool is_p2pdev, char *name, u8 *mac_addr);
+++			      bool is_p2pdev, const char *name, u8 *mac_addr);
++ void brcmf_remove_interface(struct brcmf_if *ifp, bool rtnl_locked);
++ void brcmf_txflowblock_if(struct brcmf_if *ifp,
++ 			  enum brcmf_netif_stop_reason reason, bool state);
+diff --git a/package/kernel/mac80211/patches/319-0003-brcmfmac-include-also-core.h-header-in-cfg80211.h.patch b/package/kernel/mac80211/patches/319-0003-brcmfmac-include-also-core.h-header-in-cfg80211.h.patch
+new file mode 100644
+index 0000000..eeda766
+--- /dev/null
++++ b/package/kernel/mac80211/patches/319-0003-brcmfmac-include-also-core.h-header-in-cfg80211.h.patch
+@@ -0,0 +1,33 @@
++From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <zajec5@gmail.com>
++Date: Sat, 18 Jun 2016 18:49:38 +0200
++Subject: [PATCH] brcmfmac: include also core.h header in cfg80211.h
++MIME-Version: 1.0
++Content-Type: text/plain; charset=UTF-8
++Content-Transfer-Encoding: 8bit
++
++This header provides two inline functions using struct brcmf_if so we
++need core.h to avoid:
++
++drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.h: In function ‘ndev_to_prof’:
++drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.h:368:13: error: dereferencing pointer to incomplete type
++  return &ifp->vif->profile;
++             ^
++drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.h: In function ‘ndev_to_vif’:
++drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.h:374:12: error: dereferencing pointer to incomplete type
++  return ifp->vif;
++            ^
++
++Signed-off-by: Rafał Miłecki <zajec5@gmail.com>
++Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
++---
++
++--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.h
+++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.h
++@@ -20,6 +20,7 @@
++ /* for brcmu_d11inf */
++ #include <brcmu_d11.h>
++ 
+++#include "core.h"
++ #include "fwil_types.h"
++ #include "p2p.h"
++ 
+diff --git a/package/kernel/mac80211/patches/319-0004-brcmfmac-add-missing-break-when-deleting-P2P_DEVICE.patch b/package/kernel/mac80211/patches/319-0004-brcmfmac-add-missing-break-when-deleting-P2P_DEVICE.patch
+new file mode 100644
+index 0000000..3819248
+--- /dev/null
++++ b/package/kernel/mac80211/patches/319-0004-brcmfmac-add-missing-break-when-deleting-P2P_DEVICE.patch
+@@ -0,0 +1,27 @@
++From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <zajec5@gmail.com>
++Date: Sun, 19 Jun 2016 01:55:57 +0200
++Subject: [PATCH] brcmfmac: add missing break when deleting P2P_DEVICE
++MIME-Version: 1.0
++Content-Type: text/plain; charset=UTF-8
++Content-Transfer-Encoding: 8bit
++
++We obviously don't want to fall through in that switch. With this change
++1) We wait for event (triggered by p2p_disc) as expected
++2) We remove interface manually on timeout
++3) We return 0 on success instead of -ENOTSUPP
++
++Signed-off-by: Rafał Miłecki <zajec5@gmail.com>
++Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
++---
++
++--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/p2p.c
+++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/p2p.c
++@@ -2263,6 +2263,8 @@ int brcmf_p2p_del_vif(struct wiphy *wiph
++ 			return 0;
++ 		brcmf_p2p_cancel_remain_on_channel(vif->ifp);
++ 		brcmf_p2p_deinit_discovery(p2p);
+++		break;
+++
++ 	default:
++ 		return -ENOTSUPP;
++ 	}
+diff --git a/package/kernel/mac80211/patches/319-0005-brcmfmac-delete-interface-directly-in-code-that-sent.patch b/package/kernel/mac80211/patches/319-0005-brcmfmac-delete-interface-directly-in-code-that-sent.patch
+new file mode 100644
+index 0000000..12d7eb4
+--- /dev/null
++++ b/package/kernel/mac80211/patches/319-0005-brcmfmac-delete-interface-directly-in-code-that-sent.patch
+@@ -0,0 +1,75 @@
++From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <zajec5@gmail.com>
++Date: Wed, 29 Jun 2016 21:54:26 +0200
++Subject: [PATCH] brcmfmac: delete interface directly in code that sent fw
++ request
++MIME-Version: 1.0
++Content-Type: text/plain; charset=UTF-8
++Content-Transfer-Encoding: 8bit
++
++So far when receiving event about in-firmware-interface removal our
++event worker was notifying listener and afterwards it was removing Linux
++interface.
++
++First of all it was resulting in slightly unexpected order. The listener
++(del_virtual_intf callback) was (usually) returning with success before
++we even called unregister_netdev(ice).
++
++Please note this couldn't be simply fixed by changing order of calls in
++brcmf_fweh_handle_if_event as unregistering interface earlier could free
++struct brcmf_if.
++
++Another problem of current implementation are possible lockups. Focus on
++the time slot between calling event handler and removing Linux
++interface. During that time original caller may leave (unlocking rtnl
++semaphore) *and* another call to the same code may be done (locking it
++again). If that happens our event handler will stuck at removing Linux
++interface, it won't handle another event and will block process holding
++rtnl lock.
++
++This can be simply solved by unregistering interface in a proper
++callback, right after receiving confirmation event from firmware. This
++only required modifying worker to don't unregister on its own if there
++is someone waiting for the event.
++
++Signed-off-by: Rafał Miłecki <zajec5@gmail.com>
++Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
++---
++
++--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fweh.c
+++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fweh.c
++@@ -18,6 +18,7 @@
++ #include "brcmu_wifi.h"
++ #include "brcmu_utils.h"
++ 
+++#include "cfg80211.h"
++ #include "core.h"
++ #include "debug.h"
++ #include "tracepoint.h"
++@@ -182,8 +183,13 @@ static void brcmf_fweh_handle_if_event(s
++ 
++ 	err = brcmf_fweh_call_event_handler(ifp, emsg->event_code, emsg, data);
++ 
++-	if (ifp && ifevent->action == BRCMF_E_IF_DEL)
++-		brcmf_remove_interface(ifp, false);
+++	if (ifp && ifevent->action == BRCMF_E_IF_DEL) {
+++		bool armed = brcmf_cfg80211_vif_event_armed(drvr->config);
+++
+++		/* Default handling in case no-one waits for this event */
+++		if (!armed)
+++			brcmf_remove_interface(ifp, false);
+++	}
++ }
++ 
++ /**
++--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/p2p.c
+++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/p2p.c
++@@ -2290,8 +2290,7 @@ int brcmf_p2p_del_vif(struct wiphy *wiph
++ 		else
++ 			err = 0;
++ 	}
++-	if (err)
++-		brcmf_remove_interface(vif->ifp, true);
+++	brcmf_remove_interface(vif->ifp, true);
++ 
++ 	brcmf_cfg80211_arm_vif_event(cfg, NULL);
++ 	if (vif->wdev.iftype != NL80211_IFTYPE_P2P_DEVICE)
+diff --git a/package/kernel/mac80211/patches/319-0006-brcmfmac-support-removing-AP-interfaces-with-interfa.patch b/package/kernel/mac80211/patches/319-0006-brcmfmac-support-removing-AP-interfaces-with-interfa.patch
+new file mode 100644
+index 0000000..2f7165e
+--- /dev/null
++++ b/package/kernel/mac80211/patches/319-0006-brcmfmac-support-removing-AP-interfaces-with-interfa.patch
+@@ -0,0 +1,84 @@
++From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <zajec5@gmail.com>
++Date: Wed, 29 Jun 2016 21:54:27 +0200
++Subject: [PATCH] brcmfmac: support removing AP interfaces with
++ "interface_remove"
++MIME-Version: 1.0
++Content-Type: text/plain; charset=UTF-8
++Content-Transfer-Encoding: 8bit
++
++New firmwares (e.g. 10.10.69.36 for BCM4366) support "interface_remove"
++for removing interfaces. Try to use this method on cfg80211 request. In
++case of older firmwares (e.g. 7.35.177.56 for BCM43602 as I tested) this
++will just result in firmware rejecting command and this won't change any
++behavior.
++
++Signed-off-by: Rafał Miłecki <zajec5@gmail.com>
++Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
++---
++
++--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
+++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
++@@ -785,12 +785,48 @@ s32 brcmf_notify_escan_complete(struct b
++ 	return err;
++ }
++ 
+++static int brcmf_cfg80211_del_ap_iface(struct wiphy *wiphy,
+++				       struct wireless_dev *wdev)
+++{
+++	struct brcmf_cfg80211_info *cfg = wiphy_priv(wiphy);
+++	struct net_device *ndev = wdev->netdev;
+++	struct brcmf_if *ifp = netdev_priv(ndev);
+++	int ret;
+++	int err;
+++
+++	brcmf_cfg80211_arm_vif_event(cfg, ifp->vif);
+++
+++	err = brcmf_fil_bsscfg_data_set(ifp, "interface_remove", NULL, 0);
+++	if (err) {
+++		brcmf_err("interface_remove failed %d\n", err);
+++		goto err_unarm;
+++	}
+++
+++	/* wait for firmware event */
+++	ret = brcmf_cfg80211_wait_vif_event(cfg, BRCMF_E_IF_DEL,
+++					    BRCMF_VIF_EVENT_TIMEOUT);
+++	if (!ret) {
+++		brcmf_err("timeout occurred\n");
+++		err = -EIO;
+++		goto err_unarm;
+++	}
+++
+++	brcmf_remove_interface(ifp, true);
+++
+++err_unarm:
+++	brcmf_cfg80211_arm_vif_event(cfg, NULL);
+++	return err;
+++}
+++
++ static
++ int brcmf_cfg80211_del_iface(struct wiphy *wiphy, struct wireless_dev *wdev)
++ {
++ 	struct brcmf_cfg80211_info *cfg = wiphy_priv(wiphy);
++ 	struct net_device *ndev = wdev->netdev;
++ 
+++	if (ndev && ndev == cfg_to_ndev(cfg))
+++		return -ENOTSUPP;
+++
++ 	/* vif event pending in firmware */
++ 	if (brcmf_cfg80211_vif_event_armed(cfg))
++ 		return -EBUSY;
++@@ -807,12 +843,13 @@ int brcmf_cfg80211_del_iface(struct wiph
++ 	switch (wdev->iftype) {
++ 	case NL80211_IFTYPE_ADHOC:
++ 	case NL80211_IFTYPE_STATION:
++-	case NL80211_IFTYPE_AP:
++ 	case NL80211_IFTYPE_AP_VLAN:
++ 	case NL80211_IFTYPE_WDS:
++ 	case NL80211_IFTYPE_MONITOR:
++ 	case NL80211_IFTYPE_MESH_POINT:
++ 		return -EOPNOTSUPP;
+++	case NL80211_IFTYPE_AP:
+++		return brcmf_cfg80211_del_ap_iface(wiphy, wdev);
++ 	case NL80211_IFTYPE_P2P_CLIENT:
++ 	case NL80211_IFTYPE_P2P_GO:
++ 	case NL80211_IFTYPE_P2P_DEVICE:
 diff --git a/package/kernel/mac80211/patches/319-cfg80211-add-function-for-802.3-conversion-with-sepa.patch b/package/kernel/mac80211/patches/319-cfg80211-add-function-for-802.3-conversion-with-sepa.patch
 deleted file mode 100644
 index b646ab3..0000000
@@ -3673,6 +5190,883 @@ index b646ab3..0000000
 - EXPORT_SYMBOL(ieee80211_data_to_8023);
 - 
 - int ieee80211_data_from_8023(struct sk_buff *skb, const u8 *addr,
+diff --git a/package/kernel/mac80211/patches/320-ath9k-Switch-to-using-mac80211-intermediate-software.patch b/package/kernel/mac80211/patches/320-ath9k-Switch-to-using-mac80211-intermediate-software.patch
+new file mode 100644
+index 0000000..f8b8f86
+--- /dev/null
++++ b/package/kernel/mac80211/patches/320-ath9k-Switch-to-using-mac80211-intermediate-software.patch
+@@ -0,0 +1,871 @@
++From: =?UTF-8?q?Toke=20H=C3=B8iland-J=C3=B8rgensen?= <toke@toke.dk>
++Date: Wed, 6 Jul 2016 21:34:17 +0200
++Subject: [PATCH] ath9k: Switch to using mac80211 intermediate software queues.
++MIME-Version: 1.0
++Content-Type: text/plain; charset=UTF-8
++Content-Transfer-Encoding: 8bit
++
++This switches ath9k over to using the mac80211 intermediate software
++queueing mechanism for data packets. It removes the queueing inside the
++driver, except for the retry queue, and instead pulls from mac80211 when
++a packet is needed. The retry queue is used to store a packet that was
++pulled but can't be sent immediately.
++
++The old code path in ath_tx_start that would queue packets has been
++removed completely, as has the qlen limit tunables (since there's no
++longer a queue in the driver to limit).
++
++Based on Tim's original patch set, but reworked quite thoroughly.
++
++Cc: Tim Shepard <shep@alum.mit.edu>
++Cc: Felix Fietkau <nbd@nbd.name>
++Signed-off-by: Toke Høiland-Jørgensen <toke@toke.dk>
++---
++
++--- a/drivers/net/wireless/ath/ath9k/ath9k.h
+++++ b/drivers/net/wireless/ath/ath9k/ath9k.h
++@@ -91,7 +91,6 @@ int ath_descdma_setup(struct ath_softc *
++ #define ATH_RXBUF               512
++ #define ATH_TXBUF               512
++ #define ATH_TXBUF_RESERVE       5
++-#define ATH_MAX_QDEPTH          (ATH_TXBUF / 4 - ATH_TXBUF_RESERVE)
++ #define ATH_TXMAXTRY            13
++ #define ATH_MAX_SW_RETRIES      30
++ 
++@@ -145,7 +144,9 @@ int ath_descdma_setup(struct ath_softc *
++ #define BAW_WITHIN(_start, _bawsz, _seqno) \
++ 	((((_seqno) - (_start)) & 4095) < (_bawsz))
++ 
++-#define ATH_AN_2_TID(_an, _tidno)  (&(_an)->tid[(_tidno)])
+++#define ATH_STA_2_TID(_sta, _tidno) ((struct ath_atx_tid *)(_sta)->txq[_tidno]->drv_priv)
+++#define ATH_VIF_2_TID(_vif) ((struct ath_atx_tid *)(_vif)->txq->drv_priv)
+++#define ATH_AN_2_TID(_an, _tidno) ((_an)->sta ? ATH_STA_2_TID((_an)->sta, _tidno) : ATH_VIF_2_TID((_an)->vif))
++ 
++ #define IS_HT_RATE(rate)   (rate & 0x80)
++ #define IS_CCK_RATE(rate)  ((rate >= 0x18) && (rate <= 0x1e))
++@@ -164,7 +165,6 @@ struct ath_txq {
++ 	spinlock_t axq_lock;
++ 	u32 axq_depth;
++ 	u32 axq_ampdu_depth;
++-	bool stopped;
++ 	bool axq_tx_inprogress;
++ 	struct list_head txq_fifo[ATH_TXFIFO_DEPTH];
++ 	u8 txq_headidx;
++@@ -232,7 +232,6 @@ struct ath_buf {
++ 
++ struct ath_atx_tid {
++ 	struct list_head list;
++-	struct sk_buff_head buf_q;
++ 	struct sk_buff_head retry_q;
++ 	struct ath_node *an;
++ 	struct ath_txq *txq;
++@@ -247,13 +246,13 @@ struct ath_atx_tid {
++ 	s8 bar_index;
++ 	bool active;
++ 	bool clear_ps_filter;
+++	bool has_queued;
++ };
++ 
++ struct ath_node {
++ 	struct ath_softc *sc;
++ 	struct ieee80211_sta *sta; /* station struct we're part of */
++ 	struct ieee80211_vif *vif; /* interface with which we're associated */
++-	struct ath_atx_tid tid[IEEE80211_NUM_TIDS];
++ 
++ 	u16 maxampdu;
++ 	u8 mpdudensity;
++@@ -276,7 +275,6 @@ struct ath_tx_control {
++ 	struct ath_node *an;
++ 	struct ieee80211_sta *sta;
++ 	u8 paprd;
++-	bool force_channel;
++ };
++ 
++ 
++@@ -293,7 +291,6 @@ struct ath_tx {
++ 	struct ath_descdma txdma;
++ 	struct ath_txq *txq_map[IEEE80211_NUM_ACS];
++ 	struct ath_txq *uapsdq;
++-	u32 txq_max_pending[IEEE80211_NUM_ACS];
++ 	u16 max_aggr_framelen[IEEE80211_NUM_ACS][4][32];
++ };
++ 
++@@ -585,6 +582,7 @@ void ath9k_release_buffered_frames(struc
++ 				   u16 tids, int nframes,
++ 				   enum ieee80211_frame_release_type reason,
++ 				   bool more_data);
+++void ath9k_wake_tx_queue(struct ieee80211_hw *hw, struct ieee80211_txq *queue);
++ 
++ /********/
++ /* VIFs */
++--- a/drivers/net/wireless/ath/ath9k/channel.c
+++++ b/drivers/net/wireless/ath/ath9k/channel.c
++@@ -1007,7 +1007,6 @@ static void ath_scan_send_probe(struct a
++ 		goto error;
++ 
++ 	txctl.txq = sc->tx.txq_map[IEEE80211_AC_VO];
++-	txctl.force_channel = true;
++ 	if (ath_tx_start(sc->hw, skb, &txctl))
++ 		goto error;
++ 
++@@ -1130,7 +1129,6 @@ ath_chanctx_send_vif_ps_frame(struct ath
++ 	memset(&txctl, 0, sizeof(txctl));
++ 	txctl.txq = sc->tx.txq_map[IEEE80211_AC_VO];
++ 	txctl.sta = sta;
++-	txctl.force_channel = true;
++ 	if (ath_tx_start(sc->hw, skb, &txctl)) {
++ 		ieee80211_free_txskb(sc->hw, skb);
++ 		return false;
++--- a/drivers/net/wireless/ath/ath9k/debug.c
+++++ b/drivers/net/wireless/ath/ath9k/debug.c
++@@ -600,7 +600,6 @@ static int read_file_xmit(struct seq_fil
++ 	PR("MPDUs XRetried:  ", xretries);
++ 	PR("Aggregates:      ", a_aggr);
++ 	PR("AMPDUs Queued HW:", a_queued_hw);
++-	PR("AMPDUs Queued SW:", a_queued_sw);
++ 	PR("AMPDUs Completed:", a_completed);
++ 	PR("AMPDUs Retried:  ", a_retries);
++ 	PR("AMPDUs XRetried: ", a_xretries);
++@@ -629,8 +628,7 @@ static void print_queue(struct ath_softc
++ 	seq_printf(file, "%s: %d ", "qnum", txq->axq_qnum);
++ 	seq_printf(file, "%s: %2d ", "qdepth", txq->axq_depth);
++ 	seq_printf(file, "%s: %2d ", "ampdu-depth", txq->axq_ampdu_depth);
++-	seq_printf(file, "%s: %3d ", "pending", txq->pending_frames);
++-	seq_printf(file, "%s: %d\n", "stopped", txq->stopped);
+++	seq_printf(file, "%s: %3d\n", "pending", txq->pending_frames);
++ 
++ 	ath_txq_unlock(sc, txq);
++ }
++@@ -1208,7 +1206,6 @@ static const char ath9k_gstrings_stats[]
++ 	AMKSTR(d_tx_mpdu_xretries),
++ 	AMKSTR(d_tx_aggregates),
++ 	AMKSTR(d_tx_ampdus_queued_hw),
++-	AMKSTR(d_tx_ampdus_queued_sw),
++ 	AMKSTR(d_tx_ampdus_completed),
++ 	AMKSTR(d_tx_ampdu_retries),
++ 	AMKSTR(d_tx_ampdu_xretries),
++@@ -1288,7 +1285,6 @@ void ath9k_get_et_stats(struct ieee80211
++ 	AWDATA(xretries);
++ 	AWDATA(a_aggr);
++ 	AWDATA(a_queued_hw);
++-	AWDATA(a_queued_sw);
++ 	AWDATA(a_completed);
++ 	AWDATA(a_retries);
++ 	AWDATA(a_xretries);
++@@ -1346,14 +1342,6 @@ int ath9k_init_debug(struct ath_hw *ah)
++ 				    read_file_xmit);
++ 	debugfs_create_devm_seqfile(sc->dev, "queues", sc->debug.debugfs_phy,
++ 				    read_file_queues);
++-	debugfs_create_u32("qlen_bk", S_IRUSR | S_IWUSR, sc->debug.debugfs_phy,
++-			   &sc->tx.txq_max_pending[IEEE80211_AC_BK]);
++-	debugfs_create_u32("qlen_be", S_IRUSR | S_IWUSR, sc->debug.debugfs_phy,
++-			   &sc->tx.txq_max_pending[IEEE80211_AC_BE]);
++-	debugfs_create_u32("qlen_vi", S_IRUSR | S_IWUSR, sc->debug.debugfs_phy,
++-			   &sc->tx.txq_max_pending[IEEE80211_AC_VI]);
++-	debugfs_create_u32("qlen_vo", S_IRUSR | S_IWUSR, sc->debug.debugfs_phy,
++-			   &sc->tx.txq_max_pending[IEEE80211_AC_VO]);
++ 	debugfs_create_devm_seqfile(sc->dev, "misc", sc->debug.debugfs_phy,
++ 				    read_file_misc);
++ 	debugfs_create_devm_seqfile(sc->dev, "reset", sc->debug.debugfs_phy,
++--- a/drivers/net/wireless/ath/ath9k/debug.h
+++++ b/drivers/net/wireless/ath/ath9k/debug.h
++@@ -147,7 +147,6 @@ struct ath_interrupt_stats {
++  * @completed: Total MPDUs (non-aggr) completed
++  * @a_aggr: Total no. of aggregates queued
++  * @a_queued_hw: Total AMPDUs queued to hardware
++- * @a_queued_sw: Total AMPDUs queued to software queues
++  * @a_completed: Total AMPDUs completed
++  * @a_retries: No. of AMPDUs retried (SW)
++  * @a_xretries: No. of AMPDUs dropped due to xretries
++@@ -174,7 +173,6 @@ struct ath_tx_stats {
++ 	u32 xretries;
++ 	u32 a_aggr;
++ 	u32 a_queued_hw;
++-	u32 a_queued_sw;
++ 	u32 a_completed;
++ 	u32 a_retries;
++ 	u32 a_xretries;
++--- a/drivers/net/wireless/ath/ath9k/debug_sta.c
+++++ b/drivers/net/wireless/ath/ath9k/debug_sta.c
++@@ -52,8 +52,8 @@ static ssize_t read_file_node_aggr(struc
++ 			 "TID", "SEQ_START", "SEQ_NEXT", "BAW_SIZE",
++ 			 "BAW_HEAD", "BAW_TAIL", "BAR_IDX", "SCHED", "PAUSED");
++ 
++-	for (tidno = 0, tid = &an->tid[tidno];
++-	     tidno < IEEE80211_NUM_TIDS; tidno++, tid++) {
+++	for (tidno = 0; tidno < IEEE80211_NUM_TIDS; tidno++) {
+++		tid = ATH_STA_2_TID(an->sta, tidno);
++ 		txq = tid->txq;
++ 		ath_txq_lock(sc, txq);
++ 		if (tid->active) {
++--- a/drivers/net/wireless/ath/ath9k/init.c
+++++ b/drivers/net/wireless/ath/ath9k/init.c
++@@ -358,7 +358,6 @@ static int ath9k_init_queues(struct ath_
++ 	for (i = 0; i < IEEE80211_NUM_ACS; i++) {
++ 		sc->tx.txq_map[i] = ath_txq_setup(sc, ATH9K_TX_QUEUE_DATA, i);
++ 		sc->tx.txq_map[i]->mac80211_qnum = i;
++-		sc->tx.txq_max_pending[i] = ATH_MAX_QDEPTH;
++ 	}
++ 	return 0;
++ }
++@@ -873,6 +872,7 @@ static void ath9k_set_hw_capab(struct at
++ 	hw->max_rate_tries = 10;
++ 	hw->sta_data_size = sizeof(struct ath_node);
++ 	hw->vif_data_size = sizeof(struct ath_vif);
+++	hw->txq_data_size = sizeof(struct ath_atx_tid);
++ 	hw->extra_tx_headroom = 4;
++ 
++ 	hw->wiphy->available_antennas_rx = BIT(ah->caps.max_rxchains) - 1;
++--- a/drivers/net/wireless/ath/ath9k/main.c
+++++ b/drivers/net/wireless/ath/ath9k/main.c
++@@ -2695,4 +2695,5 @@ struct ieee80211_ops ath9k_ops = {
++ 	.sw_scan_start	    = ath9k_sw_scan_start,
++ 	.sw_scan_complete   = ath9k_sw_scan_complete,
++ 	.get_txpower        = ath9k_get_txpower,
+++	.wake_tx_queue      = ath9k_wake_tx_queue,
++ };
++--- a/drivers/net/wireless/ath/ath9k/xmit.c
+++++ b/drivers/net/wireless/ath/ath9k/xmit.c
++@@ -65,6 +65,8 @@ static struct ath_buf *ath_tx_setup_buff
++ 					   struct ath_txq *txq,
++ 					   struct ath_atx_tid *tid,
++ 					   struct sk_buff *skb);
+++static int ath_tx_prepare(struct ieee80211_hw *hw, struct sk_buff *skb,
+++			  struct ath_tx_control *txctl);
++ 
++ enum {
++ 	MCS_HT20,
++@@ -118,6 +120,26 @@ static void ath_tx_queue_tid(struct ath_
++ 		list_add_tail(&tid->list, list);
++ }
++ 
+++void ath9k_wake_tx_queue(struct ieee80211_hw *hw, struct ieee80211_txq *queue)
+++{
+++	struct ath_softc *sc = hw->priv;
+++	struct ath_common *common = ath9k_hw_common(sc->sc_ah);
+++	struct ath_atx_tid *tid = (struct ath_atx_tid *) queue->drv_priv;
+++	struct ath_txq *txq = tid->txq;
+++
+++	ath_dbg(common, QUEUE, "Waking TX queue: %pM (%d)\n",
+++		queue->sta ? queue->sta->addr : queue->vif->addr,
+++		tid->tidno);
+++
+++	ath_txq_lock(sc, txq);
+++
+++	tid->has_queued = true;
+++	ath_tx_queue_tid(sc, txq, tid);
+++	ath_txq_schedule(sc, txq);
+++
+++	ath_txq_unlock(sc, txq);
+++}
+++
++ static struct ath_frame_info *get_frame_info(struct sk_buff *skb)
++ {
++ 	struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
++@@ -160,7 +182,6 @@ static void ath_set_rates(struct ieee802
++ static void ath_txq_skb_done(struct ath_softc *sc, struct ath_txq *txq,
++ 			     struct sk_buff *skb)
++ {
++-	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
++ 	struct ath_frame_info *fi = get_frame_info(skb);
++ 	int q = fi->txq;
++ 
++@@ -171,14 +192,6 @@ static void ath_txq_skb_done(struct ath_
++ 	if (WARN_ON(--txq->pending_frames < 0))
++ 		txq->pending_frames = 0;
++ 
++-	if (txq->stopped &&
++-	    txq->pending_frames < sc->tx.txq_max_pending[q]) {
++-		if (ath9k_is_chanctx_enabled())
++-			ieee80211_wake_queue(sc->hw, info->hw_queue);
++-		else
++-			ieee80211_wake_queue(sc->hw, q);
++-		txq->stopped = false;
++-	}
++ }
++ 
++ static struct ath_atx_tid *
++@@ -188,9 +201,47 @@ ath_get_skb_tid(struct ath_softc *sc, st
++ 	return ATH_AN_2_TID(an, tidno);
++ }
++ 
+++static struct sk_buff *
+++ath_tid_pull(struct ath_atx_tid *tid)
+++{
+++	struct ath_softc *sc = tid->an->sc;
+++	struct ieee80211_hw *hw = sc->hw;
+++	struct ath_tx_control txctl = {
+++		.txq = tid->txq,
+++		.sta = tid->an->sta,
+++	};
+++	struct sk_buff *skb;
+++	struct ath_frame_info *fi;
+++	int q;
+++
+++	if (!tid->has_queued)
+++		return NULL;
+++
+++	skb = ieee80211_tx_dequeue(hw, container_of((void*)tid, struct ieee80211_txq, drv_priv));
+++	if (!skb) {
+++		tid->has_queued = false;
+++		return NULL;
+++	}
+++
+++	if (ath_tx_prepare(hw, skb, &txctl)) {
+++		ieee80211_free_txskb(hw, skb);
+++		return NULL;
+++	}
+++
+++	q = skb_get_queue_mapping(skb);
+++	if (tid->txq == sc->tx.txq_map[q]) {
+++		fi = get_frame_info(skb);
+++		fi->txq = q;
+++		++tid->txq->pending_frames;
+++	}
+++
+++	return skb;
+++ }
+++
+++
++ static bool ath_tid_has_buffered(struct ath_atx_tid *tid)
++ {
++-	return !skb_queue_empty(&tid->buf_q) || !skb_queue_empty(&tid->retry_q);
+++	return !skb_queue_empty(&tid->retry_q) || tid->has_queued;
++ }
++ 
++ static struct sk_buff *ath_tid_dequeue(struct ath_atx_tid *tid)
++@@ -199,46 +250,11 @@ static struct sk_buff *ath_tid_dequeue(s
++ 
++ 	skb = __skb_dequeue(&tid->retry_q);
++ 	if (!skb)
++-		skb = __skb_dequeue(&tid->buf_q);
+++		skb = ath_tid_pull(tid);
++ 
++ 	return skb;
++ }
++ 
++-/*
++- * ath_tx_tid_change_state:
++- * - clears a-mpdu flag of previous session
++- * - force sequence number allocation to fix next BlockAck Window
++- */
++-static void
++-ath_tx_tid_change_state(struct ath_softc *sc, struct ath_atx_tid *tid)
++-{
++-	struct ath_txq *txq = tid->txq;
++-	struct ieee80211_tx_info *tx_info;
++-	struct sk_buff *skb, *tskb;
++-	struct ath_buf *bf;
++-	struct ath_frame_info *fi;
++-
++-	skb_queue_walk_safe(&tid->buf_q, skb, tskb) {
++-		fi = get_frame_info(skb);
++-		bf = fi->bf;
++-
++-		tx_info = IEEE80211_SKB_CB(skb);
++-		tx_info->flags &= ~IEEE80211_TX_CTL_AMPDU;
++-
++-		if (bf)
++-			continue;
++-
++-		bf = ath_tx_setup_buffer(sc, txq, tid, skb);
++-		if (!bf) {
++-			__skb_unlink(skb, &tid->buf_q);
++-			ath_txq_skb_done(sc, txq, skb);
++-			ieee80211_free_txskb(sc->hw, skb);
++-			continue;
++-		}
++-	}
++-
++-}
++-
++ static void ath_tx_flush_tid(struct ath_softc *sc, struct ath_atx_tid *tid)
++ {
++ 	struct ath_txq *txq = tid->txq;
++@@ -873,20 +889,16 @@ static int ath_compute_num_delims(struct
++ 
++ static struct ath_buf *
++ ath_tx_get_tid_subframe(struct ath_softc *sc, struct ath_txq *txq,
++-			struct ath_atx_tid *tid, struct sk_buff_head **q)
+++			struct ath_atx_tid *tid)
++ {
++ 	struct ieee80211_tx_info *tx_info;
++ 	struct ath_frame_info *fi;
++-	struct sk_buff *skb;
+++	struct sk_buff *skb, *first_skb = NULL;
++ 	struct ath_buf *bf;
++ 	u16 seqno;
++ 
++ 	while (1) {
++-		*q = &tid->retry_q;
++-		if (skb_queue_empty(*q))
++-			*q = &tid->buf_q;
++-
++-		skb = skb_peek(*q);
+++		skb = ath_tid_dequeue(tid);
++ 		if (!skb)
++ 			break;
++ 
++@@ -898,7 +910,6 @@ ath_tx_get_tid_subframe(struct ath_softc
++ 			bf->bf_state.stale = false;
++ 
++ 		if (!bf) {
++-			__skb_unlink(skb, *q);
++ 			ath_txq_skb_done(sc, txq, skb);
++ 			ieee80211_free_txskb(sc->hw, skb);
++ 			continue;
++@@ -927,8 +938,19 @@ ath_tx_get_tid_subframe(struct ath_softc
++ 		seqno = bf->bf_state.seqno;
++ 
++ 		/* do not step over block-ack window */
++-		if (!BAW_WITHIN(tid->seq_start, tid->baw_size, seqno))
+++		if (!BAW_WITHIN(tid->seq_start, tid->baw_size, seqno)) {
+++			__skb_queue_tail(&tid->retry_q, skb);
+++
+++			/* If there are other skbs in the retry q, they are
+++			 * probably within the BAW, so loop immediately to get
+++			 * one of them. Otherwise the queue can get stuck. */
+++			if (!skb_queue_is_first(&tid->retry_q, skb) && skb != first_skb) {
+++				if(!first_skb) /* infinite loop prevention */
+++					first_skb = skb;
+++				continue;
+++			}
++ 			break;
+++		}
++ 
++ 		if (tid->bar_index > ATH_BA_INDEX(tid->seq_start, seqno)) {
++ 			struct ath_tx_status ts = {};
++@@ -936,7 +958,6 @@ ath_tx_get_tid_subframe(struct ath_softc
++ 
++ 			INIT_LIST_HEAD(&bf_head);
++ 			list_add(&bf->list, &bf_head);
++-			__skb_unlink(skb, *q);
++ 			ath_tx_update_baw(sc, tid, seqno);
++ 			ath_tx_complete_buf(sc, bf, txq, &bf_head, &ts, 0);
++ 			continue;
++@@ -948,11 +969,10 @@ ath_tx_get_tid_subframe(struct ath_softc
++ 	return NULL;
++ }
++ 
++-static bool
+++static int
++ ath_tx_form_aggr(struct ath_softc *sc, struct ath_txq *txq,
++ 		 struct ath_atx_tid *tid, struct list_head *bf_q,
++-		 struct ath_buf *bf_first, struct sk_buff_head *tid_q,
++-		 int *aggr_len)
+++		 struct ath_buf *bf_first)
++ {
++ #define PADBYTES(_len) ((4 - ((_len) % 4)) % 4)
++ 	struct ath_buf *bf = bf_first, *bf_prev = NULL;
++@@ -962,12 +982,13 @@ ath_tx_form_aggr(struct ath_softc *sc, s
++ 	struct ieee80211_tx_info *tx_info;
++ 	struct ath_frame_info *fi;
++ 	struct sk_buff *skb;
++-	bool closed = false;
+++
++ 
++ 	bf = bf_first;
++ 	aggr_limit = ath_lookup_rate(sc, bf, tid);
++ 
++-	do {
+++	while (bf)
+++	{
++ 		skb = bf->bf_mpdu;
++ 		fi = get_frame_info(skb);
++ 
++@@ -976,12 +997,12 @@ ath_tx_form_aggr(struct ath_softc *sc, s
++ 		if (nframes) {
++ 			if (aggr_limit < al + bpad + al_delta ||
++ 			    ath_lookup_legacy(bf) || nframes >= h_baw)
++-				break;
+++				goto stop;
++ 
++ 			tx_info = IEEE80211_SKB_CB(bf->bf_mpdu);
++ 			if ((tx_info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE) ||
++ 			    !(tx_info->flags & IEEE80211_TX_CTL_AMPDU))
++-				break;
+++				goto stop;
++ 		}
++ 
++ 		/* add padding for previous frame to aggregation length */
++@@ -1003,20 +1024,18 @@ ath_tx_form_aggr(struct ath_softc *sc, s
++ 			ath_tx_addto_baw(sc, tid, bf);
++ 		bf->bf_state.ndelim = ndelim;
++ 
++-		__skb_unlink(skb, tid_q);
++ 		list_add_tail(&bf->list, bf_q);
++ 		if (bf_prev)
++ 			bf_prev->bf_next = bf;
++ 
++ 		bf_prev = bf;
++ 
++-		bf = ath_tx_get_tid_subframe(sc, txq, tid, &tid_q);
++-		if (!bf) {
++-			closed = true;
++-			break;
++-		}
++-	} while (ath_tid_has_buffered(tid));
++-
+++		bf = ath_tx_get_tid_subframe(sc, txq, tid);
+++	}
+++	goto finish;
+++stop:
+++	__skb_queue_tail(&tid->retry_q, bf->bf_mpdu);
+++finish:
++ 	bf = bf_first;
++ 	bf->bf_lastbf = bf_prev;
++ 
++@@ -1027,9 +1046,7 @@ ath_tx_form_aggr(struct ath_softc *sc, s
++ 		TX_STAT_INC(txq->axq_qnum, a_aggr);
++ 	}
++ 
++-	*aggr_len = al;
++-
++-	return closed;
+++	return al;
++ #undef PADBYTES
++ }
++ 
++@@ -1406,18 +1423,15 @@ static void ath_tx_fill_desc(struct ath_
++ static void
++ ath_tx_form_burst(struct ath_softc *sc, struct ath_txq *txq,
++ 		  struct ath_atx_tid *tid, struct list_head *bf_q,
++-		  struct ath_buf *bf_first, struct sk_buff_head *tid_q)
+++		  struct ath_buf *bf_first)
++ {
++ 	struct ath_buf *bf = bf_first, *bf_prev = NULL;
++-	struct sk_buff *skb;
++ 	int nframes = 0;
++ 
++ 	do {
++ 		struct ieee80211_tx_info *tx_info;
++-		skb = bf->bf_mpdu;
++ 
++ 		nframes++;
++-		__skb_unlink(skb, tid_q);
++ 		list_add_tail(&bf->list, bf_q);
++ 		if (bf_prev)
++ 			bf_prev->bf_next = bf;
++@@ -1426,13 +1440,15 @@ ath_tx_form_burst(struct ath_softc *sc,
++ 		if (nframes >= 2)
++ 			break;
++ 
++-		bf = ath_tx_get_tid_subframe(sc, txq, tid, &tid_q);
+++		bf = ath_tx_get_tid_subframe(sc, txq, tid);
++ 		if (!bf)
++ 			break;
++ 
++ 		tx_info = IEEE80211_SKB_CB(bf->bf_mpdu);
++-		if (tx_info->flags & IEEE80211_TX_CTL_AMPDU)
+++		if (tx_info->flags & IEEE80211_TX_CTL_AMPDU) {
+++			__skb_queue_tail(&tid->retry_q, bf->bf_mpdu);
++ 			break;
+++		}
++ 
++ 		ath_set_rates(tid->an->vif, tid->an->sta, bf, false);
++ 	} while (1);
++@@ -1443,34 +1459,33 @@ static bool ath_tx_sched_aggr(struct ath
++ {
++ 	struct ath_buf *bf;
++ 	struct ieee80211_tx_info *tx_info;
++-	struct sk_buff_head *tid_q;
++ 	struct list_head bf_q;
++ 	int aggr_len = 0;
++-	bool aggr, last = true;
+++	bool aggr;
++ 
++ 	if (!ath_tid_has_buffered(tid))
++ 		return false;
++ 
++ 	INIT_LIST_HEAD(&bf_q);
++ 
++-	bf = ath_tx_get_tid_subframe(sc, txq, tid, &tid_q);
+++	bf = ath_tx_get_tid_subframe(sc, txq, tid);
++ 	if (!bf)
++ 		return false;
++ 
++ 	tx_info = IEEE80211_SKB_CB(bf->bf_mpdu);
++ 	aggr = !!(tx_info->flags & IEEE80211_TX_CTL_AMPDU);
++ 	if ((aggr && txq->axq_ampdu_depth >= ATH_AGGR_MIN_QDEPTH) ||
++-		(!aggr && txq->axq_depth >= ATH_NON_AGGR_MIN_QDEPTH)) {
+++	    (!aggr && txq->axq_depth >= ATH_NON_AGGR_MIN_QDEPTH)) {
+++		__skb_queue_tail(&tid->retry_q, bf->bf_mpdu);
++ 		*stop = true;
++ 		return false;
++ 	}
++ 
++ 	ath_set_rates(tid->an->vif, tid->an->sta, bf, false);
++ 	if (aggr)
++-		last = ath_tx_form_aggr(sc, txq, tid, &bf_q, bf,
++-					tid_q, &aggr_len);
+++		aggr_len = ath_tx_form_aggr(sc, txq, tid, &bf_q, bf);
++ 	else
++-		ath_tx_form_burst(sc, txq, tid, &bf_q, bf, tid_q);
+++		ath_tx_form_burst(sc, txq, tid, &bf_q, bf);
++ 
++ 	if (list_empty(&bf_q))
++ 		return false;
++@@ -1513,9 +1528,6 @@ int ath_tx_aggr_start(struct ath_softc *
++ 		an->mpdudensity = density;
++ 	}
++ 
++-	/* force sequence number allocation for pending frames */
++-	ath_tx_tid_change_state(sc, txtid);
++-
++ 	txtid->active = true;
++ 	*ssn = txtid->seq_start = txtid->seq_next;
++ 	txtid->bar_index = -1;
++@@ -1540,7 +1552,6 @@ void ath_tx_aggr_stop(struct ath_softc *
++ 	ath_txq_lock(sc, txq);
++ 	txtid->active = false;
++ 	ath_tx_flush_tid(sc, txtid);
++-	ath_tx_tid_change_state(sc, txtid);
++ 	ath_txq_unlock_complete(sc, txq);
++ }
++ 
++@@ -1550,14 +1561,12 @@ void ath_tx_aggr_sleep(struct ieee80211_
++ 	struct ath_common *common = ath9k_hw_common(sc->sc_ah);
++ 	struct ath_atx_tid *tid;
++ 	struct ath_txq *txq;
++-	bool buffered;
++ 	int tidno;
++ 
++ 	ath_dbg(common, XMIT, "%s called\n", __func__);
++ 
++-	for (tidno = 0, tid = &an->tid[tidno];
++-	     tidno < IEEE80211_NUM_TIDS; tidno++, tid++) {
++-
+++	for (tidno = 0; tidno < IEEE80211_NUM_TIDS; tidno++) {
+++		tid = ATH_AN_2_TID(an, tidno);
++ 		txq = tid->txq;
++ 
++ 		ath_txq_lock(sc, txq);
++@@ -1567,13 +1576,12 @@ void ath_tx_aggr_sleep(struct ieee80211_
++ 			continue;
++ 		}
++ 
++-		buffered = ath_tid_has_buffered(tid);
+++		if (!skb_queue_empty(&tid->retry_q))
+++			ieee80211_sta_set_buffered(sta, tid->tidno, true);
++ 
++ 		list_del_init(&tid->list);
++ 
++ 		ath_txq_unlock(sc, txq);
++-
++-		ieee80211_sta_set_buffered(sta, tidno, buffered);
++ 	}
++ }
++ 
++@@ -1586,19 +1594,16 @@ void ath_tx_aggr_wakeup(struct ath_softc
++ 
++ 	ath_dbg(common, XMIT, "%s called\n", __func__);
++ 
++-	for (tidno = 0, tid = &an->tid[tidno];
++-	     tidno < IEEE80211_NUM_TIDS; tidno++, tid++) {
++-
+++	for (tidno = 0; tidno < IEEE80211_NUM_TIDS; tidno++) {
+++		tid = ATH_AN_2_TID(an, tidno);
++ 		txq = tid->txq;
++ 
++ 		ath_txq_lock(sc, txq);
++ 		tid->clear_ps_filter = true;
++-
++ 		if (ath_tid_has_buffered(tid)) {
++ 			ath_tx_queue_tid(sc, txq, tid);
++ 			ath_txq_schedule(sc, txq);
++ 		}
++-
++ 		ath_txq_unlock_complete(sc, txq);
++ 	}
++ }
++@@ -1621,11 +1626,6 @@ void ath_tx_aggr_resume(struct ath_softc
++ 
++ 	tid->baw_size = IEEE80211_MIN_AMPDU_BUF << sta->ht_cap.ampdu_factor;
++ 
++-	if (ath_tid_has_buffered(tid)) {
++-		ath_tx_queue_tid(sc, txq, tid);
++-		ath_txq_schedule(sc, txq);
++-	}
++-
++ 	ath_txq_unlock_complete(sc, txq);
++ }
++ 
++@@ -1641,7 +1641,6 @@ void ath9k_release_buffered_frames(struc
++ 	struct ieee80211_tx_info *info;
++ 	struct list_head bf_q;
++ 	struct ath_buf *bf_tail = NULL, *bf;
++-	struct sk_buff_head *tid_q;
++ 	int sent = 0;
++ 	int i;
++ 
++@@ -1656,11 +1655,10 @@ void ath9k_release_buffered_frames(struc
++ 
++ 		ath_txq_lock(sc, tid->txq);
++ 		while (nframes > 0) {
++-			bf = ath_tx_get_tid_subframe(sc, sc->tx.uapsdq, tid, &tid_q);
+++			bf = ath_tx_get_tid_subframe(sc, sc->tx.uapsdq, tid);
++ 			if (!bf)
++ 				break;
++ 
++-			__skb_unlink(bf->bf_mpdu, tid_q);
++ 			list_add_tail(&bf->list, &bf_q);
++ 			ath_set_rates(tid->an->vif, tid->an->sta, bf, true);
++ 			if (bf_isampdu(bf)) {
++@@ -1675,7 +1673,7 @@ void ath9k_release_buffered_frames(struc
++ 			sent++;
++ 			TX_STAT_INC(txq->axq_qnum, a_queued_hw);
++ 
++-			if (an->sta && !ath_tid_has_buffered(tid))
+++			if (an->sta && skb_queue_empty(&tid->retry_q))
++ 				ieee80211_sta_set_buffered(an->sta, i, false);
++ 		}
++ 		ath_txq_unlock_complete(sc, tid->txq);
++@@ -1902,13 +1900,7 @@ bool ath_drain_all_txq(struct ath_softc
++ 		if (!ATH_TXQ_SETUP(sc, i))
++ 			continue;
++ 
++-		/*
++-		 * The caller will resume queues with ieee80211_wake_queues.
++-		 * Mark the queue as not stopped to prevent ath_tx_complete
++-		 * from waking the queue too early.
++-		 */
++ 		txq = &sc->tx.txq[i];
++-		txq->stopped = false;
++ 		ath_draintxq(sc, txq);
++ 	}
++ 
++@@ -2308,15 +2300,12 @@ int ath_tx_start(struct ieee80211_hw *hw
++ 	struct ath_txq *txq = txctl->txq;
++ 	struct ath_atx_tid *tid = NULL;
++ 	struct ath_buf *bf;
++-	bool queue, ps_resp;
+++	bool ps_resp;
++ 	int q, ret;
++ 
++ 	if (vif)
++ 		avp = (void *)vif->drv_priv;
++ 
++-	if (info->flags & IEEE80211_TX_CTL_TX_OFFCHAN)
++-		txctl->force_channel = true;
++-
++ 	ps_resp = !!(info->control.flags & IEEE80211_TX_CTRL_PS_RESPONSE);
++ 
++ 	ret = ath_tx_prepare(hw, skb, txctl);
++@@ -2331,63 +2320,13 @@ int ath_tx_start(struct ieee80211_hw *hw
++ 
++ 	q = skb_get_queue_mapping(skb);
++ 
+++	if (ps_resp)
+++		txq = sc->tx.uapsdq;
+++
++ 	ath_txq_lock(sc, txq);
++ 	if (txq == sc->tx.txq_map[q]) {
++ 		fi->txq = q;
++-		if (++txq->pending_frames > sc->tx.txq_max_pending[q] &&
++-		    !txq->stopped) {
++-			if (ath9k_is_chanctx_enabled())
++-				ieee80211_stop_queue(sc->hw, info->hw_queue);
++-			else
++-				ieee80211_stop_queue(sc->hw, q);
++-			txq->stopped = true;
++-		}
++-	}
++-
++-	queue = ieee80211_is_data_present(hdr->frame_control);
++-
++-	/* If chanctx, queue all null frames while NOA could be there */
++-	if (ath9k_is_chanctx_enabled() &&
++-	    ieee80211_is_nullfunc(hdr->frame_control) &&
++-	    !txctl->force_channel)
++-		queue = true;
++-
++-	/* Force queueing of all frames that belong to a virtual interface on
++-	 * a different channel context, to ensure that they are sent on the
++-	 * correct channel.
++-	 */
++-	if (((avp && avp->chanctx != sc->cur_chan) ||
++-	     sc->cur_chan->stopped) && !txctl->force_channel) {
++-		if (!txctl->an)
++-			txctl->an = &avp->mcast_node;
++-		queue = true;
++-		ps_resp = false;
++-	}
++-
++-	if (txctl->an && queue)
++-		tid = ath_get_skb_tid(sc, txctl->an, skb);
++-
++-	if (ps_resp) {
++-		ath_txq_unlock(sc, txq);
++-		txq = sc->tx.uapsdq;
++-		ath_txq_lock(sc, txq);
++-	} else if (txctl->an && queue) {
++-		WARN_ON(tid->txq != txctl->txq);
++-
++-		if (info->flags & IEEE80211_TX_CTL_CLEAR_PS_FILT)
++-			tid->clear_ps_filter = true;
++-
++-		/*
++-		 * Add this frame to software queue for scheduling later
++-		 * for aggregation.
++-		 */
++-		TX_STAT_INC(txq->axq_qnum, a_queued_sw);
++-		__skb_queue_tail(&tid->buf_q, skb);
++-		if (!txctl->an->sleeping)
++-			ath_tx_queue_tid(sc, txq, tid);
++-
++-		ath_txq_schedule(sc, txq);
++-		goto out;
+++		++txq->pending_frames;
++ 	}
++ 
++ 	bf = ath_tx_setup_buffer(sc, txq, tid, skb);
++@@ -2871,9 +2810,8 @@ void ath_tx_node_init(struct ath_softc *
++ 	struct ath_atx_tid *tid;
++ 	int tidno, acno;
++ 
++-	for (tidno = 0, tid = &an->tid[tidno];
++-	     tidno < IEEE80211_NUM_TIDS;
++-	     tidno++, tid++) {
+++	for (tidno = 0; tidno < IEEE80211_NUM_TIDS; tidno++) {
+++		tid = ATH_AN_2_TID(an, tidno);
++ 		tid->an        = an;
++ 		tid->tidno     = tidno;
++ 		tid->seq_start = tid->seq_next = 0;
++@@ -2881,11 +2819,14 @@ void ath_tx_node_init(struct ath_softc *
++ 		tid->baw_head  = tid->baw_tail = 0;
++ 		tid->active	   = false;
++ 		tid->clear_ps_filter = true;
++-		__skb_queue_head_init(&tid->buf_q);
+++		tid->has_queued  = false;
++ 		__skb_queue_head_init(&tid->retry_q);
++ 		INIT_LIST_HEAD(&tid->list);
++ 		acno = TID_TO_WME_AC(tidno);
++ 		tid->txq = sc->tx.txq_map[acno];
+++
+++		if (!an->sta)
+++			break; /* just one multicast ath_atx_tid */
++ 	}
++ }
++ 
++@@ -2895,9 +2836,8 @@ void ath_tx_node_cleanup(struct ath_soft
++ 	struct ath_txq *txq;
++ 	int tidno;
++ 
++-	for (tidno = 0, tid = &an->tid[tidno];
++-	     tidno < IEEE80211_NUM_TIDS; tidno++, tid++) {
++-
+++	for (tidno = 0; tidno < IEEE80211_NUM_TIDS; tidno++) {
+++		tid = ATH_AN_2_TID(an, tidno);
++ 		txq = tid->txq;
++ 
++ 		ath_txq_lock(sc, txq);
++@@ -2909,6 +2849,9 @@ void ath_tx_node_cleanup(struct ath_soft
++ 		tid->active = false;
++ 
++ 		ath_txq_unlock(sc, txq);
+++
+++		if (!an->sta)
+++			break; /* just one multicast ath_atx_tid */
++ 	}
++ }
++ 
 diff --git a/package/kernel/mac80211/patches/320-cfg80211-add-support-for-non-linear-skbs-in-ieee8021.patch b/package/kernel/mac80211/patches/320-cfg80211-add-support-for-non-linear-skbs-in-ieee8021.patch
 deleted file mode 100644
 index 2eeed22..0000000
@@ -3838,6 +6232,37 @@ index 2eeed22..0000000
 - 	return;
 - 
 -  purge:
+diff --git a/package/kernel/mac80211/patches/321-ath9k_hw-reset-AHB-WMAC-interface-on-AR91xx.patch b/package/kernel/mac80211/patches/321-ath9k_hw-reset-AHB-WMAC-interface-on-AR91xx.patch
+new file mode 100644
+index 0000000..9caa76d
+--- /dev/null
++++ b/package/kernel/mac80211/patches/321-ath9k_hw-reset-AHB-WMAC-interface-on-AR91xx.patch
+@@ -0,0 +1,25 @@
++From: Felix Fietkau <nbd@nbd.name>
++Date: Sat, 9 Jul 2016 15:25:24 +0200
++Subject: [PATCH] ath9k_hw: reset AHB-WMAC interface on AR91xx
++
++Should fix a few stability issues
++
++Signed-off-by: Felix Fietkau <nbd@nbd.name>
++---
++
++--- a/drivers/net/wireless/ath/ath9k/hw.c
+++++ b/drivers/net/wireless/ath/ath9k/hw.c
++@@ -1398,8 +1398,12 @@ static bool ath9k_hw_set_reset(struct at
++ 	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);
+++	}
++ 
++ 	return true;
++ }
 diff --git a/package/kernel/mac80211/patches/321-mac80211-Parse-legacy-and-HT-rate-in-injected-frames.patch b/package/kernel/mac80211/patches/321-mac80211-Parse-legacy-and-HT-rate-in-injected-frames.patch
 deleted file mode 100644
 index c4155a1..0000000
@@ -3999,6 +6424,137 @@ index c4155a1..0000000
 - 		goto fail;
 - 
 - 	rcu_read_lock();
+diff --git a/package/kernel/mac80211/patches/322-ath9k_hw-issue-external-reset-for-QCA9550.patch b/package/kernel/mac80211/patches/322-ath9k_hw-issue-external-reset-for-QCA9550.patch
+new file mode 100644
+index 0000000..5d4e849
+--- /dev/null
++++ b/package/kernel/mac80211/patches/322-ath9k_hw-issue-external-reset-for-QCA9550.patch
+@@ -0,0 +1,125 @@
++From: Felix Fietkau <nbd@nbd.name>
++Date: Sat, 9 Jul 2016 15:26:44 +0200
++Subject: [PATCH] ath9k_hw: issue external reset for QCA9550
++
++The RTC interface on the SoC needs to be reset along with the rest of
++the WMAC.
++
++Signed-off-by: Felix Fietkau <nbd@nbd.name>
++---
++
++--- a/drivers/net/wireless/ath/ath9k/hw.c
+++++ b/drivers/net/wireless/ath/ath9k/hw.c
++@@ -1275,39 +1275,56 @@ void ath9k_hw_get_delta_slope_vals(struc
++ 	*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, 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, 0);
+++		udelay(10);
++ 	}
++ 
+++	REG_WRITE(ah, AR_RTC_RESET, 1);
+++	udelay(10);
+++
++ 	return true;
++ }
++ 
++@@ -1360,24 +1377,23 @@ static bool ath9k_hw_set_reset(struct at
++ 			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);
++ 	}
++ 
+++	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, rst_flags);
++ 
++ 	REGWRITE_BUFFER_FLUSH(ah);
 diff --git a/package/kernel/mac80211/patches/322-mac80211-add-A-MSDU-tx-support.patch b/package/kernel/mac80211/patches/322-mac80211-add-A-MSDU-tx-support.patch
 deleted file mode 100644
 index e7bfb9c..0000000
@@ -4730,6 +7286,130 @@ index 35887fc..0000000
 - 	BRCMF_PCIE_DEVICE(BRCM_PCIE_4366_DEVICE_ID),
 - 	BRCMF_PCIE_DEVICE(BRCM_PCIE_4366_2G_DEVICE_ID),
 - 	BRCMF_PCIE_DEVICE(BRCM_PCIE_4366_5G_DEVICE_ID),
+diff --git a/package/kernel/mac80211/patches/323-ath9k-Fix-programming-of-minCCA-power-threshold.patch b/package/kernel/mac80211/patches/323-ath9k-Fix-programming-of-minCCA-power-threshold.patch
+new file mode 100644
+index 0000000..59ac29b
+--- /dev/null
++++ b/package/kernel/mac80211/patches/323-ath9k-Fix-programming-of-minCCA-power-threshold.patch
+@@ -0,0 +1,26 @@
++From: Sven Eckelmann <sven@narfation.org>
++Date: Fri, 17 Jun 2016 11:58:20 +0200
++Subject: [PATCH] ath9k: Fix programming of minCCA power threshold
++
++The function ar9003_hw_apply_minccapwr_thresh takes as second parameter not
++a pointer to the channel but a boolean value describing whether the channel
++is 2.4GHz or not. This broke (according to the origin commit) the ETSI
++regulatory compliance on 5GHz channels.
++
++Fixes: 3533bf6b15a0 ("ath9k: Fix regulatory compliance")
++Signed-off-by: Sven Eckelmann <sven@narfation.org>
++Cc: Simon Wunderlich <sw@simonwunderlich.de>
++Cc: Sujith Manoharan <c_manoha@qca.qualcomm.com>
++---
++
++--- a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c
+++++ b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c
++@@ -4175,7 +4175,7 @@ static void ath9k_hw_ar9300_set_board_va
++ 	if (!AR_SREV_9330(ah) && !AR_SREV_9340(ah) && !AR_SREV_9531(ah))
++ 		ar9003_hw_internal_regulator_apply(ah);
++ 	ar9003_hw_apply_tuning_caps(ah);
++-	ar9003_hw_apply_minccapwr_thresh(ah, chan);
+++	ar9003_hw_apply_minccapwr_thresh(ah, is2ghz);
++ 	ar9003_hw_txend_to_xpa_off_apply(ah, is2ghz);
++ 	ar9003_hw_thermometer_apply(ah);
++ 	ar9003_hw_thermo_cal_apply(ah);
+diff --git a/package/kernel/mac80211/patches/324-ath9k_hw-fix-spectral-scan-on-AR9285-and-newer.patch b/package/kernel/mac80211/patches/324-ath9k_hw-fix-spectral-scan-on-AR9285-and-newer.patch
+new file mode 100644
+index 0000000..b6f4868
+--- /dev/null
++++ b/package/kernel/mac80211/patches/324-ath9k_hw-fix-spectral-scan-on-AR9285-and-newer.patch
+@@ -0,0 +1,86 @@
++From: Felix Fietkau <nbd@nbd.name>
++Date: Mon, 11 Jul 2016 10:34:37 +0200
++Subject: [PATCH] ath9k_hw: fix spectral scan on AR9285 and newer
++
++The register layout of AR_PHY_SPECTRAL_SCAN has changed, only AR9280
++uses the old layout
++
++Signed-off-by: Felix Fietkau <nbd@nbd.name>
++---
++
++--- a/drivers/net/wireless/ath/ath9k/ar9002_phy.c
+++++ b/drivers/net/wireless/ath/ath9k/ar9002_phy.c
++@@ -476,6 +476,7 @@ static void ar9002_hw_set_bt_ant_diversi
++ static void ar9002_hw_spectral_scan_config(struct ath_hw *ah,
++ 				    struct ath_spec_scan *param)
++ {
+++	u32 repeat_bit;
++ 	u8 count;
++ 
++ 	if (!param->enabled) {
++@@ -486,12 +487,15 @@ static void ar9002_hw_spectral_scan_conf
++ 	REG_SET_BIT(ah, AR_PHY_RADAR_0, AR_PHY_RADAR_0_FFT_ENA);
++ 	REG_SET_BIT(ah, AR_PHY_SPECTRAL_SCAN, AR_PHY_SPECTRAL_SCAN_ENABLE);
++ 
+++	if (AR_SREV_9280(ah))
+++		repeat_bit = AR_PHY_SPECTRAL_SCAN_SHORT_REPEAT;
+++	else
+++		repeat_bit = AR_PHY_SPECTRAL_SCAN_SHORT_REPEAT_KIWI;
+++
++ 	if (param->short_repeat)
++-		REG_SET_BIT(ah, AR_PHY_SPECTRAL_SCAN,
++-			    AR_PHY_SPECTRAL_SCAN_SHORT_REPEAT);
+++		REG_SET_BIT(ah, AR_PHY_SPECTRAL_SCAN, repeat_bit);
++ 	else
++-		REG_CLR_BIT(ah, AR_PHY_SPECTRAL_SCAN,
++-			    AR_PHY_SPECTRAL_SCAN_SHORT_REPEAT);
+++		REG_CLR_BIT(ah, AR_PHY_SPECTRAL_SCAN, repeat_bit);
++ 
++ 	/* on AR92xx, the highest bit of count will make the the chip send
++ 	 * spectral samples endlessly. Check if this really was intended,
++@@ -499,15 +503,25 @@ static void ar9002_hw_spectral_scan_conf
++ 	 */
++ 	count = param->count;
++ 	if (param->endless) {
++-		if (AR_SREV_9271(ah))
++-			count = 0;
++-		else
+++		if (AR_SREV_9280(ah))
++ 			count = 0x80;
+++		else
+++			count = 0;
++ 	} else if (count & 0x80)
++ 		count = 0x7f;
+++	else if (!count)
+++		count = 1;
+++
+++	if (AR_SREV_9280(ah)) {
+++		REG_RMW_FIELD(ah, AR_PHY_SPECTRAL_SCAN,
+++			      AR_PHY_SPECTRAL_SCAN_COUNT, count);
+++	} else {
+++		REG_RMW_FIELD(ah, AR_PHY_SPECTRAL_SCAN,
+++			      AR_PHY_SPECTRAL_SCAN_COUNT_KIWI, count);
+++		REG_SET_BIT(ah, AR_PHY_SPECTRAL_SCAN,
+++			    AR_PHY_SPECTRAL_SCAN_PHYERR_MASK_SELECT);
+++	}
++ 
++-	REG_RMW_FIELD(ah, AR_PHY_SPECTRAL_SCAN,
++-		      AR_PHY_SPECTRAL_SCAN_COUNT, count);
++ 	REG_RMW_FIELD(ah, AR_PHY_SPECTRAL_SCAN,
++ 		      AR_PHY_SPECTRAL_SCAN_PERIOD, param->period);
++ 	REG_RMW_FIELD(ah, AR_PHY_SPECTRAL_SCAN,
++--- a/drivers/net/wireless/ath/ath9k/ar9002_phy.h
+++++ b/drivers/net/wireless/ath/ath9k/ar9002_phy.h
++@@ -177,8 +177,11 @@
++ #define AR_PHY_SPECTRAL_SCAN_PERIOD_S		8
++ #define AR_PHY_SPECTRAL_SCAN_COUNT		0x00FF0000  /* Number of reports, reg 68, bits 16-23*/
++ #define AR_PHY_SPECTRAL_SCAN_COUNT_S		16
+++#define AR_PHY_SPECTRAL_SCAN_COUNT_KIWI		0x0FFF0000  /* Number of reports, reg 68, bits 16-27*/
+++#define AR_PHY_SPECTRAL_SCAN_COUNT_KIWI_S	16
++ #define AR_PHY_SPECTRAL_SCAN_SHORT_REPEAT	0x01000000  /* Short repeat, reg 68, bit 24*/
++-#define AR_PHY_SPECTRAL_SCAN_SHORT_REPEAT_S	24  /* Short repeat, reg 68, bit 24*/
+++#define AR_PHY_SPECTRAL_SCAN_SHORT_REPEAT_KIWI	0x10000000  /* Short repeat, reg 68, bit 28*/
+++#define AR_PHY_SPECTRAL_SCAN_PHYERR_MASK_SELECT	0x40000000
++ 
++ #define AR_PHY_RX_DELAY           0x9914
++ #define AR_PHY_SEARCH_START_DELAY 0x9918
 diff --git a/package/kernel/mac80211/patches/324-brcmfmac-treat-NULL-character-in-NVRAM-as-separator.patch b/package/kernel/mac80211/patches/324-brcmfmac-treat-NULL-character-in-NVRAM-as-separator.patch
 deleted file mode 100644
 index 6ce60f1..0000000
@@ -4768,6 +7448,69 @@ index 6ce60f1..0000000
 - 		goto proceed;
 - 	if (c == '#')
 - 		return COMMENT;
+diff --git a/package/kernel/mac80211/patches/325-ath9k_hw-fix-duplicate-and-partially-wrong-definitio.patch b/package/kernel/mac80211/patches/325-ath9k_hw-fix-duplicate-and-partially-wrong-definitio.patch
+new file mode 100644
+index 0000000..6685f33
+--- /dev/null
++++ b/package/kernel/mac80211/patches/325-ath9k_hw-fix-duplicate-and-partially-wrong-definitio.patch
+@@ -0,0 +1,57 @@
++From: Felix Fietkau <nbd@nbd.name>
++Date: Mon, 11 Jul 2016 11:31:39 +0200
++Subject: [PATCH] ath9k_hw: fix duplicate (and partially wrong) definition
++ of AR_CH0_THERM
++
++AR_PHY_65NM_CH0_THERM and AR_CH0_THERM were supposed to refer to the
++same register, however they had different SREV checks.
++
++Remove the duplicate and use the checks. Since there were other SREV
++checks present in the only place that uses this, this will probaby not
++affect runtime behavior.
++
++Signed-off-by: Felix Fietkau <nbd@nbd.name>
++---
++
++--- a/drivers/net/wireless/ath/ath9k/ar9003_phy.h
+++++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.h
++@@ -689,13 +689,6 @@
++ #define AR_CH0_TOP_XPABIASLVL (AR_SREV_9550(ah) ? 0x3c0 : 0x300)
++ #define AR_CH0_TOP_XPABIASLVL_S (AR_SREV_9550(ah) ? 6 : 8)
++ 
++-#define AR_CH0_THERM	(AR_SREV_9300(ah) ? 0x16290 : \
++-				((AR_SREV_9485(ah) ? 0x1628c : 0x16294)))
++-#define AR_CH0_THERM_XPABIASLVL_MSB 0x3
++-#define AR_CH0_THERM_XPABIASLVL_MSB_S 0
++-#define AR_CH0_THERM_XPASHORT2GND 0x4
++-#define AR_CH0_THERM_XPASHORT2GND_S 2
++-
++ #define AR_SWITCH_TABLE_COM_ALL (0xffff)
++ #define AR_SWITCH_TABLE_COM_ALL_S (0)
++ #define AR_SWITCH_TABLE_COM_AR9462_ALL (0xffffff)
++@@ -712,15 +705,17 @@
++ #define AR_SWITCH_TABLE_ALL (0xfff)
++ #define AR_SWITCH_TABLE_ALL_S (0)
++ 
++-#define AR_PHY_65NM_CH0_THERM       (AR_SREV_9300(ah) ? 0x16290 :\
++-				     ((AR_SREV_9462(ah) || AR_SREV_9565(ah)) ? 0x16294 : 0x1628c))
+++#define AR_CH0_THERM       (AR_SREV_9300(ah) ? 0x16290 :\
+++			    ((AR_SREV_9462(ah) || AR_SREV_9565(ah)) ? 0x16294 : 0x1628c))
+++#define AR_CH0_THERM_XPABIASLVL_MSB 0x3
+++#define AR_CH0_THERM_XPABIASLVL_MSB_S 0
+++#define AR_CH0_THERM_XPASHORT2GND 0x4
+++#define AR_CH0_THERM_XPASHORT2GND_S 2
++ 
++-#define AR_PHY_65NM_CH0_THERM_LOCAL   0x80000000
++-#define AR_PHY_65NM_CH0_THERM_LOCAL_S 31
++-#define AR_PHY_65NM_CH0_THERM_START   0x20000000
++-#define AR_PHY_65NM_CH0_THERM_START_S 29
++-#define AR_PHY_65NM_CH0_THERM_SAR_ADC_OUT   0x0000ff00
++-#define AR_PHY_65NM_CH0_THERM_SAR_ADC_OUT_S 8
+++#define AR_CH0_THERM_LOCAL   0x80000000
+++#define AR_CH0_THERM_START   0x20000000
+++#define AR_CH0_THERM_SAR_ADC_OUT   0x0000ff00
+++#define AR_CH0_THERM_SAR_ADC_OUT_S 8
++ 
++ #define AR_CH0_TOP2		(AR_SREV_9300(ah) ? 0x1628c : \
++ 					(AR_SREV_9462(ah) ? 0x16290 : 0x16284))
 diff --git a/package/kernel/mac80211/patches/325-brcmfmac-sdio-Increase-the-default-timeouts-a-bit.patch b/package/kernel/mac80211/patches/325-brcmfmac-sdio-Increase-the-default-timeouts-a-bit.patch
 deleted file mode 100644
 index 012dea1..0000000
@@ -4908,6 +7651,200 @@ index 71f7a40..0000000
 - 		ath_dbg(common, ANY,
 - 			"Timeout while waiting for nf to load: AR_PHY_AGC_CONTROL=0x%x\n",
 - 			REG_READ(ah, AR_PHY_AGC_CONTROL));
+diff --git a/package/kernel/mac80211/patches/326-ath9k_hw-simplify-ar9003_hw_per_calibration.patch b/package/kernel/mac80211/patches/326-ath9k_hw-simplify-ar9003_hw_per_calibration.patch
+new file mode 100644
+index 0000000..999d993
+--- /dev/null
++++ b/package/kernel/mac80211/patches/326-ath9k_hw-simplify-ar9003_hw_per_calibration.patch
+@@ -0,0 +1,88 @@
++From: Felix Fietkau <nbd@nbd.name>
++Date: Mon, 11 Jul 2016 11:34:47 +0200
++Subject: [PATCH] ath9k_hw: simplify ar9003_hw_per_calibration
++
++Reduce indentation, use a variable to save a few pointer dereferences
++
++Signed-off-by: Felix Fietkau <nbd@nbd.name>
++---
++
++--- a/drivers/net/wireless/ath/ath9k/ar9003_calib.c
+++++ b/drivers/net/wireless/ath/ath9k/ar9003_calib.c
++@@ -75,50 +75,49 @@ static bool ar9003_hw_per_calibration(st
++ 				      struct ath9k_cal_list *currCal)
++ {
++ 	struct ath9k_hw_cal_data *caldata = ah->caldata;
++-	/* Cal is assumed not done until explicitly set below */
++-	bool iscaldone = false;
+++	const struct ath9k_percal_data *cur_caldata = currCal->calData;
++ 
++ 	/* Calibration in progress. */
++ 	if (currCal->calState == CAL_RUNNING) {
++ 		/* Check to see if it has finished. */
++-		if (!(REG_READ(ah, AR_PHY_TIMING4) & AR_PHY_TIMING4_DO_CAL)) {
++-			/*
++-			* Accumulate cal measures for active chains
++-			*/
++-			currCal->calData->calCollect(ah);
++-			ah->cal_samples++;
+++		if (REG_READ(ah, AR_PHY_TIMING4) & AR_PHY_TIMING4_DO_CAL)
+++			return false;
++ 
++-			if (ah->cal_samples >=
++-			    currCal->calData->calNumSamples) {
++-				unsigned int i, numChains = 0;
++-				for (i = 0; i < AR9300_MAX_CHAINS; i++) {
++-					if (rxchainmask & (1 << i))
++-						numChains++;
++-				}
+++		/*
+++		* Accumulate cal measures for active chains
+++		*/
+++		cur_caldata->calCollect(ah);
+++		ah->cal_samples++;
++ 
++-				/*
++-				* Process accumulated data
++-				*/
++-				currCal->calData->calPostProc(ah, numChains);
+++		if (ah->cal_samples >= cur_caldata->calNumSamples) {
+++			unsigned int i, numChains = 0;
+++			for (i = 0; i < AR9300_MAX_CHAINS; i++) {
+++				if (rxchainmask & (1 << i))
+++					numChains++;
+++			}
++ 
++-				/* Calibration has finished. */
++-				caldata->CalValid |= currCal->calData->calType;
++-				currCal->calState = CAL_DONE;
++-				iscaldone = true;
++-			} else {
+++			/*
+++			* Process accumulated data
+++			*/
+++			cur_caldata->calPostProc(ah, numChains);
+++
+++			/* Calibration has finished. */
+++			caldata->CalValid |= cur_caldata->calType;
+++			currCal->calState = CAL_DONE;
+++			return true;
+++		} else {
++ 			/*
++ 			 * Set-up collection of another sub-sample until we
++ 			 * get desired number
++ 			 */
++ 			ar9003_hw_setup_calibration(ah, currCal);
++-			}
++ 		}
++-	} else if (!(caldata->CalValid & currCal->calData->calType)) {
+++	} else if (!(caldata->CalValid & cur_caldata->calType)) {
++ 		/* If current cal is marked invalid in channel, kick it off */
++ 		ath9k_hw_reset_calibration(ah, currCal);
++ 	}
++ 
++-	return iscaldone;
+++	return false;
++ }
++ 
++ static int ar9003_hw_calibrate(struct ath_hw *ah, struct ath9k_channel *chan,
+diff --git a/package/kernel/mac80211/patches/327-ath9k_hw-get-rid-of-some-duplicate-code-in-calibrati.patch b/package/kernel/mac80211/patches/327-ath9k_hw-get-rid-of-some-duplicate-code-in-calibrati.patch
+new file mode 100644
+index 0000000..b7f3823
+--- /dev/null
++++ b/package/kernel/mac80211/patches/327-ath9k_hw-get-rid-of-some-duplicate-code-in-calibrati.patch
+@@ -0,0 +1,94 @@
++From: Felix Fietkau <nbd@nbd.name>
++Date: Mon, 11 Jul 2016 11:35:20 +0200
++Subject: [PATCH] ath9k_hw: get rid of some duplicate code in calibration
++ init
++
++Remove a misleading debug message as well
++
++Signed-off-by: Felix Fietkau <nbd@nbd.name>
++---
++
++--- a/drivers/net/wireless/ath/ath9k/ar9003_calib.c
+++++ b/drivers/net/wireless/ath/ath9k/ar9003_calib.c
++@@ -1373,6 +1373,26 @@ static void ar9003_hw_cl_cal_post_proc(s
++ 	}
++ }
++ 
+++static void ar9003_hw_init_cal_common(struct ath_hw *ah)
+++{
+++	struct ath9k_hw_cal_data *caldata = ah->caldata;
+++
+++	/* Initialize list pointers */
+++	ah->cal_list = ah->cal_list_last = ah->cal_list_curr = NULL;
+++
+++	INIT_CAL(&ah->iq_caldata);
+++	INSERT_CAL(ah, &ah->iq_caldata);
+++
+++	/* Initialize current pointer to first element in list */
+++	ah->cal_list_curr = ah->cal_list;
+++
+++	if (ah->cal_list_curr)
+++		ath9k_hw_reset_calibration(ah, ah->cal_list_curr);
+++
+++	if (caldata)
+++		caldata->CalValid = 0;
+++}
+++
++ static bool ar9003_hw_init_cal_pcoem(struct ath_hw *ah,
++ 				     struct ath9k_channel *chan)
++ {
++@@ -1532,21 +1552,7 @@ skip_tx_iqcal:
++ 	/* Revert chainmask to runtime parameters */
++ 	ar9003_hw_set_chain_masks(ah, ah->rxchainmask, ah->txchainmask);
++ 
++-	/* Initialize list pointers */
++-	ah->cal_list = ah->cal_list_last = ah->cal_list_curr = NULL;
++-
++-	INIT_CAL(&ah->iq_caldata);
++-	INSERT_CAL(ah, &ah->iq_caldata);
++-	ath_dbg(common, CALIBRATE, "enabling IQ Calibration\n");
++-
++-	/* Initialize current pointer to first element in list */
++-	ah->cal_list_curr = ah->cal_list;
++-
++-	if (ah->cal_list_curr)
++-		ath9k_hw_reset_calibration(ah, ah->cal_list_curr);
++-
++-	if (caldata)
++-		caldata->CalValid = 0;
+++	ar9003_hw_init_cal_common(ah);
++ 
++ 	return true;
++ }
++@@ -1577,8 +1583,6 @@ static bool do_ar9003_agc_cal(struct ath
++ static bool ar9003_hw_init_cal_soc(struct ath_hw *ah,
++ 				   struct ath9k_channel *chan)
++ {
++-	struct ath_common *common = ath9k_hw_common(ah);
++-	struct ath9k_hw_cal_data *caldata = ah->caldata;
++ 	bool txiqcal_done = false;
++ 	bool status = true;
++ 	bool run_agc_cal = false, sep_iq_cal = false;
++@@ -1676,21 +1680,7 @@ skip_tx_iqcal:
++ 	/* Revert chainmask to runtime parameters */
++ 	ar9003_hw_set_chain_masks(ah, ah->rxchainmask, ah->txchainmask);
++ 
++-	/* Initialize list pointers */
++-	ah->cal_list = ah->cal_list_last = ah->cal_list_curr = NULL;
++-
++-	INIT_CAL(&ah->iq_caldata);
++-	INSERT_CAL(ah, &ah->iq_caldata);
++-	ath_dbg(common, CALIBRATE, "enabling IQ Calibration\n");
++-
++-	/* Initialize current pointer to first element in list */
++-	ah->cal_list_curr = ah->cal_list;
++-
++-	if (ah->cal_list_curr)
++-		ath9k_hw_reset_calibration(ah, ah->cal_list_curr);
++-
++-	if (caldata)
++-		caldata->CalValid = 0;
+++	ar9003_hw_init_cal_common(ah);
++ 
++ 	return true;
++ }
 diff --git a/package/kernel/mac80211/patches/327-mac80211-Remove-MPP-table-entries-with-MPath.patch b/package/kernel/mac80211/patches/327-mac80211-Remove-MPP-table-entries-with-MPath.patch
 deleted file mode 100644
 index f7f9df9..0000000
@@ -4968,6 +7905,109 @@ index f7f9df9..0000000
 - 	read_lock_bh(&pathtbl_resize_lock);
 - 	tbl = resize_dereference_mesh_paths();
 - 	hash_idx = mesh_table_hash(addr, sdata, tbl);
+diff --git a/package/kernel/mac80211/patches/328-ath9k_hw-implement-temperature-compensation-support-.patch b/package/kernel/mac80211/patches/328-ath9k_hw-implement-temperature-compensation-support-.patch
+new file mode 100644
+index 0000000..cff32ad
+--- /dev/null
++++ b/package/kernel/mac80211/patches/328-ath9k_hw-implement-temperature-compensation-support-.patch
+@@ -0,0 +1,97 @@
++From: Felix Fietkau <nbd@nbd.name>
++Date: Mon, 11 Jul 2016 11:35:55 +0200
++Subject: [PATCH] ath9k_hw: implement temperature compensation support for
++ AR9003+
++
++Signed-off-by: Felix Fietkau <nbd@nbd.name>
++---
++
++--- a/drivers/net/wireless/ath/ath9k/ar9003_calib.c
+++++ b/drivers/net/wireless/ath/ath9k/ar9003_calib.c
++@@ -33,6 +33,7 @@ struct coeff {
++ 
++ enum ar9003_cal_types {
++ 	IQ_MISMATCH_CAL = BIT(0),
+++	TEMP_COMP_CAL = BIT(1),
++ };
++ 
++ static void ar9003_hw_setup_calibration(struct ath_hw *ah,
++@@ -58,6 +59,12 @@ static void ar9003_hw_setup_calibration(
++ 		/* Kick-off cal */
++ 		REG_SET_BIT(ah, AR_PHY_TIMING4, AR_PHY_TIMING4_DO_CAL);
++ 		break;
+++	case TEMP_COMP_CAL:
+++		ath_dbg(common, CALIBRATE,
+++			"starting Temperature Compensation Calibration\n");
+++		REG_SET_BIT(ah, AR_CH0_THERM, AR_CH0_THERM_LOCAL);
+++		REG_SET_BIT(ah, AR_CH0_THERM, AR_CH0_THERM_START);
+++		break;
++ 	default:
++ 		ath_err(common, "Invalid calibration type\n");
++ 		break;
++@@ -86,7 +93,8 @@ static bool ar9003_hw_per_calibration(st
++ 		/*
++ 		* Accumulate cal measures for active chains
++ 		*/
++-		cur_caldata->calCollect(ah);
+++		if (cur_caldata->calCollect)
+++			cur_caldata->calCollect(ah);
++ 		ah->cal_samples++;
++ 
++ 		if (ah->cal_samples >= cur_caldata->calNumSamples) {
++@@ -99,7 +107,8 @@ static bool ar9003_hw_per_calibration(st
++ 			/*
++ 			* Process accumulated data
++ 			*/
++-			cur_caldata->calPostProc(ah, numChains);
+++			if (cur_caldata->calPostProc)
+++				cur_caldata->calPostProc(ah, numChains);
++ 
++ 			/* Calibration has finished. */
++ 			caldata->CalValid |= cur_caldata->calType;
++@@ -314,9 +323,16 @@ static const struct ath9k_percal_data iq
++ 	ar9003_hw_iqcalibrate
++ };
++ 
+++static const struct ath9k_percal_data temp_cal_single_sample = {
+++	TEMP_COMP_CAL,
+++	MIN_CAL_SAMPLES,
+++	PER_MAX_LOG_COUNT,
+++};
+++
++ static void ar9003_hw_init_cal_settings(struct ath_hw *ah)
++ {
++ 	ah->iq_caldata.calData = &iq_cal_single_sample;
+++	ah->temp_caldata.calData = &temp_cal_single_sample;
++ 
++ 	if (AR_SREV_9300_20_OR_LATER(ah)) {
++ 		ah->enabled_cals |= TX_IQ_CAL;
++@@ -324,7 +340,7 @@ static void ar9003_hw_init_cal_settings(
++ 			ah->enabled_cals |= TX_IQ_ON_AGC_CAL;
++ 	}
++ 
++-	ah->supp_cals = IQ_MISMATCH_CAL;
+++	ah->supp_cals = IQ_MISMATCH_CAL | TEMP_COMP_CAL;
++ }
++ 
++ #define OFF_UPPER_LT 24
++@@ -1383,6 +1399,9 @@ static void ar9003_hw_init_cal_common(st
++ 	INIT_CAL(&ah->iq_caldata);
++ 	INSERT_CAL(ah, &ah->iq_caldata);
++ 
+++	INIT_CAL(&ah->temp_caldata);
+++	INSERT_CAL(ah, &ah->temp_caldata);
+++
++ 	/* Initialize current pointer to first element in list */
++ 	ah->cal_list_curr = ah->cal_list;
++ 
++--- a/drivers/net/wireless/ath/ath9k/hw.h
+++++ b/drivers/net/wireless/ath/ath9k/hw.h
++@@ -830,6 +830,7 @@ struct ath_hw {
++ 	/* Calibration */
++ 	u32 supp_cals;
++ 	struct ath9k_cal_list iq_caldata;
+++	struct ath9k_cal_list temp_caldata;
++ 	struct ath9k_cal_list adcgain_caldata;
++ 	struct ath9k_cal_list adcdc_caldata;
++ 	struct ath9k_cal_list *cal_list;
 diff --git a/package/kernel/mac80211/patches/328-mac80211-let-unused-MPP-table-entries-timeout.patch b/package/kernel/mac80211/patches/328-mac80211-let-unused-MPP-table-entries-timeout.patch
 deleted file mode 100644
 index 740993c..0000000
@@ -5227,6 +8267,75 @@ index 0c36b1d..0000000
 - 	return err;
 - }
 - 
+diff --git a/package/kernel/mac80211/patches/329-mac80211-fix-check-for-buffered-powersave-frames-wit.patch b/package/kernel/mac80211/patches/329-mac80211-fix-check-for-buffered-powersave-frames-wit.patch
+new file mode 100644
+index 0000000..38e541c
+--- /dev/null
++++ b/package/kernel/mac80211/patches/329-mac80211-fix-check-for-buffered-powersave-frames-wit.patch
+@@ -0,0 +1,21 @@
++From: Felix Fietkau <nbd@nbd.name>
++Date: Mon, 11 Jul 2016 15:07:06 +0200
++Subject: [PATCH] mac80211: fix check for buffered powersave frames with txq
++
++The logic was inverted here, set the bit if frames are pending.
++
++Fixes: ba8c3d6f16a1 ("mac80211: add an intermediate software queue implementation")
++Signed-off-by: Felix Fietkau <nbd@nbd.name>
++---
++
++--- a/net/mac80211/rx.c
+++++ b/net/mac80211/rx.c
++@@ -1268,7 +1268,7 @@ static void sta_ps_start(struct sta_info
++ 	for (tid = 0; tid < ARRAY_SIZE(sta->sta.txq); tid++) {
++ 		struct txq_info *txqi = to_txq_info(sta->sta.txq[tid]);
++ 
++-		if (!txqi->tin.backlog_packets)
+++		if (txqi->tin.backlog_packets)
++ 			set_bit(tid, &sta->txq_buffered_tids);
++ 		else
++ 			clear_bit(tid, &sta->txq_buffered_tids);
+diff --git a/package/kernel/mac80211/patches/330-ath10k-fix-rx-status-reporting-for-A-MSDU-subframes.patch b/package/kernel/mac80211/patches/330-ath10k-fix-rx-status-reporting-for-A-MSDU-subframes.patch
+new file mode 100644
+index 0000000..a6031b9
+--- /dev/null
++++ b/package/kernel/mac80211/patches/330-ath10k-fix-rx-status-reporting-for-A-MSDU-subframes.patch
+@@ -0,0 +1,36 @@
++From: Felix Fietkau <nbd@nbd.name>
++Date: Sun, 17 Jul 2016 12:49:59 +0200
++Subject: [PATCH] ath10k: fix rx status reporting for A-MSDU subframes
++
++Patch by Nagarajan, Ashok Raj <arnagara@qti.qualcomm.com>
++
++Signed-off-by: Felix Fietkau <nbd@nbd.name>
++---
++
++--- a/drivers/net/wireless/ath/ath10k/htt_rx.c
+++++ b/drivers/net/wireless/ath/ath10k/htt_rx.c
++@@ -1525,7 +1525,7 @@ static void ath10k_htt_rx_h_filter(struc
++ static int ath10k_htt_rx_handle_amsdu(struct ath10k_htt *htt)
++ {
++ 	struct ath10k *ar = htt->ar;
++-	static struct ieee80211_rx_status rx_status;
+++	struct ieee80211_rx_status *rx_status = &htt->rx_status;
++ 	struct sk_buff_head amsdu;
++ 	int ret;
++ 
++@@ -1549,11 +1549,11 @@ static int ath10k_htt_rx_handle_amsdu(st
++ 		return ret;
++ 	}
++ 
++-	ath10k_htt_rx_h_ppdu(ar, &amsdu, &rx_status, 0xffff);
+++	ath10k_htt_rx_h_ppdu(ar, &amsdu, rx_status, 0xffff);
++ 	ath10k_htt_rx_h_unchain(ar, &amsdu, ret > 0);
++-	ath10k_htt_rx_h_filter(ar, &amsdu, &rx_status);
++-	ath10k_htt_rx_h_mpdu(ar, &amsdu, &rx_status);
++-	ath10k_htt_rx_h_deliver(ar, &amsdu, &rx_status);
+++	ath10k_htt_rx_h_filter(ar, &amsdu, rx_status);
+++	ath10k_htt_rx_h_mpdu(ar, &amsdu, rx_status);
+++	ath10k_htt_rx_h_deliver(ar, &amsdu, rx_status);
++ 
++ 	return 0;
++ }
 diff --git a/package/kernel/mac80211/patches/330-mac80211-minstrel-Change-expected-throughput-unit-ba.patch b/package/kernel/mac80211/patches/330-mac80211-minstrel-Change-expected-throughput-unit-ba.patch
 deleted file mode 100644
 index 4dc6d66..0000000
@@ -6614,26 +9723,26 @@ index 7351353..4634283 100644
   WLAN_VENDOR_ATH=
   ATH_DEBUG=
 diff --git a/package/kernel/mac80211/patches/410-ath9k_allow_adhoc_and_ap.patch b/package/kernel/mac80211/patches/410-ath9k_allow_adhoc_and_ap.patch
-index 1a62484..819e64f 100644
+index 1a62484..f2f52f9 100644
 --- a/package/kernel/mac80211/patches/410-ath9k_allow_adhoc_and_ap.patch
 +++ b/package/kernel/mac80211/patches/410-ath9k_allow_adhoc_and_ap.patch
 @@ -1,6 +1,6 @@
  --- a/drivers/net/wireless/ath/ath9k/init.c
  +++ b/drivers/net/wireless/ath/ath9k/init.c
 -@@ -722,6 +722,7 @@ static const struct ieee80211_iface_limi
-+@@ -728,6 +728,7 @@ static const struct ieee80211_iface_limi
++@@ -727,6 +727,7 @@ static const struct ieee80211_iface_limi
   				 BIT(NL80211_IFTYPE_AP) },
   	{ .max = 1,	.types = BIT(NL80211_IFTYPE_P2P_CLIENT) |
   				 BIT(NL80211_IFTYPE_P2P_GO) },
 diff --git a/package/kernel/mac80211/patches/500-ath9k_eeprom_debugfs.patch b/package/kernel/mac80211/patches/500-ath9k_eeprom_debugfs.patch
-index a7f9d9f..4b6da97 100644
+index a7f9d9f..f21eed1 100644
 --- a/package/kernel/mac80211/patches/500-ath9k_eeprom_debugfs.patch
 +++ b/package/kernel/mac80211/patches/500-ath9k_eeprom_debugfs.patch
 @@ -1,6 +1,6 @@
  --- a/drivers/net/wireless/ath/ath9k/debug.c
  +++ b/drivers/net/wireless/ath/ath9k/debug.c
 -@@ -1301,6 +1301,53 @@ void ath9k_deinit_debug(struct ath_softc
-+@@ -1319,6 +1319,53 @@ void ath9k_deinit_debug(struct ath_softc
++@@ -1315,6 +1315,53 @@ void ath9k_deinit_debug(struct ath_softc
   	ath9k_cmn_spectral_deinit_debug(&sc->spec_priv);
   }
   
@@ -6642,7 +9751,7 @@ index a7f9d9f..4b6da97 100644
   {
   	struct ath_common *common = ath9k_hw_common(ah);
 -@@ -1320,6 +1367,8 @@ int ath9k_init_debug(struct ath_hw *ah)
-+@@ -1338,6 +1385,8 @@ int ath9k_init_debug(struct ath_hw *ah)
++@@ -1334,6 +1381,8 @@ 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);
   
@@ -6658,15 +9767,25 @@ index 5892c3e..1825d77 100644
   {
   	int error;
   
+diff --git a/package/kernel/mac80211/patches/511-ath9k_reduce_rxbuf.patch b/package/kernel/mac80211/patches/511-ath9k_reduce_rxbuf.patch
+index 6766111..15b8d7b 100644
+--- a/package/kernel/mac80211/patches/511-ath9k_reduce_rxbuf.patch
++++ b/package/kernel/mac80211/patches/511-ath9k_reduce_rxbuf.patch
+@@ -8,4 +8,4 @@
+ +#define ATH_RXBUF               256
+  #define ATH_TXBUF               512
+  #define ATH_TXBUF_RESERVE       5
+- #define ATH_MAX_QDEPTH          (ATH_TXBUF / 4 - ATH_TXBUF_RESERVE)
++ #define ATH_TXMAXTRY            13
 diff --git a/package/kernel/mac80211/patches/512-ath9k_channelbw_debugfs.patch b/package/kernel/mac80211/patches/512-ath9k_channelbw_debugfs.patch
-index 5ecf528..a105d40 100644
+index 5ecf528..c98072b 100644
 --- a/package/kernel/mac80211/patches/512-ath9k_channelbw_debugfs.patch
 +++ b/package/kernel/mac80211/patches/512-ath9k_channelbw_debugfs.patch
 @@ -1,6 +1,6 @@
  --- a/drivers/net/wireless/ath/ath9k/debug.c
  +++ b/drivers/net/wireless/ath/ath9k/debug.c
 -@@ -1348,6 +1348,52 @@ static const struct file_operations fops
-+@@ -1366,6 +1366,52 @@ static const struct file_operations fops
++@@ -1362,6 +1362,52 @@ static const struct file_operations fops
   	.owner = THIS_MODULE
   };
   
@@ -6675,7 +9794,7 @@ index 5ecf528..a105d40 100644
   {
   	struct ath_common *common = ath9k_hw_common(ah);
 -@@ -1369,6 +1415,8 @@ int ath9k_init_debug(struct ath_hw *ah)
-+@@ -1387,6 +1433,8 @@ int ath9k_init_debug(struct ath_hw *ah)
++@@ -1383,6 +1429,8 @@ int ath9k_init_debug(struct ath_hw *ah)
   
   	debugfs_create_file("eeprom", S_IRUSR, sc->debug.debugfs_phy, sc,
   			    &fops_eeprom);
@@ -6702,14 +9821,14 @@ index c84d1bc..167eeff 100644
   #endif
   
 diff --git a/package/kernel/mac80211/patches/522-mac80211_configure_antenna_gain.patch b/package/kernel/mac80211/patches/522-mac80211_configure_antenna_gain.patch
-index e151a12..28f5dcc 100644
+index e151a12..c40598d 100644
 --- a/package/kernel/mac80211/patches/522-mac80211_configure_antenna_gain.patch
 +++ b/package/kernel/mac80211/patches/522-mac80211_configure_antenna_gain.patch
 @@ -1,6 +1,6 @@
  --- a/include/net/cfg80211.h
  +++ b/include/net/cfg80211.h
 -@@ -2363,6 +2363,7 @@ struct cfg80211_qos_map {
-+@@ -2406,6 +2406,7 @@ struct cfg80211_qos_map {
++@@ -2410,6 +2410,7 @@ struct cfg80211_qos_map {
    *	(as advertised by the nl80211 feature flag.)
    * @get_tx_power: store the current TX power into the dbm variable;
    *	return 0 if successful
@@ -6718,7 +9837,7 @@ index e151a12..28f5dcc 100644
    * @set_wds_peer: set the WDS peer for a WDS interface
    *
 -@@ -2624,6 +2625,7 @@ struct cfg80211_ops {
-+@@ -2667,6 +2668,7 @@ struct cfg80211_ops {
++@@ -2671,6 +2672,7 @@ struct cfg80211_ops {
   				enum nl80211_tx_power_setting type, int mbm);
   	int	(*get_tx_power)(struct wiphy *wiphy, struct wireless_dev *wdev,
   				int *dbm);
@@ -6727,7 +9846,7 @@ index e151a12..28f5dcc 100644
  --- a/include/net/mac80211.h
  +++ b/include/net/mac80211.h
 -@@ -1286,6 +1286,7 @@ enum ieee80211_smps_mode {
-+@@ -1305,6 +1305,7 @@ enum ieee80211_smps_mode {
++@@ -1317,6 +1317,7 @@ enum ieee80211_smps_mode {
    *
    * @power_level: requested transmit power (in dBm), backward compatibility
    *	value only that is set to the minimum of all interfaces
@@ -6736,7 +9855,7 @@ index e151a12..28f5dcc 100644
    * @chandef: the channel definition to tune to
    * @radar_enabled: whether radar detection is enabled
 -@@ -1306,6 +1307,7 @@ enum ieee80211_smps_mode {
-+@@ -1325,6 +1326,7 @@ enum ieee80211_smps_mode {
++@@ -1337,6 +1338,7 @@ enum ieee80211_smps_mode {
   struct ieee80211_conf {
   	u32 flags;
   	int power_level, dynamic_ps_timeout;
@@ -6747,9 +9866,9 @@ index e151a12..28f5dcc 100644
 -@@ -1790,6 +1790,9 @@ enum nl80211_commands {
 -  *	between scans. The scan plans are executed sequentially.
 -  *	Each scan plan is a nested attribute of &enum nl80211_sched_scan_plan.
-+@@ -1819,6 +1819,9 @@ enum nl80211_commands {
-+  *
-+  * @NL80211_ATTR_PAD: attribute used for padding for 64-bit alignment
++@@ -1829,6 +1829,9 @@ enum nl80211_commands {
++  *	%NL80211_ATTR_EXT_CAPA_MASK, to specify the extended capabilities per
++  *	interface type.
    *
  + * @NL80211_ATTR_WIPHY_ANTENNA_GAIN: Configured antenna gain. Used to reduce
  + *	transmit power to stay within regulatory limits. u32, dBi.
@@ -6760,9 +9879,9 @@ index e151a12..28f5dcc 100644
 -@@ -2164,6 +2167,8 @@ enum nl80211_attrs {
 - 	NL80211_ATTR_MAX_SCAN_PLAN_ITERATIONS,
 - 	NL80211_ATTR_SCHED_SCAN_PLANS,
-+@@ -2201,6 +2204,8 @@ enum nl80211_attrs {
++@@ -2213,6 +2216,8 @@ enum nl80211_attrs {
 + 
-+ 	NL80211_ATTR_PAD,
++ 	NL80211_ATTR_IFTYPE_EXT_CAPA,
   
  +	NL80211_ATTR_WIPHY_ANTENNA_GAIN,
  +
@@ -6789,7 +9908,7 @@ index e151a12..28f5dcc 100644
  --- a/net/mac80211/ieee80211_i.h
  +++ b/net/mac80211/ieee80211_i.h
 -@@ -1318,6 +1318,7 @@ struct ieee80211_local {
-+@@ -1322,6 +1322,7 @@ struct ieee80211_local {
++@@ -1338,6 +1338,7 @@ struct ieee80211_local {
   	int dynamic_ps_forced_timeout;
   
   	int user_power_level; /* in dBm, for all interfaces */
@@ -6810,7 +9929,7 @@ index e151a12..28f5dcc 100644
 - 	[NL80211_ATTR_NETNS_FD] = { .type = NLA_U32 },
 - 	[NL80211_ATTR_SCHED_SCAN_DELAY] = { .type = NLA_U32 },
 - 	[NL80211_ATTR_REG_INDOOR] = { .type = NLA_FLAG },
-+@@ -406,6 +406,7 @@ static const struct nla_policy nl80211_p
++@@ -407,6 +407,7 @@ static const struct nla_policy nl80211_p
 + 	[NL80211_ATTR_PBSS] = { .type = NLA_FLAG },
 + 	[NL80211_ATTR_BSS_SELECT] = { .type = NLA_NESTED },
 + 	[NL80211_ATTR_STA_SUPPORT_P2P_PS] = { .type = NLA_U8 },
@@ -6819,19 +9938,18 @@ index e151a12..28f5dcc 100644
   
   /* policy for the key attributes */
 -@@ -2220,6 +2221,20 @@ static int nl80211_set_wiphy(struct sk_b
-+@@ -2251,6 +2252,20 @@ static int nl80211_set_wiphy(struct sk_b
++@@ -2294,6 +2295,20 @@ static int nl80211_set_wiphy(struct sk_b
   		if (result)
   			return result;
   	}
 diff --git a/package/kernel/mac80211/patches/530-ath9k_extra_leds.patch b/package/kernel/mac80211/patches/530-ath9k_extra_leds.patch
-index 5a5e464..6001266 100644
+index 5a5e464..0b25749 100644
 --- a/package/kernel/mac80211/patches/530-ath9k_extra_leds.patch
 +++ b/package/kernel/mac80211/patches/530-ath9k_extra_leds.patch
 @@ -1,16 +1,16 @@
  --- a/drivers/net/wireless/ath/ath9k/ath9k.h
  +++ b/drivers/net/wireless/ath/ath9k/ath9k.h
--@@ -814,6 +814,9 @@ static inline int ath9k_dump_btcoex(stru
-+@@ -813,6 +813,9 @@ static inline int ath9k_dump_btcoex(stru
+ @@ -814,6 +814,9 @@ static inline int ath9k_dump_btcoex(stru
 + #ifdef CPTCFG_MAC80211_LEDS
   void ath_init_leds(struct ath_softc *sc);
   void ath_deinit_leds(struct ath_softc *sc);
@@ -6844,7 +9962,7 @@ index 5a5e464..6001266 100644
   static inline void ath_init_leds(struct ath_softc *sc)
   {
 -@@ -953,6 +956,13 @@ void ath_ant_comb_scan(struct ath_softc
-+@@ -949,6 +952,13 @@ void ath_ant_comb_scan(struct ath_softc
++@@ -950,6 +953,13 @@ void ath_ant_comb_scan(struct ath_softc
   
   #define ATH9K_NUM_CHANCTX  2 /* supports 2 operating channels */
   
@@ -6853,7 +9971,7 @@ index 5a5e464..6001266 100644
   	struct ieee80211_hw *hw;
   	struct device *dev;
 -@@ -1005,9 +1015,8 @@ struct ath_softc {
-+@@ -1001,9 +1011,8 @@ struct ath_softc {
++@@ -1002,9 +1012,8 @@ struct ath_softc {
   	spinlock_t chan_lock;
   
   #ifdef CPTCFG_MAC80211_LEDS
@@ -7005,7 +10123,7 @@ index 5a5e464..6001266 100644
  --- a/drivers/net/wireless/ath/ath9k/debug.c
  +++ b/drivers/net/wireless/ath/ath9k/debug.c
 -@@ -1393,6 +1393,61 @@ static const struct file_operations fops
-+@@ -1411,6 +1411,61 @@ static const struct file_operations fops
++@@ -1407,6 +1407,61 @@ static const struct file_operations fops
   	.llseek = default_llseek,
   };
   
@@ -7014,7 +10132,7 @@ index 5a5e464..6001266 100644
   int ath9k_init_debug(struct ath_hw *ah)
   {
 -@@ -1417,6 +1472,10 @@ int ath9k_init_debug(struct ath_hw *ah)
-+@@ -1435,6 +1490,10 @@ int ath9k_init_debug(struct ath_hw *ah)
++@@ -1431,6 +1486,10 @@ int ath9k_init_debug(struct ath_hw *ah)
   			    &fops_eeprom);
   	debugfs_create_file("chanbw", S_IRUSR | S_IWUSR, sc->debug.debugfs_phy,
   			    sc, &fops_chanbw);
@@ -7070,7 +10188,7 @@ index 7c10ea6..f656697 100644
   
 - void ath_fill_led_pin(struct ath_softc *sc)
 diff --git a/package/kernel/mac80211/patches/532-ath9k_get_led_polarity_from_platform_data.patch b/package/kernel/mac80211/patches/532-ath9k_get_led_polarity_from_platform_data.patch
-index 6d62a2b..986f155 100644
+index 6d62a2b..50d8a7a 100644
 --- a/package/kernel/mac80211/patches/532-ath9k_get_led_polarity_from_platform_data.patch
 +++ b/package/kernel/mac80211/patches/532-ath9k_get_led_polarity_from_platform_data.patch
 @@ -1,6 +1,6 @@
@@ -7086,36 +10204,40 @@ index 6d62a2b..986f155 100644
  --- a/drivers/net/wireless/ath/ath9k/init.c
  +++ b/drivers/net/wireless/ath/ath9k/init.c
 -@@ -577,6 +577,7 @@ static int ath9k_init_softc(u16 devid, s
-+@@ -581,6 +581,7 @@ static int ath9k_init_softc(u16 devid, s
++@@ -580,6 +580,7 @@ static int ath9k_init_softc(u16 devid, s
   		ah->external_reset = pdata->external_reset;
   		ah->disable_2ghz = pdata->disable_2ghz;
   		ah->disable_5ghz = pdata->disable_5ghz;
-diff --git a/package/kernel/mac80211/patches/533-mac80211_correct_4addr_skbsize.patch b/package/kernel/mac80211/patches/533-mac80211_correct_4addr_skbsize.patch
-new file mode 100644
-index 0000000..afd8cca
---- /dev/null
-+++ b/package/kernel/mac80211/patches/533-mac80211_correct_4addr_skbsize.patch
-@@ -0,0 +1,11 @@
-+--- a/net/wireless/util.c
-++++ b/net/wireless/util.c
-+@@ -509,7 +509,7 @@ static int __ieee80211_data_to_8023(stru
-+ 		 * replace EtherType */
-+ 		hdrlen += ETH_ALEN + 2;
-+ 	else
-+-		tmp.h_proto = htons(skb->len);
-++		tmp.h_proto = htons(skb->len - hdrlen);
-+ 
-+ 	pskb_pull(skb, hdrlen);
-+ 
+diff --git a/package/kernel/mac80211/patches/541-ath9k_rx_dma_stop_check.patch b/package/kernel/mac80211/patches/541-ath9k_rx_dma_stop_check.patch
+index 3c5e9f5..c2d2781 100644
+--- a/package/kernel/mac80211/patches/541-ath9k_rx_dma_stop_check.patch
++++ b/package/kernel/mac80211/patches/541-ath9k_rx_dma_stop_check.patch
+@@ -1,6 +1,6 @@
+ --- a/drivers/net/wireless/ath/ath9k/mac.c
+ +++ b/drivers/net/wireless/ath/ath9k/mac.c
+-@@ -695,7 +695,7 @@ bool ath9k_hw_stopdmarecv(struct ath_hw
++@@ -698,7 +698,7 @@ bool ath9k_hw_stopdmarecv(struct ath_hw
+  {
+  #define AH_RX_STOP_DMA_TIMEOUT 10000   /* usec */
+  	struct ath_common *common = ath9k_hw_common(ah);
+@@ -9,7 +9,7 @@
+  	int i;
+  
+  	/* Enable access to the DMA observation bus */
+-@@ -725,6 +725,16 @@ bool ath9k_hw_stopdmarecv(struct ath_hw
++@@ -728,6 +728,16 @@ bool ath9k_hw_stopdmarecv(struct ath_hw
+  	}
+  
+  	if (i == 0) {
 diff --git a/package/kernel/mac80211/patches/542-ath9k_debugfs_diag.patch b/package/kernel/mac80211/patches/542-ath9k_debugfs_diag.patch
-index e83c6bf..f4bb0f2 100644
+index e83c6bf..4615643 100644
 --- a/package/kernel/mac80211/patches/542-ath9k_debugfs_diag.patch
 +++ b/package/kernel/mac80211/patches/542-ath9k_debugfs_diag.patch
 @@ -1,6 +1,6 @@
  --- a/drivers/net/wireless/ath/ath9k/debug.c
  +++ b/drivers/net/wireless/ath/ath9k/debug.c
 -@@ -1449,6 +1449,50 @@ static const struct file_operations fops
-+@@ -1467,6 +1467,50 @@ static const struct file_operations fops
++@@ -1463,6 +1463,50 @@ static const struct file_operations fops
   #endif
   
   
@@ -7124,7 +10246,7 @@ index e83c6bf..f4bb0f2 100644
   {
   	struct ath_common *common = ath9k_hw_common(ah);
 -@@ -1476,6 +1520,8 @@ int ath9k_init_debug(struct ath_hw *ah)
-+@@ -1494,6 +1538,8 @@ int ath9k_init_debug(struct ath_hw *ah)
++@@ -1490,6 +1534,8 @@ int ath9k_init_debug(struct ath_hw *ah)
   	debugfs_create_file("gpio_led", S_IWUSR,
   			   sc->debug.debugfs_phy, sc, &fops_gpio_led);
   #endif
@@ -7151,7 +10273,7 @@ index e83c6bf..f4bb0f2 100644
   	bool htc_reset_init;
   
 -@@ -1066,6 +1074,7 @@ void ath9k_hw_check_nav(struct ath_hw *a
-+@@ -1067,6 +1075,7 @@ void ath9k_hw_check_nav(struct ath_hw *a
++@@ -1068,6 +1076,7 @@ void ath9k_hw_check_nav(struct ath_hw *a
   bool ath9k_hw_check_alive(struct ath_hw *ah);
   
   bool ath9k_hw_setpower(struct ath_hw *ah, enum ath9k_power_mode mode);
@@ -7160,7 +10282,7 @@ index e83c6bf..f4bb0f2 100644
  --- a/drivers/net/wireless/ath/ath9k/hw.c
  +++ b/drivers/net/wireless/ath/ath9k/hw.c
 -@@ -1819,6 +1819,20 @@ u32 ath9k_hw_get_tsf_offset(struct times
-+@@ -1821,6 +1821,20 @@ u32 ath9k_hw_get_tsf_offset(struct times
++@@ -1841,6 +1841,20 @@ u32 ath9k_hw_get_tsf_offset(struct times
   }
   EXPORT_SYMBOL(ath9k_hw_get_tsf_offset);
   
@@ -7169,12 +10291,12 @@ index e83c6bf..f4bb0f2 100644
   		   struct ath9k_hw_cal_data *caldata, bool fastcc)
   {
 -@@ -2027,6 +2041,7 @@ int ath9k_hw_reset(struct ath_hw *ah, st
-+@@ -2029,6 +2043,7 @@ int ath9k_hw_reset(struct ath_hw *ah, st
++@@ -2049,6 +2063,7 @@ int ath9k_hw_reset(struct ath_hw *ah, st
   		ar9003_hw_disable_phy_restart(ah);
   
   	ath9k_hw_apply_gpio_override(ah);
 diff --git a/package/kernel/mac80211/patches/543-ath9k_entropy_from_adc.patch b/package/kernel/mac80211/patches/543-ath9k_entropy_from_adc.patch
-index d7bb5a1..7da7165 100644
+index d7bb5a1..656ed43 100644
 --- a/package/kernel/mac80211/patches/543-ath9k_entropy_from_adc.patch
 +++ b/package/kernel/mac80211/patches/543-ath9k_entropy_from_adc.patch
 @@ -1,6 +1,6 @@
@@ -7217,7 +10339,7 @@ index d7bb5a1..7da7165 100644
  --- a/drivers/net/wireless/ath/ath9k/init.c
  +++ b/drivers/net/wireless/ath/ath9k/init.c
 -@@ -711,7 +711,8 @@ static void ath9k_init_txpower_limits(st
-+@@ -717,7 +717,8 @@ static void ath9k_init_txpower_limits(st
++@@ -716,7 +716,8 @@ static void ath9k_init_txpower_limits(st
   	if (ah->caps.hw_caps & ATH9K_HW_CAP_5GHZ)
 - 		ath9k_init_band_txpower(sc, IEEE80211_BAND_5GHZ);
 + 		ath9k_init_band_txpower(sc, NL80211_BAND_5GHZ);
@@ -7260,16 +10382,46 @@ index d7bb5a1..7da7165 100644
   	if (ret)
   	    return ret;
   
+@@ -175,7 +175,7 @@
+  #define AR_PHY_TIMING2           0x9810
+  #define AR_PHY_TIMING3           0x9814
+  #define AR_PHY_TIMING3_DSC_MAN   0xFFFE0000
+-@@ -390,6 +399,8 @@
++@@ -393,6 +402,8 @@
+  #define AR_PHY_RFBUS_GRANT       0x9C20
+  #define AR_PHY_RFBUS_GRANT_EN    0x00000001
+  
 diff --git a/package/kernel/mac80211/patches/544-ath9k-ar933x-usb-hang-workaround.patch b/package/kernel/mac80211/patches/544-ath9k-ar933x-usb-hang-workaround.patch
-index 8768c5d..9462fca 100644
+index 8768c5d..b9c962e 100644
 --- a/package/kernel/mac80211/patches/544-ath9k-ar933x-usb-hang-workaround.patch
 +++ b/package/kernel/mac80211/patches/544-ath9k-ar933x-usb-hang-workaround.patch
+@@ -20,9 +20,9 @@
+  /******************/
+  /* Chip Revisions */
+  /******************/
+-@@ -1397,6 +1410,9 @@ static bool ath9k_hw_set_reset(struct at
+- 	if (AR_SREV_9100(ah))
++@@ -1417,6 +1430,9 @@ static bool ath9k_hw_set_reset(struct at
+  		udelay(50);
++ 	}
+  
+ +	if (AR_SREV_9330(ah) || AR_SREV_9340(ah))
+ +		ath9k_hw_disable_pll_lock_detect(ah);
+@@ -30,7 +30,7 @@
+  	return true;
+  }
+  
+-@@ -1496,6 +1512,9 @@ static bool ath9k_hw_chip_reset(struct a
++@@ -1516,6 +1532,9 @@ static bool ath9k_hw_chip_reset(struct a
+  		ar9003_hw_internal_regulator_apply(ah);
+  	ath9k_hw_init_pll(ah, chan);
+  
 @@ -40,7 +40,7 @@
   	return true;
   }
   
 -@@ -1797,8 +1816,14 @@ static int ath9k_hw_do_fastcc(struct ath
-+@@ -1799,8 +1818,14 @@ static int ath9k_hw_do_fastcc(struct ath
++@@ -1819,8 +1838,14 @@ static int ath9k_hw_do_fastcc(struct ath
   	if (AR_SREV_9271(ah))
   		ar9002_hw_load_ani_reg(ah, chan);
   
@@ -7278,7 +10430,7 @@ index 8768c5d..9462fca 100644
   }
   
 -@@ -2052,6 +2077,9 @@ int ath9k_hw_reset(struct ath_hw *ah, st
-+@@ -2054,6 +2079,9 @@ int ath9k_hw_reset(struct ath_hw *ah, st
++@@ -2074,6 +2099,9 @@ int ath9k_hw_reset(struct ath_hw *ah, st
   		ath9k_hw_set_radar_params(ah);
   	}
   
@@ -7403,10 +10555,10 @@ index 0000000..5d84cf0
 + }
 diff --git a/package/kernel/mac80211/patches/548-ath9k_enable_gpio_chip.patch b/package/kernel/mac80211/patches/548-ath9k_enable_gpio_chip.patch
 new file mode 100644
-index 0000000..1c89e42
+index 0000000..de7c0ac
 --- /dev/null
 +++ b/package/kernel/mac80211/patches/548-ath9k_enable_gpio_chip.patch
-@@ -0,0 +1,237 @@
+@@ -0,0 +1,234 @@
 +From: Michal Cieslakiewicz <michal.cieslakiewicz@wp.pl>
 +Date: Sun, 31 Jan 2016 21:01:31 +0100
 +Subject: [PATCH v4 4/8] mac80211: ath9k: enable access to GPIO
@@ -7427,7 +10579,7 @@ index 0000000..1c89e42
 + 
 + #include "common.h"
 + #include "debug.h"
-+@@ -959,6 +960,14 @@ struct ath_led {
++@@ -960,6 +961,14 @@ struct ath_led {
 + 	struct led_classdev cdev;
 + };
 + 
@@ -7442,7 +10594,7 @@ index 0000000..1c89e42
 + struct ath_softc {
 + 	struct ieee80211_hw *hw;
 + 	struct device *dev;
-+@@ -1013,6 +1022,9 @@ struct ath_softc {
++@@ -1014,6 +1023,9 @@ struct ath_softc {
 + #ifdef CPTCFG_MAC80211_LEDS
 + 	const char *led_default_trigger;
 + 	struct list_head leds;
@@ -7454,7 +10606,7 @@ index 0000000..1c89e42
 + #ifdef CPTCFG_ATH9K_DEBUGFS
 +--- a/drivers/net/wireless/ath/ath9k/gpio.c
 ++++ b/drivers/net/wireless/ath/ath9k/gpio.c
-+@@ -16,13 +16,138 @@
++@@ -16,13 +16,135 @@
 + 
 + #include "ath9k.h"
 + #include <linux/ath9k_platform.h>
@@ -7526,15 +10678,7 @@ index 0000000..1c89e42
 ++static void ath9k_register_gpio_chip(struct ath_softc *sc)
 ++{
 ++	struct ath9k_gpio_chip *gc;
-++	u16 ng;
-++
-++	/* for now only AR9285 and AR9287 are recognized */
-++	if (AR_SREV_9287(sc->sc_ah))
-++		ng = AR9287_NUM_GPIO;
-++	else if (AR_SREV_9285(sc->sc_ah))
-++		ng = AR9285_NUM_GPIO;
-++	else
-++		return;
+++	struct ath_hw *ah = sc->sc_ah;
 ++
 ++	gc = kzalloc(sizeof(struct ath9k_gpio_chip), GFP_KERNEL);
 ++	if (!gc)
@@ -7542,21 +10686,26 @@ index 0000000..1c89e42
 ++
 ++	snprintf(gc->label, sizeof(gc->label), "ath9k-%s",
 ++		 wiphy_name(sc->hw->wiphy));
+++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,5,0)
+++	gc->gchip.parent = sc->dev;
+++#else
+++	gc->gchip.dev = sc->dev;
+++#endif
 ++	gc->gchip.label = gc->label;
 ++	gc->gchip.base = -1;	/* determine base automatically */
-++	gc->gchip.ngpio = ng;
+++	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;
-++	gc->gchip.owner = THIS_MODULE;
 ++
 ++	if (gpiochip_add(&gc->gchip)) {
 ++		kfree(gc);
 ++		return;
 ++	}
 ++
+++	gc->gchip.owner = NULL;
 ++	sc->gpiochip = gc;
 ++	gc->sc = sc;
 ++}
@@ -7595,7 +10744,7 @@ index 0000000..1c89e42
 + static void ath_fill_led_pin(struct ath_softc *sc)
 + {
 + 	struct ath_hw *ah = sc->sc_ah;
-+@@ -80,6 +205,12 @@ static int ath_add_led(struct ath_softc
++@@ -80,6 +202,12 @@ static int ath_add_led(struct ath_softc
 + 	else
 + 		ath9k_hw_set_gpio(sc->sc_ah, gpio->gpio, gpio->active_low);
 + 
@@ -7608,7 +10757,7 @@ index 0000000..1c89e42
 + 	return 0;
 + }
 + 
-+@@ -136,12 +267,18 @@ void ath_deinit_leds(struct ath_softc *s
++@@ -136,12 +264,18 @@ void ath_deinit_leds(struct ath_softc *s
 + 
 + 	while (!list_empty(&sc->leds)) {
 + 		led = list_first_entry(&sc->leds, struct ath_led, list);
@@ -7627,7 +10776,7 @@ index 0000000..1c89e42
 + }
 + 
 + void ath_init_leds(struct ath_softc *sc)
-+@@ -158,6 +295,8 @@ void ath_init_leds(struct ath_softc *sc)
++@@ -158,6 +292,8 @@ void ath_init_leds(struct ath_softc *sc)
 + 
 + 	ath_fill_led_pin(sc);
 + 
@@ -7636,7 +10785,7 @@ index 0000000..1c89e42
 + 	if (pdata && pdata->led_name)
 + 		strncpy(led_name, pdata->led_name, sizeof(led_name));
 + 	else
-+@@ -178,6 +317,7 @@ void ath_init_leds(struct ath_softc *sc)
++@@ -178,6 +314,7 @@ void ath_init_leds(struct ath_softc *sc)
 + 	for (i = 0; i < pdata->num_leds; i++)
 + 		ath_create_platform_led(sc, &pdata->leds[i]);
 + }
@@ -7646,7 +10795,7 @@ index 0000000..1c89e42
 + /*******************/
 diff --git a/package/kernel/mac80211/patches/549-ath9k_enable_gpio_buttons.patch b/package/kernel/mac80211/patches/549-ath9k_enable_gpio_buttons.patch
 new file mode 100644
-index 0000000..c7973bb
+index 0000000..b9d1883
 --- /dev/null
 +++ b/package/kernel/mac80211/patches/549-ath9k_enable_gpio_buttons.patch
 @@ -0,0 +1,149 @@
@@ -7662,7 +10811,7 @@ index 0000000..c7973bb
 +---
 +--- a/drivers/net/wireless/ath/ath9k/ath9k.h
 ++++ b/drivers/net/wireless/ath/ath9k/ath9k.h
-+@@ -1024,6 +1024,7 @@ struct ath_softc {
++@@ -1025,6 +1025,7 @@ struct ath_softc {
 + 	struct list_head leds;
 + #ifdef CONFIG_GPIOLIB
 + 	struct ath9k_gpio_chip *gpiochip;
@@ -7681,7 +10830,7 @@ index 0000000..c7973bb
 + 
 + #ifdef CPTCFG_MAC80211_LEDS
 + 
-+@@ -132,6 +134,64 @@ static void ath9k_unregister_gpio_chip(s
++@@ -129,6 +131,64 @@ static void ath9k_unregister_gpio_chip(s
 + 	sc->gpiochip = NULL;
 + }
 + 
@@ -7746,7 +10895,7 @@ index 0000000..c7973bb
 + #else /* CONFIG_GPIOLIB */
 + 
 + static inline void ath9k_register_gpio_chip(struct ath_softc *sc)
-+@@ -142,6 +202,14 @@ static inline void ath9k_unregister_gpio
++@@ -139,6 +199,14 @@ static inline void ath9k_unregister_gpio
 + {
 + }
 + 
@@ -7761,7 +10910,7 @@ index 0000000..c7973bb
 + #endif /* CONFIG_GPIOLIB */
 + 
 + /********************************/
-+@@ -265,6 +333,7 @@ void ath_deinit_leds(struct ath_softc *s
++@@ -262,6 +330,7 @@ void ath_deinit_leds(struct ath_softc *s
 + {
 + 	struct ath_led *led;
 + 
@@ -7769,7 +10918,7 @@ index 0000000..c7973bb
 + 	while (!list_empty(&sc->leds)) {
 + 		led = list_first_entry(&sc->leds, struct ath_led, list);
 + #ifdef CONFIG_GPIOLIB
-+@@ -296,6 +365,7 @@ void ath_init_leds(struct ath_softc *sc)
++@@ -293,6 +362,7 @@ void ath_init_leds(struct ath_softc *sc)
 + 	ath_fill_led_pin(sc);
 + 
 + 	ath9k_register_gpio_chip(sc);
@@ -7777,7 +10926,7 @@ index 0000000..c7973bb
 + 
 + 	if (pdata && pdata->led_name)
 + 		strncpy(led_name, pdata->led_name, sizeof(led_name));
-+@@ -311,7 +381,7 @@ void ath_init_leds(struct ath_softc *sc)
++@@ -308,7 +378,7 @@ void ath_init_leds(struct ath_softc *sc)
 + 	ath_create_gpio_led(sc, sc->sc_ah->led_pin, led_name, trigger,
 + 			   !sc->sc_ah->config.led_active_high);
 + 
@@ -7799,39 +10948,6 @@ index 0000000..c7973bb
 + };
 + 
 + #endif /* _LINUX_ATH9K_PLATFORM_H */
-diff --git a/package/kernel/mac80211/patches/550-ath9k_add_ar9280_gpio_chip.patch b/package/kernel/mac80211/patches/550-ath9k_add_ar9280_gpio_chip.patch
-new file mode 100644
-index 0000000..22e2c66
---- /dev/null
-+++ b/package/kernel/mac80211/patches/550-ath9k_add_ar9280_gpio_chip.patch
-@@ -0,0 +1,27 @@
-+From: Michal Cieslakiewicz <michal.cieslakiewicz@wp.pl>
-+Date: Thu, 21 Apr 2016 23:00:54 +0200
-+Subject: [PATCH] mac80211: ath9k: add GPIO support for AR9280 chip
-+
-+Enable access to GPIO on Atheros wireless chip AR9280.
-+Support for 9280 is added to existing 9285/9287 subsystem
-+because these 3 chips differ only in number of GPIO pins.
-+
-+Signed-off-by: Michal Cieslakiewicz <michal.cieslakiewicz@wp.pl>
-+---
-+--- a/drivers/net/wireless/ath/ath9k/gpio.c
-++++ b/drivers/net/wireless/ath/ath9k/gpio.c
-+@@ -88,11 +88,13 @@ static void ath9k_register_gpio_chip(str
-+ 	struct ath9k_gpio_chip *gc;
-+ 	u16 ng;
-+ 
-+-	/* for now only AR9285 and AR9287 are recognized */
-++	/* supported chips are AR9280, AR9285 and AR9287 */
-+ 	if (AR_SREV_9287(sc->sc_ah))
-+ 		ng = AR9287_NUM_GPIO;
-+ 	else if (AR_SREV_9285(sc->sc_ah))
-+ 		ng = AR9285_NUM_GPIO;
-++	else if (AR_SREV_9280(sc->sc_ah))
-++		ng = AR9280_NUM_GPIO;
-+ 	else
-+ 		return;
-+ 
 diff --git a/package/kernel/mac80211/patches/600-0002-rt2x00-rt2800lib-introduce-RT2800_HAS_HIGH_SHARED_ME.patch b/package/kernel/mac80211/patches/600-0002-rt2x00-rt2800lib-introduce-RT2800_HAS_HIGH_SHARED_ME.patch
 index 8245909..db70a33 100644
 --- a/package/kernel/mac80211/patches/600-0002-rt2x00-rt2800lib-introduce-RT2800_HAS_HIGH_SHARED_ME.patch
@@ -8224,15 +11340,42 @@ index 74cd448..0000000
 - #endif
 - #ifdef CPTCFG_B43_SSB
 diff --git a/package/kernel/mac80211/patches/820-b43-add-antenna-control.patch b/package/kernel/mac80211/patches/820-b43-add-antenna-control.patch
-index 06c731f..b60ef76 100644
+index 06c731f..f8f555f 100644
 --- a/package/kernel/mac80211/patches/820-b43-add-antenna-control.patch
 +++ b/package/kernel/mac80211/patches/820-b43-add-antenna-control.patch
+@@ -9,7 +9,7 @@
+  	antenna = b43_antenna_to_phyctl(antenna);
+  	ctl = b43_shm_read16(dev, B43_SHM_SHARED, B43_SHM_SH_BEACPHYCTL);
+  	/* We can't send beacons with short preamble. Would get PHY errors. */
+-@@ -3300,8 +3300,8 @@ static int b43_chip_init(struct b43_wlde
++@@ -3297,8 +3297,8 @@ static int b43_chip_init(struct b43_wlde
+  
+  	/* Select the antennae */
+  	if (phy->ops->set_rx_antenna)
+@@ -20,7 +20,7 @@
+  
+  	if (phy->type == B43_PHYTYPE_B) {
+  		value16 = b43_read16(dev, 0x005E);
+-@@ -4001,7 +4001,6 @@ static int b43_op_config(struct ieee8021
++@@ -3998,7 +3998,6 @@ static int b43_op_config(struct ieee8021
+  	struct b43_wldev *dev = wl->current_dev;
+  	struct b43_phy *phy = &dev->phy;
+  	struct ieee80211_conf *conf = &hw->conf;
+@@ -28,7 +28,7 @@
+  	int err = 0;
+  
+  	mutex_lock(&wl->mutex);
+-@@ -4044,11 +4043,9 @@ static int b43_op_config(struct ieee8021
++@@ -4041,11 +4040,9 @@ static int b43_op_config(struct ieee8021
+  	}
+  
+  	/* Antennas for RX and management frame TX. */
 @@ -42,7 +42,7 @@
   
   	if (wl->radio_enabled != phy->radio_on) {
   		if (wl->radio_enabled) {
 -@@ -5209,6 +5206,47 @@ static int b43_op_get_survey(struct ieee
-+@@ -5207,6 +5204,47 @@ static int b43_op_get_survey(struct ieee
++@@ -5189,6 +5186,47 @@ static int b43_op_get_survey(struct ieee
   	return 0;
   }
   
@@ -8241,7 +11384,7 @@ index 06c731f..b60ef76 100644
   	.tx			= b43_op_tx,
   	.conf_tx		= b43_op_conf_tx,
 -@@ -5230,6 +5268,8 @@ static const struct ieee80211_ops b43_hw
-+@@ -5228,6 +5266,8 @@ static const struct ieee80211_ops b43_hw
++@@ -5210,6 +5248,8 @@ static const struct ieee80211_ops b43_hw
   	.sw_scan_complete	= b43_op_sw_scan_complete_notifier,
   	.get_survey		= b43_op_get_survey,
   	.rfkill_poll		= b43_rfkill_poll,
@@ -8250,7 +11393,7 @@ index 06c731f..b60ef76 100644
   
   /* Hard-reset the chip. Do not call this directly.
 -@@ -5538,6 +5578,8 @@ static int b43_one_core_attach(struct b4
-+@@ -5536,6 +5576,8 @@ static int b43_one_core_attach(struct b4
++@@ -5513,6 +5553,8 @@ static int b43_one_core_attach(struct b4
   	if (!wldev)
   		goto out;
   
@@ -8259,84 +11402,277 @@ index 06c731f..b60ef76 100644
   	wldev->dev = dev;
   	wldev->wl = wl;
 -@@ -5628,6 +5670,9 @@ static struct b43_wl *b43_wireless_init(
-+@@ -5626,6 +5668,9 @@ static struct b43_wl *b43_wireless_init(
++@@ -5603,6 +5645,9 @@ static struct b43_wl *b43_wireless_init(
   
   	hw->wiphy->flags |= WIPHY_FLAG_IBSS_RSN;
   
-diff --git a/package/kernel/mac80211/patches/860-brcmfmac-add-missing-eth_type_trans-call.patch b/package/kernel/mac80211/patches/860-brcmfmac-add-missing-eth_type_trans-call.patch
+diff --git a/package/kernel/mac80211/patches/860-brcmfmac-register-wiphy-s-during-module_init.patch b/package/kernel/mac80211/patches/860-brcmfmac-register-wiphy-s-during-module_init.patch
 new file mode 100644
-index 0000000..46227c4
+index 0000000..ae571c9
 --- /dev/null
-+++ b/package/kernel/mac80211/patches/860-brcmfmac-add-missing-eth_type_trans-call.patch
-@@ -0,0 +1,26 @@
++++ b/package/kernel/mac80211/patches/860-brcmfmac-register-wiphy-s-during-module_init.patch
+@@ -0,0 +1,97 @@
 +From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <zajec5@gmail.com>
-+Subject: [PATCH] brcmfmac: add missing eth_type_trans call
++Date: Mon, 8 Jun 2015 16:11:40 +0200
++Subject: [PATCH] brcmfmac: register wiphy(s) during module_init
 +MIME-Version: 1.0
 +Content-Type: text/plain; charset=UTF-8
 +Content-Transfer-Encoding: 8bit
 +
-+There are 2 protocols supported by brcmfmac and msgbuf one was missing a
-+proper skb setup before passing it to the netif. This was triggering
-+"NULL pointer dereference".
++This is needed by OpenWrt which expects all PHYs to be created after
++module loads successfully.
 +
-+Fixes: 9c349892ccc9 ("brcmfmac: revise handling events in receive path")
 +Signed-off-by: Rafał Miłecki <zajec5@gmail.com>
 +---
 +
-+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c
-++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c
-+@@ -1157,6 +1157,9 @@ brcmf_msgbuf_process_rx_complete(struct
-+ 		brcmu_pkt_buf_free_skb(skb);
++--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
+++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
++@@ -1213,6 +1213,7 @@ int __init brcmf_core_init(void)
++ {
++ 	if (!schedule_work(&brcmf_driver_work))
++ 		return -EBUSY;
+++	flush_work(&brcmf_driver_work);
++ 
++ 	return 0;
++ }
++--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c
+++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c
++@@ -444,6 +444,7 @@ struct brcmf_fw {
++ 	u16 bus_nr;
++ 	void (*done)(struct device *dev, const struct firmware *fw,
++ 		     void *nvram_image, u32 nvram_len);
+++	struct completion *completion;
++ };
++ 
++ static void brcmf_fw_request_nvram_done(const struct firmware *fw, void *ctx)
++@@ -478,6 +479,8 @@ static void brcmf_fw_request_nvram_done(
++ 		goto fail;
++ 
++ 	fwctx->done(fwctx->dev, fwctx->code, nvram, nvram_length);
+++	if (fwctx->completion)
+++		complete(fwctx->completion);
++ 	kfree(fwctx);
++ 	return;
++ 
++@@ -485,6 +488,8 @@ fail:
++ 	brcmf_dbg(TRACE, "failed: dev=%s\n", dev_name(fwctx->dev));
++ 	release_firmware(fwctx->code);
++ 	device_release_driver(fwctx->dev);
+++	if (fwctx->completion)
+++		complete(fwctx->completion);
++ 	kfree(fwctx);
++ }
++ 
++@@ -500,6 +505,8 @@ static void brcmf_fw_request_code_done(c
++ 	/* only requested code so done here */
++ 	if (!(fwctx->flags & BRCMF_FW_REQUEST_NVRAM)) {
++ 		fwctx->done(fwctx->dev, fw, NULL, 0);
+++		if (fwctx->completion)
+++			complete(fwctx->completion);
++ 		kfree(fwctx);
 + 		return;
 + 	}
++@@ -517,6 +524,8 @@ static void brcmf_fw_request_code_done(c
++ fail:
++ 	brcmf_dbg(TRACE, "failed: dev=%s\n", dev_name(fwctx->dev));
++ 	device_release_driver(fwctx->dev);
+++	if (fwctx->completion)
+++		complete(fwctx->completion);
++ 	kfree(fwctx);
++ }
++ 
++@@ -528,6 +537,8 @@ int brcmf_fw_get_firmwares_pcie(struct d
++ 				u16 domain_nr, u16 bus_nr)
++ {
++ 	struct brcmf_fw *fwctx;
+++	struct completion completion;
+++	int err;
++ 
++ 	brcmf_dbg(TRACE, "enter: dev=%s\n", dev_name(dev));
++ 	if (!fw_cb || !code)
++@@ -548,9 +559,17 @@ int brcmf_fw_get_firmwares_pcie(struct d
++ 	fwctx->domain_nr = domain_nr;
++ 	fwctx->bus_nr = bus_nr;
++ 
++-	return request_firmware_nowait(THIS_MODULE, true, code, dev,
+++	init_completion(&completion);
+++	fwctx->completion = &completion;
 ++
-++	skb->protocol = eth_type_trans(skb, ifp->ndev);
-++
-+ 	brcmf_netif_rx(ifp, skb);
+++	err = request_firmware_nowait(THIS_MODULE, true, code, dev,
++ 				       GFP_KERNEL, fwctx,
++ 				       brcmf_fw_request_code_done);
+++	if (!err)
+++		wait_for_completion_timeout(fwctx->completion,
+++					    msecs_to_jiffies(5000));
+++	fwctx->completion = NULL;
+++	return err;
 + }
 + 
++ int brcmf_fw_get_firmwares(struct device *dev, u16 flags,
 diff --git a/package/kernel/mac80211/patches/861-brcmfmac-register-wiphy-s-during-module_init.patch b/package/kernel/mac80211/patches/861-brcmfmac-register-wiphy-s-during-module_init.patch
-index 00181f6..8cf9ea2 100644
+deleted file mode 100644
+index 00181f6..0000000
 --- a/package/kernel/mac80211/patches/861-brcmfmac-register-wiphy-s-during-module_init.patch
-+++ b/package/kernel/mac80211/patches/861-brcmfmac-register-wiphy-s-during-module_init.patch
-@@ -13,8 +13,8 @@ Signed-off-by: Rafał Miłecki <zajec5@gmail.com>
- 
- --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
- +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
++++ /dev/null
+@@ -1,97 +0,0 @@
+-From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <zajec5@gmail.com>
+-Date: Mon, 8 Jun 2015 16:11:40 +0200
+-Subject: [PATCH] brcmfmac: register wiphy(s) during module_init
+-MIME-Version: 1.0
+-Content-Type: text/plain; charset=UTF-8
+-Content-Transfer-Encoding: 8bit
+-
+-This is needed by OpenWrt which expects all PHYs to be created after
+-module loads successfully.
+-
+-Signed-off-by: Rafał Miłecki <zajec5@gmail.com>
+----
+-
+---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
+-+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
 -@@ -1332,6 +1332,7 @@ static int __init brcmfmac_module_init(v
 - #endif
-+@@ -1232,6 +1232,7 @@ int __init brcmf_core_init(void)
+- 	if (!schedule_work(&brcmf_driver_work))
+- 		return -EBUSY;
+-+	flush_work(&brcmf_driver_work);
+- 
+- 	return 0;
+- }
+---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c
+-+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c
+-@@ -444,6 +444,7 @@ struct brcmf_fw {
+- 	u16 bus_nr;
+- 	void (*done)(struct device *dev, const struct firmware *fw,
+- 		     void *nvram_image, u32 nvram_len);
+-+	struct completion *completion;
+- };
+- 
+- static void brcmf_fw_request_nvram_done(const struct firmware *fw, void *ctx)
+-@@ -478,6 +479,8 @@ static void brcmf_fw_request_nvram_done(
+- 		goto fail;
+- 
+- 	fwctx->done(fwctx->dev, fwctx->code, nvram, nvram_length);
+-+	if (fwctx->completion)
+-+		complete(fwctx->completion);
+- 	kfree(fwctx);
+- 	return;
+- 
+-@@ -485,6 +488,8 @@ fail:
+- 	brcmf_dbg(TRACE, "failed: dev=%s\n", dev_name(fwctx->dev));
+- 	release_firmware(fwctx->code);
+- 	device_release_driver(fwctx->dev);
+-+	if (fwctx->completion)
+-+		complete(fwctx->completion);
+- 	kfree(fwctx);
+- }
+- 
+-@@ -500,6 +505,8 @@ static void brcmf_fw_request_code_done(c
+- 	/* only requested code so done here */
+- 	if (!(fwctx->flags & BRCMF_FW_REQUEST_NVRAM)) {
+- 		fwctx->done(fwctx->dev, fw, NULL, 0);
+-+		if (fwctx->completion)
+-+			complete(fwctx->completion);
+- 		kfree(fwctx);
+- 		return;
+- 	}
+-@@ -517,6 +524,8 @@ static void brcmf_fw_request_code_done(c
+- fail:
+- 	brcmf_dbg(TRACE, "failed: dev=%s\n", dev_name(fwctx->dev));
+- 	device_release_driver(fwctx->dev);
+-+	if (fwctx->completion)
+-+		complete(fwctx->completion);
+- 	kfree(fwctx);
+- }
+- 
+-@@ -528,6 +537,8 @@ int brcmf_fw_get_firmwares_pcie(struct d
+- 				u16 domain_nr, u16 bus_nr)
+- {
+- 	struct brcmf_fw *fwctx;
+-+	struct completion completion;
+-+	int err;
+- 
+- 	brcmf_dbg(TRACE, "enter: dev=%s\n", dev_name(dev));
+- 	if (!fw_cb || !code)
+-@@ -548,9 +559,17 @@ int brcmf_fw_get_firmwares_pcie(struct d
+- 	fwctx->domain_nr = domain_nr;
+- 	fwctx->bus_nr = bus_nr;
+- 
+--	return request_firmware_nowait(THIS_MODULE, true, code, dev,
+-+	init_completion(&completion);
+-+	fwctx->completion = &completion;
+-+
+-+	err = request_firmware_nowait(THIS_MODULE, true, code, dev,
+- 				       GFP_KERNEL, fwctx,
+- 				       brcmf_fw_request_code_done);
+-+	if (!err)
+-+		wait_for_completion_timeout(fwctx->completion,
+-+					    msecs_to_jiffies(5000));
+-+	fwctx->completion = NULL;
+-+	return err;
+- }
+- 
+- int brcmf_fw_get_firmwares(struct device *dev, u16 flags,
+diff --git a/package/kernel/mac80211/patches/861-brcmfmac-workaround-bug-with-some-inconsistent-BSSes.patch b/package/kernel/mac80211/patches/861-brcmfmac-workaround-bug-with-some-inconsistent-BSSes.patch
+new file mode 100644
+index 0000000..8721155
+--- /dev/null
++++ b/package/kernel/mac80211/patches/861-brcmfmac-workaround-bug-with-some-inconsistent-BSSes.patch
+@@ -0,0 +1,50 @@
++From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <zajec5@gmail.com>
++Date: Thu, 9 Jul 2015 00:07:59 +0200
++Subject: [PATCH] brcmfmac: workaround bug with some inconsistent BSSes state
++MIME-Version: 1.0
++Content-Type: text/plain; charset=UTF-8
++Content-Transfer-Encoding: 8bit
++
++Signed-off-by: Rafał Miłecki <zajec5@gmail.com>
++---
++
++--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
+++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
++@@ -665,9 +665,37 @@ static struct wireless_dev *brcmf_cfg802
++ 						     u32 *flags,
++ 						     struct vif_params *params)
 + {
-  	if (!schedule_work(&brcmf_driver_work))
-  		return -EBUSY;
- +	flush_work(&brcmf_driver_work);
-diff --git a/package/kernel/mac80211/patches/862-brcmfmac-workaround-bug-with-some-inconsistent-BSSes.patch b/package/kernel/mac80211/patches/862-brcmfmac-workaround-bug-with-some-inconsistent-BSSes.patch
-index 4295b4b..4f22a4e 100644
---- a/package/kernel/mac80211/patches/862-brcmfmac-workaround-bug-with-some-inconsistent-BSSes.patch
-+++ b/package/kernel/mac80211/patches/862-brcmfmac-workaround-bug-with-some-inconsistent-BSSes.patch
-@@ -10,7 +10,7 @@ Signed-off-by: Rafał Miłecki <zajec5@gmail.com>
- 
- --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
- +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
--@@ -615,9 +615,37 @@ static struct wireless_dev *brcmf_cfg802
-+@@ -650,9 +650,37 @@ static struct wireless_dev *brcmf_cfg802
-  						     u32 *flags,
-  						     struct vif_params *params)
-  {
-@@ -42,7 +42,7 @@ Signed-off-by: Rafał Miłecki <zajec5@gmail.com>
- +	dev = dev_get_by_name(&init_net, name);
- +	if (dev) {
- +		dev_put(dev);
--+		return ERR_PTR(-EEXIST);
+++	struct net_device *dev;
++ 	struct wireless_dev *wdev;
++ 	int err;
++ 
+++	/*
+++	 * There is a bug with in-firmware BSS management. When adding virtual
+++	 * interface brcmfmac first tells firmware to create new BSS and then
+++	 * it creates new struct net_device.
+++	 *
+++	 * If creating/registering netdev(ice) fails, BSS remains in some bugged
+++	 * state. It conflicts with existing BSSes by overtaking their auth
+++	 * requests.
+++	 *
+++	 * It results in one BSS (addresss X) sending beacons and another BSS
+++	 * (address Y) replying to authentication requests. This makes interface
+++	 * unusable as AP.
+++	 *
+++	 * To workaround this bug we may try to guess if register_netdev(ice)
+++	 * will fail. The most obvious case is using interface name that already
+++	 * exists. This is actually quite likely with brcmfmac & some user space
+++	 * scripts as brcmfmac doesn't allow deleting virtual interfaces.
+++	 * So this bug can be triggered even by something trivial like:
+++	 * iw dev wlan0 delete
+++	 * iw phy phy0 interface add wlan0 type __ap
+++	 */
+++	dev = dev_get_by_name(&init_net, name);
+++	if (dev) {
+++		dev_put(dev);
 ++		return ERR_PTR(-ENFILE);
- +	}
- +
-  	brcmf_dbg(TRACE, "enter: %s type %d\n", name, type);
-diff --git a/package/kernel/mac80211/patches/863-brcmfmac-Disable-power-management.patch b/package/kernel/mac80211/patches/863-brcmfmac-Disable-power-management.patch
+++	}
+++
++ 	brcmf_dbg(TRACE, "enter: %s type %d\n", name, type);
++ 	err = brcmf_vif_add_validate(wiphy_to_cfg(wiphy), type);
++ 	if (err) {
+diff --git a/package/kernel/mac80211/patches/862-brcmfmac-Disable-power-management.patch b/package/kernel/mac80211/patches/862-brcmfmac-Disable-power-management.patch
 new file mode 100644
-index 0000000..f971bb7
+index 0000000..f301fe1
 --- /dev/null
-+++ b/package/kernel/mac80211/patches/863-brcmfmac-Disable-power-management.patch
++++ b/package/kernel/mac80211/patches/862-brcmfmac-Disable-power-management.patch
 @@ -0,0 +1,27 @@
 +From 66ae1b1750720a33e29792a177b1e696f4f005fb Mon Sep 17 00:00:00 2001
 +From: Phil Elwell <phil@raspberrypi.org>
@@ -8354,7 +11690,7 @@ index 0000000..f971bb7
 +
 +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
 ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
-+@@ -2711,6 +2711,10 @@ brcmf_cfg80211_set_power_mgmt(struct wip
++@@ -2783,6 +2783,10 @@ brcmf_cfg80211_set_power_mgmt(struct wip
 + 	 * preference in cfg struct to apply this to
 + 	 * FW later while initializing the dongle
 + 	 */
@@ -8365,6 +11701,62 @@ index 0000000..f971bb7
 + 	cfg->pwr_save = enabled;
 + 	if (!check_vif_up(ifp->vif)) {
 + 
+diff --git a/package/kernel/mac80211/patches/862-brcmfmac-workaround-bug-with-some-inconsistent-BSSes.patch b/package/kernel/mac80211/patches/862-brcmfmac-workaround-bug-with-some-inconsistent-BSSes.patch
+deleted file mode 100644
+index 4295b4b..0000000
+--- a/package/kernel/mac80211/patches/862-brcmfmac-workaround-bug-with-some-inconsistent-BSSes.patch
++++ /dev/null
+@@ -1,50 +0,0 @@
+-From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <zajec5@gmail.com>
+-Date: Thu, 9 Jul 2015 00:07:59 +0200
+-Subject: [PATCH] brcmfmac: workaround bug with some inconsistent BSSes state
+-MIME-Version: 1.0
+-Content-Type: text/plain; charset=UTF-8
+-Content-Transfer-Encoding: 8bit
+-
+-Signed-off-by: Rafał Miłecki <zajec5@gmail.com>
+----
+-
+---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
+-+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
+-@@ -615,9 +615,37 @@ static struct wireless_dev *brcmf_cfg802
+- 						     u32 *flags,
+- 						     struct vif_params *params)
+- {
+-+	struct net_device *dev;
+- 	struct wireless_dev *wdev;
+- 	int err;
+- 
+-+	/*
+-+	 * There is a bug with in-firmware BSS management. When adding virtual
+-+	 * interface brcmfmac first tells firmware to create new BSS and then
+-+	 * it creates new struct net_device.
+-+	 *
+-+	 * If creating/registering netdev(ice) fails, BSS remains in some bugged
+-+	 * state. It conflicts with existing BSSes by overtaking their auth
+-+	 * requests.
+-+	 *
+-+	 * It results in one BSS (addresss X) sending beacons and another BSS
+-+	 * (address Y) replying to authentication requests. This makes interface
+-+	 * unusable as AP.
+-+	 *
+-+	 * To workaround this bug we may try to guess if register_netdev(ice)
+-+	 * will fail. The most obvious case is using interface name that already
+-+	 * exists. This is actually quite likely with brcmfmac & some user space
+-+	 * scripts as brcmfmac doesn't allow deleting virtual interfaces.
+-+	 * So this bug can be triggered even by something trivial like:
+-+	 * iw dev wlan0 delete
+-+	 * iw phy phy0 interface add wlan0 type __ap
+-+	 */
+-+	dev = dev_get_by_name(&init_net, name);
+-+	if (dev) {
+-+		dev_put(dev);
+-+		return ERR_PTR(-EEXIST);
+-+	}
+-+
+- 	brcmf_dbg(TRACE, "enter: %s type %d\n", name, type);
+- 	err = brcmf_vif_add_validate(wiphy_to_cfg(wiphy), type);
+- 	if (err) {
 diff --git a/package/kernel/mac80211/patches/910-01-add-support-for-mt7620.patch b/package/kernel/mac80211/patches/910-01-add-support-for-mt7620.patch
 index f2e21ea..be210f2 100644
 --- a/package/kernel/mac80211/patches/910-01-add-support-for-mt7620.patch
@@ -8388,7 +11780,7 @@ index f2e21ea..be210f2 100644
   	case RF5390:
   	case RF5392:
 diff --git a/package/kernel/mac80211/patches/921-ath10k_init_devices_synchronously.patch b/package/kernel/mac80211/patches/921-ath10k_init_devices_synchronously.patch
-index 8c6d720..9322b45 100644
+index 8c6d720..e842d61 100644
 --- a/package/kernel/mac80211/patches/921-ath10k_init_devices_synchronously.patch
 +++ b/package/kernel/mac80211/patches/921-ath10k_init_devices_synchronously.patch
 @@ -14,7 +14,7 @@ Signed-off-by: Sven Eckelmann <sven@open-mesh.com>
@@ -8396,40 +11788,45 @@ index 8c6d720..9322b45 100644
  --- a/drivers/net/wireless/ath/ath10k/core.c
  +++ b/drivers/net/wireless/ath/ath10k/core.c
 -@@ -1914,6 +1914,16 @@ int ath10k_core_register(struct ath10k *
-+@@ -2012,6 +2012,16 @@ int ath10k_core_register(struct ath10k *
++@@ -2107,6 +2107,16 @@ int ath10k_core_register(struct ath10k *
   	ar->chip_id = chip_id;
   	queue_work(ar->workqueue, &ar->register_work);
   
 diff --git a/package/kernel/mac80211/patches/930-ath10k_add_tpt_led_trigger.patch b/package/kernel/mac80211/patches/930-ath10k_add_tpt_led_trigger.patch
-index 281b447..1bfded0 100644
+index 281b447..a501b99 100644
 --- a/package/kernel/mac80211/patches/930-ath10k_add_tpt_led_trigger.patch
 +++ b/package/kernel/mac80211/patches/930-ath10k_add_tpt_led_trigger.patch
 @@ -1,6 +1,6 @@
  --- a/drivers/net/wireless/ath/ath10k/mac.c
  +++ b/drivers/net/wireless/ath/ath10k/mac.c
 -@@ -7141,6 +7141,21 @@ struct ath10k_vif *ath10k_get_arvif(stru
-+@@ -7717,6 +7717,21 @@ struct ath10k_vif *ath10k_get_arvif(stru
++@@ -7742,6 +7742,21 @@ struct ath10k_vif *ath10k_get_arvif(stru
   	return arvif_iter.arvif;
   }
   
-@@ -22,7 +22,7 @@
+@@ -22,11 +22,11 @@
   int ath10k_mac_register(struct ath10k *ar)
   {
   	static const u32 cipher_suites[] = {
 -@@ -7357,6 +7372,12 @@ int ath10k_mac_register(struct ath10k *a
-+@@ -7941,6 +7956,12 @@ int ath10k_mac_register(struct ath10k *a
++@@ -7975,6 +7990,12 @@ int ath10k_mac_register(struct ath10k *a
   	ar->hw->wiphy->cipher_suites = cipher_suites;
   	ar->hw->wiphy->n_cipher_suites = ARRAY_SIZE(cipher_suites);
   
+-+#if CPTCFG_MAC80211_LEDS
+++#ifdef CPTCFG_MAC80211_LEDS
+ +	ieee80211_create_tpt_led_trigger(ar->hw,
+ +		IEEE80211_TPT_LEDTRIG_FL_RADIO, ath10k_tpt_blink,
+ +		ARRAY_SIZE(ath10k_tpt_blink));
 diff --git a/package/kernel/mac80211/patches/936-ath10k_skip_otp_check.patch b/package/kernel/mac80211/patches/936-ath10k_skip_otp_check.patch
 new file mode 100644
-index 0000000..7f51dd2
+index 0000000..596ef98
 --- /dev/null
 +++ b/package/kernel/mac80211/patches/936-ath10k_skip_otp_check.patch
-@@ -0,0 +1,42 @@
+@@ -0,0 +1,51 @@
 +--- a/drivers/net/wireless/ath/ath10k/core.c
 ++++ b/drivers/net/wireless/ath/ath10k/core.c
-+@@ -1168,9 +1168,6 @@ static int ath10k_core_fetch_firmware_fi
++@@ -1243,9 +1243,6 @@ static int ath10k_core_fetch_firmware_fi
 + {
 + 	int ret;
 + 
@@ -8439,17 +11836,26 @@ index 0000000..7f51dd2
 + 	ar->fw_api = 5;
 + 	ath10k_dbg(ar, ATH10K_DBG_BOOT, "trying fw api %d\n", ar->fw_api);
 + 
-+@@ -1873,6 +1870,9 @@ static int ath10k_core_probe_fw(struct a
++@@ -1944,7 +1941,7 @@ EXPORT_SYMBOL(ath10k_core_stop);
++ static int ath10k_core_probe_fw(struct ath10k *ar)
++ {
++ 	struct bmi_target_info target_info;
++-	int ret = 0;
+++	int calret, ret = 0;
++ 
++ 	ret = ath10k_hif_power_up(ar);
++ 	if (ret) {
++@@ -1968,6 +1965,9 @@ static int ath10k_core_probe_fw(struct a
 + 		goto err_power_down;
 + 	}
 + 
 ++	/* calibration file is optional, don't check for any errors */
-++	int calret = ath10k_fetch_cal_file(ar);
+++	calret = ath10k_fetch_cal_file(ar);
 ++
 + 	ret = ath10k_core_fetch_firmware_files(ar);
 + 	if (ret) {
 + 		ath10k_err(ar, "could not fetch firmware files (%d)\n", ret);
-+@@ -1895,11 +1895,14 @@ static int ath10k_core_probe_fw(struct a
++@@ -1990,11 +1990,14 @@ static int ath10k_core_probe_fw(struct a
 + 			   "could not load pre cal data: %d\n", ret);
 + 	}
 + 
@@ -8470,7 +11876,7 @@ index 0000000..7f51dd2
 + 
 + 	ret = ath10k_core_fetch_board_file(ar);
 diff --git a/package/kernel/mt76/Makefile b/package/kernel/mt76/Makefile
-index e49dd48..0f832e4 100644
+index e49dd48..90430b9 100644
 --- a/package/kernel/mt76/Makefile
 +++ b/package/kernel/mt76/Makefile
 @@ -1,7 +1,7 @@
@@ -8478,7 +11884,7 @@ index e49dd48..0f832e4 100644
  
  PKG_NAME:=mt76
 -PKG_VERSION:=2016-03-03
-+PKG_VERSION:=2016-06-17
++PKG_VERSION:=2016-07-08
  PKG_RELEASE=1
  
  PKG_LICENSE:=GPLv2
@@ -8487,7 +11893,7 @@ index e49dd48..0f832e4 100644
  PKG_SOURCE_PROTO:=git
  PKG_SOURCE_SUBDIR:=$(PKG_NAME)-$(PKG_VERSION)
 -PKG_SOURCE_VERSION:=310d420178c86e253a172413da30ecf479b64251
-+PKG_SOURCE_VERSION:=f06ed811cda67ab2ed9932c3e87ba03229e75f4e
++PKG_SOURCE_VERSION:=9226e96c40e9ae19996a262365ce764f7b0b9c4a
  PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION)-$(PKG_SOURCE_VERSION).tar.xz
  
 -PKG_MAINTAINER:=Felix Fietkau <nbd@openwrt.org>
@@ -8529,7 +11935,7 @@ index e49dd48..0f832e4 100644
  		$(PKG_BUILD_DIR)/firmware/mt7662.bin \
  		$(1)/lib/firmware
 diff --git a/package/kernel/mwlwifi/Makefile b/package/kernel/mwlwifi/Makefile
-index 091928d..6a59a02 100644
+index 091928d..880803e 100644
 --- a/package/kernel/mwlwifi/Makefile
 +++ b/package/kernel/mwlwifi/Makefile
 @@ -8,7 +8,7 @@
@@ -8537,7 +11943,7 @@ index 091928d..6a59a02 100644
  
  PKG_NAME:=mwlwifi
 -PKG_VERSION:=10.3.0.16-20160105
-+PKG_VERSION:=10.3.0.17-20160520-1
++PKG_VERSION:=10.3.0.17-20160617
  PKG_RELEASE=1
  
  PKG_LICENSE:=ISC
@@ -8546,424 +11952,133 @@ index 091928d..6a59a02 100644
  PKG_SOURCE_PROTO:=git
  PKG_SOURCE_SUBDIR:=$(PKG_NAME)-$(PKG_VERSION)
 -PKG_SOURCE_VERSION:=99d3879cc72f2a25d44fb4bee96fd84eca028b04
-+PKG_SOURCE_VERSION:=7d49296d12b44025278a52c5a26fb1b4236f320f
++PKG_SOURCE_VERSION:=b7aff3c2839b048407d716d1cb9326122ee401f8
  PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION)-$(PKG_SOURCE_VERSION).tar.xz
  
  PKG_MAINTAINER:=Imre Kaloz <kaloz@openwrt.org>
 diff --git a/package/kernel/mwlwifi/patches/100-drop_old_api.patch b/package/kernel/mwlwifi/patches/100-drop_old_api.patch
-index d2e149e..086edeb 100644
+deleted file mode 100644
+index d2e149e..0000000
 --- a/package/kernel/mwlwifi/patches/100-drop_old_api.patch
-+++ b/package/kernel/mwlwifi/patches/100-drop_old_api.patch
-@@ -1,6 +1,6 @@
- --- a/main.c
- +++ b/main.c
++++ /dev/null
+@@ -1,92 +0,0 @@
+---- a/main.c
+-+++ b/main.c
 -@@ -418,11 +418,7 @@ static void mwl_set_ht_caps(struct mwl_p
-+@@ -423,11 +423,7 @@ static void mwl_set_ht_caps(struct mwl_p
-  	band->ht_cap.cap |= IEEE80211_HT_CAP_SGI_20;
-  	band->ht_cap.cap |= IEEE80211_HT_CAP_SGI_40;
-  
-@@ -12,7 +12,7 @@
-  	band->ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K;
-  	band->ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_4;
-  
+- 	band->ht_cap.cap |= IEEE80211_HT_CAP_SGI_20;
+- 	band->ht_cap.cap |= IEEE80211_HT_CAP_SGI_40;
+- 
+--#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 2, 0)
+--	hw->flags |= IEEE80211_HW_AMPDU_AGGREGATION;
+--#else
+- 	ieee80211_hw_set(hw, AMPDU_AGGREGATION);
+--#endif
+- 	band->ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K;
+- 	band->ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_4;
+- 
 -@@ -524,29 +520,16 @@ static int mwl_wl_init(struct mwl_priv *
-+@@ -563,29 +559,16 @@ static int mwl_wl_init(struct mwl_priv *
-  	hw->queues = SYSADPT_TX_WMM_QUEUES;
-  
-  	/* Set rssi values to dBm */
-@@ -41,10 +41,10 @@
- -#endif
-  
-  	hw->wiphy->flags |= WIPHY_FLAG_IBSS_RSN;
+- 	hw->queues = SYSADPT_TX_WMM_QUEUES;
+- 
+- 	/* Set rssi values to dBm */
+--#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 2, 0)
+--	hw->flags |= IEEE80211_HW_SIGNAL_DBM | IEEE80211_HW_HAS_RATE_CONTROL;
+--#else
+- 	ieee80211_hw_set(hw, SIGNAL_DBM);
+- 	ieee80211_hw_set(hw, HAS_RATE_CONTROL);
+--#endif
 - 
-+ 	hw->wiphy->flags |= WIPHY_FLAG_HAS_CHANNEL_SWITCH;
- --- a/dev.h
- +++ b/dev.h
+- 	/* Ask mac80211 not to trigger PS mode
+- 	 * based on PM bit of incoming frames.
+- 	 */
+--#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 2, 0)
+--	hw->flags |= IEEE80211_HW_AP_LINK_PS;
+--#else
+- 	ieee80211_hw_set(hw, AP_LINK_PS);
+--#endif
+- 
+--#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 2, 0)
+--	hw->flags |= IEEE80211_HW_SUPPORTS_PER_STA_GTK |
+--		     IEEE80211_HW_MFP_CAPABLE;
+--#else
+- 	ieee80211_hw_set(hw, SUPPORTS_PER_STA_GTK);
+- 	ieee80211_hw_set(hw, MFP_CAPABLE);
+--#endif
+- 
+- 	hw->wiphy->flags |= WIPHY_FLAG_IBSS_RSN;
+- 
+---- a/dev.h
+-+++ b/dev.h
 -@@ -484,10 +484,6 @@ static inline struct mwl_sta *mwl_dev_ge
-+@@ -506,10 +506,6 @@ static inline struct mwl_sta *mwl_dev_ge
-  	return (struct mwl_sta *)&sta->drv_priv;
-  }
-  
-@@ -57,7 +57,7 @@
-  
- --- a/mac80211.c
- +++ b/mac80211.c
+- 	return (struct mwl_sta *)&sta->drv_priv;
+- }
+- 
+--#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 14, 0)
+--#define ether_addr_copy(dst, src) memcpy(dst, src, ETH_ALEN)
+--#endif
+--
+- /* Defined in mac80211.c. */
+- extern const struct ieee80211_ops mwl_mac80211_ops;
+- 
+---- a/mac80211.c
+-+++ b/mac80211.c
 -@@ -572,19 +572,11 @@ static int mwl_mac80211_get_survey(struc
-+@@ -598,19 +598,11 @@ static int mwl_mac80211_get_survey(struc
-  	return 0;
-  }
-  
+- 	return 0;
+- }
+- 
+--#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 3, 0)
+--static int mwl_mac80211_ampdu_action(struct ieee80211_hw *hw,
+--				     struct ieee80211_vif *vif,
+--				     enum ieee80211_ampdu_mlme_action action,
+--				     struct ieee80211_sta *sta,
+--				     u16 tid, u16 *ssn, u8 buf_size)
+--#else
+- static int mwl_mac80211_ampdu_action(struct ieee80211_hw *hw,
+- 				     struct ieee80211_vif *vif,
+- 				     enum ieee80211_ampdu_mlme_action action,
+- 				     struct ieee80211_sta *sta,
+- 				     u16 tid, u16 *ssn, u8 buf_size, bool amsdu)
+--#endif
+- {
+- 	int rc = 0;
+- 	struct mwl_priv *priv = hw->priv;
+---- a/rx.c
+-+++ b/rx.c
+-@@ -232,10 +232,8 @@ static inline void mwl_rx_prepare_status
+- 		status->flag |= RX_FLAG_VHT;
+- 		if (bw == RX_RATE_INFO_HT40)
+- 			status->flag |= RX_FLAG_40MHZ;
+--#if LINUX_VERSION_CODE > KERNEL_VERSION(3, 18, 0)
+- 		if (bw == RX_RATE_INFO_HT80)
+- 			status->vht_flag |= RX_VHT_FLAG_80MHZ;
+--#endif
+- 		if (gi == RX_RATE_INFO_SHORT_INTERVAL)
+- 			status->flag |= RX_FLAG_SHORT_GI;
+- 		status->vht_nss = (nss + 1);
 diff --git a/package/kernel/mwlwifi/patches/110-api_sync.patch b/package/kernel/mwlwifi/patches/110-api_sync.patch
-index ed3e06a..920cb8c 100644
+deleted file mode 100644
+index ed3e06a..0000000
 --- a/package/kernel/mwlwifi/patches/110-api_sync.patch
-+++ b/package/kernel/mwlwifi/patches/110-api_sync.patch
-@@ -1,6 +1,30 @@
- --- a/mac80211.c
- +++ b/mac80211.c
++++ /dev/null
+@@ -1,19 +0,0 @@
+---- a/mac80211.c
+-+++ b/mac80211.c
 -@@ -597,10 +597,13 @@ static int mwl_mac80211_get_survey(struc
-+@@ -260,12 +260,12 @@ static int mwl_mac80211_config(struct ie
-+ 	if (changed & IEEE80211_CONF_CHANGE_CHANNEL) {
-+ 		int rate = 0;
-+ 
-+-		if (conf->chandef.chan->band == IEEE80211_BAND_2GHZ) {
-++		if (conf->chandef.chan->band == NL80211_BAND_2GHZ) {
-+ 			mwl_fwcmd_set_apmode(hw, AP_MODE_2_4GHZ_11AC_MIXED);
-+ 			mwl_fwcmd_set_linkadapt_cs_mode(hw,
-+ 							LINK_CS_STATE_CONSERV);
-+ 			rate = mwl_rates_24[0].hw_value;
-+-		} else if (conf->chandef.chan->band == IEEE80211_BAND_5GHZ) {
-++		} else if (conf->chandef.chan->band == NL80211_BAND_5GHZ) {
-+ 			mwl_fwcmd_set_apmode(hw, AP_MODE_11AC);
-+ 			mwl_fwcmd_set_linkadapt_cs_mode(hw,
-+ 							LINK_CS_STATE_AUTO);
-+@@ -333,7 +333,7 @@ static void mwl_mac80211_bss_info_change
-+ 		if (idx)
-+ 			idx--;
-+ 
-+-		if (hw->conf.chandef.chan->band == IEEE80211_BAND_2GHZ)
-++		if (hw->conf.chandef.chan->band == NL80211_BAND_2GHZ)
-+ 			rate = mwl_rates_24[idx].hw_value;
-+ 		else
-+ 			rate = mwl_rates_50[idx].hw_value;
-+@@ -600,10 +600,13 @@ static int mwl_mac80211_get_survey(struc
-  
-  static int mwl_mac80211_ampdu_action(struct ieee80211_hw *hw,
-  				     struct ieee80211_vif *vif,
-@@ -17,3 +41,227 @@
-  	int rc = 0;
-  	struct mwl_priv *priv = hw->priv;
-  	struct mwl_ampdu_stream *stream;
-+--- a/fwcmd.c
-++++ b/fwcmd.c
-+@@ -730,9 +730,9 @@ static int mwl_fwcmd_set_country_code(st
-+ 	bool enable = false;
-+ 
-+ 	if (b_inf->ie_country_ptr) {
-+-		if (bss_conf->chandef.chan->band == IEEE80211_BAND_2GHZ)
-++		if (bss_conf->chandef.chan->band == NL80211_BAND_2GHZ)
-+ 			a_band = false;
-+-		else if (bss_conf->chandef.chan->band == IEEE80211_BAND_5GHZ)
-++		else if (bss_conf->chandef.chan->band == NL80211_BAND_5GHZ)
-+ 			a_band = true;
-+ 		else
-+ 			return -EINVAL;
-+@@ -1075,9 +1075,9 @@ int mwl_fwcmd_max_tx_power(struct ieee80
-+ 		break;
-+ 	}
-+ 
-+-	if (channel->band == IEEE80211_BAND_2GHZ)
-++	if (channel->band == NL80211_BAND_2GHZ)
-+ 		band = FREQ_BAND_2DOT4GHZ;
-+-	else if (channel->band == IEEE80211_BAND_5GHZ)
-++	else if (channel->band == NL80211_BAND_5GHZ)
-+ 		band = FREQ_BAND_5GHZ;
-+ 
-+ 	switch (conf->chandef.width) {
-+@@ -1161,9 +1161,9 @@ int mwl_fwcmd_tx_power(struct ieee80211_
-+ 		break;
-+ 	}
-+ 
-+-	if (channel->band == IEEE80211_BAND_2GHZ)
-++	if (channel->band == NL80211_BAND_2GHZ)
-+ 		band = FREQ_BAND_2DOT4GHZ;
-+-	else if (channel->band == IEEE80211_BAND_5GHZ)
-++	else if (channel->band == NL80211_BAND_5GHZ)
-+ 		band = FREQ_BAND_5GHZ;
-+ 
-+ 	switch (conf->chandef.width) {
-+@@ -1354,9 +1354,9 @@ int mwl_fwcmd_set_rf_channel(struct ieee
-+ 	pcmd->action = cpu_to_le16(WL_SET);
-+ 	pcmd->curr_chnl = channel->hw_value;
-+ 
-+-	if (channel->band == IEEE80211_BAND_2GHZ) {
-++	if (channel->band == NL80211_BAND_2GHZ) {
-+ 		freq_band = FREQ_BAND_2DOT4GHZ;
-+-	} else if (channel->band == IEEE80211_BAND_5GHZ) {
-++	} else if (channel->band == NL80211_BAND_5GHZ) {
-+ 		freq_band = FREQ_BAND_5GHZ;
-+ 	} else {
-+ 		mutex_unlock(&priv->fwcmd_mutex);
-+@@ -1923,10 +1923,10 @@ int mwl_fwcmd_set_new_stn_add(struct iee
-+ 	}
-+ 	ether_addr_copy(pcmd->mac_addr, sta->addr);
-+ 
-+-	if (hw->conf.chandef.chan->band == IEEE80211_BAND_2GHZ)
-+-		rates = sta->supp_rates[IEEE80211_BAND_2GHZ];
-++	if (hw->conf.chandef.chan->band == NL80211_BAND_2GHZ)
-++		rates = sta->supp_rates[NL80211_BAND_2GHZ];
-+ 	else
-+-		rates = sta->supp_rates[IEEE80211_BAND_5GHZ] << 5;
-++		rates = sta->supp_rates[NL80211_BAND_5GHZ] << 5;
-+ 	pcmd->peer_info.legacy_rate_bitmap = cpu_to_le32(rates);
-+ 
-+ 	if (sta->ht_cap.ht_supported) {
-+@@ -2097,9 +2097,9 @@ int mwl_fwcmd_set_switch_channel(struct
-+ 	if (priv->csa_active)
-+ 		return 0;
-+ 
-+-	if (channel->band == IEEE80211_BAND_2GHZ)
-++	if (channel->band == NL80211_BAND_2GHZ)
-+ 		freq_band = FREQ_BAND_2DOT4GHZ;
-+-	else if (channel->band == IEEE80211_BAND_5GHZ)
-++	else if (channel->band == NL80211_BAND_5GHZ)
-+ 		freq_band = FREQ_BAND_5GHZ;
-+ 	else
-+ 		return -EINVAL;
-+--- a/main.c
-++++ b/main.c
-+@@ -63,20 +63,20 @@ static struct mwl_chip_info mwl_chip_tbl
-+ };
-+ 
-+ static const struct ieee80211_channel mwl_channels_24[] = {
-+-	{ .band = IEEE80211_BAND_2GHZ, .center_freq = 2412, .hw_value = 1, },
-+-	{ .band = IEEE80211_BAND_2GHZ, .center_freq = 2417, .hw_value = 2, },
-+-	{ .band = IEEE80211_BAND_2GHZ, .center_freq = 2422, .hw_value = 3, },
-+-	{ .band = IEEE80211_BAND_2GHZ, .center_freq = 2427, .hw_value = 4, },
-+-	{ .band = IEEE80211_BAND_2GHZ, .center_freq = 2432, .hw_value = 5, },
-+-	{ .band = IEEE80211_BAND_2GHZ, .center_freq = 2437, .hw_value = 6, },
-+-	{ .band = IEEE80211_BAND_2GHZ, .center_freq = 2442, .hw_value = 7, },
-+-	{ .band = IEEE80211_BAND_2GHZ, .center_freq = 2447, .hw_value = 8, },
-+-	{ .band = IEEE80211_BAND_2GHZ, .center_freq = 2452, .hw_value = 9, },
-+-	{ .band = IEEE80211_BAND_2GHZ, .center_freq = 2457, .hw_value = 10, },
-+-	{ .band = IEEE80211_BAND_2GHZ, .center_freq = 2462, .hw_value = 11, },
-+-	{ .band = IEEE80211_BAND_2GHZ, .center_freq = 2467, .hw_value = 12, },
-+-	{ .band = IEEE80211_BAND_2GHZ, .center_freq = 2472, .hw_value = 13, },
-+-	{ .band = IEEE80211_BAND_2GHZ, .center_freq = 2484, .hw_value = 14, },
-++	{ .band = NL80211_BAND_2GHZ, .center_freq = 2412, .hw_value = 1, },
-++	{ .band = NL80211_BAND_2GHZ, .center_freq = 2417, .hw_value = 2, },
-++	{ .band = NL80211_BAND_2GHZ, .center_freq = 2422, .hw_value = 3, },
-++	{ .band = NL80211_BAND_2GHZ, .center_freq = 2427, .hw_value = 4, },
-++	{ .band = NL80211_BAND_2GHZ, .center_freq = 2432, .hw_value = 5, },
-++	{ .band = NL80211_BAND_2GHZ, .center_freq = 2437, .hw_value = 6, },
-++	{ .band = NL80211_BAND_2GHZ, .center_freq = 2442, .hw_value = 7, },
-++	{ .band = NL80211_BAND_2GHZ, .center_freq = 2447, .hw_value = 8, },
-++	{ .band = NL80211_BAND_2GHZ, .center_freq = 2452, .hw_value = 9, },
-++	{ .band = NL80211_BAND_2GHZ, .center_freq = 2457, .hw_value = 10, },
-++	{ .band = NL80211_BAND_2GHZ, .center_freq = 2462, .hw_value = 11, },
-++	{ .band = NL80211_BAND_2GHZ, .center_freq = 2467, .hw_value = 12, },
-++	{ .band = NL80211_BAND_2GHZ, .center_freq = 2472, .hw_value = 13, },
-++	{ .band = NL80211_BAND_2GHZ, .center_freq = 2484, .hw_value = 14, },
-+ };
-+ 
-+ static const struct ieee80211_rate mwl_rates_24[] = {
-+@@ -96,30 +96,30 @@ static const struct ieee80211_rate mwl_r
-+ };
-+ 
-+ static const struct ieee80211_channel mwl_channels_50[] = {
-+-	{ .band = IEEE80211_BAND_5GHZ, .center_freq = 5180, .hw_value = 36, },
-+-	{ .band = IEEE80211_BAND_5GHZ, .center_freq = 5200, .hw_value = 40, },
-+-	{ .band = IEEE80211_BAND_5GHZ, .center_freq = 5220, .hw_value = 44, },
-+-	{ .band = IEEE80211_BAND_5GHZ, .center_freq = 5240, .hw_value = 48, },
-+-	{ .band = IEEE80211_BAND_5GHZ, .center_freq = 5260, .hw_value = 52, },
-+-	{ .band = IEEE80211_BAND_5GHZ, .center_freq = 5280, .hw_value = 56, },
-+-	{ .band = IEEE80211_BAND_5GHZ, .center_freq = 5300, .hw_value = 60, },
-+-	{ .band = IEEE80211_BAND_5GHZ, .center_freq = 5320, .hw_value = 64, },
-+-	{ .band = IEEE80211_BAND_5GHZ, .center_freq = 5500, .hw_value = 100, },
-+-	{ .band = IEEE80211_BAND_5GHZ, .center_freq = 5520, .hw_value = 104, },
-+-	{ .band = IEEE80211_BAND_5GHZ, .center_freq = 5540, .hw_value = 108, },
-+-	{ .band = IEEE80211_BAND_5GHZ, .center_freq = 5560, .hw_value = 112, },
-+-	{ .band = IEEE80211_BAND_5GHZ, .center_freq = 5580, .hw_value = 116, },
-+-	{ .band = IEEE80211_BAND_5GHZ, .center_freq = 5600, .hw_value = 120, },
-+-	{ .band = IEEE80211_BAND_5GHZ, .center_freq = 5620, .hw_value = 124, },
-+-	{ .band = IEEE80211_BAND_5GHZ, .center_freq = 5640, .hw_value = 128, },
-+-	{ .band = IEEE80211_BAND_5GHZ, .center_freq = 5660, .hw_value = 132, },
-+-	{ .band = IEEE80211_BAND_5GHZ, .center_freq = 5680, .hw_value = 136, },
-+-	{ .band = IEEE80211_BAND_5GHZ, .center_freq = 5700, .hw_value = 140, },
-+-	{ .band = IEEE80211_BAND_5GHZ, .center_freq = 5720, .hw_value = 144, },
-+-	{ .band = IEEE80211_BAND_5GHZ, .center_freq = 5745, .hw_value = 149, },
-+-	{ .band = IEEE80211_BAND_5GHZ, .center_freq = 5765, .hw_value = 153, },
-+-	{ .band = IEEE80211_BAND_5GHZ, .center_freq = 5785, .hw_value = 157, },
-+-	{ .band = IEEE80211_BAND_5GHZ, .center_freq = 5805, .hw_value = 161, },
-++	{ .band = NL80211_BAND_5GHZ, .center_freq = 5180, .hw_value = 36, },
-++	{ .band = NL80211_BAND_5GHZ, .center_freq = 5200, .hw_value = 40, },
-++	{ .band = NL80211_BAND_5GHZ, .center_freq = 5220, .hw_value = 44, },
-++	{ .band = NL80211_BAND_5GHZ, .center_freq = 5240, .hw_value = 48, },
-++	{ .band = NL80211_BAND_5GHZ, .center_freq = 5260, .hw_value = 52, },
-++	{ .band = NL80211_BAND_5GHZ, .center_freq = 5280, .hw_value = 56, },
-++	{ .band = NL80211_BAND_5GHZ, .center_freq = 5300, .hw_value = 60, },
-++	{ .band = NL80211_BAND_5GHZ, .center_freq = 5320, .hw_value = 64, },
-++	{ .band = NL80211_BAND_5GHZ, .center_freq = 5500, .hw_value = 100, },
-++	{ .band = NL80211_BAND_5GHZ, .center_freq = 5520, .hw_value = 104, },
-++	{ .band = NL80211_BAND_5GHZ, .center_freq = 5540, .hw_value = 108, },
-++	{ .band = NL80211_BAND_5GHZ, .center_freq = 5560, .hw_value = 112, },
-++	{ .band = NL80211_BAND_5GHZ, .center_freq = 5580, .hw_value = 116, },
-++	{ .band = NL80211_BAND_5GHZ, .center_freq = 5600, .hw_value = 120, },
-++	{ .band = NL80211_BAND_5GHZ, .center_freq = 5620, .hw_value = 124, },
-++	{ .band = NL80211_BAND_5GHZ, .center_freq = 5640, .hw_value = 128, },
-++	{ .band = NL80211_BAND_5GHZ, .center_freq = 5660, .hw_value = 132, },
-++	{ .band = NL80211_BAND_5GHZ, .center_freq = 5680, .hw_value = 136, },
-++	{ .band = NL80211_BAND_5GHZ, .center_freq = 5700, .hw_value = 140, },
-++	{ .band = NL80211_BAND_5GHZ, .center_freq = 5720, .hw_value = 144, },
-++	{ .band = NL80211_BAND_5GHZ, .center_freq = 5745, .hw_value = 149, },
-++	{ .band = NL80211_BAND_5GHZ, .center_freq = 5765, .hw_value = 153, },
-++	{ .band = NL80211_BAND_5GHZ, .center_freq = 5785, .hw_value = 157, },
-++	{ .band = NL80211_BAND_5GHZ, .center_freq = 5805, .hw_value = 161, },
-+ };
-+ 
-+ static const struct ieee80211_rate mwl_rates_50[] = {
-+@@ -478,7 +478,7 @@ static void mwl_set_caps(struct mwl_priv
-+ 		BUILD_BUG_ON(sizeof(priv->rates_24) != sizeof(mwl_rates_24));
-+ 		memcpy(priv->rates_24, mwl_rates_24, sizeof(mwl_rates_24));
-+ 
-+-		priv->band_24.band = IEEE80211_BAND_2GHZ;
-++		priv->band_24.band = NL80211_BAND_2GHZ;
-+ 		priv->band_24.channels = priv->channels_24;
-+ 		priv->band_24.n_channels = ARRAY_SIZE(mwl_channels_24);
-+ 		priv->band_24.bitrates = priv->rates_24;
-+@@ -487,7 +487,7 @@ static void mwl_set_caps(struct mwl_priv
-+ 		mwl_set_ht_caps(priv, &priv->band_24);
-+ 		mwl_set_vht_caps(priv, &priv->band_24);
-+ 
-+-		hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &priv->band_24;
-++		hw->wiphy->bands[NL80211_BAND_2GHZ] = &priv->band_24;
-+ 	}
-+ 
-+ 	/* set up band information for 5G */
-+@@ -500,7 +500,7 @@ static void mwl_set_caps(struct mwl_priv
-+ 		BUILD_BUG_ON(sizeof(priv->rates_50) != sizeof(mwl_rates_50));
-+ 		memcpy(priv->rates_50, mwl_rates_50, sizeof(mwl_rates_50));
-+ 
-+-		priv->band_50.band = IEEE80211_BAND_5GHZ;
-++		priv->band_50.band = NL80211_BAND_5GHZ;
-+ 		priv->band_50.channels = priv->channels_50;
-+ 		priv->band_50.n_channels = ARRAY_SIZE(mwl_channels_50);
-+ 		priv->band_50.bitrates = priv->rates_50;
-+@@ -509,7 +509,7 @@ static void mwl_set_caps(struct mwl_priv
-+ 		mwl_set_ht_caps(priv, &priv->band_50);
-+ 		mwl_set_vht_caps(priv, &priv->band_50);
-+ 
-+-		hw->wiphy->bands[IEEE80211_BAND_5GHZ] = &priv->band_50;
-++		hw->wiphy->bands[NL80211_BAND_5GHZ] = &priv->band_50;
-+ 	}
-+ }
-+ 
-+--- a/rx.c
-++++ b/rx.c
-+@@ -243,7 +243,7 @@ static inline void mwl_rx_prepare_status
-+ 	status->rate_idx = rt;
-+ 
-+ 	if (pdesc->channel > BAND_24_CHANNEL_NUM) {
-+-		status->band = IEEE80211_BAND_5GHZ;
-++		status->band = NL80211_BAND_5GHZ;
-+ 		if ((!(status->flag & RX_FLAG_HT)) &&
-+ 		    (!(status->flag & RX_FLAG_VHT))) {
-+ 			status->rate_idx -= 5;
-+@@ -251,7 +251,7 @@ static inline void mwl_rx_prepare_status
-+ 				status->rate_idx = BAND_50_RATE_NUM - 1;
-+ 		}
-+ 	} else {
-+-		status->band = IEEE80211_BAND_2GHZ;
-++		status->band = NL80211_BAND_2GHZ;
-+ 		if ((!(status->flag & RX_FLAG_HT)) &&
-+ 		    (!(status->flag & RX_FLAG_VHT))) {
-+ 			if (status->rate_idx >= BAND_24_RATE_NUM)
-diff --git a/package/kernel/mwlwifi/patches/200-fix_excessive_delays.patch b/package/kernel/mwlwifi/patches/200-fix_excessive_delays.patch
-new file mode 100644
-index 0000000..43523ed
---- /dev/null
-+++ b/package/kernel/mwlwifi/patches/200-fix_excessive_delays.patch
-@@ -0,0 +1,73 @@
-+--- a/fwcmd.c
-++++ b/fwcmd.c
-+@@ -132,7 +132,7 @@ static int mwl_fwcmd_wait_complete(struc
-+ 			int_code = le16_to_cpu(*((__le16 *)&priv->pcmd_buf[2]));
-+ 		else
-+ 			int_code = le16_to_cpu(*((__le16 *)&priv->pcmd_buf[0]));
-+-		mdelay(1);
-++		usleep_range(1000, 2000);
-+ 	} while ((int_code != cmd) && (--curr_iteration));
-+ 
-+ 	if (curr_iteration == 0) {
-+@@ -142,7 +142,7 @@ static int mwl_fwcmd_wait_complete(struc
-+ 		return -EIO;
-+ 	}
-+ 
-+-	mdelay(3);
-++	usleep_range(3000, 5000);
-+ 
-+ 	return 0;
-+ }
-+--- a/fwdl.c
-++++ b/fwdl.c
-+@@ -74,7 +74,7 @@ int mwl_fwdl_download_firmware(struct ie
-+ 	/* FW before jumping to boot rom, it will enable PCIe transaction retry,
-+ 	 * wait for boot code to stop it.
-+ 	 */
-+-	mdelay(FW_CHECK_MSECS);
-++	usleep_range(FW_CHECK_MSECS * 1000, FW_CHECK_MSECS * 2000);
-+ 
-+ 	writel(MACREG_A2HRIC_BIT_MASK,
-+ 	       priv->iobase1 + MACREG_REG_A2H_INTERRUPT_CLEAR_SEL);
-+@@ -95,7 +95,7 @@ int mwl_fwdl_download_firmware(struct ie
-+ 
-+ 	/* make sure SCRATCH2 C40 is clear, in case we are too quick */
-+ 	while (readl(priv->iobase1 + 0xc40) == 0)
-+-		;
-++		cond_resched();
-+ 
-+ 	while (size_fw_downloaded < fw->size) {
-+ 		len = readl(priv->iobase1 + 0xc40);
-+@@ -125,6 +125,7 @@ int mwl_fwdl_download_firmware(struct ie
-+ 			int_code = readl(priv->iobase1 + 0xc1c);
-+ 			if (int_code != 0)
-+ 				break;
-++			cond_resched();
-+ 			curr_iteration--;
-+ 		} while (curr_iteration);
-+ 
-+@@ -133,6 +134,7 @@ int mwl_fwdl_download_firmware(struct ie
-+ 			if ((int_code & MACREG_H2ARIC_BIT_DOOR_BELL) !=
-+ 			    MACREG_H2ARIC_BIT_DOOR_BELL)
-+ 				break;
-++			cond_resched();
-+ 			curr_iteration--;
-+ 		} while (curr_iteration);
-+ 
-+@@ -167,12 +169,14 @@ int mwl_fwdl_download_firmware(struct ie
-+ 	do {
-+ 		curr_iteration--;
-+ 		if (priv->mfg_mode && priv->chip_type == MWL8897) {
-+-			mdelay(FW_CHECK_MSECS);
-++			usleep_range(FW_CHECK_MSECS * 1000,
-++				     FW_CHECK_MSECS * 2000);
-+ 			int_code = readl(priv->iobase1 + 0xc44);
-+ 		} else {
-+ 			writel(HOSTCMD_SOFTAP_MODE,
-+ 			       priv->iobase1 + MACREG_REG_GEN_PTR);
-+-			mdelay(FW_CHECK_MSECS);
-++			usleep_range(FW_CHECK_MSECS * 1000,
-++				     FW_CHECK_MSECS * 2000);
-+ 			int_code = readl(priv->iobase1 + MACREG_REG_INT_CODE);
-+ 		}
-+ 		if (!(curr_iteration % 0xff) && (int_code != 0))
-diff --git a/package/kernel/mwlwifi/patches/210-fix_logspam.patch b/package/kernel/mwlwifi/patches/210-fix_logspam.patch
-new file mode 100644
-index 0000000..99b247f
---- /dev/null
-+++ b/package/kernel/mwlwifi/patches/210-fix_logspam.patch
-@@ -0,0 +1,22 @@
-+--- a/fwcmd.c
-++++ b/fwcmd.c
-+@@ -2393,8 +2393,6 @@ int mwl_fwcmd_check_ba(struct ieee80211_
-+ 
-+ 	if (pcmd->cmd_hdr.result != 0) {
-+ 		mutex_unlock(&priv->fwcmd_mutex);
-+-		wiphy_err(hw->wiphy, "check ba result error %d\n",
-+-			  le16_to_cpu(pcmd->cmd_hdr.result));
-+ 		return -EINVAL;
-+ 	}
-+ 
-+--- a/mac80211.c
-++++ b/mac80211.c
-+@@ -644,8 +644,6 @@ static int mwl_mac80211_ampdu_action(str
-+ 		spin_lock_bh(&priv->stream_lock);
-+ 		if (rc) {
-+ 			mwl_fwcmd_remove_stream(hw, stream);
-+-			wiphy_err(hw->wiphy,
-+-				  "ampdu start error code: %d\n", rc);
-+ 			rc = -EPERM;
-+ 			break;
-+ 		}
+- 
+- static int mwl_mac80211_ampdu_action(struct ieee80211_hw *hw,
+- 				     struct ieee80211_vif *vif,
+--				     enum ieee80211_ampdu_mlme_action action,
+--				     struct ieee80211_sta *sta,
+--				     u16 tid, u16 *ssn, u8 buf_size, bool amsdu)
+-+				     struct ieee80211_ampdu_params *params)
+- {
+-+	enum ieee80211_ampdu_mlme_action action = params->action;
+-+	struct ieee80211_sta *sta = params->sta;
+-+	u16 tid = params->tid;
+-+	u16 *ssn = &params->ssn;
+-+	u8 buf_size = params->buf_size;
+- 	int rc = 0;
+- 	struct mwl_priv *priv = hw->priv;
+- 	struct mwl_ampdu_stream *stream;
 diff --git a/package/network/utils/iw/Makefile b/package/network/utils/iw/Makefile
 index ad82081..d17cbca 100644
 --- a/package/network/utils/iw/Makefile
diff --git a/patches/openwrt/0105-mt76-fix-build-with-kernel-3.18.patch b/patches/openwrt/0105-mt76-fix-build-with-kernel-3.18.patch
index 8a731f92d..d7eeb7ab5 100644
--- a/patches/openwrt/0105-mt76-fix-build-with-kernel-3.18.patch
+++ b/patches/openwrt/0105-mt76-fix-build-with-kernel-3.18.patch
@@ -20,7 +20,7 @@ index 0000000..ea389cd
 + 
 + /*
 diff --git a/package/kernel/mt76/Makefile b/package/kernel/mt76/Makefile
-index 0f832e4..801188f 100644
+index 90430b9..47f41da 100644
 --- a/package/kernel/mt76/Makefile
 +++ b/package/kernel/mt76/Makefile
 @@ -24,7 +24,7 @@ include $(INCLUDE_DIR)/package.mk
diff --git a/targets/ar71xx-generic/profiles.mk b/targets/ar71xx-generic/profiles.mk
index 3db73aa23..123e3c0db 100644
--- a/targets/ar71xx-generic/profiles.mk
+++ b/targets/ar71xx-generic/profiles.mk
@@ -158,7 +158,7 @@ $(eval $(call GluonModel,TLWR2543,tl-wr2543-v1,tp-link-tl-wr2543n-nd-v1))
 
 ifneq ($(BROKEN),)
 # Archer C5 v1, C7 v2
-$(eval $(call GluonProfile,ARCHERC7,kmod-ath10k ath10k-firmware-qca988x-ct))
+$(eval $(call GluonProfile,ARCHERC7,kmod-ath10k-ct ath10k-firmware-qca988x-ct))
 $(eval $(call GluonModel,ARCHERC7,archer-c5,tp-link-archer-c5-v1)) # BROKEN: ath10k
 $(eval $(call GluonModel,ARCHERC7,archer-c7-v2,tp-link-archer-c7-v2)) # BROKEN: ath10k
 endif
@@ -195,11 +195,11 @@ endif
 
 # Ubiquiti (ath10k)
 ifneq ($(BROKEN),)
-$(eval $(call GluonProfile,UBNTUNIFIACLITE,kmod-ath10k ath10k-firmware-qca988x-ct))
+$(eval $(call GluonProfile,UBNTUNIFIACLITE,kmod-ath10k-ct ath10k-firmware-qca988x-ct))
 $(eval $(call GluonProfileFactorySuffix,UBNTUNIFIACLITE))
 $(eval $(call GluonModel,UBNTUNIFIACLITE,ubnt-unifiac-lite,ubiquiti-unifi-ac-lite)) # BROKEN: untested, ath10k
 
-$(eval $(call GluonProfile,UBNTUNIFIACPRO,kmod-ath10k ath10k-firmware-qca988x-ct))
+$(eval $(call GluonProfile,UBNTUNIFIACPRO,kmod-ath10k-ct ath10k-firmware-qca988x-ct))
 $(eval $(call GluonProfileFactorySuffix,UBNTUNIFIACPRO))
 $(eval $(call GluonModel,UBNTUNIFIACPRO,ubnt-unifiac-pro,ubiquiti-unifi-ac-pro)) # BROKEN: ath10k
 endif
@@ -314,7 +314,7 @@ $(eval $(call GluonModel,OMEGA,onion-omega,onion-omega))
 ## OpenMesh
 
 # MR1750
-$(eval $(call GluonProfile,MR1750,om-watchdog uboot-envtools kmod-ath10k ath10k-firmware-qca988x-ct))
+$(eval $(call GluonProfile,MR1750,om-watchdog uboot-envtools kmod-ath10k-ct ath10k-firmware-qca988x-ct))
 $(eval $(call GluonModel,MR1750,mr1750,openmesh-mr1750))
 $(eval $(call GluonModelAlias,MR1750,openmesh-mr1750,openmesh-mr1750v2))
 
@@ -343,7 +343,7 @@ $(eval $(call GluonModel,OM5P,om5p,openmesh-om5p))
 $(eval $(call GluonModelAlias,OM5P,openmesh-om5p,openmesh-om5p-an))
 
 # OM5P-AC
-$(eval $(call GluonProfile,OM5PAC,om-watchdog uboot-envtools kmod-ath10k ath10k-firmware-qca988x-ct))
+$(eval $(call GluonProfile,OM5PAC,om-watchdog uboot-envtools kmod-ath10k-ct ath10k-firmware-qca988x-ct))
 $(eval $(call GluonModel,OM5PAC,om5pac,openmesh-om5p-ac))
 $(eval $(call GluonModelAlias,OM5PAC,openmesh-om5p-ac,openmesh-om5p-acv2))
 
-- 
GitLab