소스 검색

mac80211: backport from trunk r47249 + additional patches

Matthias Schiffer 8 년 전
부모
커밋
2c6484ca15

+ 0 - 95
patches/openwrt/0005-ath10k-add-Candelatech-community-firmware-as-an-additional-choice.patch

@@ -1,95 +0,0 @@
-From: Matthias Schiffer <mschiffer@universe-factory.net>
-Date: Tue, 10 Mar 2015 13:17:14 +0100
-Subject: ath10k: add Candelatech community firmware as an additional choice
-
-diff --git a/package/kernel/mac80211/Makefile b/package/kernel/mac80211/Makefile
-index a1eedce..1c0aebe 100644
---- a/package/kernel/mac80211/Makefile
-+++ b/package/kernel/mac80211/Makefile
-@@ -604,6 +604,14 @@ This module adds support for wireless adapters based on
- Atheros USB AR9271 and AR7010 family of chipsets.
- endef
- 
-+ATH10K_CT_COMMUNITY_FW:=firmware-2-ct-full-community-14.bin
-+define Download/ath10k-firmware-ct-community
-+  FILE:=$(ATH10K_CT_COMMUNITY_FW)
-+  URL:=http://www.candelatech.com/downloads/
-+  MD5SUM:=800799459c20c1683138c74b3ba58f25
-+endef
-+$(eval $(call Download,ath10k-firmware-ct-community))
-+
- define KernelPackage/ath10k
-   $(call KernelPackage/mac80211/Default)
-   TITLE:=Atheros 802.11ac wireless cards support
-@@ -624,21 +632,37 @@ endef
- define KernelPackage/ath10k/config
-   if PACKAGE_kmod-ath10k
- 
-+	choice
-+		prompt "ath10k firmware flavour"
-+		default ATH10K_AP_FW
-+		help
-+		  This option allows you to choose between different ath10k firmwares.
-+
-+	config ATH10K_AP_FW
-+		bool "Firmware optimized for AP operation"
-+		help
-+		  Use the ath10k firmware optimized for access point operation.
-+		  Supports only AP mode, will crash in IBSS (ad-hoc) mode.
-+
- 	config ATH10K_STA_FW
- 		bool "Firmware optimized for STA operation"
--		default n
- 		help
- 		  Use the ath10k firmware optimized for wireless client instead
--		  of access point operation.
-+		  of access point operation. Might be unstable in AP mode.
-+
-+	config ATH10K_CT_COMMUNITY_FW
-+		bool "Firmware by Candela Technologies (community version)"
-+		help
-+		  Supports both AP and IBSS (ad-hoc) mode. Doesn't support
-+		  encryption when using multiple VIFs.
- 
- 	config ATH10K_API2_FW
- 		bool "Firmware optimized for AP operation (v10.1 / API v2)"
--		default n
--		depends on !ATH10K_STA_FW
- 		help
- 		  Use the ath10k firmware from the 10.1 SDK using API v2 optimized
- 		  for access point operation if the default firmware keeps crashing.
- 
-+	endchoice
-   endif
- endef
- 
-@@ -1866,18 +1890,25 @@ define KernelPackage/ath10k/install
- 	$(INSTALL_DATA) \
- 		$(PKG_BUILD_DIR)/$(PKG_ATH10K_LINUX_FIRMWARE_SUBDIR)/ath10k/QCA988X/hw2.0/board.bin \
- 		$(1)/lib/firmware/ath10k/QCA988X/hw2.0/
-+ifeq ($(CONFIG_ATH10K_AP_FW),y)
-+	$(INSTALL_DATA) \
-+		$(PKG_BUILD_DIR)/$(PKG_ATH10K_LINUX_FIRMWARE_SUBDIR)/10.2.4/firmware-4.bin_10.2.4.45 \
-+		$(1)/lib/firmware/ath10k/QCA988X/hw2.0/firmware-4.bin
-+endif
- ifeq ($(CONFIG_ATH10K_STA_FW),y)
- 	$(INSTALL_DATA) \
- 		$(PKG_BUILD_DIR)/$(PKG_ATH10K_LINUX_FIRMWARE_SUBDIR)/main/firmware-2.bin_999.999.0.636 \
- 		$(1)/lib/firmware/ath10k/QCA988X/hw2.0/firmware-2.bin
--else ifeq ($(CONFIG_ATH10K_API2_FW),y)
-+endif
-+ifeq ($(CONFIG_ATH10K_API2_FW),y)
- 	$(INSTALL_DATA) \
- 		$(PKG_BUILD_DIR)/$(PKG_ATH10K_LINUX_FIRMWARE_SUBDIR)/10.1/firmware-2.bin_10.1.467.2-1 \
- 		$(1)/lib/firmware/ath10k/QCA988X/hw2.0/firmware-2.bin
--else
-+endif
-+ifeq ($(CONFIG_ATH10K_CT_COMMUNITY_FW),y)
- 	$(INSTALL_DATA) \
--		$(PKG_BUILD_DIR)/$(PKG_ATH10K_LINUX_FIRMWARE_SUBDIR)/10.2.4/firmware-4.bin_10.2.4.45 \
--		$(1)/lib/firmware/ath10k/QCA988X/hw2.0/firmware-4.bin
-+		$(DL_DIR)/$(ATH10K_CT_COMMUNITY_FW) \
-+		$(1)/lib/firmware/ath10k/QCA988X/hw2.0/firmware-2.bin
- endif
- endef
- 

+ 0 - 0
patches/openwrt/0006-base-files-disable-reset-button-handling.patch → patches/openwrt/0005-base-files-disable-reset-button-handling.patch


+ 23813 - 0
patches/openwrt/0006-mac80211-backport-from-trunk-r47249.patch

@@ -0,0 +1,23813 @@
+From: Matthias Schiffer <mschiffer@universe-factory.net>
+Date: Tue, 23 Dec 2014 18:57:16 +0100
+Subject: mac80211: backport from trunk r47249
+
+diff --git a/package/kernel/mac80211/Makefile b/package/kernel/mac80211/Makefile
+index a1eedce..f332cbd 100644
+--- a/package/kernel/mac80211/Makefile
++++ b/package/kernel/mac80211/Makefile
+@@ -10,11 +10,11 @@ include $(INCLUDE_DIR)/kernel.mk
+ 
+ PKG_NAME:=mac80211
+ 
+-PKG_VERSION:=2015-03-09
+-PKG_RELEASE:=3
++PKG_VERSION:=2015-07-21
++PKG_RELEASE:=1
+ PKG_SOURCE_URL:=http://mirror2.openwrt.org/sources
+ PKG_BACKPORT_VERSION:=
+-PKG_MD5SUM:=6d4b04e4ce8a1f54dabfb04f4709453c
++PKG_MD5SUM:=ec529acfb9c942daf8116e5cff47c999
+ 
+ PKG_SOURCE:=compat-wireless-$(PKG_VERSION)$(PKG_BACKPORT_VERSION).tar.bz2
+ PKG_BUILD_DIR:=$(KERNEL_BUILD_DIR)/compat-wireless-$(PKG_VERSION)
+@@ -23,15 +23,28 @@ PKG_BUILD_PARALLEL:=1
+ PKG_MAINTAINER:=Felix Fietkau <nbd@openwrt.org>
+ 
+ PKG_DRIVERS = \
+-	adm8211 ath5k libertas-usb libertas-sdio p54-common p54-pci p54-usb p54-spi \
+-	rt2x00-lib rt2x00-pci rt2x00-usb rt2800-lib rt2400-pci rt2500-pci \
+-	rt2500-usb rt61-pci rt73-usb rt2800-mmio rt2800-pci rt2800-usb rt2800-soc \
+-	rtl8180 rtl8187 zd1211rw mac80211-hwsim carl9170 b43 b43legacy \
+-	ath9k-common ath9k ath9k-htc ath10k ath net-libipw net-ipw2100 net-ipw2200 \
+-	mwl8k mwifiex-pcie net-hermes net-hermes-pci net-hermes-plx net-hermes-pcmcia \
+-	iwl-legacy iwl3945 iwl4965 iwlagn wlcore wl12xx wl18xx lib80211 \
++	adm8211 \
++	ath ath5k ath9k ath9k-common ath9k-htc ath10k \
++	b43 b43legacy \
++	carl9170 \
++	hermes hermes-pci hermes-pcmcia hermes-plx\
++	iwl-legacy iwl3945 iwl4965 iwlwifi \
++	lib80211 \
++	libipw ipw2100 ipw2200 \
++	libertas-sdio libertas-usb \
++	mac80211-hwsim \
++	mt7601u \
++	mwl8k mwifiex-pcie \
++	p54-common p54-pci p54-spi p54-usb \
++	rt2x00-lib rt2x00-pci rt2x00-usb \
++	rt2400-pci rt2500-pci rt2500-usb \
++	rt2800-lib rt2800-mmio rt2800-pci rt2800-soc rt2800-usb \
++	rt61-pci rt73-usb \
++	rtl8180 rtl8187 \
+ 	rtlwifi rtlwifi-pci rtlwifi-usb rtl8192c-common rtl8192ce rtl8192se \
+-	rtl8192de rtl8192cu
++	rtl8192de rtl8192cu \
++	wlcore wl12xx wl18xx \
++	zd1211rw
+ 
+ PKG_CONFIG_DEPENDS:= \
+ 	CONFIG_PACKAGE_kmod-mac80211 \
+@@ -60,7 +73,6 @@ define KernelPackage/mac80211/Default
+   SUBMENU:=$(WMENU)
+   URL:=https://wireless.wiki.kernel.org/
+   MAINTAINER:=Felix Fietkau <nbd@openwrt.org>
+-  DEPENDS:=@!TARGET_uml
+ endef
+ 
+ define KernelPackage/cfg80211
+@@ -79,7 +91,7 @@ endef
+ define KernelPackage/mac80211
+   $(call KernelPackage/mac80211/Default)
+   TITLE:=Linux 802.11 Wireless Networking Stack
+-  DEPENDS+= +kmod-crypto-core +kmod-crypto-arc4 +kmod-crypto-aes +kmod-cfg80211 +hostapd-common
++  DEPENDS+= +kmod-cfg80211 +hostapd-common
+   KCONFIG:=\
+ 	CONFIG_AVERAGE=y
+   FILES:= $(PKG_BUILD_DIR)/net/mac80211/mac80211.ko
+@@ -109,8 +121,8 @@ Generic IEEE 802.11 Networking Stack (mac80211)
+ endef
+ 
+ PKG_LINUX_FIRMWARE_NAME:=linux-firmware
+-PKG_LINUX_FIRMWARE_VERSION:=f404336ba808cbd57547196e13367079a23b822c
+-PKG_LINUX_FIRMWARE_SOURCE:=$(PKG_LINUX_FIRMWARE_NAME)-2015-03-20-$(PKG_LINUX_FIRMWARE_VERSION).tar.bz2
++PKG_LINUX_FIRMWARE_VERSION:=6ebf5d57d9f6d0cf05558baef1af2b90a3fe98ed
++PKG_LINUX_FIRMWARE_SOURCE:=$(PKG_LINUX_FIRMWARE_NAME)-2015-09-03-$(PKG_LINUX_FIRMWARE_VERSION).tar.xz
+ PKG_LINUX_FIRMWARE_PROTO:=git
+ PKG_LINUX_FIRMWARE_SOURCE_URL:=https://git.kernel.org/pub/scm/linux/kernel/git/firmware/linux-firmware.git
+ PKG_LINUX_FIRMWARE_SUBDIR:=$(PKG_LINUX_FIRMWARE_NAME)-$(PKG_LINUX_FIRMWARE_VERSION)
+@@ -127,723 +139,769 @@ define Download/linux-firmware
+ endef
+ $(eval $(call Download,linux-firmware))
+ 
+-PKG_ATH10K_LINUX_FIRMWARE_NAME:=ath10k-firmware
+-PKG_ATH10K_LINUX_FIRMWARE_VERSION:=da0f85d924226ee30c46e037120621c9e192b39e
+-PKG_ATH10K_LINUX_FIRMWARE_SOURCE:=$(PKG_ATH10K_LINUX_FIRMWARE_NAME)-$(PKG_ATH10K_LINUX_FIRMWARE_VERSION).tar.bz2
+-PKG_ATH10K_LINUX_FIRMWARE_PROTO:=git
+-PKG_ATH10K_LINUX_FIRMWARE_SOURCE_URL:=https://github.com/kvalo/ath10k-firmware.git
+-PKG_ATH10K_LINUX_FIRMWARE_SUBDIR:=$(PKG_ATH10K_LINUX_FIRMWARE_NAME)-$(PKG_ATH10K_LINUX_FIRMWARE_VERSION)
+-#PKG_ATH10K_LINUX_FIRMWARE_MIRROR_MD5SUM:=?
+ 
+-define Download/ath10k-firmware
+-  FILE:=$(PKG_ATH10K_LINUX_FIRMWARE_SOURCE)
+-  URL:=$(PKG_ATH10K_LINUX_FIRMWARE_SOURCE_URL)
+-  PROTO:=$(PKG_ATH10K_LINUX_FIRMWARE_PROTO)
+-  VERSION:=$(PKG_ATH10K_LINUX_FIRMWARE_VERSION)
+-  SUBDIR:=$(PKG_ATH10K_LINUX_FIRMWARE_SUBDIR)
+-  #MIRROR_MD5SUM:=$(PKG_ATH10K_LINUX_FIRMWARE_MIRROR_MD5SUM)
++define KernelPackage/adm8211
++  $(call KernelPackage/mac80211/Default)
++  TITLE:=ADMTek 8211 support
++  DEPENDS+=@PCI_SUPPORT +kmod-mac80211 +kmod-eeprom-93cx6
++  FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/adm8211.ko
++  AUTOLOAD:=$(call AutoProbe,adm8211)
+ endef
+-$(eval $(call Download,ath10k-firmware))
+ 
+-# 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 KernelPackage/ath/config
++  if PACKAGE_kmod-ath
++	config ATH_USER_REGD
++		bool "Force Atheros drivers to respect the user's regdomain settings"
++		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
++		  even further, even if the country allows frequencies or power levels that
++		  are forbidden by the EEPROM settings.
+ 
+-define Download/p54usb
+-  FILE:=$(P54USBFW)
+-  URL:=http://daemonizer.de/prism54/prism54-fw/fw-usb
+-  MD5SUM:=8e8ab005a4f8f0123bcdc51bc25b47f6
+-endef
+-$(eval $(call Download,p54usb))
++		  Select this option if you want the driver to respect the user's decision about
++		  regulatory settings.
+ 
+-define Download/p54pci
+-  FILE:=$(P54PCIFW)
+-  URL:=http://daemonizer.de/prism54/prism54-fw/fw-softmac
+-  MD5SUM:=ff7536af2092b1c4b21315bd103ef4c4
+-endef
+-$(eval $(call Download,p54pci))
++	config PACKAGE_ATH_DEBUG
++		bool "Atheros wireless debugging"
++		help
++		  Say Y, if you want to debug atheros wireless drivers.
++		  Only ath9k & ath10k make use of this.
+ 
+-define Download/p54spi
+-  FILE:=$(P54SPIFW)
+-  URL:=http://daemonizer.de/prism54/prism54-fw/stlc4560
+-  MD5SUM:=42661f8ecbadd88012807493f596081d
+-endef
+-$(eval $(call Download,p54spi))
++	config PACKAGE_ATH_DFS
++		bool "Enable DFS support"
++		default y
++		help
++		  Dynamic frequency selection (DFS) is required for most of the 5 GHz band
++		  channels in Europe, US, and Japan.
+ 
+-define KernelPackage/p54/Default
+-  $(call KernelPackage/mac80211/Default)
+-  TITLE:=Prism54 Drivers
+-endef
++		  Select this option if you want to use such channels.
+ 
+-define KernelPackage/p54/description
+-  Kernel module for Prism54 chipsets (mac80211)
++  endif
+ endef
+ 
+-define KernelPackage/p54-common
+-  $(call KernelPackage/p54/Default)
+-  DEPENDS+= @PCI_SUPPORT||@USB_SUPPORT||@TARGET_omap24xx +kmod-mac80211 +kmod-lib-crc-ccitt
+-  TITLE+= (COMMON)
+-  FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/p54/p54common.ko
++define KernelPackage/ath
++  $(call KernelPackage/mac80211/Default)
++  TITLE:=Atheros common driver part
++  DEPENDS+= @PCI_SUPPORT||USB_SUPPORT||TARGET_ar71xx||TARGET_ath25 +kmod-mac80211
++  FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/ath/ath.ko
++  MENU:=1
+ endef
+ 
+-define KernelPackage/p54-pci
+-  $(call KernelPackage/p54/Default)
+-  TITLE+= (PCI)
+-  DEPENDS+= @PCI_SUPPORT +kmod-p54-common
+-  FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/p54/p54pci.ko
+-  AUTOLOAD:=$(call AutoProbe,p54pci)
++define KernelPackage/ath/description
++ This module contains some common parts needed by Atheros Wireless drivers.
+ endef
+ 
+-define KernelPackage/p54-usb
+-  $(call KernelPackage/p54/Default)
+-  TITLE+= (USB)
+-  DEPENDS+= @USB_SUPPORT +kmod-usb-core +kmod-p54-common
+-  FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/p54/p54usb.ko
+-  AUTOLOAD:=$(call AutoProbe,p54usb)
++define KernelPackage/ath5k
++  $(call KernelPackage/mac80211/Default)
++  TITLE:=Atheros 5xxx wireless cards support
++  URL:=https://wireless.wiki.kernel.org/en/users/drivers/ath5k
++  DEPENDS+= @PCI_SUPPORT||@TARGET_ath25 +kmod-ath
++  FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/ath/ath5k/ath5k.ko
++  AUTOLOAD:=$(call AutoProbe,ath5k)
+ endef
+ 
+-define KernelPackage/p54-spi
+-  $(call KernelPackage/p54/Default)
+-  TITLE+= (SPI)
+-  DEPENDS+= @TARGET_omap24xx +kmod-p54-common
+-  FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/p54/p54spi.ko
+-  AUTOLOAD:=$(call AutoProbe,p54spi)
++define KernelPackage/ath5k/description
++ This module adds support for wireless adapters based on
++ Atheros 5xxx chipset.
+ endef
+ 
+-define KernelPackage/rt2x00/Default
++define KernelPackage/ath9k-common
+   $(call KernelPackage/mac80211/Default)
+-  TITLE:=Ralink Drivers for RT2x00 cards
++  TITLE:=Atheros 802.11n wireless devices (common code for ath9k and ath9k_htc)
++  URL:=https://wireless.wiki.kernel.org/en/users/drivers/ath9k
++  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 \
++	$(PKG_BUILD_DIR)/drivers/net/wireless/ath/ath9k/ath9k_hw.ko
+ endef
+ 
+-define KernelPackage/rt2x00-lib
+-$(call KernelPackage/rt2x00/Default)
+-  DEPENDS+= @(PCI_SUPPORT||USB_SUPPORT||TARGET_ramips) +kmod-mac80211 +kmod-lib-crc-itu-t
+-  TITLE+= (LIB)
+-  FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/rt2x00/rt2x00lib.ko
+-  MENU:=1
++define KernelPackage/ath9k
++  $(call KernelPackage/mac80211/Default)
++  TITLE:=Atheros 802.11n PCI wireless cards support
++  URL:=https://wireless.wiki.kernel.org/en/users/drivers/ath9k
++  DEPENDS+= @PCI_SUPPORT||TARGET_ar71xx +kmod-ath9k-common
++  FILES:= \
++	$(PKG_BUILD_DIR)/drivers/net/wireless/ath/ath9k/ath9k.ko
++  AUTOLOAD:=$(call AutoProbe,ath9k)
+ endef
+ 
+-define KernelPackage/rt2x00-lib/config
+-  if PACKAGE_kmod-rt2x00-lib
+-
+-	config PACKAGE_RT2X00_LIB_DEBUGFS
+-		bool "Enable rt2x00 debugfs support"
+-		depends on PACKAGE_MAC80211_DEBUGFS
+-		help
+-		  Enable creation of debugfs files for the rt2x00 drivers.
+-		  These debugfs files support both reading and writing of the
+-		  most important register types of the rt2x00 hardware.
+-
+-	config PACKAGE_RT2X00_DEBUG
+-		bool "Enable rt2x00 debug output"
+-		help
+-		  Enable debugging output for all rt2x00 modules
+-
+-  endif
++define KernelPackage/ath9k/description
++This module adds support for wireless adapters based on
++Atheros IEEE 802.11n AR5008 and AR9001 family of chipsets.
+ endef
+ 
+-define KernelPackage/rt2x00-mmio
+-$(call KernelPackage/rt2x00/Default)
+-  DEPENDS+= @(PCI_SUPPORT||TARGET_ramips) +kmod-rt2x00-lib +kmod-eeprom-93cx6
+-  HIDDEN:=1
+-  TITLE+= (MMIO)
+-  FILES:= $(PKG_BUILD_DIR)/drivers/net/wireless/rt2x00/rt2x00mmio.ko
+-endef
++define KernelPackage/ath9k/config
+ 
+-define KernelPackage/rt2x00-pci
+-$(call KernelPackage/rt2x00/Default)
+-  DEPENDS+= @PCI_SUPPORT +kmod-rt2x00-mmio +kmod-rt2x00-lib
+-  HIDDEN:=1
+-  TITLE+= (PCI)
+-  FILES:= $(PKG_BUILD_DIR)/drivers/net/wireless/rt2x00/rt2x00pci.ko
+-  AUTOLOAD:=$(call AutoProbe,rt2x00pci)
+-endef
++	config ATH9K_SUPPORT_PCOEM
++		bool "Support chips used in PC OEM cards"
++		depends on PACKAGE_kmod-ath9k
+ 
+-define KernelPackage/rt2x00-usb
+-$(call KernelPackage/rt2x00/Default)
+-  DEPENDS+= @USB_SUPPORT +kmod-rt2x00-lib +kmod-usb-core
+-  HIDDEN:=1
+-  TITLE+= (USB)
+-  FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/rt2x00/rt2x00usb.ko
+-  AUTOLOAD:=$(call AutoProbe,rt2x00usb)
+ endef
+ 
+-define KernelPackage/rt2800-lib
+-$(call KernelPackage/rt2x00/Default)
+-  DEPENDS+= @(PCI_SUPPORT||USB_SUPPORT||TARGET_ramips) +kmod-rt2x00-lib +kmod-lib-crc-ccitt +@DRIVER_11N_SUPPORT
+-  HIDDEN:=1
+-  TITLE+= (rt2800 LIB)
+-  FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/rt2x00/rt2800lib.ko
++define KernelPackage/ath9k-htc
++  $(call KernelPackage/mac80211/Default)
++  TITLE:=Atheros 802.11n USB device support
++  URL:=https://wireless.wiki.kernel.org/en/users/drivers/ath9k
++  DEPENDS+= @USB_SUPPORT +kmod-ath9k-common +kmod-usb-core
++  FILES:= \
++	$(PKG_BUILD_DIR)/drivers/net/wireless/ath/ath9k/ath9k_htc.ko
++  AUTOLOAD:=$(call AutoProbe,ath9k_htc)
+ endef
+ 
+-define KernelPackage/rt2400-pci
+-$(call KernelPackage/rt2x00/Default)
+-  DEPENDS+= @PCI_SUPPORT +kmod-rt2x00-pci
+-  TITLE+= (RT2400 PCI)
+-  FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/rt2x00/rt2400pci.ko
+-  AUTOLOAD:=$(call AutoProbe,rt2400pci)
++define KernelPackage/ath9k-htc/description
++This module adds support for wireless adapters based on
++Atheros USB AR9271 and AR7010 family of chipsets.
+ endef
+ 
+-define KernelPackage/rt2500-pci
+-$(call KernelPackage/rt2x00/Default)
+-  DEPENDS+= @PCI_SUPPORT +kmod-rt2x00-pci
+-  TITLE+= (RT2500 PCI)
+-  FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/rt2x00/rt2500pci.ko
+-  AUTOLOAD:=$(call AutoProbe,rt2500pci)
++define KernelPackage/ath10k
++  $(call KernelPackage/mac80211/Default)
++  TITLE:=Atheros 802.11ac wireless cards support
++  URL:=https://wireless.wiki.kernel.org/en/users/Drivers/ath10k
++  DEPENDS+= @PCI_SUPPORT +kmod-ath +@DRIVER_11N_SUPPORT +@DRIVER_11W_SUPPORT
++  FILES:= \
++	$(PKG_BUILD_DIR)/drivers/net/wireless/ath/ath10k/ath10k_core.ko \
++	$(PKG_BUILD_DIR)/drivers/net/wireless/ath/ath10k/ath10k_pci.ko
++  AUTOLOAD:=$(call AutoLoad,55,ath10k_core ath10k_pci)
+ endef
+ 
+-define KernelPackage/rt2500-usb
+-$(call KernelPackage/rt2x00/Default)
+-  DEPENDS+= @USB_SUPPORT +kmod-rt2x00-usb
+-  TITLE+= (RT2500 USB)
+-  FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/rt2x00/rt2500usb.ko
+-  AUTOLOAD:=$(call AutoProbe,rt2500usb)
++define KernelPackage/ath10k/description
++This module adds support for wireless adapters based on
++Atheros IEEE 802.11ac family of chipsets. For now only
++PCI is supported.
+ endef
+ 
+-define KernelPackage/rt61-pci
+-$(call KernelPackage/rt2x00/Default)
+-  DEPENDS+= @PCI_SUPPORT +kmod-rt2x00-pci
+-  TITLE+= (RT2x61 PCI)
+-  FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/rt2x00/rt61pci.ko
+-  AUTOLOAD:=$(call AutoProbe,rt61pci)
+-endef
++PKG_ATH10K_LINUX_FIRMWARE_NAME:=ath10k-firmware
++PKG_ATH10K_LINUX_FIRMWARE_VERSION:=b46f3e01a6c1f9150fb4612ef53611d714565842
++PKG_ATH10K_LINUX_FIRMWARE_SOURCE:=$(PKG_ATH10K_LINUX_FIRMWARE_NAME)-$(PKG_ATH10K_LINUX_FIRMWARE_VERSION).tar.bz2
++PKG_ATH10K_LINUX_FIRMWARE_PROTO:=git
++PKG_ATH10K_LINUX_FIRMWARE_SOURCE_URL:=https://github.com/kvalo/ath10k-firmware.git
++PKG_ATH10K_LINUX_FIRMWARE_SUBDIR:=$(PKG_ATH10K_LINUX_FIRMWARE_NAME)-$(PKG_ATH10K_LINUX_FIRMWARE_VERSION)
++#PKG_ATH10K_LINUX_FIRMWARE_MIRROR_MD5SUM:=?
+ 
+-define KernelPackage/rt73-usb
+-  $(call KernelPackage/rt2x00/Default)
+-  DEPENDS+= @USB_SUPPORT +kmod-rt2x00-usb
+-  TITLE+= (RT73 USB)
+-  FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/rt2x00/rt73usb.ko
+-  AUTOLOAD:=$(call AutoProbe,rt73usb)
++define Download/ath10k-firmware
++  FILE:=$(PKG_ATH10K_LINUX_FIRMWARE_SOURCE)
++  URL:=$(PKG_ATH10K_LINUX_FIRMWARE_SOURCE_URL)
++  PROTO:=$(PKG_ATH10K_LINUX_FIRMWARE_PROTO)
++  VERSION:=$(PKG_ATH10K_LINUX_FIRMWARE_VERSION)
++  SUBDIR:=$(PKG_ATH10K_LINUX_FIRMWARE_SUBDIR)
++  #MIRROR_MD5SUM:=$(PKG_ATH10K_LINUX_FIRMWARE_MIRROR_MD5SUM)
+ endef
++$(eval $(call Download,ath10k-firmware))
+ 
+-define KernelPackage/rt2800-mmio
+-$(call KernelPackage/rt2x00/Default)
+-  TITLE += (RT28xx/RT3xxx MMIO)
+-  DEPENDS += +kmod-rt2800-lib +kmod-rt2x00-mmio
+-  HIDDEN:=1
+-  FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/rt2x00/rt2800mmio.ko
+-endef
+ 
+-define KernelPackage/rt2800-soc
+-$(call KernelPackage/rt2x00/Default)
+-  DEPENDS += @(TARGET_ramips_rt288x||TARGET_ramips_rt305x||TARGET_ramips_rt3883||TARGET_ramips_mt7620) +kmod-rt2800-mmio +kmod-rt2800-lib
+-  TITLE += (RT28xx/RT3xxx SoC)
+-  FILES := \
+-	$(PKG_BUILD_DIR)/drivers/net/wireless/rt2x00/rt2x00soc.ko \
+-	$(PKG_BUILD_DIR)/drivers/net/wireless/rt2x00/rt2800soc.ko
+-  AUTOLOAD:=$(call AutoProbe,rt2800soc)
+-endef
++#Broadcom firmware
++ifneq ($(CONFIG_B43_FW_6_30),)
++  PKG_B43_FWV4_NAME:=broadcom-wl
++  PKG_B43_FWV4_VERSION:=6.30.163.46
++  PKG_B43_FWV4_OBJECT:=$(PKG_B43_FWV4_NAME)-$(PKG_B43_FWV4_VERSION).wl_apsta.o
++  PKG_B43_FWV4_SOURCE:=$(PKG_B43_FWV4_NAME)-$(PKG_B43_FWV4_VERSION).tar.bz2
++  PKG_B43_FWV4_SOURCE_URL:=http://www.lwfinger.com/b43-firmware/
++  PKG_B43_FWV4_MD5SUM:=6fe97e9368d25342a1ab943d3cf3496d
++else
++ifneq ($(CONFIG_B43_FW_5_10),)
++  PKG_B43_FWV4_NAME:=broadcom-wl
++  PKG_B43_FWV4_VERSION:=5.10.56.27.3
++  PKG_B43_FWV4_OBJECT:=$(PKG_B43_FWV4_NAME)-$(PKG_B43_FWV4_VERSION)/driver/wl_apsta/wl_prebuilt.o
++  PKG_B43_FWV4_SOURCE:=$(PKG_B43_FWV4_NAME)-$(PKG_B43_FWV4_VERSION)_mipsel.tar.bz2
++  PKG_B43_FWV4_SOURCE_URL:=http://mirror2.openwrt.org/sources/
++  PKG_B43_FWV4_MD5SUM:=3363e3a6b3d9d73c49dea870c7834eac
++else
++ifneq ($(CONFIG_B43_FW_4_178),)
++  PKG_B43_FWV4_NAME:=broadcom-wl
++  PKG_B43_FWV4_VERSION:=4.178.10.4
++  PKG_B43_FWV4_OBJECT:=$(PKG_B43_FWV4_NAME)-$(PKG_B43_FWV4_VERSION)/linux/wl_apsta.o
++  PKG_B43_FWV4_SOURCE:=$(PKG_B43_FWV4_NAME)-$(PKG_B43_FWV4_VERSION).tar.bz2
++  PKG_B43_FWV4_SOURCE_URL:=http://mirror2.openwrt.org/sources/
++  PKG_B43_FWV4_MD5SUM:=14477e8cbbb91b11896affac9b219fdb
++else
++ifneq ($(CONFIG_B43_FW_5_100_138),)
++  PKG_B43_FWV4_NAME:=broadcom-wl
++  PKG_B43_FWV4_VERSION:=5.100.138
++  PKG_B43_FWV4_OBJECT:=$(PKG_B43_FWV4_NAME)-$(PKG_B43_FWV4_VERSION)/linux/wl_apsta.o
++  PKG_B43_FWV4_SOURCE:=$(PKG_B43_FWV4_NAME)-$(PKG_B43_FWV4_VERSION).tar.bz2
++  PKG_B43_FWV4_SOURCE_URL:=http://www.lwfinger.com/b43-firmware/
++  PKG_B43_FWV4_MD5SUM:=f4e357b09eaf5d8b1f1920cf3493a555
++else
++  PKG_B43_FWV4_NAME:=broadcom-wl
++  PKG_B43_FWV4_VERSION:=4.150.10.5
++  PKG_B43_FWV4_OBJECT:=$(PKG_B43_FWV4_NAME)-$(PKG_B43_FWV4_VERSION)/driver/wl_apsta_mimo.o
++  PKG_B43_FWV4_SOURCE:=$(PKG_B43_FWV4_NAME)-$(PKG_B43_FWV4_VERSION).tar.bz2
++  PKG_B43_FWV4_SOURCE_URL:=http://mirror2.openwrt.org/sources/
++  PKG_B43_FWV4_MD5SUM:=0c6ba9687114c6b598e8019e262d9a60
++endif
++endif
++endif
++endif
++ifneq ($(CONFIG_B43_OPENFIRMWARE),)
++  PKG_B43_FWV4_NAME:=broadcom-wl
++  PKG_B43_FWV4_VERSION:=5.2
++  PKG_B43_FWV4_OBJECT:=openfwwf-$(PKG_B43_FWV4_VERSION)
++  PKG_B43_FWV4_SOURCE:=openfwwf-$(PKG_B43_FWV4_VERSION).tar.gz
++  PKG_B43_FWV4_SOURCE_URL:=http://www.ing.unibs.it/openfwwf/firmware/
++  PKG_B43_FWV4_MD5SUM:=e045a135453274e439ae183f8498b0fa
++endif
+ 
+-define KernelPackage/rt2800-pci
+-$(call KernelPackage/rt2x00/Default)
+-  DEPENDS+= @PCI_SUPPORT +kmod-rt2x00-pci +kmod-rt2800-lib +kmod-rt2800-mmio
+-  TITLE+= (RT2860 PCI)
+-  FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/rt2x00/rt2800pci.ko
+-  AUTOLOAD:=$(call AutoProbe,rt2800pci)
++
++PKG_B43_FWV3_NAME:=wl_apsta
++PKG_B43_FWV3_VERSION:=3.130.20.0
++PKG_B43_FWV3_SOURCE:=$(PKG_B43_FWV3_NAME)-$(PKG_B43_FWV3_VERSION).o
++PKG_B43_FWV3_SOURCE_URL:=http://downloads.openwrt.org/sources/
++PKG_B43_FWV3_MD5SUM:=e08665c5c5b66beb9c3b2dd54aa80cb3
++
++define Download/b43
++  FILE:=$(PKG_B43_FWV4_SOURCE)
++  URL:=$(PKG_B43_FWV4_SOURCE_URL)
++  MD5SUM:=$(PKG_B43_FWV4_MD5SUM)
+ endef
++$(eval $(call Download,b43))
+ 
+-define KernelPackage/rt2800-usb
+-$(call KernelPackage/rt2x00/Default)
+-  DEPENDS+= @USB_SUPPORT +kmod-rt2x00-usb +kmod-rt2800-lib +kmod-lib-crc-ccitt
+-  TITLE+= (RT2870 USB)
+-  FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/rt2x00/rt2800usb.ko
+-  AUTOLOAD:=$(call AutoProbe,rt2800usb)
++define Download/b43legacy
++  FILE:=$(PKG_B43_FWV3_SOURCE)
++  URL:=$(PKG_B43_FWV3_SOURCE_URL)
++  MD5SUM:=$(PKG_B43_FWV3_MD5SUM)
+ endef
++$(eval $(call Download,b43legacy))
+ 
+-define KernelPackage/rtl818x/Default
++
++define KernelPackage/b43
+   $(call KernelPackage/mac80211/Default)
+-  TITLE:=Realtek Drivers for RTL818x devices
+-  URL:=http://wireless.kernel.org/en/users/Drivers/rtl8187
+-  DEPENDS+= +kmod-eeprom-93cx6 +kmod-mac80211
++  TITLE:=Broadcom 43xx wireless support
++  URL:=https://wireless.wiki.kernel.org/en/users/drivers/b43
++  KCONFIG:= \
++  	CONFIG_HW_RANDOM=y
++  # Depend on PCI_SUPPORT to make sure we can select kmod-bcma or kmod-ssb
++  DEPENDS += \
++	@PCI_SUPPORT +kmod-mac80211 \
++	$(if $(CONFIG_PACKAGE_B43_USE_SSB),+kmod-ssb) \
++	$(if $(CONFIG_PACKAGE_B43_USE_BCMA),+kmod-bcma)
++  FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/b43/b43.ko
++  AUTOLOAD:=$(call AutoProbe,b43)
++  MENU:=1
+ endef
+ 
+-define KernelPackage/rtl8180
+-  $(call KernelPackage/rtl818x/Default)
+-  DEPENDS+= @PCI_SUPPORT
+-  TITLE+= (RTL8180 PCI)
+-  FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/rtl818x/rtl8180/rtl818x_pci.ko
+-  AUTOLOAD:=$(call AutoProbe,rtl818x_pci)
+-endef
++define KernelPackage/b43/config
+ 
+-define KernelPackage/rtl8187
+-$(call KernelPackage/rtl818x/Default)
+-  DEPENDS+= @USB_SUPPORT +kmod-usb-core
+-  TITLE+= (RTL8187 USB)
+-  FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/rtl818x/rtl8187/rtl8187.ko
+-  AUTOLOAD:=$(call AutoProbe,rtl8187)
+-endef
++config PACKAGE_B43_USE_SSB
++	select PACKAGE_kmod-ssb
++	tristate
++	depends on !TARGET_brcm47xx && !TARGET_brcm63xx
++	default PACKAGE_kmod-b43 if PACKAGE_B43_BUSES_BCMA_AND_SSB
++	default PACKAGE_kmod-b43 if PACKAGE_B43_BUSES_SSB
+ 
+-define KernelPackage/rtlwifi/config
+-	config PACKAGE_RTLWIFI_DEBUG
+-		bool "Realtek wireless debugging"
+-		depends on PACKAGE_kmod-rtlwifi
++config PACKAGE_B43_USE_BCMA
++	select PACKAGE_kmod-bcma
++	tristate
++	depends on !TARGET_brcm47xx && !TARGET_bcm53xx
++	default PACKAGE_kmod-b43 if PACKAGE_B43_BUSES_BCMA_AND_SSB
++	default PACKAGE_kmod-b43 if PACKAGE_B43_BUSES_BCMA
++
++  if PACKAGE_kmod-b43
++
++	choice
++		prompt "b43 firmware version"
++		default B43_FW_5_100_138
+ 		help
+-		  Say Y, if you want to debug realtek wireless drivers.
++		  This option allows you to select the version of the b43 firmware.
+ 
+-endef
++	config B43_FW_4_150
++		bool "Firmware 410.2160 from driver 4.150.10.5 (old stable)"
++		help
++		  Old stable firmware for BCM43xx devices.
+ 
+-define KernelPackage/rtlwifi
+-  $(call KernelPackage/mac80211/Default)
+-  TITLE:=Realtek common driver part
+-  DEPENDS+= @(PCI_SUPPORT||USB_SUPPORT) +kmod-mac80211 +@DRIVER_11N_SUPPORT
+-  FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/rtlwifi/rtlwifi.ko
+-  HIDDEN:=1
+-endef
++		  If unsure, select this.
+ 
+-define KernelPackage/rtlwifi-pci
+-  $(call KernelPackage/mac80211/Default)
+-  TITLE:=Realtek common driver part (PCI support)
+-  DEPENDS+= @PCI_SUPPORT +kmod-rtlwifi
+-  FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/rtlwifi/rtl_pci.ko
+-  AUTOLOAD:=$(call AutoProbe,rtl_pci)
+-  HIDDEN:=1
+-endef
++	config B43_FW_4_178
++		bool "Firmware 478.104 from driver 4.178.10.4"
++		help
++		  Older firmware for BCM43xx devices.
+ 
+-define KernelPackage/rtlwifi-usb
+-  $(call KernelPackage/mac80211/Default)
+-  TITLE:=Realtek common driver part (USB support)
+-  DEPENDS+= @USB_SUPPORT +kmod-usb-core +kmod-rtlwifi
+-  FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/rtlwifi/rtl_usb.ko
+-  AUTOLOAD:=$(call AutoProbe,rtl_usb)
+-  HIDDEN:=1
+-endef
++		  If unsure, select the "stable" firmware.
+ 
+-define KernelPackage/rtl8192c-common
+-  $(call KernelPackage/mac80211/Default)
+-  TITLE:=Realtek RTL8192CE/RTL8192CU common support module
+-  DEPENDS+= +kmod-rtlwifi
+-  FILES:= $(PKG_BUILD_DIR)/drivers/net/wireless/rtlwifi/rtl8192c/rtl8192c-common.ko
+-  HIDDEN:=1
+-endef
++	config B43_FW_5_10
++		bool "Firmware 508.1084 from driver 5.10.56.27"
++		help
++		  Older firmware for BCM43xx devices.
+ 
+-define KernelPackage/rtl8192ce
+-  $(call KernelPackage/mac80211/Default)
+-  TITLE:=Realtek RTL8192CE/RTL8188CE support
+-  DEPENDS+= +kmod-rtlwifi-pci +kmod-rtl8192c-common
+-  FILES:= $(PKG_BUILD_DIR)/drivers/net/wireless/rtlwifi/rtl8192ce/rtl8192ce.ko
+-  AUTOLOAD:=$(call AutoProbe,rtl8192ce)
+-endef
++		  If unsure, select the "stable" firmware.
+ 
+-define KernelPackage/rtl8192ce/install
+-	$(INSTALL_DIR) $(1)/lib/firmware/rtlwifi
+-	$(INSTALL_DATA) $(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/rtlwifi/rtl8192cfw.bin $(1)/lib/firmware/rtlwifi
+-	$(INSTALL_DATA) $(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/rtlwifi/rtl8192cfwU.bin $(1)/lib/firmware/rtlwifi
+-	$(INSTALL_DATA) $(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/rtlwifi/rtl8192cfwU_B.bin $(1)/lib/firmware/rtlwifi
+-endef
++	config B43_FW_5_100_138
++		bool "Firmware 666.2 from driver 5.100.138 (stable)"
++		help
++		  The currently default firmware for BCM43xx devices.
+ 
+-define KernelPackage/rtl8192se
+-  $(call KernelPackage/mac80211/Default)
+-  TITLE:=Realtek RTL8192SE/RTL8191SE support
+-  DEPENDS+= +kmod-rtlwifi-pci
+-  FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/rtlwifi/rtl8192se/rtl8192se.ko
+-  AUTOLOAD:=$(call AutoProbe,rtl8192se)
+-endef
++		  This firmware currently gets most of the testing and is needed for some N-PHY devices.
+ 
+-define KernelPackage/rtl8192se/install
+-	$(INSTALL_DIR) $(1)/lib/firmware/rtlwifi
+-	$(INSTALL_DATA) $(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/rtlwifi/rtl8192sefw.bin $(1)/lib/firmware/rtlwifi
+-endef
++		  If unsure, select the this firmware.
+ 
+-define KernelPackage/rtl8192de
+-  $(call KernelPackage/mac80211/Default)
+-  TITLE:=Realtek RTL8192DE/RTL8188DE support
+-  DEPENDS+= +kmod-rtlwifi-pci
+-  FILES:= $(PKG_BUILD_DIR)/drivers/net/wireless/rtlwifi/rtl8192de/rtl8192de.ko
+-  AUTOLOAD:=$(call AutoProbe,rtl8192de)
+-endef
++	config B43_FW_6_30
++		bool "Firmware 784.2 from driver 6.30.163.46 (experimental)"
++		help
++		  Newer experimental firmware for BCM43xx devices.
+ 
+-define KernelPackage/rtl8192de/install
+-	$(INSTALL_DIR) $(1)/lib/firmware/rtlwifi
+-	$(INSTALL_DATA) $(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/rtlwifi/rtl8192defw.bin $(1)/lib/firmware/rtlwifi
+-endef
++		  This firmware is mostly untested.
+ 
+-define KernelPackage/rtl8192cu
+-  $(call KernelPackage/mac80211/Default)
+-  TITLE:=Realtek RTL8192CU/RTL8188CU support
+-  DEPENDS+= +kmod-rtlwifi-usb +kmod-rtl8192c-common
+-  FILES:= $(PKG_BUILD_DIR)/drivers/net/wireless/rtlwifi/rtl8192cu/rtl8192cu.ko
+-  AUTOLOAD:=$(call AutoProbe,rtl8192cu)
+-endef
++		  If unsure, select the "stable" firmware.
+ 
+-define KernelPackage/rtl8192cu/install
+-	$(INSTALL_DIR) $(1)/lib/firmware/rtlwifi
+-	$(INSTALL_DATA) $(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/rtlwifi/rtl8192cufw.bin $(1)/lib/firmware/rtlwifi
+-	$(INSTALL_DATA) $(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/rtlwifi/rtl8192cufw_A.bin $(1)/lib/firmware/rtlwifi
+-	$(INSTALL_DATA) $(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/rtlwifi/rtl8192cufw_B.bin $(1)/lib/firmware/rtlwifi
+-	$(INSTALL_DATA) $(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/rtlwifi/rtl8192cufw_TMSC.bin $(1)/lib/firmware/rtlwifi
+-endef
++	config B43_OPENFIRMWARE
++		bool "Open FirmWare for WiFi networks"
++		help
++		  Opensource firmware for BCM43xx devices.
+ 
+-ZD1211FW_NAME:=zd1211-firmware
+-ZD1211FW_VERSION:=1.4
+-define Download/zd1211rw
+-  FILE:=$(ZD1211FW_NAME)-$(ZD1211FW_VERSION).tar.bz2
+-  URL:=@SF/zd1211/
+-  MD5SUM:=19f28781d76569af8551c9d11294c870
+-endef
+-$(eval $(call Download,zd1211rw))
++		  Do _not_ select this, unless you know what you are doing.
++		  The Opensource firmware is not suitable for embedded devices, yet.
++		  It does not support QoS, which is bad for AccessPoints.
++		  It does not support hardware crypto acceleration, which is a showstopper
++		  for embedded devices with low CPU resources.
+ 
+-define KernelPackage/zd1211rw
+-  $(call KernelPackage/mac80211/Default)
+-  TITLE:=Zydas ZD1211 support
+-  DEPENDS+= @USB_SUPPORT +kmod-usb-core +kmod-mac80211
+-  FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/zd1211rw/zd1211rw.ko
+-  AUTOLOAD:=$(call AutoProbe,zd1211rw)
+-endef
++		  If unsure, select the "stable" firmware.
+ 
+-define KernelPackage/adm8211
+-  $(call KernelPackage/mac80211/Default)
+-  TITLE:=ADMTek 8211 support
+-  DEPENDS+=@PCI_SUPPORT +kmod-mac80211 +kmod-eeprom-93cx6
+-  FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/adm8211.ko
+-  AUTOLOAD:=$(call AutoProbe,adm8211)
+-endef
++	endchoice
++
++	config B43_FW_SQUASH
++		bool "Remove unnecessary firmware files"
++		depends on !B43_OPENFIRMWARE
++		default y
++		help
++		  This options allows you to remove unnecessary b43 firmware files
++		  from the final rootfs image. This can reduce the rootfs size by
++		  up to 200k.
++
++		  If unsure, say Y.
++
++	config B43_FW_SQUASH_COREREVS
++		string "Core revisions to include"
++		depends on B43_FW_SQUASH
++		default "5,6,7,8,9,10,11,13,15" if TARGET_brcm47xx_legacy
++		default "16,28,29,30" if TARGET_brcm47xx_mips74k
++		default "5,6,7,8,9,10,11,13,15,16,28,29,30"
++		help
++		  This is a comma seperated list of core revision numbers.
++
++		  Example (keep files for rev5 only):
++		    5
++
++		  Example (keep files for rev5 and rev11):
++		    5,11
++
++	config B43_FW_SQUASH_PHYTYPES
++		string "PHY types to include"
++		depends on B43_FW_SQUASH
++		default "G,N,LP" if TARGET_brcm47xx_legacy
++		default "N,HT" if TARGET_brcm47xx_mips74k
++		default "G,N,LP,HT"
++		help
++		  This is a comma seperated list of PHY types:
++		    A  => A-PHY
++		    AG => Dual A-PHY G-PHY
++		    G  => G-PHY
++		    LP => LP-PHY
++		    N  => N-PHY
++		    HT  => HT-PHY
++		    LCN  => LCN-PHY
++		    LCN40  => LCN40-PHY
++		    AC  => AC-PHY
++
++		  Example (keep files for G-PHY only):
++		    G
++
++		  Example (keep files for G-PHY and N-PHY):
++		    G,N
++
++	choice
++		prompt "Supported buses"
++		default PACKAGE_B43_BUSES_BCMA_AND_SSB
++		help
++		  This allows choosing buses that b43 should support.
++
++	config PACKAGE_B43_BUSES_BCMA_AND_SSB
++		depends on !TARGET_brcm47xx_legacy && !TARGET_brcm47xx_mips74k && !TARGET_bcm53xx
++		bool "BCMA and SSB"
++
++	config PACKAGE_B43_BUSES_BCMA
++		depends on !TARGET_brcm47xx_legacy
++		bool "BCMA only"
++
++	config PACKAGE_B43_BUSES_SSB
++		depends on !TARGET_brcm47xx_mips74k && !TARGET_bcm53xx
++		bool "SSB only"
++
++	endchoice
++
++	config PACKAGE_B43_DEBUG
++		bool "Enable debug output and debugfs for b43"
++		default n
++		help
++		  Enable additional debug output and runtime sanity checks for b43
++		  and enables the debugfs interface.
++
++		  If unsure, say N.
++
++	config PACKAGE_B43_PIO
++		bool "Enable support for PIO transfer mode"
++		default n
++		help
++		  Enable support for using PIO instead of DMA. Unless you have DMA
++		  transfer problems you don't need this.
++
++		  If unsure, say N.
++
++	config PACKAGE_B43_PHY_G
++		bool "Enable support for G-PHYs"
++		default n if TARGET_brcm47xx_mips74k
++		default y
++		help
++		  Enable support for G-PHY. This includes support for the following devices:
++		  PCI: BCM4306, BCM4311, BCM4318
++		  SoC: BCM5352E, BCM4712
+ 
+-define KernelPackage/ath/config
+-  if PACKAGE_kmod-ath
+-	config ATH_USER_REGD
+-		bool "Force Atheros drivers to respect the user's regdomain settings"
++		  If unsure, say Y.
++
++	config PACKAGE_B43_PHY_N
++		bool "Enable support for N-PHYs"
++		default y
+ 		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
+-		  even further, even if the country allows frequencies or power levels that
+-		  are forbidden by the EEPROM settings.
++		  Enable support for N-PHY. This includes support for the following devices:
++		  PCI: BCM4321, BCM4322, BCM43222, BCM43224, BCM43225
++		  SoC: BCM4716, BCM4717, BCM4718
+ 
+-		  Select this option if you want the driver to respect the user's decision about
+-		  regulatory settings.
++		  Currently only 11g speed is available.
+ 
+-	config PACKAGE_ATH_DEBUG
+-		bool "Atheros wireless debugging"
++		  If unsure, say Y.
++
++	config PACKAGE_B43_PHY_LP
++		bool "Enable support for LP-PHYs"
++		default n if TARGET_brcm47xx_mips74k
++		default y
+ 		help
+-		  Say Y, if you want to debug atheros wireless drivers.
+-		  Right now only ath9k makes use of this.
++		  Enable support for LP-PHY. This includes support for the following devices:
++		  PCI: BCM4312
++		  SoC: BCM5354
+ 
+-	config PACKAGE_ATH_DFS
+-		bool "Enable DFS support"
++		  If unsure, say Y.
++
++	config PACKAGE_B43_PHY_HT
++		bool "Enable support for HT-PHYs"
++		default n if TARGET_brcm47xx_legacy
+ 		default y
+ 		help
+-		  Dynamic frequency selection (DFS) is required for most of the 5 GHz band
+-		  channels in Europe, US, and Japan.
++		  Enable support for HT-PHY. This includes support for the following devices:
++		  PCI: BCM4331
+ 
+-		  Select this option if you want to use such channels.
++		  Currently only 11g speed is available.
+ 
+-  endif
+-endef
++		  If unsure, say Y.
+ 
+-define KernelPackage/ath
+-  $(call KernelPackage/mac80211/Default)
+-  TITLE:=Atheros common driver part
+-  DEPENDS+= @PCI_SUPPORT||USB_SUPPORT||TARGET_ar71xx||TARGET_ath25 +kmod-mac80211
+-  FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/ath/ath.ko
+-  MENU:=1
+-endef
++	config PACKAGE_B43_PHY_LCN
++		bool "Enable support for LCN-PHYs"
++		depends on BROKEN
++		default n
++		help
++		  Currently broken.
+ 
+-define KernelPackage/ath/description
+- This module contains some common parts needed by Atheros Wireless drivers.
+-endef
++		  If unsure, say N.
+ 
+-define KernelPackage/ath5k
+-  $(call KernelPackage/mac80211/Default)
+-  TITLE:=Atheros 5xxx wireless cards support
+-  URL:=https://wireless.wiki.kernel.org/en/users/drivers/ath5k
+-  DEPENDS+= @PCI_SUPPORT||@TARGET_ath25 +kmod-ath
+-  FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/ath/ath5k/ath5k.ko
+-  AUTOLOAD:=$(call AutoProbe,ath5k)
++  endif
+ endef
+ 
+-define KernelPackage/ath5k/description
+- This module adds support for wireless adapters based on
+- Atheros 5xxx chipset.
++define KernelPackage/b43/description
++Kernel module for Broadcom 43xx wireless support (mac80211 stack) new
+ endef
+ 
+-define KernelPackage/ath9k-common
++define KernelPackage/b43legacy
+   $(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
+-  DEPENDS+= @PCI_SUPPORT||USB_SUPPORT||TARGET_ar71xx +kmod-ath +@DRIVER_11N_SUPPORT +@KERNEL_RELAY
+-  FILES:= \
+-	$(PKG_BUILD_DIR)/drivers/net/wireless/ath/ath9k/ath9k_common.ko \
+-	$(PKG_BUILD_DIR)/drivers/net/wireless/ath/ath9k/ath9k_hw.ko
++  TITLE:=Broadcom 43xx-legacy wireless support
++  URL:=https://wireless.wiki.kernel.org/en/users/drivers/b43
++  KCONFIG:= \
++  	CONFIG_HW_RANDOM=y
++  DEPENDS+= +kmod-mac80211 +!(TARGET_brcm47xx||TARGET_brcm63xx):kmod-ssb
++  FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/b43legacy/b43legacy.ko
++  AUTOLOAD:=$(call AutoProbe,b43legacy)
++  MENU:=1
+ endef
+ 
+-define KernelPackage/ath9k
+-  $(call KernelPackage/mac80211/Default)
+-  TITLE:=Atheros 802.11n PCI wireless cards support
+-  URL:=https://wireless.wiki.kernel.org/en/users/drivers/ath9k
+-  DEPENDS+= @PCI_SUPPORT||TARGET_ar71xx +kmod-ath9k-common
+-  FILES:= \
+-	$(PKG_BUILD_DIR)/drivers/net/wireless/ath/ath9k/ath9k.ko
+-  AUTOLOAD:=$(call AutoProbe,ath9k)
+-endef
++define KernelPackage/b43legacy/config
++  if PACKAGE_kmod-b43legacy
+ 
+-define KernelPackage/ath9k/description
+-This module adds support for wireless adapters based on
+-Atheros IEEE 802.11n AR5008 and AR9001 family of chipsets.
+-endef
++	config B43LEGACY_FW_SQUASH
++		bool "Remove unnecessary firmware files"
++		default y
++		help
++		  This options allows you to remove unnecessary b43legacy firmware files
++		  from the final rootfs image. This can reduce the rootfs size by
++		  up to 50k.
+ 
+-define KernelPackage/ath9k/config
++		  If unsure, say Y.
+ 
+-	config ATH9K_SUPPORT_PCOEM
+-		bool "Support chips used in PC OEM cards"
+-		depends on PACKAGE_kmod-ath9k
+-	
+-endef
++	config B43LEGACY_FW_SQUASH_COREREVS
++		string "Core revisions to include"
++		depends on B43LEGACY_FW_SQUASH
++		default "1,2,3,4"
++		help
++		  This is a comma seperated list of core revision numbers.
+ 
+-define KernelPackage/ath9k-htc
+-  $(call KernelPackage/mac80211/Default)
+-  TITLE:=Atheros 802.11n USB device support
+-  URL:=https://wireless.wiki.kernel.org/en/users/drivers/ath9k
+-  DEPENDS+= @USB_SUPPORT +kmod-ath9k-common +kmod-usb-core
+-  FILES:= \
+-	$(PKG_BUILD_DIR)/drivers/net/wireless/ath/ath9k/ath9k_htc.ko
+-  AUTOLOAD:=$(call AutoProbe,ath9k_htc)
++		  Example (keep files for rev4 only):
++		    4
++
++		  Example (keep files for rev2 and rev4):
++		    2,4
++
++  endif
+ endef
+ 
+-define KernelPackage/ath9k-htc/description
+-This module adds support for wireless adapters based on
+-Atheros USB AR9271 and AR7010 family of chipsets.
++define KernelPackage/b43legacy/description
++Kernel module for Broadcom 43xx-legacy wireless support (mac80211 stack) new
+ endef
+ 
+-define KernelPackage/ath10k
++
++define KernelPackage/brcmutil
+   $(call KernelPackage/mac80211/Default)
+-  TITLE:=Atheros 802.11ac wireless cards support
+-  URL:=https://wireless.wiki.kernel.org/en/users/Drivers/ath10k
+-  DEPENDS+= @PCI_SUPPORT +kmod-ath +@DRIVER_11N_SUPPORT
+-  FILES:= \
+-	$(PKG_BUILD_DIR)/drivers/net/wireless/ath/ath10k/ath10k_core.ko \
+-	$(PKG_BUILD_DIR)/drivers/net/wireless/ath/ath10k/ath10k_pci.ko
+-  AUTOLOAD:=$(call AutoLoad,55,ath10k_core ath10k_pci)
++  TITLE:=Broadcom IEEE802.11n common driver parts
++  URL:=https://wireless.wiki.kernel.org/en/users/drivers/brcm80211
++  DEPENDS+=@PCI_SUPPORT||USB_SUPPORT
++  FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/brcm80211/brcmutil/brcmutil.ko
++  AUTOLOAD:=$(call AutoProbe,brcmutil)
++  MENU:=1
+ endef
+ 
+-define KernelPackage/ath10k/description
+-This module adds support for wireless adapters based on
+-Atheros IEEE 802.11ac family of chipsets. For now only
+-PCI is supported.
++define KernelPackage/brcmutil/description
++ This module contains some common parts needed by Broadcom Wireless drivers brcmsmac and brcmfmac.
+ endef
+ 
+-define KernelPackage/ath10k/config
+-  if PACKAGE_kmod-ath10k
+-
+-	config ATH10K_STA_FW
+-		bool "Firmware optimized for STA operation"
+-		default n
+-		help
+-		  Use the ath10k firmware optimized for wireless client instead
+-		  of access point operation.
++define KernelPackage/brcmutil/config
++  if PACKAGE_kmod-brcmutil
+ 
+-	config ATH10K_API2_FW
+-		bool "Firmware optimized for AP operation (v10.1 / API v2)"
+-		default n
+-		depends on !ATH10K_STA_FW
++	config PACKAGE_BRCM80211_DEBUG
++		bool "Broadcom wireless driver debugging"
+ 		help
+-		  Use the ath10k firmware from the 10.1 SDK using API v2 optimized
+-		  for access point operation if the default firmware keeps crashing.
++		  Say Y, if you want to debug brcmsmac and brcmfmac wireless driver.
+ 
+   endif
+ endef
+ 
+-define KernelPackage/carl9170
+-  $(call KernelPackage/mac80211/Default)
+-  TITLE:=Driver for Atheros AR9170 USB sticks
+-  DEPENDS:=@USB_SUPPORT +kmod-mac80211 +kmod-ath +kmod-usb-core +kmod-input-core +@DRIVER_11N_SUPPORT
+-  FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/ath/carl9170/carl9170.ko
+-  AUTOLOAD:=$(call AutoProbe,carl9170)
++PKG_BRCMSMAC_FW_NAME:=broadcom-wl
++PKG_BRCMSMAC_FW_VERSION:=5.100.138
++PKG_BRCMSMAC_FW_OBJECT:=$(PKG_BRCMSMAC_FW_NAME)-$(PKG_BRCMSMAC_FW_VERSION)/linux/wl_apsta.o
++PKG_BRCMSMAC_FW_SOURCE:=$(PKG_BRCMSMAC_FW_NAME)-$(PKG_BRCMSMAC_FW_VERSION).tar.bz2
++PKG_BRCMSMAC_FW_SOURCE_URL:=http://www.lwfinger.com/b43-firmware/
++PKG_BRCMSMAC_FW_MD5SUM:=f4e357b09eaf5d8b1f1920cf3493a555
++
++define Download/brcmsmac
++  FILE:=$(PKG_BRCMSMAC_FW_SOURCE)
++  URL:=$(PKG_BRCMSMAC_FW_SOURCE_URL)
++  MD5SUM:=$(PKG_BRCMSMAC_FW_MD5SUM)
+ endef
++$(eval $(call Download,brcmsmac))
+ 
+-define KernelPackage/lib80211
++define KernelPackage/brcmsmac
+   $(call KernelPackage/mac80211/Default)
+-  TITLE:=802.11 Networking stack
+-  DEPENDS:=+kmod-cfg80211
+-  FILES:= \
+-	$(PKG_BUILD_DIR)/net/wireless/lib80211.ko \
+-	$(PKG_BUILD_DIR)/net/wireless/lib80211_crypt_wep.ko \
+-	$(PKG_BUILD_DIR)/net/wireless/lib80211_crypt_ccmp.ko \
+-	$(PKG_BUILD_DIR)/net/wireless/lib80211_crypt_tkip.ko
+-  AUTOLOAD:=$(call AutoProbe, \
+-	lib80211 \
+-	lib80211_crypt_wep \
+-	lib80211_crypt_ccmp \
+-	lib80211_crypt_tkip \
+-  )
++  TITLE:=Broadcom IEEE802.11n PCIe SoftMAC WLAN driver
++  URL:=https://wireless.wiki.kernel.org/en/users/drivers/brcm80211
++  DEPENDS+= +kmod-mac80211 +@DRIVER_11N_SUPPORT +!TARGET_brcm47xx:kmod-bcma +kmod-lib-cordic +kmod-lib-crc8 +kmod-brcmutil
++  FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/brcm80211/brcmsmac/brcmsmac.ko
++  AUTOLOAD:=$(call AutoProbe,brcmsmac)
++  MENU:=1
+ endef
+ 
+-define KernelPackage/lib80211/description
+- Kernel modules for 802.11 Networking stack
+- Includes:
+- - lib80211
+- - lib80211_crypt_wep
+- - lib80211_crypt_tkip
+- - lib80211_crytp_ccmp
++define KernelPackage/brcmsmac/description
++ Kernel module for Broadcom IEEE802.11n PCIe Wireless cards
+ endef
+ 
+-define KernelPackage/libertas-usb
+-  $(call KernelPackage/mac80211/Default)
+-  DEPENDS+= @USB_SUPPORT +kmod-cfg80211 +kmod-usb-core +kmod-lib80211 +@DRIVER_WEXT_SUPPORT
+-  TITLE:=Marvell 88W8015 Wireless Driver
+-  FILES:= \
+-	$(PKG_BUILD_DIR)/drivers/net/wireless/libertas/libertas.ko \
+-	$(PKG_BUILD_DIR)/drivers/net/wireless/libertas/usb8xxx.ko
+-  AUTOLOAD:=$(call AutoProbe,libertas usb8xxx)
+-endef
++define KernelPackage/brcmsmac/config
++  if PACKAGE_kmod-brcmsmac
+ 
+-define KernelPackage/libertas-sdio
+-  $(call KernelPackage/mac80211/Default)
+-  DEPENDS+= +kmod-cfg80211 +kmod-lib80211 +kmod-mmc +@DRIVER_WEXT_SUPPORT @!TARGET_uml
+-  TITLE:=Marvell 88W8686 Wireless Driver
+-  FILES:= \
+-	$(PKG_BUILD_DIR)/drivers/net/wireless/libertas/libertas.ko \
+-	$(PKG_BUILD_DIR)/drivers/net/wireless/libertas/libertas_sdio.ko
+-  AUTOLOAD:=$(call AutoProbe,libertas libertas_sdio)
++	config BRCMSMAC_USE_FW_FROM_WL
++		bool "Use firmware extracted from broadcom proprietary driver"
++		default y
++		help
++		  Instead of using the official brcmsmac firmware a firmware
++		  version 666.2 extracted from the proprietary Broadcom driver
++		  is used. This is needed to get core rev 17 used in bcm4716
++		  to work.
++
++		  If unsure, say Y.
++
++  endif
+ endef
+ 
+-define KernelPackage/mac80211-hwsim
+-  $(call KernelPackage/mac80211/Default)
+-  TITLE:=mac80211 HW simulation device
+-  DEPENDS+= +kmod-mac80211 +@DRIVER_11N_SUPPORT
+-  FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/mac80211_hwsim.ko
+-  AUTOLOAD:=$(call AutoProbe,mac80211_hwsim)
+-endef
+ 
+-define KernelPackage/net-libipw
++define KernelPackage/brcmfmac
+   $(call KernelPackage/mac80211/Default)
+-  TITLE:=libipw for ipw2100 and ipw2200
+-  DEPENDS:=@PCI_SUPPORT +kmod-crypto-core +kmod-crypto-arc4 +kmod-crypto-aes +kmod-crypto-michael-mic +kmod-lib80211 +kmod-cfg80211 +@DRIVER_WEXT_SUPPORT @!BIG_ENDIAN
+-  FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/ipw2x00/libipw.ko
+-  AUTOLOAD:=$(call AutoProbe,libipw)
++  TITLE:=Broadcom IEEE802.11n USB FullMAC WLAN driver
++  URL:=https://wireless.wiki.kernel.org/en/users/drivers/brcm80211
++  DEPENDS+= @USB_SUPPORT +kmod-cfg80211 +@DRIVER_11N_SUPPORT +kmod-brcmutil +BRCMFMAC_SDIO:kmod-mmc +BRCMFMAC_USB:kmod-usb-core
++  FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/brcm80211/brcmfmac/brcmfmac.ko
++  AUTOLOAD:=$(call AutoProbe,brcmfmac)
+ endef
+ 
+-define KernelPackage/net-libipw/description
+- Hardware independent IEEE 802.11 networking stack for ipw2100 and ipw2200.
++define KernelPackage/brcmfmac/description
++ Kernel module for Broadcom IEEE802.11n USB Wireless cards
+ endef
+ 
+-IPW2100_NAME:=ipw2100-fw
+-IPW2100_VERSION:=1.3
+-
+-define Download/net-ipw2100
+-  URL:=http://bughost.org/firmware/
+-  FILE:=$(IPW2100_NAME)-$(IPW2100_VERSION).tgz
+-  MD5SUM=46aa75bcda1a00efa841f9707bbbd113
+-endef
+-$(eval $(call Download,net-ipw2100))
++define KernelPackage/brcmfmac/config
++  if PACKAGE_kmod-brcmfmac
+ 
+-define KernelPackage/net-ipw2100
+-  $(call KernelPackage/mac80211/Default)
+-  TITLE:=Intel IPW2100 driver
+-  DEPENDS:=@PCI_SUPPORT +kmod-net-libipw
+-  FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/ipw2x00/ipw2100.ko
+-  AUTOLOAD:=$(call AutoProbe,ipw2100)
+-endef
++	config BRCMFMAC_SDIO
++		bool "Enable SDIO bus interface support"
++		default n
++		help
++		  Enable support for cards attached to an SDIO bus.
++		  Select this option only if you are sure that your
++		  board has a Broadcom wireless chip atacched to
++		  that bus.
+ 
+-define KernelPackage/net-ipw2100/description
+- Kernel support for Intel IPW2100
+- Includes:
+- - ipw2100
+-endef
++	config BRCMFMAC_USB
++		bool "Enable USB bus interface support"
++		depends on USB_SUPPORT
++		default y
++		help
++		  Supported USB connected chipsets:
++		  BCM43235, BCM43236, BCM43238 (all in revision 3 only)
++		  BCM43143, BCM43242, BCM43566, BCM43569
+ 
+-IPW2200_NAME:=ipw2200-fw
+-IPW2200_VERSION:=3.1
++	config BRCMFMAC_PCIE
++		bool "Enable PCIE bus interface support"
++		depends on PCI_SUPPORT
++		default y
++		help
++		  Supported PCIe connected chipsets:
++		  BCM4354, BCM4356, BCM43567, BCM43570, BCM43602
+ 
+-define Download/net-ipw2200
+-  URL:=http://bughost.org/firmware/
+-  FILE:=$(IPW2200_NAME)-$(IPW2200_VERSION).tgz
+-  MD5SUM=eaba788643c7cc7483dd67ace70f6e99
++  endif
+ endef
+-$(eval $(call Download,net-ipw2200))
+ 
+-define KernelPackage/net-ipw2200
+-  $(call KernelPackage/mac80211/Default)
+-  TITLE:=Intel IPW2200 driver
+-  DEPENDS:=@PCI_SUPPORT +kmod-net-libipw
+-  FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/ipw2x00/ipw2200.ko
+-  AUTOLOAD:=$(call AutoProbe,ipw2200)
+-endef
+ 
+-define KernelPackage/net-ipw2200/description
+- Kernel support for Intel IPW2200
+- Includes:
+- - ipw2200
++define KernelPackage/carl9170
++  $(call KernelPackage/mac80211/Default)
++  TITLE:=Driver for Atheros AR9170 USB sticks
++  DEPENDS:=@USB_SUPPORT +kmod-mac80211 +kmod-ath +kmod-usb-core +kmod-input-core +@DRIVER_11N_SUPPORT
++  FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/ath/carl9170/carl9170.ko
++  AUTOLOAD:=$(call AutoProbe,carl9170)
+ endef
+ 
+ 
+-define KernelPackage/net-hermes
++define KernelPackage/hermes
+   $(call KernelPackage/mac80211/Default)
+   TITLE:=Hermes 802.11b chipset support
+-  DEPENDS:=@PCI_SUPPORT||PCMCIA_SUPPORT +kmod-cfg80211 +@DRIVER_WEXT_SUPPORT
++  DEPENDS:=@PCI_SUPPORT||PCMCIA_SUPPORT +kmod-cfg80211 +@DRIVER_WEXT_SUPPORT +kmod-crypto-michael-mic
+   FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/orinoco/orinoco.ko
+   AUTOLOAD:=$(call AutoProbe,orinoco)
+ endef
+ 
+-define KernelPackage/net-hermes/description
++define KernelPackage/hermes/description
+  Kernel support for Hermes 802.11b chipsets
+ endef
+ 
+-define KernelPackage/net-hermes-pci
++define KernelPackage/hermes-pci
+   $(call KernelPackage/mac80211/Default)
+   TITLE:=Intersil Prism 2.5 PCI support
+-  DEPENDS:=@PCI_SUPPORT +kmod-net-hermes
++  DEPENDS:=@PCI_SUPPORT +kmod-hermes
+   FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/orinoco/orinoco_pci.ko
+   AUTOLOAD:=$(call AutoProbe,orinoco_pci)
+ endef
+ 
+-define KernelPackage/net-hermes-pci/description
++define KernelPackage/hermes-pci/description
+  Kernel modules for Intersil Prism 2.5 PCI support
+ endef
+ 
+-define KernelPackage/net-hermes-plx
++define KernelPackage/hermes-plx
+   $(call KernelPackage/mac80211/Default)
+   TITLE:=PLX9052 based PCI adaptor
+-  DEPENDS:=@PCI_SUPPORT +kmod-net-hermes
++  DEPENDS:=@PCI_SUPPORT +kmod-hermes
+   FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/orinoco/orinoco_plx.ko
+   AUTOLOAD:=$(call AutoProbe,orinoco_plx)
+ endef
+ 
+-define KernelPackage/net-hermes-plx/description
++define KernelPackage/hermes-plx/description
+  Kernel modules for Hermes in PLX9052 based PCI adaptors
+ endef
+ 
+-define KernelPackage/net-hermes-pcmcia
++define KernelPackage/hermes-pcmcia
+   $(call KernelPackage/mac80211/Default)
+   TITLE:=Hermes based PCMCIA adaptors
+-  DEPENDS:=@PCMCIA_SUPPORT +kmod-net-hermes @BROKEN
++  DEPENDS:=@PCMCIA_SUPPORT +kmod-hermes @BROKEN
+   FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/orinoco/orinoco_cs.ko
+   AUTOLOAD:=$(call AutoProbe,orinoco_cs)
+ endef
+ 
+-define KernelPackage/net-hermes-pcmcia/description
++define KernelPackage/hermes-pcmcia/description
+  Kernel modules for Hermes based PCMCIA adaptors
+ endef
+ 
+-define KernelPackage/iwlagn
++
++define KernelPackage/iwlwifi
+   $(call KernelPackage/mac80211/Default)
+   DEPENDS:= +kmod-mac80211 @PCI_SUPPORT +@DRIVER_11N_SUPPORT
+   TITLE:=Intel AGN Wireless support
+   FILES:= \
+ 	$(PKG_BUILD_DIR)/drivers/net/wireless/iwlwifi/iwlwifi.ko \
+-	$(PKG_BUILD_DIR)/drivers/net/wireless/iwlwifi/dvm/iwldvm.ko
+-  AUTOLOAD:=$(call AutoProbe,iwlwifi iwldvm)
++	$(PKG_BUILD_DIR)/drivers/net/wireless/iwlwifi/dvm/iwldvm.ko \
++	$(PKG_BUILD_DIR)/drivers/net/wireless/iwlwifi/mvm/iwlmvm.ko
++  AUTOLOAD:=$(call AutoProbe,iwlwifi iwldvm iwlmvm)
+   MENU:=1
+ endef
+ 
+-define KernelPackage/iwlagn/description
+- iwlagn kernel module for Intel 5000/5150/1000/6000/6050/6005/6030/100 support
+-endef
++define KernelPackage/iwlwifi/description
++ iwlwifi kernel module for
++ Intel Wireless WiFi Link 6250AGN Adapter
++ Intel 6000 Series Wi-Fi Adapters (6200AGN and 6300AGN)
++ Intel WiFi Link 1000BGN
++ Intel Wireless WiFi 5150AGN
++ Intel Wireless WiFi 5100AGN, 5300AGN, and 5350AGN
++ Intel 6005 Series Wi-Fi Adapters
++ Intel 6030 Series Wi-Fi Adapters
++ Intel Wireless WiFi Link 6150BGN 2 Adapter
++ Intel 100 Series Wi-Fi Adapters (100BGN and 130BGN)
++ Intel 2000 Series Wi-Fi Adapters
++ Intel 7260 Wi-Fi Adapter
++ Intel 3160 Wi-Fi Adapter
++ Intel 7265 Wi-Fi Adapter
++ Intel 8260 Wi-Fi Adapter
++ Intel 3165 Wi-Fi Adapter
++endef
++
++define KernelPackage/iwlwifi/config
++  if PACKAGE_kmod-iwlwifi
++
++	config PACKAGE_IWLWIFI_DEBUG
++		bool "Enable full debugging output in the iwlwifi driver"
++		default n
++		help
++		  This option will enable debug tracing output for the iwlwifi drivers
+ 
+-define KernelPackage/iwlagn/config
+-  if PACKAGE_kmod-iwlagn
++		  This will result in the kernel module being ~100k larger.  You can
++		  control which debug output is sent to the kernel log by setting the
++		  value in
+ 
+-	config IWL5000_FW
+-		bool "Intel 5000 Firmware"
+-		default y
++			/sys/module/iwlwifi/parameters/debug
++
++		  This entry will only exist if this option is enabled.
++
++		  To set a value, simply echo an 8-byte hex value to the same file:
++
++			  % echo 0x43fff > /sys/module/iwlwifi/parameters/debug
++
++		  You can find the list of debug mask values in:
++			  drivers/net/wireless/iwlwifi/iwl-debug.h
++
++		  If this is your first time using this driver, you should say Y here
++		  as the debug information can assist others in helping you resolve
++		  any problems you may encounter.
++
++	config PACKAGE_IWLWIFI_DEBUGFS
++	        bool "iwlwifi debugfs support"
++		depends on PACKAGE_MAC80211_DEBUGFS
++		default n
+ 		help
+-		  Download and install firmware for:
+-		    Intel Wireless WiFi 5100AGN, 5300AGN, and 5350AGN
++		  Enable creation of debugfs files for the iwlwifi drivers. This
++		  is a low-impact option that allows getting insight into the
++		  driver's state at runtime.
+ 
+-	config IWL5150_FW
+-		bool "Intel 5150 Firmware"
++	config IWL100_FW
++		bool "Intel 100 Firmware"
+ 		default y
+ 		help
+ 		  Download and install firmware for:
+-		    Intel Wireless WiFi 5150AGN
++		    Intel Centrino Wireless-N 100
+ 
+ 	config IWL1000_FW
+ 		bool "Intel 1000 Firmware"
+@@ -852,89 +910,104 @@ define KernelPackage/iwlagn/config
+ 		  Download and install firmware for:
+ 		    Intel Centrino Wireless-N 1000
+ 
+-	config IWL6000_FW
+-		bool "Intel 6000 Firmware"
++	config IWL105_FW
++		bool "Intel 105 Firmware"
+ 		default y
+ 		help
+ 		  Download and install firmware for:
+-		    Intel Centrino Ultimate-N 6300 and Advanced-N 6200
++		    Intel Centrino Wireless-N 105
+ 
+-	config IWL6050_FW
+-		bool "Intel 6050 Firmware"
++	config IWL135_FW
++		bool "Intel 135 Firmware"
+ 		default y
+ 		help
+ 		  Download and install firmware for:
+-		    Intel Centrino Advanced-N + WiMAX 6250 and Wireless-N + WiMAX 6150
++		    Intel Centrino Wireless-N 135
+ 
+-	config IWL6005_FW
+-		bool "Intel 6005 Firmware"
++	config IWL2000_FW
++		bool "Intel 2000 Firmware"
+ 		default y
+ 		help
+ 		  Download and install firmware for:
+-		    Intel Centrino Advanced-N 6205
++		    Intel Centrino Wireless-N 2200
+ 
+-	config IWL6030_FW
+-		bool "Intel 6030 Firmware"
++	config IWL2030_FW
++		bool "Intel 2030 Firmware"
+ 		default y
+ 		help
+ 		  Download and install firmware for:
+-		    Intel Centrino Advanced-N 6230, Wireless-N 1030, Wireless-N 130 and Advanced-N 6235
++		    Intel Centrino Wireless-N 2230
+ 
+-	config IWL7260_FW
+-		bool "Intel 7260 Firmware"
++	config IWL3160_FW
++		bool "Intel 3160 Firmware"
+ 		default y
+ 		help
+ 		  Download and install firmware for:
+-		    Intel Dual Band Wireless-N 7260 and Intel Dual Band Wireless-AC 7260
++		    Intel Wireless WiFi 3160
+ 
+-	config IWL7265_FW
+-		bool "Intel 7265 Firmware"
++	config IWL5000_FW
++		bool "Intel 5000 Firmware"
+ 		default y
+ 		help
+ 		  Download and install firmware for:
+-		    Intel Wireless 7265
++		    Intel Wireless WiFi 5100AGN, 5300AGN, and 5350AGN
+ 
+-	config IWL100_FW
+-		bool "Intel 100 Firmware"
++	config IWL5150_FW
++		bool "Intel 5150 Firmware"
+ 		default y
+ 		help
+ 		  Download and install firmware for:
+-		    Intel Centrino Wireless-N 100
++		    Intel Wireless WiFi 5150AGN
+ 
+-	config IWL2000_FW
+-		bool "Intel 2000 Firmware"
++	config IWL6000_FW
++		bool "Intel 6000 Firmware"
+ 		default y
+ 		help
+ 		  Download and install firmware for:
+-		    Intel Centrino Wireless-N 2200
++		    Intel Centrino Ultimate-N 6300 and Advanced-N 6200
+ 
+-	config IWL2030_FW
+-		bool "Intel 2030 Firmware"
++	config IWL6005_FW
++		bool "Intel 6005 Firmware"
+ 		default y
+ 		help
+ 		  Download and install firmware for:
+-		    Intel Centrino Wireless-N 2230
++		    Intel Centrino Advanced-N 6205
+ 
+-	config IWL105_FW
+-		bool "Intel 105 Firmware"
++	config IWL6030_FW
++		bool "Intel 6030 Firmware"
+ 		default y
+ 		help
+ 		  Download and install firmware for:
+-		    Intel Centrino Wireless-N 105
++		    Intel Centrino Advanced-N 6230, Wireless-N 1030, Wireless-N 130 and Advanced-N 6235
+ 
+-	config IWL135_FW
+-		bool "Intel 135 Firmware"
++	config IWL6050_FW
++		bool "Intel 6050 Firmware"
+ 		default y
+ 		help
+ 		  Download and install firmware for:
+-		    Intel Centrino Wireless-N 135
++		    Intel Centrino Advanced-N + WiMAX 6250 and Wireless-N + WiMAX 6150
+ 
+-	config IWL3160_FW
+-		bool "Intel 3160 Firmware"
++	config IWL7260_FW
++		bool "Intel 7260 Firmware"
++		default y
++		help
++		  Download and install firmware for:
++		    Intel Dual Band Wireless-N 7260 and Intel Dual Band Wireless-AC 7260
++
++	config IWL7265_FW
++		bool "Intel 7265 Firmware"
++		default y
++		help
++		  Download and install firmware for:
++		    Intel Wireless 7265, 7265D, 3165
++
++	config IWL8000_FW
++		bool "Intel 8000 Series Firmware"
+ 		default y
+ 		help
+ 		  Download and install firmware for:
+-		    Intel Wireless 3160
++		    Intel Wireless Series 8260, 4165
++
+   endif
+ endef
+ 
+@@ -953,578 +1026,587 @@ endef
+ define KernelPackage/iwl3945
+   $(call KernelPackage/mac80211/Default)
+   DEPENDS:= +kmod-mac80211 +kmod-iwl-legacy
+-  TITLE:=Intel iwl3945 Wireless support
+-  FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/iwlegacy/iwl3945.ko
+-  AUTOLOAD:=$(call AutoProbe,iwl3945)
+-endef
+-
+-define KernelPackage/iwl3945/description
+- iwl3945 kernel module for Intel 3945 support
+-endef
+-
+-define KernelPackage/iwl4965
+-  $(call KernelPackage/mac80211/Default)
+-  DEPENDS:= +kmod-mac80211 +kmod-iwl-legacy +@DRIVER_11N_SUPPORT
+-  TITLE:=Intel iwl4965 Wireless support
+-  FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/iwlegacy/iwl4965.ko
+-  AUTOLOAD:=$(call AutoProbe,iwl4965)
+-endef
+-
+-define KernelPackage/iwl4965/description
+- iwl4965 kernel module for Intel 4965 support
+-endef
+-
+-
+-define KernelPackage/mwl8k
+-  $(call KernelPackage/mac80211/Default)
+-  TITLE:=Driver for Marvell TOPDOG 802.11 Wireless cards
+-  URL:=http://wireless.kernel.org/en/users/Drivers/mwl8k
+-  DEPENDS+= @PCI_SUPPORT +kmod-mac80211 +@DRIVER_11N_SUPPORT
+-  FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/mwl8k.ko
+-  AUTOLOAD:=$(call AutoProbe,mwl8k)
+-endef
+-
+-define KernelPackage/mwl8k/description
+- Kernel modules for Marvell TOPDOG 802.11 Wireless cards
+-endef
+-
+-
+-define KernelPackage/mwifiex-pcie
+-  $(call KernelPackage/mac80211/Default)
+-  TITLE:=Driver for Marvell 802.11n/802.11ac PCIe Wireless cards
+-  URL:=http://wireless.kernel.org/en/users/Drivers/mwifiex
+-  DEPENDS+= @PCI_SUPPORT +kmod-mac80211 +@DRIVER_11N_SUPPORT
+-  FILES:= \
+-	$(PKG_BUILD_DIR)/drivers/net/wireless/mwifiex/mwifiex.ko \
+-	$(PKG_BUILD_DIR)/drivers/net/wireless/mwifiex/mwifiex_pcie.ko
+-  AUTOLOAD:=$(call AutoProbe,mwifiex_pcie)
+-endef
+-
+-define KernelPackage/mwifiex-pcie/description
+- Kernel modules for Marvell 802.11n/802.11ac PCIe Wireless cards
+-endef
+-
+-
+-define KernelPackage/wlcore
+-  $(call KernelPackage/mac80211/Default)
+-  TITLE:=TI common driver part
+-  DEPENDS+= @TARGET_omap +kmod-mac80211 +@DRIVER_11N_SUPPORT
+-  FILES:= \
+-	$(PKG_BUILD_DIR)/drivers/net/wireless/ti/wlcore/wlcore.ko \
+-	$(PKG_BUILD_DIR)/drivers/net/wireless/ti/wlcore/wlcore_sdio.ko
+-  AUTOLOAD:=$(call AutoProbe,wlcore wlcore_sdio)
+-endef
+-
+-define KernelPackage/wlcore/description
+- This module contains some common parts needed by TI Wireless drivers.
+-endef
+-
+-define KernelPackage/wl12xx
+-  $(call KernelPackage/mac80211/Default)
+-  TITLE:=Driver for TI WL12xx
+-  URL:=http://wireless.kernel.org/en/users/Drivers/wl12xx
+-  DEPENDS+= +kmod-wlcore
+-  FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/ti/wl12xx/wl12xx.ko
+-  AUTOLOAD:=$(call AutoProbe,wl12xx)
++  TITLE:=Intel iwl3945 Wireless support
++  FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/iwlegacy/iwl3945.ko
++  AUTOLOAD:=$(call AutoProbe,iwl3945)
+ endef
+ 
+-define KernelPackage/wl12xx/description
+- Kernel modules for TI WL12xx
++define KernelPackage/iwl3945/description
++ iwl3945 kernel module for Intel 3945 support
+ endef
+ 
+-define KernelPackage/wl18xx
++define KernelPackage/iwl4965
+   $(call KernelPackage/mac80211/Default)
+-  TITLE:=Driver for TI WL18xx
+-  URL:=http://wireless.kernel.org/en/users/Drivers/wl18xx
+-  DEPENDS+= +kmod-wlcore
+-  FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/ti/wl18xx/wl18xx.ko
+-  AUTOLOAD:=$(call AutoProbe,wl18xx)
++  DEPENDS:= +kmod-mac80211 +kmod-iwl-legacy +@DRIVER_11N_SUPPORT
++  TITLE:=Intel iwl4965 Wireless support
++  FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/iwlegacy/iwl4965.ko
++  AUTOLOAD:=$(call AutoProbe,iwl4965)
+ endef
+ 
+-define KernelPackage/wl18xx/description
+- Kernel modules for TI WL18xx
++define KernelPackage/iwl4965/description
++ iwl4965 kernel module for Intel 4965 support
+ endef
+ 
+ 
+-#Broadcom firmware
+-ifneq ($(CONFIG_B43_FW_6_30),)
+-  PKG_B43_FWV4_NAME:=broadcom-wl
+-  PKG_B43_FWV4_VERSION:=6.30.163.46
+-  PKG_B43_FWV4_OBJECT:=$(PKG_B43_FWV4_NAME)-$(PKG_B43_FWV4_VERSION).wl_apsta.o
+-  PKG_B43_FWV4_SOURCE:=$(PKG_B43_FWV4_NAME)-$(PKG_B43_FWV4_VERSION).tar.bz2
+-  PKG_B43_FWV4_SOURCE_URL:=http://www.lwfinger.com/b43-firmware/
+-  PKG_B43_FWV4_MD5SUM:=6fe97e9368d25342a1ab943d3cf3496d
+-else
+-ifneq ($(CONFIG_B43_FW_5_10),)
+-  PKG_B43_FWV4_NAME:=broadcom-wl
+-  PKG_B43_FWV4_VERSION:=5.10.56.27.3
+-  PKG_B43_FWV4_OBJECT:=$(PKG_B43_FWV4_NAME)-$(PKG_B43_FWV4_VERSION)/driver/wl_apsta/wl_prebuilt.o
+-  PKG_B43_FWV4_SOURCE:=$(PKG_B43_FWV4_NAME)-$(PKG_B43_FWV4_VERSION)_mipsel.tar.bz2
+-  PKG_B43_FWV4_SOURCE_URL:=http://mirror2.openwrt.org/sources/
+-  PKG_B43_FWV4_MD5SUM:=3363e3a6b3d9d73c49dea870c7834eac
+-else
+-ifneq ($(CONFIG_B43_FW_4_178),)
+-  PKG_B43_FWV4_NAME:=broadcom-wl
+-  PKG_B43_FWV4_VERSION:=4.178.10.4
+-  PKG_B43_FWV4_OBJECT:=$(PKG_B43_FWV4_NAME)-$(PKG_B43_FWV4_VERSION)/linux/wl_apsta.o
+-  PKG_B43_FWV4_SOURCE:=$(PKG_B43_FWV4_NAME)-$(PKG_B43_FWV4_VERSION).tar.bz2
+-  PKG_B43_FWV4_SOURCE_URL:=http://mirror2.openwrt.org/sources/
+-  PKG_B43_FWV4_MD5SUM:=14477e8cbbb91b11896affac9b219fdb
+-else
+-ifneq ($(CONFIG_B43_FW_5_100_138),)
+-  PKG_B43_FWV4_NAME:=broadcom-wl
+-  PKG_B43_FWV4_VERSION:=5.100.138
+-  PKG_B43_FWV4_OBJECT:=$(PKG_B43_FWV4_NAME)-$(PKG_B43_FWV4_VERSION)/linux/wl_apsta.o
+-  PKG_B43_FWV4_SOURCE:=$(PKG_B43_FWV4_NAME)-$(PKG_B43_FWV4_VERSION).tar.bz2
+-  PKG_B43_FWV4_SOURCE_URL:=http://www.lwfinger.com/b43-firmware/
+-  PKG_B43_FWV4_MD5SUM:=f4e357b09eaf5d8b1f1920cf3493a555
+-else
+-  PKG_B43_FWV4_NAME:=broadcom-wl
+-  PKG_B43_FWV4_VERSION:=4.150.10.5
+-  PKG_B43_FWV4_OBJECT:=$(PKG_B43_FWV4_NAME)-$(PKG_B43_FWV4_VERSION)/driver/wl_apsta_mimo.o
+-  PKG_B43_FWV4_SOURCE:=$(PKG_B43_FWV4_NAME)-$(PKG_B43_FWV4_VERSION).tar.bz2
+-  PKG_B43_FWV4_SOURCE_URL:=http://mirror2.openwrt.org/sources/
+-  PKG_B43_FWV4_MD5SUM:=0c6ba9687114c6b598e8019e262d9a60
+-endif
+-endif
+-endif
+-endif
+-ifneq ($(CONFIG_B43_OPENFIRMWARE),)
+-  PKG_B43_FWV4_NAME:=broadcom-wl
+-  PKG_B43_FWV4_VERSION:=5.2
+-  PKG_B43_FWV4_OBJECT:=openfwwf-$(PKG_B43_FWV4_VERSION)
+-  PKG_B43_FWV4_SOURCE:=openfwwf-$(PKG_B43_FWV4_VERSION).tar.gz
+-  PKG_B43_FWV4_SOURCE_URL:=http://www.ing.unibs.it/openfwwf/firmware/
+-  PKG_B43_FWV4_MD5SUM:=e045a135453274e439ae183f8498b0fa
+-endif
+-
+-
+-PKG_B43_FWV3_NAME:=wl_apsta
+-PKG_B43_FWV3_VERSION:=3.130.20.0
+-PKG_B43_FWV3_SOURCE:=$(PKG_B43_FWV3_NAME)-$(PKG_B43_FWV3_VERSION).o
+-PKG_B43_FWV3_SOURCE_URL:=http://downloads.openwrt.org/sources/
+-PKG_B43_FWV3_MD5SUM:=e08665c5c5b66beb9c3b2dd54aa80cb3
+-
+-define Download/b43
+-  FILE:=$(PKG_B43_FWV4_SOURCE)
+-  URL:=$(PKG_B43_FWV4_SOURCE_URL)
+-  MD5SUM:=$(PKG_B43_FWV4_MD5SUM)
++define KernelPackage/lib80211
++  $(call KernelPackage/mac80211/Default)
++  TITLE:=802.11 Networking stack
++  DEPENDS:=+kmod-cfg80211
++  FILES:= \
++	$(PKG_BUILD_DIR)/net/wireless/lib80211.ko \
++	$(PKG_BUILD_DIR)/net/wireless/lib80211_crypt_wep.ko \
++	$(PKG_BUILD_DIR)/net/wireless/lib80211_crypt_ccmp.ko \
++	$(PKG_BUILD_DIR)/net/wireless/lib80211_crypt_tkip.ko
++  AUTOLOAD:=$(call AutoProbe, \
++	lib80211 \
++	lib80211_crypt_wep \
++	lib80211_crypt_ccmp \
++	lib80211_crypt_tkip \
++  )
+ endef
+-$(eval $(call Download,b43))
+ 
+-define Download/b43legacy
+-  FILE:=$(PKG_B43_FWV3_SOURCE)
+-  URL:=$(PKG_B43_FWV3_SOURCE_URL)
+-  MD5SUM:=$(PKG_B43_FWV3_MD5SUM)
++define KernelPackage/lib80211/description
++ Kernel modules for 802.11 Networking stack
++ Includes:
++ - lib80211
++ - lib80211_crypt_wep
++ - lib80211_crypt_tkip
++ - lib80211_crytp_ccmp
+ endef
+-$(eval $(call Download,b43legacy))
+ 
+ 
+-define KernelPackage/b43
++define KernelPackage/libipw
+   $(call KernelPackage/mac80211/Default)
+-  TITLE:=Broadcom 43xx wireless support
+-  URL:=https://wireless.wiki.kernel.org/en/users/drivers/b43
+-  KCONFIG:= \
+-  	CONFIG_HW_RANDOM=y
+-  # Depend on PCI_SUPPORT to make sure we can select kmod-bcma or kmod-ssb
+-  DEPENDS += \
+-	@PCI_SUPPORT +kmod-mac80211 \
+-	$(if $(CONFIG_PACKAGE_B43_USE_SSB),+kmod-ssb) \
+-	$(if $(CONFIG_PACKAGE_B43_USE_BCMA),+kmod-bcma)
+-  FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/b43/b43.ko
+-  AUTOLOAD:=$(call AutoProbe,b43)
+-  MENU:=1
++  TITLE:=libipw for ipw2100 and ipw2200
++  DEPENDS:=@PCI_SUPPORT +kmod-crypto-michael-mic +kmod-lib80211 +kmod-cfg80211 +@DRIVER_WEXT_SUPPORT @!BIG_ENDIAN
++  FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/ipw2x00/libipw.ko
++  AUTOLOAD:=$(call AutoProbe,libipw)
+ endef
+ 
+-define KernelPackage/b43/config
+-
+-config PACKAGE_B43_USE_SSB
+-	select PACKAGE_kmod-ssb
+-	tristate
+-	depends on !TARGET_brcm47xx && !TARGET_brcm63xx
+-	default PACKAGE_kmod-b43 if PACKAGE_B43_BUSES_BCMA_AND_SSB
+-	default PACKAGE_kmod-b43 if PACKAGE_B43_BUSES_SSB
++define KernelPackage/libipw/description
++ Hardware independent IEEE 802.11 networking stack for ipw2100 and ipw2200.
++endef
+ 
+-config PACKAGE_B43_USE_BCMA
+-	select PACKAGE_kmod-bcma
+-	tristate
+-	depends on !TARGET_brcm47xx && !TARGET_bcm53xx
+-	default PACKAGE_kmod-b43 if PACKAGE_B43_BUSES_BCMA_AND_SSB
+-	default PACKAGE_kmod-b43 if PACKAGE_B43_BUSES_BCMA
++IPW2100_NAME:=ipw2100-fw
++IPW2100_VERSION:=1.3
+ 
+-  if PACKAGE_kmod-b43
++define Download/ipw2100
++  URL:=http://bughost.org/firmware/
++  FILE:=$(IPW2100_NAME)-$(IPW2100_VERSION).tgz
++  MD5SUM=46aa75bcda1a00efa841f9707bbbd113
++endef
++$(eval $(call Download,ipw2100))
+ 
+-	choice
+-		prompt "b43 firmware version"
+-		default B43_FW_5_100_138
+-		help
+-		  This option allows you to select the version of the b43 firmware.
++define KernelPackage/ipw2100
++  $(call KernelPackage/mac80211/Default)
++  TITLE:=Intel IPW2100 driver
++  DEPENDS:=@PCI_SUPPORT +kmod-libipw
++  FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/ipw2x00/ipw2100.ko
++  AUTOLOAD:=$(call AutoProbe,ipw2100)
++endef
+ 
+-	config B43_FW_4_150
+-		bool "Firmware 410.2160 from driver 4.150.10.5 (old stable)"
+-		help
+-		  Old stable firmware for BCM43xx devices.
++define KernelPackage/ipw2100/description
++ Kernel support for Intel IPW2100
++ Includes:
++ - ipw2100
++endef
+ 
+-		  If unsure, select this.
++IPW2200_NAME:=ipw2200-fw
++IPW2200_VERSION:=3.1
+ 
+-	config B43_FW_4_178
+-		bool "Firmware 478.104 from driver 4.178.10.4"
+-		help
+-		  Older firmware for BCM43xx devices.
++define Download/ipw2200
++  URL:=http://bughost.org/firmware/
++  FILE:=$(IPW2200_NAME)-$(IPW2200_VERSION).tgz
++  MD5SUM=eaba788643c7cc7483dd67ace70f6e99
++endef
++$(eval $(call Download,ipw2200))
+ 
+-		  If unsure, select the "stable" firmware.
++define KernelPackage/ipw2200
++  $(call KernelPackage/mac80211/Default)
++  TITLE:=Intel IPW2200 driver
++  DEPENDS:=@PCI_SUPPORT +kmod-libipw
++  FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/ipw2x00/ipw2200.ko
++  AUTOLOAD:=$(call AutoProbe,ipw2200)
++endef
+ 
+-	config B43_FW_5_10
+-		bool "Firmware 508.1084 from driver 5.10.56.27"
+-		help
+-		  Older firmware for BCM43xx devices.
++define KernelPackage/ipw2200/description
++ Kernel support for Intel IPW2200
++ Includes:
++ - ipw2200
++endef
+ 
+-		  If unsure, select the "stable" firmware.
+ 
+-	config B43_FW_5_100_138
+-		bool "Firmware 666.2 from driver 5.100.138 (stable)"
+-		help
+-		  The currently default firmware for BCM43xx devices.
++define KernelPackage/libertas-usb
++  $(call KernelPackage/mac80211/Default)
++  DEPENDS+= @USB_SUPPORT +kmod-cfg80211 +kmod-usb-core +kmod-lib80211 +@DRIVER_WEXT_SUPPORT
++  TITLE:=Marvell 88W8015 Wireless Driver
++  FILES:= \
++	$(PKG_BUILD_DIR)/drivers/net/wireless/libertas/libertas.ko \
++	$(PKG_BUILD_DIR)/drivers/net/wireless/libertas/usb8xxx.ko
++  AUTOLOAD:=$(call AutoProbe,libertas usb8xxx)
++endef
+ 
+-		  This firmware currently gets most of the testing and is needed for some N-PHY devices.
++define KernelPackage/libertas-sdio
++  $(call KernelPackage/mac80211/Default)
++  DEPENDS+= +kmod-cfg80211 +kmod-lib80211 +kmod-mmc +@DRIVER_WEXT_SUPPORT @!TARGET_uml
++  TITLE:=Marvell 88W8686 Wireless Driver
++  FILES:= \
++	$(PKG_BUILD_DIR)/drivers/net/wireless/libertas/libertas.ko \
++	$(PKG_BUILD_DIR)/drivers/net/wireless/libertas/libertas_sdio.ko
++  AUTOLOAD:=$(call AutoProbe,libertas libertas_sdio)
++endef
+ 
+-		  If unsure, select the this firmware.
++define KernelPackage/mac80211-hwsim
++  $(call KernelPackage/mac80211/Default)
++  TITLE:=mac80211 HW simulation device
++  DEPENDS+= +kmod-mac80211 +@DRIVER_11N_SUPPORT
++  FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/mac80211_hwsim.ko
++  AUTOLOAD:=$(call AutoProbe,mac80211_hwsim)
++endef
+ 
+-	config B43_FW_6_30
+-		bool "Firmware 784.2 from driver 6.30.163.46 (experimental)"
+-		help
+-		  Newer experimental firmware for BCM43xx devices.
++PKG_MT7601U_FW_NAME:=DPO_MT7601U_LinuxSTA
++PKG_MT7601U_FW_VERSION:=3.0.0.4_20130913
++PKG_MT7601U_FW_MD5SUM:=5f440dccc8bc952745a191994fc34699
++PKG_MT7601U_FW_SOURCE:=$(PKG_MT7601U_FW_NAME)_$(PKG_MT7601U_FW_VERSION).tar.bz2
++PKG_MT7601U_FW_SOURCE_URL:=http://www.mediatek.com/AmazonS3/Downloads/linux/
++define Download/mt7601u-firmware
++  FILE:=$(PKG_MT7601U_FW_SOURCE)
++  URL:=$(PKG_MT7601U_FW_SOURCE_URL)
++  MD5SUM:=$(PKG_MT7601U_FW_MD5SUM)
++  SUBDIR:=$(PKG_MT7601U_FW_NAME)_$(PKG_MT7601U_FW_VERSION)
++endef
++$(eval $(call Download,mt7601u-firmware))
+ 
+-		  This firmware is mostly untested.
++define KernelPackage/mt7601u
++  $(call KernelPackage/mac80211/Default)
++  TITLE:=MT7601U-based USB dongles Wireless Driver
++  DEPENDS+= +kmod-mac80211 +@DRIVER_11N_SUPPORT @USB_SUPPORT +kmod-usb-core
++  FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/mediatek/mt7601u/mt7601u.ko
++  AUTOLOAD:=$(call AutoProbe,mt7601)
++endef
+ 
+-		  If unsure, select the "stable" firmware.
+ 
+-	config B43_OPENFIRMWARE
+-		bool "Open FirmWare for WiFi networks"
+-		help
+-		  Opensource firmware for BCM43xx devices.
++define KernelPackage/mwl8k
++  $(call KernelPackage/mac80211/Default)
++  TITLE:=Driver for Marvell TOPDOG 802.11 Wireless cards
++  URL:=http://wireless.kernel.org/en/users/Drivers/mwl8k
++  DEPENDS+= @PCI_SUPPORT +kmod-mac80211 +@DRIVER_11N_SUPPORT
++  FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/mwl8k.ko
++  AUTOLOAD:=$(call AutoProbe,mwl8k)
++endef
+ 
+-		  Do _not_ select this, unless you know what you are doing.
+-		  The Opensource firmware is not suitable for embedded devices, yet.
+-		  It does not support QoS, which is bad for AccessPoints.
+-		  It does not support hardware crypto acceleration, which is a showstopper
+-		  for embedded devices with low CPU resources.
++define KernelPackage/mwl8k/description
++ Kernel modules for Marvell TOPDOG 802.11 Wireless cards
++endef
+ 
+-		  If unsure, select the "stable" firmware.
+ 
+-	endchoice
++define KernelPackage/mwifiex-pcie
++  $(call KernelPackage/mac80211/Default)
++  TITLE:=Driver for Marvell 802.11n/802.11ac PCIe Wireless cards
++  URL:=http://wireless.kernel.org/en/users/Drivers/mwifiex
++  DEPENDS+= @PCI_SUPPORT +kmod-mac80211 +@DRIVER_11N_SUPPORT
++  FILES:= \
++	$(PKG_BUILD_DIR)/drivers/net/wireless/mwifiex/mwifiex.ko \
++	$(PKG_BUILD_DIR)/drivers/net/wireless/mwifiex/mwifiex_pcie.ko
++  AUTOLOAD:=$(call AutoProbe,mwifiex_pcie)
++endef
+ 
+-	config B43_FW_SQUASH
+-		bool "Remove unnecessary firmware files"
+-		depends on !B43_OPENFIRMWARE
+-		default y
+-		help
+-		  This options allows you to remove unnecessary b43 firmware files
+-		  from the final rootfs image. This can reduce the rootfs size by
+-		  up to 200k.
++define KernelPackage/mwifiex-pcie/description
++ Kernel modules for Marvell 802.11n/802.11ac PCIe Wireless cards
++endef
+ 
+-		  If unsure, say Y.
+ 
+-	config B43_FW_SQUASH_COREREVS
+-		string "Core revisions to include"
+-		depends on B43_FW_SQUASH
+-		default "5,6,7,8,9,10,11,13,15" if TARGET_brcm47xx_legacy
+-		default "16,28,29,30" if TARGET_brcm47xx_mips74k
+-		default "5,6,7,8,9,10,11,13,15,16,28,29,30"
+-		help
+-		  This is a comma seperated list of core revision numbers.
++# Prism54 drivers
++P54PCIFW:=2.13.12.0.arm
++P54USBFW:=2.13.24.0.lm87.arm
++P54SPIFW:=2.13.0.0.a.13.14.arm
+ 
+-		  Example (keep files for rev5 only):
+-		    5
++define Download/p54usb
++  FILE:=$(P54USBFW)
++  URL:=http://daemonizer.de/prism54/prism54-fw/fw-usb
++  MD5SUM:=8e8ab005a4f8f0123bcdc51bc25b47f6
++endef
++$(eval $(call Download,p54usb))
+ 
+-		  Example (keep files for rev5 and rev11):
+-		    5,11
++define Download/p54pci
++  FILE:=$(P54PCIFW)
++  URL:=http://daemonizer.de/prism54/prism54-fw/fw-softmac
++  MD5SUM:=ff7536af2092b1c4b21315bd103ef4c4
++endef
++$(eval $(call Download,p54pci))
+ 
+-	config B43_FW_SQUASH_PHYTYPES
+-		string "PHY types to include"
+-		depends on B43_FW_SQUASH
+-		default "G,N,LP" if TARGET_brcm47xx_legacy
+-		default "N,HT" if TARGET_brcm47xx_mips74k
+-		default "G,N,LP,HT"
+-		help
+-		  This is a comma seperated list of PHY types:
+-		    A  => A-PHY
+-		    AG => Dual A-PHY G-PHY
+-		    G  => G-PHY
+-		    LP => LP-PHY
+-		    N  => N-PHY
+-		    HT  => HT-PHY
+-		    LCN  => LCN-PHY
+-		    LCN40  => LCN40-PHY
+-		    AC  => AC-PHY
++define Download/p54spi
++  FILE:=$(P54SPIFW)
++  URL:=http://daemonizer.de/prism54/prism54-fw/stlc4560
++  MD5SUM:=42661f8ecbadd88012807493f596081d
++endef
++$(eval $(call Download,p54spi))
+ 
+-		  Example (keep files for G-PHY only):
+-		    G
++define KernelPackage/p54/Default
++  $(call KernelPackage/mac80211/Default)
++  TITLE:=Prism54 Drivers
++endef
+ 
+-		  Example (keep files for G-PHY and N-PHY):
+-		    G,N
++define KernelPackage/p54/description
++  Kernel module for Prism54 chipsets (mac80211)
++endef
+ 
+-	choice
+-		prompt "Supported buses"
+-		default PACKAGE_B43_BUSES_BCMA_AND_SSB
+-		help
+-		  This allows choosing buses that b43 should support.
++define KernelPackage/p54-common
++  $(call KernelPackage/p54/Default)
++  DEPENDS+= @PCI_SUPPORT||@USB_SUPPORT||@TARGET_omap24xx +kmod-mac80211 +kmod-lib-crc-ccitt
++  TITLE+= (COMMON)
++  FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/p54/p54common.ko
++endef
+ 
+-	config PACKAGE_B43_BUSES_BCMA_AND_SSB
+-		depends on !TARGET_brcm47xx_legacy && !TARGET_brcm47xx_mips74k && !TARGET_bcm53xx
+-		bool "BCMA and SSB"
++define KernelPackage/p54-pci
++  $(call KernelPackage/p54/Default)
++  TITLE+= (PCI)
++  DEPENDS+= @PCI_SUPPORT +kmod-p54-common
++  FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/p54/p54pci.ko
++  AUTOLOAD:=$(call AutoProbe,p54pci)
++endef
+ 
+-	config PACKAGE_B43_BUSES_BCMA
+-		depends on !TARGET_brcm47xx_legacy
+-		bool "BCMA only"
++define KernelPackage/p54-usb
++  $(call KernelPackage/p54/Default)
++  TITLE+= (USB)
++  DEPENDS+= @USB_SUPPORT +kmod-usb-core +kmod-p54-common
++  FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/p54/p54usb.ko
++  AUTOLOAD:=$(call AutoProbe,p54usb)
++endef
+ 
+-	config PACKAGE_B43_BUSES_SSB
+-		depends on !TARGET_brcm47xx_mips74k && !TARGET_bcm53xx
+-		bool "SSB only"
++define KernelPackage/p54-spi
++  $(call KernelPackage/p54/Default)
++  TITLE+= (SPI)
++  DEPENDS+= @TARGET_omap24xx +kmod-p54-common
++  FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/p54/p54spi.ko
++  AUTOLOAD:=$(call AutoProbe,p54spi)
++endef
+ 
+-	endchoice
++define KernelPackage/rt2x00/Default
++  $(call KernelPackage/mac80211/Default)
++  TITLE:=Ralink Drivers for RT2x00 cards
++endef
+ 
+-	config PACKAGE_B43_DEBUG
+-		bool "Enable debug output and debugfs for b43"
+-		default n
+-		help
+-		  Enable additional debug output and runtime sanity checks for b43
+-		  and enables the debugfs interface.
++define KernelPackage/rt2x00-lib
++$(call KernelPackage/rt2x00/Default)
++  DEPENDS+= @(PCI_SUPPORT||USB_SUPPORT||TARGET_ramips) +kmod-mac80211 +kmod-lib-crc-itu-t
++  TITLE+= (LIB)
++  FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/rt2x00/rt2x00lib.ko
++  MENU:=1
++endef
+ 
+-		  If unsure, say N.
++define KernelPackage/rt2x00-lib/config
++  if PACKAGE_kmod-rt2x00-lib
+ 
+-	config PACKAGE_B43_PIO
+-		bool "Enable support for PIO transfer mode"
+-		default n
++	config PACKAGE_RT2X00_LIB_DEBUGFS
++		bool "Enable rt2x00 debugfs support"
++		depends on PACKAGE_MAC80211_DEBUGFS
+ 		help
+-		  Enable support for using PIO instead of DMA. Unless you have DMA
+-		  transfer problems you don't need this.
+-
+-		  If unsure, say N.
++		  Enable creation of debugfs files for the rt2x00 drivers.
++		  These debugfs files support both reading and writing of the
++		  most important register types of the rt2x00 hardware.
+ 
+-	config PACKAGE_B43_PHY_G
+-		bool "Enable support for G-PHYs"
+-		default n if TARGET_brcm47xx_mips74k
+-		default y
++	config PACKAGE_RT2X00_DEBUG
++		bool "Enable rt2x00 debug output"
+ 		help
+-		  Enable support for G-PHY. This includes support for the following devices:
+-		  PCI: BCM4306, BCM4311, BCM4318
+-		  SoC: BCM5352E, BCM4712
++		  Enable debugging output for all rt2x00 modules
+ 
+-		  If unsure, say Y.
++  endif
++endef
+ 
+-	config PACKAGE_B43_PHY_N
+-		bool "Enable support for N-PHYs"
+-		default y
+-		help
+-		  Enable support for N-PHY. This includes support for the following devices:
+-		  PCI: BCM4321, BCM4322, BCM43222, BCM43224, BCM43225
+-		  SoC: BCM4716, BCM4717, BCM4718
++define KernelPackage/rt2x00-mmio
++$(call KernelPackage/rt2x00/Default)
++  DEPENDS+= @(PCI_SUPPORT||TARGET_ramips) +kmod-rt2x00-lib +kmod-eeprom-93cx6
++  HIDDEN:=1
++  TITLE+= (MMIO)
++  FILES:= $(PKG_BUILD_DIR)/drivers/net/wireless/rt2x00/rt2x00mmio.ko
++endef
+ 
+-		  Currently only 11g speed is available.
++define KernelPackage/rt2x00-pci
++$(call KernelPackage/rt2x00/Default)
++  DEPENDS+= @PCI_SUPPORT +kmod-rt2x00-mmio +kmod-rt2x00-lib
++  HIDDEN:=1
++  TITLE+= (PCI)
++  FILES:= $(PKG_BUILD_DIR)/drivers/net/wireless/rt2x00/rt2x00pci.ko
++  AUTOLOAD:=$(call AutoProbe,rt2x00pci)
++endef
+ 
+-		  If unsure, say Y.
++define KernelPackage/rt2x00-usb
++$(call KernelPackage/rt2x00/Default)
++  DEPENDS+= @USB_SUPPORT +kmod-rt2x00-lib +kmod-usb-core
++  HIDDEN:=1
++  TITLE+= (USB)
++  FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/rt2x00/rt2x00usb.ko
++  AUTOLOAD:=$(call AutoProbe,rt2x00usb)
++endef
+ 
+-	config PACKAGE_B43_PHY_LP
+-		bool "Enable support for LP-PHYs"
+-		default n if TARGET_brcm47xx_mips74k
+-		default y
+-		help
+-		  Enable support for LP-PHY. This includes support for the following devices:
+-		  PCI: BCM4312
+-		  SoC: BCM5354
++define KernelPackage/rt2800-lib
++$(call KernelPackage/rt2x00/Default)
++  DEPENDS+= @(PCI_SUPPORT||USB_SUPPORT||TARGET_ramips) +kmod-rt2x00-lib +kmod-lib-crc-ccitt +@DRIVER_11N_SUPPORT
++  HIDDEN:=1
++  TITLE+= (rt2800 LIB)
++  FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/rt2x00/rt2800lib.ko
++endef
+ 
+-		  If unsure, say Y.
++define KernelPackage/rt2400-pci
++$(call KernelPackage/rt2x00/Default)
++  DEPENDS+= @PCI_SUPPORT +kmod-rt2x00-pci
++  TITLE+= (RT2400 PCI)
++  FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/rt2x00/rt2400pci.ko
++  AUTOLOAD:=$(call AutoProbe,rt2400pci)
++endef
+ 
+-	config PACKAGE_B43_PHY_HT
+-		bool "Enable support for HT-PHYs"
+-		default n if TARGET_brcm47xx_legacy
+-		default y
+-		help
+-		  Enable support for HT-PHY. This includes support for the following devices:
+-		  PCI: BCM4331
++define KernelPackage/rt2500-pci
++$(call KernelPackage/rt2x00/Default)
++  DEPENDS+= @PCI_SUPPORT +kmod-rt2x00-pci
++  TITLE+= (RT2500 PCI)
++  FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/rt2x00/rt2500pci.ko
++  AUTOLOAD:=$(call AutoProbe,rt2500pci)
++endef
++
++define KernelPackage/rt2500-usb
++$(call KernelPackage/rt2x00/Default)
++  DEPENDS+= @USB_SUPPORT +kmod-rt2x00-usb
++  TITLE+= (RT2500 USB)
++  FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/rt2x00/rt2500usb.ko
++  AUTOLOAD:=$(call AutoProbe,rt2500usb)
++endef
++
++define KernelPackage/rt2800-mmio
++$(call KernelPackage/rt2x00/Default)
++  TITLE += (RT28xx/RT3xxx MMIO)
++  DEPENDS += +kmod-rt2800-lib +kmod-rt2x00-mmio
++  HIDDEN:=1
++  FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/rt2x00/rt2800mmio.ko
++endef
+ 
+-		  Currently only 11g speed is available.
++define KernelPackage/rt2800-soc
++$(call KernelPackage/rt2x00/Default)
++  DEPENDS += @(TARGET_ramips_rt288x||TARGET_ramips_rt305x||TARGET_ramips_rt3883||TARGET_ramips_mt7620) +kmod-rt2800-mmio +kmod-rt2800-lib
++  TITLE += (RT28xx/RT3xxx SoC)
++  FILES := \
++	$(PKG_BUILD_DIR)/drivers/net/wireless/rt2x00/rt2x00soc.ko \
++	$(PKG_BUILD_DIR)/drivers/net/wireless/rt2x00/rt2800soc.ko
++  AUTOLOAD:=$(call AutoProbe,rt2800soc)
++endef
+ 
+-		  If unsure, say Y.
++define KernelPackage/rt2800-pci
++$(call KernelPackage/rt2x00/Default)
++  DEPENDS+= @PCI_SUPPORT +kmod-rt2x00-pci +kmod-rt2800-lib +kmod-rt2800-mmio
++  TITLE+= (RT2860 PCI)
++  FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/rt2x00/rt2800pci.ko
++  AUTOLOAD:=$(call AutoProbe,rt2800pci)
++endef
+ 
+-	config PACKAGE_B43_PHY_LCN
+-		bool "Enable support for LCN-PHYs"
+-		depends on BROKEN
+-		default n
+-		help
+-		  Currently broken.
++define KernelPackage/rt2800-usb
++$(call KernelPackage/rt2x00/Default)
++  DEPENDS+= @USB_SUPPORT +kmod-rt2x00-usb +kmod-rt2800-lib +kmod-lib-crc-ccitt
++  TITLE+= (RT2870 USB)
++  FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/rt2x00/rt2800usb.ko
++  AUTOLOAD:=$(call AutoProbe,rt2800usb)
++endef
+ 
+-		  If unsure, say N.
+ 
+-  endif
++define KernelPackage/rt61-pci
++$(call KernelPackage/rt2x00/Default)
++  DEPENDS+= @PCI_SUPPORT +kmod-rt2x00-pci
++  TITLE+= (RT2x61 PCI)
++  FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/rt2x00/rt61pci.ko
++  AUTOLOAD:=$(call AutoProbe,rt61pci)
+ endef
+ 
+-define KernelPackage/b43/description
+-Kernel module for Broadcom 43xx wireless support (mac80211 stack) new
++define KernelPackage/rt73-usb
++  $(call KernelPackage/rt2x00/Default)
++  DEPENDS+= @USB_SUPPORT +kmod-rt2x00-usb
++  TITLE+= (RT73 USB)
++  FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/rt2x00/rt73usb.ko
++  AUTOLOAD:=$(call AutoProbe,rt73usb)
+ endef
+ 
+-define KernelPackage/b43legacy
++
++define KernelPackage/rtl818x/Default
+   $(call KernelPackage/mac80211/Default)
+-  TITLE:=Broadcom 43xx-legacy wireless support
+-  URL:=https://wireless.wiki.kernel.org/en/users/drivers/b43
+-  KCONFIG:= \
+-  	CONFIG_HW_RANDOM=y
+-  DEPENDS+= +kmod-mac80211 +!(TARGET_brcm47xx||TARGET_brcm63xx):kmod-ssb
+-  FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/b43legacy/b43legacy.ko
+-  AUTOLOAD:=$(call AutoProbe,b43legacy)
+-  MENU:=1
++  TITLE:=Realtek Drivers for RTL818x devices
++  URL:=http://wireless.kernel.org/en/users/Drivers/rtl8187
++  DEPENDS+= +kmod-eeprom-93cx6 +kmod-mac80211
+ endef
+ 
+-define KernelPackage/b43legacy/config
+-  if PACKAGE_kmod-b43legacy
+-
+-	config B43LEGACY_FW_SQUASH
+-		bool "Remove unnecessary firmware files"
+-		default y
+-		help
+-		  This options allows you to remove unnecessary b43legacy firmware files
+-		  from the final rootfs image. This can reduce the rootfs size by
+-		  up to 50k.
++define KernelPackage/rtl8180
++  $(call KernelPackage/rtl818x/Default)
++  DEPENDS+= @PCI_SUPPORT
++  TITLE+= (RTL8180 PCI)
++  FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/rtl818x/rtl8180/rtl818x_pci.ko
++  AUTOLOAD:=$(call AutoProbe,rtl818x_pci)
++endef
+ 
+-		  If unsure, say Y.
++define KernelPackage/rtl8187
++$(call KernelPackage/rtl818x/Default)
++  DEPENDS+= @USB_SUPPORT +kmod-usb-core
++  TITLE+= (RTL8187 USB)
++  FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/rtl818x/rtl8187/rtl8187.ko
++  AUTOLOAD:=$(call AutoProbe,rtl8187)
++endef
+ 
+-	config B43LEGACY_FW_SQUASH_COREREVS
+-		string "Core revisions to include"
+-		depends on B43LEGACY_FW_SQUASH
+-		default "1,2,3,4"
++define KernelPackage/rtlwifi/config
++	config PACKAGE_RTLWIFI_DEBUG
++		bool "Realtek wireless debugging"
++		depends on PACKAGE_kmod-rtlwifi
+ 		help
+-		  This is a comma seperated list of core revision numbers.
++		  Say Y, if you want to debug realtek wireless drivers.
+ 
+-		  Example (keep files for rev4 only):
+-		    4
++endef
+ 
+-		  Example (keep files for rev2 and rev4):
+-		    2,4
++define KernelPackage/rtlwifi
++  $(call KernelPackage/mac80211/Default)
++  TITLE:=Realtek common driver part
++  DEPENDS+= @(PCI_SUPPORT||USB_SUPPORT) +kmod-mac80211 +@DRIVER_11N_SUPPORT
++  FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/rtlwifi/rtlwifi.ko
++  HIDDEN:=1
++endef
+ 
+-  endif
++define KernelPackage/rtlwifi-pci
++  $(call KernelPackage/mac80211/Default)
++  TITLE:=Realtek common driver part (PCI support)
++  DEPENDS+= @PCI_SUPPORT +kmod-rtlwifi
++  FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/rtlwifi/rtl_pci.ko
++  AUTOLOAD:=$(call AutoProbe,rtl_pci)
++  HIDDEN:=1
+ endef
+ 
+-define KernelPackage/b43legacy/description
+-Kernel module for Broadcom 43xx-legacy wireless support (mac80211 stack) new
++define KernelPackage/rtlwifi-usb
++  $(call KernelPackage/mac80211/Default)
++  TITLE:=Realtek common driver part (USB support)
++  DEPENDS+= @USB_SUPPORT +kmod-usb-core +kmod-rtlwifi
++  FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/rtlwifi/rtl_usb.ko
++  AUTOLOAD:=$(call AutoProbe,rtl_usb)
++  HIDDEN:=1
+ endef
+ 
++define KernelPackage/rtl8192c-common
++  $(call KernelPackage/mac80211/Default)
++  TITLE:=Realtek RTL8192CE/RTL8192CU common support module
++  DEPENDS+= +kmod-rtlwifi
++  FILES:= $(PKG_BUILD_DIR)/drivers/net/wireless/rtlwifi/rtl8192c/rtl8192c-common.ko
++  HIDDEN:=1
++endef
+ 
+-define KernelPackage/brcmutil
++define KernelPackage/rtl8192ce
+   $(call KernelPackage/mac80211/Default)
+-  TITLE:=Broadcom IEEE802.11n common driver parts
+-  URL:=https://wireless.wiki.kernel.org/en/users/drivers/brcm80211
+-  DEPENDS+=@PCI_SUPPORT||USB_SUPPORT
+-  FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/brcm80211/brcmutil/brcmutil.ko
+-  AUTOLOAD:=$(call AutoProbe,brcmutil)
+-  MENU:=1
++  TITLE:=Realtek RTL8192CE/RTL8188CE support
++  DEPENDS+= +kmod-rtlwifi-pci +kmod-rtl8192c-common
++  FILES:= $(PKG_BUILD_DIR)/drivers/net/wireless/rtlwifi/rtl8192ce/rtl8192ce.ko
++  AUTOLOAD:=$(call AutoProbe,rtl8192ce)
+ endef
+ 
+-define KernelPackage/brcmutil/description
+- This module contains some common parts needed by Broadcom Wireless drivers brcmsmac and brcmfmac.
++define KernelPackage/rtl8192ce/install
++	$(INSTALL_DIR) $(1)/lib/firmware/rtlwifi
++	$(INSTALL_DATA) $(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/rtlwifi/rtl8192cfw.bin $(1)/lib/firmware/rtlwifi
++	$(INSTALL_DATA) $(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/rtlwifi/rtl8192cfwU.bin $(1)/lib/firmware/rtlwifi
++	$(INSTALL_DATA) $(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/rtlwifi/rtl8192cfwU_B.bin $(1)/lib/firmware/rtlwifi
+ endef
+ 
+-define KernelPackage/brcmutil/config
+-  if PACKAGE_kmod-brcmutil
++define KernelPackage/rtl8192se
++  $(call KernelPackage/mac80211/Default)
++  TITLE:=Realtek RTL8192SE/RTL8191SE support
++  DEPENDS+= +kmod-rtlwifi-pci
++  FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/rtlwifi/rtl8192se/rtl8192se.ko
++  AUTOLOAD:=$(call AutoProbe,rtl8192se)
++endef
+ 
+-	config PACKAGE_BRCM80211_DEBUG
+-		bool "Broadcom wireless driver debugging"
+-		help
+-		  Say Y, if you want to debug brcmsmac and brcmfmac wireless driver.
++define KernelPackage/rtl8192se/install
++	$(INSTALL_DIR) $(1)/lib/firmware/rtlwifi
++	$(INSTALL_DATA) $(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/rtlwifi/rtl8192sefw.bin $(1)/lib/firmware/rtlwifi
++endef
+ 
+-  endif
++define KernelPackage/rtl8192de
++  $(call KernelPackage/mac80211/Default)
++  TITLE:=Realtek RTL8192DE/RTL8188DE support
++  DEPENDS+= +kmod-rtlwifi-pci
++  FILES:= $(PKG_BUILD_DIR)/drivers/net/wireless/rtlwifi/rtl8192de/rtl8192de.ko
++  AUTOLOAD:=$(call AutoProbe,rtl8192de)
+ endef
+ 
+-PKG_BRCMSMAC_FW_NAME:=broadcom-wl
+-PKG_BRCMSMAC_FW_VERSION:=5.100.138
+-PKG_BRCMSMAC_FW_OBJECT:=$(PKG_BRCMSMAC_FW_NAME)-$(PKG_BRCMSMAC_FW_VERSION)/linux/wl_apsta.o
+-PKG_BRCMSMAC_FW_SOURCE:=$(PKG_BRCMSMAC_FW_NAME)-$(PKG_BRCMSMAC_FW_VERSION).tar.bz2
+-PKG_BRCMSMAC_FW_SOURCE_URL:=http://www.lwfinger.com/b43-firmware/
+-PKG_BRCMSMAC_FW_MD5SUM:=f4e357b09eaf5d8b1f1920cf3493a555
++define KernelPackage/rtl8192de/install
++	$(INSTALL_DIR) $(1)/lib/firmware/rtlwifi
++	$(INSTALL_DATA) $(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/rtlwifi/rtl8192defw.bin $(1)/lib/firmware/rtlwifi
++endef
+ 
+-define Download/brcmsmac
+-  FILE:=$(PKG_BRCMSMAC_FW_SOURCE)
+-  URL:=$(PKG_BRCMSMAC_FW_SOURCE_URL)
+-  MD5SUM:=$(PKG_BRCMSMAC_FW_MD5SUM)
++define KernelPackage/rtl8192cu
++  $(call KernelPackage/mac80211/Default)
++  TITLE:=Realtek RTL8192CU/RTL8188CU support
++  DEPENDS+= +kmod-rtlwifi-usb +kmod-rtl8192c-common
++  FILES:= $(PKG_BUILD_DIR)/drivers/net/wireless/rtlwifi/rtl8192cu/rtl8192cu.ko
++  AUTOLOAD:=$(call AutoProbe,rtl8192cu)
+ endef
+-$(eval $(call Download,brcmsmac))
+ 
+-define KernelPackage/brcmsmac
++define KernelPackage/rtl8192cu/install
++	$(INSTALL_DIR) $(1)/lib/firmware/rtlwifi
++	$(INSTALL_DATA) $(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/rtlwifi/rtl8192cufw.bin $(1)/lib/firmware/rtlwifi
++	$(INSTALL_DATA) $(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/rtlwifi/rtl8192cufw_A.bin $(1)/lib/firmware/rtlwifi
++	$(INSTALL_DATA) $(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/rtlwifi/rtl8192cufw_B.bin $(1)/lib/firmware/rtlwifi
++	$(INSTALL_DATA) $(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/rtlwifi/rtl8192cufw_TMSC.bin $(1)/lib/firmware/rtlwifi
++endef
++
++
++define KernelPackage/wlcore
+   $(call KernelPackage/mac80211/Default)
+-  TITLE:=Broadcom IEEE802.11n PCIe SoftMAC WLAN driver
+-  URL:=https://wireless.wiki.kernel.org/en/users/drivers/brcm80211
+-  DEPENDS+= +kmod-mac80211 +@DRIVER_11N_SUPPORT +!TARGET_brcm47xx:kmod-bcma +kmod-lib-cordic +kmod-lib-crc8 +kmod-brcmutil
+-  FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/brcm80211/brcmsmac/brcmsmac.ko
+-  AUTOLOAD:=$(call AutoProbe,brcmsmac)
+-  MENU:=1
++  TITLE:=TI common driver part
++  DEPENDS+= @TARGET_omap +kmod-mac80211 +@DRIVER_11N_SUPPORT
++  FILES:= \
++	$(PKG_BUILD_DIR)/drivers/net/wireless/ti/wlcore/wlcore.ko \
++	$(PKG_BUILD_DIR)/drivers/net/wireless/ti/wlcore/wlcore_sdio.ko
++  AUTOLOAD:=$(call AutoProbe,wlcore wlcore_sdio)
+ endef
+ 
+-define KernelPackage/brcmsmac/description
+- Kernel module for Broadcom IEEE802.11n PCIe Wireless cards
++define KernelPackage/wlcore/description
++ This module contains some common parts needed by TI Wireless drivers.
+ endef
+ 
+-define KernelPackage/brcmsmac/config
+-  if PACKAGE_kmod-brcmsmac
++define KernelPackage/wl12xx
++  $(call KernelPackage/mac80211/Default)
++  TITLE:=Driver for TI WL12xx
++  URL:=http://wireless.kernel.org/en/users/Drivers/wl12xx
++  DEPENDS+= +kmod-wlcore
++  FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/ti/wl12xx/wl12xx.ko
++  AUTOLOAD:=$(call AutoProbe,wl12xx)
++endef
+ 
+-	config BRCMSMAC_USE_FW_FROM_WL
+-		bool "Use firmware extracted from broadcom proprietary driver"
+-		default y
+-		help
+-		  Instead of using the official brcmsmac firmware a firmware
+-		  version 666.2 extracted from the proprietary Broadcom driver
+-		  is used. This is needed to get core rev 17 used in bcm4716
+-		  to work.
++define KernelPackage/wl12xx/description
++ Kernel modules for TI WL12xx
++endef
+ 
+-		  If unsure, say Y.
++define KernelPackage/wl18xx
++  $(call KernelPackage/mac80211/Default)
++  TITLE:=Driver for TI WL18xx
++  URL:=http://wireless.kernel.org/en/users/Drivers/wl18xx
++  DEPENDS+= +kmod-wlcore
++  FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/ti/wl18xx/wl18xx.ko
++  AUTOLOAD:=$(call AutoProbe,wl18xx)
++endef
+ 
+-  endif
++define KernelPackage/wl18xx/description
++ Kernel modules for TI WL18xx
+ endef
+ 
+ 
+-define KernelPackage/brcmfmac
+-  $(call KernelPackage/mac80211/Default)
+-  TITLE:=Broadcom IEEE802.11n USB FullMAC WLAN driver
+-  URL:=https://wireless.wiki.kernel.org/en/users/drivers/brcm80211
+-  DEPENDS+= @USB_SUPPORT +kmod-cfg80211 +@DRIVER_11N_SUPPORT +kmod-brcmutil +BRCMFMAC_SDIO:kmod-mmc +BRCMFMAC_USB:kmod-usb-core
+-  FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/brcm80211/brcmfmac/brcmfmac.ko
+-  AUTOLOAD:=$(call AutoProbe,brcmfmac)
++ZD1211FW_NAME:=zd1211-firmware
++ZD1211FW_VERSION:=1.4
++define Download/zd1211rw
++  FILE:=$(ZD1211FW_NAME)-$(ZD1211FW_VERSION).tar.bz2
++  URL:=@SF/zd1211/
++  MD5SUM:=19f28781d76569af8551c9d11294c870
+ endef
++$(eval $(call Download,zd1211rw))
+ 
+-define KernelPackage/brcmfmac/description
+- Kernel module for Broadcom IEEE802.11n USB Wireless cards
++define KernelPackage/zd1211rw
++  $(call KernelPackage/mac80211/Default)
++  TITLE:=Zydas ZD1211 support
++  DEPENDS+= @USB_SUPPORT +kmod-usb-core +kmod-mac80211
++  FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/zd1211rw/zd1211rw.ko
++  AUTOLOAD:=$(call AutoProbe,zd1211rw)
+ endef
+ 
+-define KernelPackage/brcmfmac/config
+-  if PACKAGE_kmod-brcmfmac
+-
+-	config BRCMFMAC_SDIO
+-		bool "Enable SDIO bus interface support"
+-		default n
+-		help
+-		  Enable support for cards attached to an SDIO bus.
+-		  Select this option only if you are sure that your
+-		  board has a Broadcom wireless chip atacched to
+-		  that bus.
+-
+-	config BRCMFMAC_USB
+-		bool "Enable USB bus interface support"
+-		depends on USB_SUPPORT
+-		default y
+-		help
+-		  Supported USB connected chipsets:
+-		  BCM43235, BCM43236, BCM43238 (all in revision 3 only)
+-		  BCM43143, BCM43242, BCM43566, BCM43569
+-
+-	config BRCMFMAC_PCIE
+-		bool "Enable PCIE bus interface support"
+-		depends on PCI_SUPPORT
+-		default y
+-		help
+-		  Supported PCIe connected chipsets:
+-		  BCM4354, BCM4356, BCM43567, BCM43570, BCM43602
+ 
+-  endif
+-endef
+ 
+ config_package=$(if $(CONFIG_PACKAGE_kmod-$(1)),m)
+ 
+@@ -1602,6 +1684,8 @@ config-$(CONFIG_BRCMFMAC_PCIE) += BRCMFMAC_PCIE
+ config-$(CONFIG_PACKAGE_BRCM80211_DEBUG) += BRCMDBG
+ 
+ config-$(call config_package,mac80211-hwsim) += MAC80211_HWSIM
++config-$(call config_package,mt7601u) += MT7601U
++config-y += WL_MEDIATEK
+ 
+ config-$(call config_package,rt2x00-lib) += RT2X00 RT2X00_LIB
+ config-$(call config_package,rt2x00-pci) += RT2X00_LIB_PCI
+@@ -1623,26 +1707,28 @@ config-$(call config_package,rt2800-pci) += RT2800PCI
+ config-y += RT2800PCI_RT33XX RT2800PCI_RT35XX RT2800PCI_RT53XX RT2800PCI_RT3290
+ 
+ config-$(call config_package,rt2800-usb) += RT2800USB
+-config-y += RT2800USB_RT33XX RT2800USB_RT35XX RT2800USB_RT3573 RT2800USB_RT53XX RT2800USB_RT55XX
++config-y += RT2800USB_RT33XX RT2800USB_RT35XX RT2800USB_RT3573 RT2800USB_RT53XX RT2800USB_RT55XX RT2800USB_UNKNOWN
+ 
+ config-$(call config_package,iwl-legacy) += IWLEGACY
+ config-$(call config_package,iwl3945) += IWL3945
+ config-$(call config_package,iwl4965) += IWL4965
+-config-$(call config_package,iwlagn) += IWLWIFI IWLDVM
++config-$(call config_package,iwlwifi) += IWLWIFI IWLDVM IWLMVM
++config-$(CONFIG_PACKAGE_IWLWIFI_DEBUG)+= IWLWIFI_DEBUG
++config-$(CONFIG_PACKAGE_IWLWIFI_DEBUGFS)+= IWLWIFI_DEBUGFS
+ 
+-config-$(call config_package,net-libipw) += LIBIPW
+-config-$(call config_package,net-ipw2100) += IPW2100
+-config-$(call config_package,net-ipw2200) += IPW2200
++config-$(call config_package,libipw) += LIBIPW
++config-$(call config_package,ipw2100) += IPW2100
++config-$(call config_package,ipw2200) += IPW2200
+ 
+ config-$(call config_package,p54-common) += P54_COMMON
+ config-$(call config_package,p54-pci) += P54_PCI
+ config-$(call config_package,p54-usb) += P54_USB
+ config-$(call config_package,p54-spi) += P54_SPI
+ 
+-config-$(call config_package,net-hermes) += HERMES
+-config-$(call config_package,net-hermes-pci) += PCI_HERMES
+-config-$(call config_package,net-hermes-plx) += PLX_HERMES
+-config-$(call config_package,net-hermes-pcmcia) += PCMCIA_HERMES
++config-$(call config_package,hermes) += HERMES
++config-$(call config_package,hermes-pci) += PCI_HERMES
++config-$(call config_package,hermes-plx) += PLX_HERMES
++config-$(call config_package,hermes-pcmcia) += PCMCIA_HERMES
+ config-y += HERMES_PRISM
+ 
+ config-$(call config_package,adm8211) += ADM8211
+@@ -1702,8 +1788,9 @@ define Build/Prepare
+ 	$(TAR) -C $(PKG_BUILD_DIR) -xzf $(DL_DIR)/$(IPW2100_NAME)-$(IPW2100_VERSION).tgz
+ 	$(TAR) -C $(PKG_BUILD_DIR) -xzf $(DL_DIR)/$(IPW2200_NAME)-$(IPW2200_VERSION).tgz
+ 	$(TAR) -C $(PKG_BUILD_DIR) -xjf $(DL_DIR)/$(ZD1211FW_NAME)-$(ZD1211FW_VERSION).tar.bz2
+-	$(TAR) -C $(PKG_BUILD_DIR) -xjf $(DL_DIR)/$(PKG_LINUX_FIRMWARE_SOURCE)
++	$(TAR) -C $(PKG_BUILD_DIR) -xJf $(DL_DIR)/$(PKG_LINUX_FIRMWARE_SOURCE)
+ 	$(TAR) -C $(PKG_BUILD_DIR) -xjf $(DL_DIR)/$(PKG_ATH10K_LINUX_FIRMWARE_SOURCE)
++	$(TAR) -C $(PKG_BUILD_DIR) -xjf $(DL_DIR)/$(PKG_MT7601U_FW_SOURCE)
+ 	rm -rf \
+ 		$(PKG_BUILD_DIR)/include/linux/ssb \
+ 		$(PKG_BUILD_DIR)/include/linux/bcma \
+@@ -1739,233 +1826,37 @@ define Build/Compile
+ 	$(MAKE) $(MAKE_OPTS) allnoconfig
+ 	$(call Build/Compile/kmod)
+ endef
+-
+-define Build/InstallDev
+-	mkdir -p \
+-		$(1)/usr/include/mac80211 \
+-		$(1)/usr/include/mac80211-backport \
+-		$(1)/usr/include/mac80211/ath \
+-		$(1)/usr/include/net/mac80211
+-	$(CP) $(PKG_BUILD_DIR)/net/mac80211/*.h $(PKG_BUILD_DIR)/include/* $(1)/usr/include/mac80211/
+-	$(CP) $(PKG_BUILD_DIR)/backport-include/* $(1)/usr/include/mac80211-backport/
+-	$(CP) $(PKG_BUILD_DIR)/net/mac80211/rate.h $(1)/usr/include/net/mac80211/
+-	$(CP) $(PKG_BUILD_DIR)/drivers/net/wireless/ath/*.h $(1)/usr/include/mac80211/ath/
+-	rm -f $(1)/usr/include/mac80211-backport/linux/module.h
+-endef
+-
+-define KernelPackage/libertas-usb/install
+-	$(INSTALL_DIR) $(1)/lib/firmware/libertas
+-	$(INSTALL_DATA) \
+-		$(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/libertas/usb8388_v9.bin \
+-		$(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/libertas/usb8682.bin \
+-		$(1)/lib/firmware/libertas/
+-endef
+-
+-define KernelPackage/libertas-sdio/install
+-	$(INSTALL_DIR) $(1)/lib/firmware/libertas
+-	$(INSTALL_DATA) \
+-		$(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/libertas/sd8385_helper.bin \
+-		$(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/libertas/sd8385.bin \
+-		$(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/libertas/sd8686_v9_helper.bin \
+-		$(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/libertas/sd8686_v9.bin \
+-		$(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/libertas/sd8688_helper.bin \
+-		$(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/libertas/sd8688.bin \
+-		$(1)/lib/firmware/libertas
+-endef
+-
+-define KernelPackage/cfg80211/install
+-	$(INSTALL_DIR) $(1)/lib/wifi $(1)/lib/netifd/wireless
+-	$(INSTALL_DATA) ./files/lib/wifi/mac80211.sh $(1)/lib/wifi
+-	$(INSTALL_BIN) ./files/lib/netifd/wireless/mac80211.sh $(1)/lib/netifd/wireless
+-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/rt61-pci/install
+-	$(INSTALL_DIR) $(1)/lib/firmware
+-	$(INSTALL_DATA) \
+-		$(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/rt2561.bin \
+-		$(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/rt2561s.bin \
+-		$(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/rt2661.bin \
+-		$(1)/lib/firmware/
+-endef
+-
+-define KernelPackage/rt73-usb/install
+-	$(INSTALL_DIR) $(1)/lib/firmware
+-	$(INSTALL_DATA) $(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/rt73.bin $(1)/lib/firmware/
+-endef
+-
+-define KernelPackage/rt2800-pci/install
+-	$(INSTALL_DIR) $(1)/lib/firmware
+-	$(INSTALL_DATA) \
+-		$(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/rt2860.bin \
+-		$(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/rt3290.bin \
+-		$(1)/lib/firmware
+-endef
+-
+-define KernelPackage/rt2800-usb/install
+-	$(INSTALL_DIR) $(1)/lib/firmware
+-	$(INSTALL_DATA) $(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/rt2870.bin $(1)/lib/firmware/
+-endef
+-
+-define KernelPackage/wl12xx/install
+-	$(INSTALL_DIR) $(1)/lib/firmware/ti-connectivity
+-	$(INSTALL_DATA) \
+-		$(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/ti-connectivity/wl127x-fw-5-mr.bin \
+-		$(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/ti-connectivity/wl127x-fw-5-plt.bin \
+-		$(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/ti-connectivity/wl127x-fw-5-sr.bin \
+-		$(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/ti-connectivity/wl1271-nvs.bin \
+-		$(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/ti-connectivity/wl128x-fw-5-mr.bin \
+-		$(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/ti-connectivity/wl128x-fw-5-plt.bin \
+-		$(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/ti-connectivity/wl128x-fw-5-sr.bin \
+-		$(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/ti-connectivity/wl128x-nvs.bin \
+-		$(1)/lib/firmware/ti-connectivity
+-endef
+-
+-define KernelPackage/wl18xx/install
+-	$(INSTALL_DIR) $(1)/lib/firmware/ti-connectivity
+-	$(INSTALL_DATA) \
+-		$(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/ti-connectivity/wl18xx-conf.bin \
+-		$(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/ti-connectivity/wl18xx-fw-3.bin \
+-		$(1)/lib/firmware/ti-connectivity
+-endef
+-
+-define KernelPackage/zd1211rw/install
+-	$(INSTALL_DIR) $(1)/lib/firmware/zd1211
+-	$(INSTALL_DATA) $(PKG_BUILD_DIR)/$(ZD1211FW_NAME)/zd1211* $(1)/lib/firmware/zd1211
+-endef
+-
+-define KernelPackage/carl9170/install
+-	$(INSTALL_DIR) $(1)/lib/firmware
+-	$(INSTALL_DATA) $(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/carl9170-1.fw $(1)/lib/firmware
+-endef
+-
+-define KernelPackage/ath9k-htc/install
+-	$(INSTALL_DIR) $(1)/lib/firmware
+-	$(INSTALL_DATA) \
+-		$(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/htc_9271.fw \
+-		$(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/htc_7010.fw \
+-		$(1)/lib/firmware/
+-endef
+-
+-define KernelPackage/ath10k/install
+-	$(INSTALL_DIR) $(1)/lib/firmware/ath10k/QCA988X/hw2.0
+-	$(INSTALL_DATA) \
+-		$(PKG_BUILD_DIR)/$(PKG_ATH10K_LINUX_FIRMWARE_SUBDIR)/ath10k/QCA988X/hw2.0/board.bin \
+-		$(1)/lib/firmware/ath10k/QCA988X/hw2.0/
+-ifeq ($(CONFIG_ATH10K_STA_FW),y)
+-	$(INSTALL_DATA) \
+-		$(PKG_BUILD_DIR)/$(PKG_ATH10K_LINUX_FIRMWARE_SUBDIR)/main/firmware-2.bin_999.999.0.636 \
+-		$(1)/lib/firmware/ath10k/QCA988X/hw2.0/firmware-2.bin
+-else ifeq ($(CONFIG_ATH10K_API2_FW),y)
+-	$(INSTALL_DATA) \
+-		$(PKG_BUILD_DIR)/$(PKG_ATH10K_LINUX_FIRMWARE_SUBDIR)/10.1/firmware-2.bin_10.1.467.2-1 \
+-		$(1)/lib/firmware/ath10k/QCA988X/hw2.0/firmware-2.bin
+-else
+-	$(INSTALL_DATA) \
+-		$(PKG_BUILD_DIR)/$(PKG_ATH10K_LINUX_FIRMWARE_SUBDIR)/10.2.4/firmware-4.bin_10.2.4.45 \
+-		$(1)/lib/firmware/ath10k/QCA988X/hw2.0/firmware-4.bin
+-endif
+-endef
+-
+-define KernelPackage/mwl8k/install
+-	$(INSTALL_DIR) $(1)/lib/firmware/mwl8k
+-	$(INSTALL_DATA) \
+-		$(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/mwl8k/fmimage_8366_ap-3.fw \
+-		$(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/mwl8k/fmimage_8366.fw \
+-		$(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/mwl8k/helper_8366.fw \
+-		$(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/mwl8k/fmimage_8687.fw \
+-		$(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/mwl8k/helper_8687.fw \
+-		$(1)/lib/firmware/mwl8k/
+-endef
+-
+-define KernelPackage/mwifiex-pcie/install
+-	$(INSTALL_DIR) $(1)/lib/firmware/mrvl
+-	$(INSTALL_DATA) \
+-		$(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/mrvl/pcie8897_uapsta.bin \
+-		$(1)/lib/firmware/mrvl/
+-endef
+-
+-define KernelPackage/net-ipw2100/install
+-	$(INSTALL_DIR) $(1)/lib/firmware
+-	$(INSTALL_DATA) $(PKG_BUILD_DIR)/ipw2100-$(IPW2100_VERSION)*.fw $(1)/lib/firmware
+-endef
+-
+-define KernelPackage/net-ipw2200/install
+-	$(INSTALL_DIR) $(1)/lib/firmware
+-	$(INSTALL_DATA) $(PKG_BUILD_DIR)/$(IPW2200_NAME)-$(IPW2200_VERSION)/ipw2200*.fw $(1)/lib/firmware
+-endef
+-
+-define KernelPackage/iwlagn/install
+-	$(INSTALL_DIR) $(1)/lib/firmware
+-ifneq ($(CONFIG_IWL5000_FW),)
+-	$(INSTALL_DATA) $(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/iwlwifi-5000-5.ucode $(1)/lib/firmware
+-endif
+-ifneq ($(CONFIG_IWL5150_FW),)
+-	$(INSTALL_DATA) $(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/iwlwifi-5150-2.ucode $(1)/lib/firmware
+-endif
+-ifneq ($(CONFIG_IWL1000_FW),)
+-	$(INSTALL_DATA) $(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/iwlwifi-1000-5.ucode $(1)/lib/firmware
+-endif
+-ifneq ($(CONFIG_IWL6000_FW),)
+-	$(INSTALL_DATA) $(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/iwlwifi-6000-4.ucode $(1)/lib/firmware
+-endif
+-ifneq ($(CONFIG_IWL6050_FW),)
+-	$(INSTALL_DATA) $(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/iwlwifi-6050-5.ucode $(1)/lib/firmware
+-endif
+-ifneq ($(CONFIG_IWL6005_FW),)
+-	$(INSTALL_DATA) $(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/iwlwifi-6000g2a-6.ucode $(1)/lib/firmware
+-endif
+-ifneq ($(CONFIG_IWL6030_FW),)
+-	$(INSTALL_DATA) $(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/iwlwifi-6000g2b-6.ucode $(1)/lib/firmware
+-endif
+-ifneq ($(CONFIG_IWL7260_FW),)
+-	$(INSTALL_DATA) $(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/iwlwifi-7260-9.ucode $(1)/lib/firmware
+-endif
+-ifneq ($(CONFIG_IWL7265_FW),)
+-	$(INSTALL_DATA) $(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/iwlwifi-7265-9.ucode $(1)/lib/firmware
+-endif
+-ifneq ($(CONFIG_IWL100_FW),)
+-	$(INSTALL_DATA) $(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/iwlwifi-100-5.ucode $(1)/lib/firmware
+-endif
+-ifneq ($(CONFIG_IWL2000_FW),)
+-	$(INSTALL_DATA) $(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/iwlwifi-2000-6.ucode $(1)/lib/firmware
+-endif
+-ifneq ($(CONFIG_IWL2030_FW),)
+-	$(INSTALL_DATA) $(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/iwlwifi-2030-6.ucode $(1)/lib/firmware
+-endif
+-ifneq ($(CONFIG_IWL105_FW),)
+-	$(INSTALL_DATA) $(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/iwlwifi-105-6.ucode $(1)/lib/firmware
+-endif
+-ifneq ($(CONFIG_IWL135_FW),)
+-	$(INSTALL_DATA) $(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/iwlwifi-135-6.ucode $(1)/lib/firmware
+-endif
+-ifneq ($(CONFIG_IWL3160_FW),)
+-	$(INSTALL_DATA) $(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/iwlwifi-3160-9.ucode $(1)/lib/firmware
+-endif
++
++define Build/InstallDev
++	mkdir -p \
++		$(1)/usr/include/mac80211 \
++		$(1)/usr/include/mac80211-backport \
++		$(1)/usr/include/mac80211/ath \
++		$(1)/usr/include/net/mac80211
++	$(CP) $(PKG_BUILD_DIR)/net/mac80211/*.h $(PKG_BUILD_DIR)/include/* $(1)/usr/include/mac80211/
++	$(CP) $(PKG_BUILD_DIR)/backport-include/* $(1)/usr/include/mac80211-backport/
++	$(CP) $(PKG_BUILD_DIR)/net/mac80211/rate.h $(1)/usr/include/net/mac80211/
++	$(CP) $(PKG_BUILD_DIR)/drivers/net/wireless/ath/*.h $(1)/usr/include/mac80211/ath/
++	rm -f $(1)/usr/include/mac80211-backport/linux/module.h
+ endef
+ 
+-define KernelPackage/iwl3945/install
++
++define KernelPackage/ath9k-htc/install
+ 	$(INSTALL_DIR) $(1)/lib/firmware
+-	$(INSTALL_DATA) $(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/iwlwifi-3945-2.ucode $(1)/lib/firmware
++	$(INSTALL_DATA) \
++		$(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/htc_9271.fw \
++		$(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/htc_7010.fw \
++		$(1)/lib/firmware/
+ endef
+ 
+-define KernelPackage/iwl4965/install
+-	$(INSTALL_DIR) $(1)/lib/firmware
+-	$(INSTALL_DATA) $(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/iwlwifi-4965-2.ucode $(1)/lib/firmware
++define KernelPackage/ath10k/install
++	$(INSTALL_DIR) $(1)/lib/firmware/ath10k/QCA988X/hw2.0
++	$(INSTALL_DATA) \
++		$(PKG_BUILD_DIR)/$(PKG_ATH10K_LINUX_FIRMWARE_SUBDIR)/ath10k/QCA988X/hw2.0/board.bin \
++		$(1)/lib/firmware/ath10k/QCA988X/hw2.0/
++	$(INSTALL_DATA) \
++		$(PKG_BUILD_DIR)/$(PKG_ATH10K_LINUX_FIRMWARE_SUBDIR)/10.2.4/untested/firmware-5.bin_10.2.4.70-2 \
++		$(1)/lib/firmware/ath10k/QCA988X/hw2.0/firmware-5.bin
+ endef
+ 
+ define KernelPackage/b43/install
+@@ -2028,13 +1919,237 @@ ifneq ($(CONFIG_BRCMFMAC_PCIE),)
+ endif
+ endef
+ 
++define KernelPackage/carl9170/install
++	$(INSTALL_DIR) $(1)/lib/firmware
++	$(INSTALL_DATA) $(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/carl9170-1.fw $(1)/lib/firmware
++endef
++
++define KernelPackage/cfg80211/install
++	$(INSTALL_DIR) $(1)/lib/wifi $(1)/lib/netifd/wireless
++	$(INSTALL_DATA) ./files/lib/wifi/mac80211.sh $(1)/lib/wifi
++	$(INSTALL_BIN) ./files/lib/netifd/wireless/mac80211.sh $(1)/lib/netifd/wireless
++endef
++
++define KernelPackage/ipw2100/install
++	$(INSTALL_DIR) $(1)/lib/firmware
++	$(INSTALL_DATA) $(PKG_BUILD_DIR)/ipw2100-$(IPW2100_VERSION)*.fw $(1)/lib/firmware
++endef
++
++define KernelPackage/ipw2200/install
++	$(INSTALL_DIR) $(1)/lib/firmware
++	$(INSTALL_DATA) $(PKG_BUILD_DIR)/$(IPW2200_NAME)-$(IPW2200_VERSION)/ipw2200*.fw $(1)/lib/firmware
++endef
++
++define KernelPackage/iwlwifi/install
++	$(INSTALL_DIR) $(1)/lib/firmware
++ifneq ($(CONFIG_IWL100_FW),)
++	$(INSTALL_DATA) $(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/iwlwifi-100-5.ucode $(1)/lib/firmware
++endif
++ifneq ($(CONFIG_IWL1000_FW),)
++	$(INSTALL_DATA) $(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/iwlwifi-1000-5.ucode $(1)/lib/firmware
++endif
++ifneq ($(CONFIG_IWL105_FW),)
++	$(INSTALL_DATA) $(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/iwlwifi-105-6.ucode $(1)/lib/firmware
++endif
++ifneq ($(CONFIG_IWL135_FW),)
++	$(INSTALL_DATA) $(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/iwlwifi-135-6.ucode $(1)/lib/firmware
++endif
++ifneq ($(CONFIG_IWL2000_FW),)
++	$(INSTALL_DATA) $(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/iwlwifi-2000-6.ucode $(1)/lib/firmware
++endif
++ifneq ($(CONFIG_IWL2030_FW),)
++	$(INSTALL_DATA) $(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/iwlwifi-2030-6.ucode $(1)/lib/firmware
++endif
++ifneq ($(CONFIG_IWL3160_FW),)
++	$(INSTALL_DATA) $(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/iwlwifi-3160-13.ucode $(1)/lib/firmware
++endif
++ifneq ($(CONFIG_IWL5000_FW),)
++	$(INSTALL_DATA) $(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/iwlwifi-5000-5.ucode $(1)/lib/firmware
++endif
++ifneq ($(CONFIG_IWL5150_FW),)
++	$(INSTALL_DATA) $(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/iwlwifi-5150-2.ucode $(1)/lib/firmware
++endif
++ifneq ($(CONFIG_IWL6000_FW),)
++	$(INSTALL_DATA) $(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/iwlwifi-6000-4.ucode $(1)/lib/firmware
++endif
++ifneq ($(CONFIG_IWL6005_FW),)
++	$(INSTALL_DATA) $(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/iwlwifi-6000g2a-6.ucode $(1)/lib/firmware
++endif
++ifneq ($(CONFIG_IWL6030_FW),)
++	$(INSTALL_DATA) $(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/iwlwifi-6000g2b-6.ucode $(1)/lib/firmware
++endif
++ifneq ($(CONFIG_IWL6050_FW),)
++	$(INSTALL_DATA) $(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/iwlwifi-6050-5.ucode $(1)/lib/firmware
++endif
++ifneq ($(CONFIG_IWL7260_FW),)
++	$(INSTALL_DATA) $(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/iwlwifi-7260-13.ucode $(1)/lib/firmware
++endif
++ifneq ($(CONFIG_IWL7265_FW),)
++	$(INSTALL_DATA) $(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/iwlwifi-7265-13.ucode $(1)/lib/firmware
++	$(INSTALL_DATA) $(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/iwlwifi-7265D-13.ucode $(1)/lib/firmware
++endif
++ifneq ($(CONFIG_IWL8000_FW),)
++	$(INSTALL_DATA) $(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/iwlwifi-8000C-13.ucode $(1)/lib/firmware
++endif
++endef
++
++define KernelPackage/iwl3945/install
++	$(INSTALL_DIR) $(1)/lib/firmware
++	$(INSTALL_DATA) $(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/iwlwifi-3945-2.ucode $(1)/lib/firmware
++endef
++
++define KernelPackage/iwl4965/install
++	$(INSTALL_DIR) $(1)/lib/firmware
++	$(INSTALL_DATA) $(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/iwlwifi-4965-2.ucode $(1)/lib/firmware
++endef
++
++define KernelPackage/libertas-usb/install
++	$(INSTALL_DIR) $(1)/lib/firmware/libertas
++	$(INSTALL_DATA) \
++		$(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/libertas/usb8388_v9.bin \
++		$(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/libertas/usb8682.bin \
++		$(1)/lib/firmware/libertas/
++endef
++
++define KernelPackage/libertas-sdio/install
++	$(INSTALL_DIR) $(1)/lib/firmware/libertas
++	$(INSTALL_DATA) \
++		$(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/libertas/sd8385_helper.bin \
++		$(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/libertas/sd8385.bin \
++		$(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/libertas/sd8686_v9_helper.bin \
++		$(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/libertas/sd8686_v9.bin \
++		$(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/libertas/sd8688_helper.bin \
++		$(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/libertas/sd8688.bin \
++		$(1)/lib/firmware/libertas
++endef
++
++define KernelPackage/mt7601u/install
++	$(INSTALL_DIR) $(1)/lib/firmware
++	$(INSTALL_DATA) \
++		$(PKG_BUILD_DIR)/$(PKG_MT7601U_FW_NAME)_$(PKG_MT7601U_FW_VERSION)/mcu/bin/MT7601.bin \
++		$(1)/lib/firmware/mt7601u.bin
++endef
++
++define KernelPackage/mwl8k/install
++	$(INSTALL_DIR) $(1)/lib/firmware/mwl8k
++	$(INSTALL_DATA) \
++		$(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/mwl8k/fmimage_8366_ap-3.fw \
++		$(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/mwl8k/fmimage_8366.fw \
++		$(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/mwl8k/helper_8366.fw \
++		$(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/mwl8k/fmimage_8687.fw \
++		$(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/mwl8k/helper_8687.fw \
++		$(1)/lib/firmware/mwl8k/
++endef
++
++define KernelPackage/mwifiex-pcie/install
++	$(INSTALL_DIR) $(1)/lib/firmware/mrvl
++	$(INSTALL_DATA) \
++		$(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/mrvl/pcie8897_uapsta.bin \
++		$(1)/lib/firmware/mrvl/
++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/rt2800-pci/install
++	$(INSTALL_DIR) $(1)/lib/firmware
++	$(INSTALL_DATA) \
++		$(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/rt2860.bin \
++		$(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/rt3290.bin \
++		$(1)/lib/firmware
++endef
++
++define KernelPackage/rt2800-usb/install
++	$(INSTALL_DIR) $(1)/lib/firmware
++	$(INSTALL_DATA) $(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/rt2870.bin $(1)/lib/firmware/
++endef
++
++define KernelPackage/rt61-pci/install
++	$(INSTALL_DIR) $(1)/lib/firmware
++	$(INSTALL_DATA) \
++		$(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/rt2561.bin \
++		$(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/rt2561s.bin \
++		$(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/rt2661.bin \
++		$(1)/lib/firmware/
++endef
++
++define KernelPackage/rt73-usb/install
++	$(INSTALL_DIR) $(1)/lib/firmware
++	$(INSTALL_DATA) $(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/rt73.bin $(1)/lib/firmware/
++endef
++
++define KernelPackage/wl12xx/install
++	$(INSTALL_DIR) $(1)/lib/firmware/ti-connectivity
++	$(INSTALL_DATA) \
++		$(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/ti-connectivity/wl127x-fw-5-mr.bin \
++		$(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/ti-connectivity/wl127x-fw-5-plt.bin \
++		$(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/ti-connectivity/wl127x-fw-5-sr.bin \
++		$(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/ti-connectivity/wl1271-nvs.bin \
++		$(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/ti-connectivity/wl128x-fw-5-mr.bin \
++		$(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/ti-connectivity/wl128x-fw-5-plt.bin \
++		$(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/ti-connectivity/wl128x-fw-5-sr.bin \
++		$(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/ti-connectivity/wl128x-nvs.bin \
++		$(1)/lib/firmware/ti-connectivity
++endef
++
++define KernelPackage/wl18xx/install
++	$(INSTALL_DIR) $(1)/lib/firmware/ti-connectivity
++	$(INSTALL_DATA) \
++		$(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/ti-connectivity/wl18xx-fw-4.bin \
++		$(1)/lib/firmware/ti-connectivity
++endef
++
++define KernelPackage/zd1211rw/install
++	$(INSTALL_DIR) $(1)/lib/firmware/zd1211
++	$(INSTALL_DATA) $(PKG_BUILD_DIR)/$(ZD1211FW_NAME)/zd1211* $(1)/lib/firmware/zd1211
++endef
++
++
+ $(eval $(call KernelPackage,adm8211))
++$(eval $(call KernelPackage,ath))
++$(eval $(call KernelPackage,ath10k))
+ $(eval $(call KernelPackage,ath5k))
++$(eval $(call KernelPackage,ath9k))
++$(eval $(call KernelPackage,ath9k-common))
++$(eval $(call KernelPackage,ath9k-htc))
++$(eval $(call KernelPackage,b43))
++$(eval $(call KernelPackage,b43legacy))
++$(eval $(call KernelPackage,brcmsmac))
++$(eval $(call KernelPackage,brcmfmac))
++$(eval $(call KernelPackage,brcmutil))
++$(eval $(call KernelPackage,carl9170))
++$(eval $(call KernelPackage,cfg80211))
++$(eval $(call KernelPackage,hermes))
++$(eval $(call KernelPackage,hermes-pci))
++$(eval $(call KernelPackage,hermes-plx))
++$(eval $(call KernelPackage,hermes-pcmcia))
++$(eval $(call KernelPackage,iwlwifi))
++$(eval $(call KernelPackage,iwl-legacy))
++$(eval $(call KernelPackage,iwl4965))
++$(eval $(call KernelPackage,iwl3945))
+ $(eval $(call KernelPackage,lib80211))
+ $(eval $(call KernelPackage,libertas-usb))
+ $(eval $(call KernelPackage,libertas-sdio))
+-$(eval $(call KernelPackage,cfg80211))
++$(eval $(call KernelPackage,libipw))
++$(eval $(call KernelPackage,ipw2100))
++$(eval $(call KernelPackage,ipw2200))
+ $(eval $(call KernelPackage,mac80211))
++$(eval $(call KernelPackage,mac80211-hwsim))
++$(eval $(call KernelPackage,mt7601u))
++$(eval $(call KernelPackage,mwl8k))
++$(eval $(call KernelPackage,mwifiex-pcie))
+ $(eval $(call KernelPackage,p54-common))
+ $(eval $(call KernelPackage,p54-pci))
+ $(eval $(call KernelPackage,p54-usb))
+@@ -2047,12 +2162,12 @@ $(eval $(call KernelPackage,rt2800-lib))
+ $(eval $(call KernelPackage,rt2400-pci))
+ $(eval $(call KernelPackage,rt2500-pci))
+ $(eval $(call KernelPackage,rt2500-usb))
+-$(eval $(call KernelPackage,rt61-pci))
+-$(eval $(call KernelPackage,rt73-usb))
+ $(eval $(call KernelPackage,rt2800-mmio))
+ $(eval $(call KernelPackage,rt2800-soc))
+ $(eval $(call KernelPackage,rt2800-pci))
+ $(eval $(call KernelPackage,rt2800-usb))
++$(eval $(call KernelPackage,rt61-pci))
++$(eval $(call KernelPackage,rt73-usb))
+ $(eval $(call KernelPackage,rtl8180))
+ $(eval $(call KernelPackage,rtl8187))
+ $(eval $(call KernelPackage,rtlwifi))
+@@ -2063,32 +2178,7 @@ $(eval $(call KernelPackage,rtl8192ce))
+ $(eval $(call KernelPackage,rtl8192se))
+ $(eval $(call KernelPackage,rtl8192de))
+ $(eval $(call KernelPackage,rtl8192cu))
+-$(eval $(call KernelPackage,zd1211rw))
+-$(eval $(call KernelPackage,mac80211-hwsim))
+-$(eval $(call KernelPackage,ath9k-common))
+-$(eval $(call KernelPackage,ath9k))
+-$(eval $(call KernelPackage,ath9k-htc))
+-$(eval $(call KernelPackage,ath10k))
+-$(eval $(call KernelPackage,ath))
+-$(eval $(call KernelPackage,carl9170))
+-$(eval $(call KernelPackage,b43))
+-$(eval $(call KernelPackage,b43legacy))
+-$(eval $(call KernelPackage,brcmutil))
+-$(eval $(call KernelPackage,brcmsmac))
+-$(eval $(call KernelPackage,brcmfmac))
+-$(eval $(call KernelPackage,net-libipw))
+-$(eval $(call KernelPackage,net-ipw2100))
+-$(eval $(call KernelPackage,net-ipw2200))
+-$(eval $(call KernelPackage,iwlagn))
+-$(eval $(call KernelPackage,iwl-legacy))
+-$(eval $(call KernelPackage,iwl4965))
+-$(eval $(call KernelPackage,iwl3945))
+-$(eval $(call KernelPackage,mwl8k))
+-$(eval $(call KernelPackage,mwifiex-pcie))
+-$(eval $(call KernelPackage,net-hermes))
+-$(eval $(call KernelPackage,net-hermes-pci))
+-$(eval $(call KernelPackage,net-hermes-plx))
+-$(eval $(call KernelPackage,net-hermes-pcmcia))
+ $(eval $(call KernelPackage,wlcore))
+ $(eval $(call KernelPackage,wl12xx))
+ $(eval $(call KernelPackage,wl18xx))
++$(eval $(call KernelPackage,zd1211rw))
+diff --git a/package/kernel/mac80211/files/lib/netifd/wireless/mac80211.sh b/package/kernel/mac80211/files/lib/netifd/wireless/mac80211.sh
+index c9bc3d6..2a8d2f9 100644
+--- a/package/kernel/mac80211/files/lib/netifd/wireless/mac80211.sh
++++ b/package/kernel/mac80211/files/lib/netifd/wireless/mac80211.sh
+@@ -486,7 +486,7 @@ mac80211_prepare_vif() {
+ 		# All interfaces must have unique mac addresses
+ 		# which can either be explicitly set in the device
+ 		# section, or automatically generated
+-		ifconfig "$ifname" hw ether "$macaddr"
++		ip link set dev "$ifname" address "$macaddr"
+ 	fi
+ 
+ 	json_select ..
+@@ -582,7 +582,7 @@ mac80211_setup_vif() {
+ 	json_get_vars mode
+ 	json_get_var vif_txpower txpower
+ 
+-	ifconfig "$ifname" up || {
++	ip link set dev "$ifname" up || {
+ 		wireless_setup_vif_failed IFUP_ERROR
+ 		json_select ..
+ 		return
+@@ -638,7 +638,7 @@ mac80211_interface_cleanup() {
+ 	local phy="$1"
+ 
+ 	for wdev in $(list_phy_interfaces "$phy"); do
+-		ifconfig "$wdev" down 2>/dev/null
++		ip link set dev "$wdev" down 2>/dev/null
+ 		iw dev "$wdev" del
+ 	done
+ }
+diff --git a/package/kernel/mac80211/files/regdb.txt b/package/kernel/mac80211/files/regdb.txt
+index ba95fc6..84413fd 100644
+--- a/package/kernel/mac80211/files/regdb.txt
++++ b/package/kernel/mac80211/files/regdb.txt
+@@ -6,7 +6,7 @@ country 00:
+ 	# Channel 14. Only JP enables this and for 802.11b only
+ 	(2474 - 2494 @ 20), (20), NO-IR, NO-OFDM
+ 	# Channel 36 - 48
+-	(5170 - 5250 @ 80), (20)
++	(5170 - 5250 @ 80), (20), AUTO-BW
+ 	# Channel 52 - 64
+ 	(5250 - 5330 @ 80), (20), NO-IR, DFS, AUTO-BW
+ 	# Channel 100 - 144
+@@ -54,8 +54,8 @@ country AL: DFS-ETSI
+ 
+ country AM: DFS-ETSI
+ 	(2402 - 2482 @ 40), (20)
+-	(5170 - 5250 @ 80), (18)
+-	(5250 - 5330 @ 80), (18), DFS
++	(5170 - 5250 @ 20), (18)
++	(5250 - 5330 @ 20), (18), DFS
+ 
+ country AN: DFS-ETSI
+ 	(2402 - 2482 @ 40), (20)
+@@ -85,7 +85,7 @@ country AT: DFS-ETSI
+ 	# 60 gHz band channels 1-4, ref: Etsi En 302 567
+ 	(57000 - 66000 @ 2160), (40)
+ 
+-country AU:
++country AU: DFS-ETSI
+ 	(2402 - 2482 @ 40), (20)
+ 	(5170 - 5250 @ 80), (17), AUTO-BW
+ 	(5250 - 5330 @ 80), (24), DFS, AUTO-BW
+@@ -141,14 +141,20 @@ country BG: DFS-ETSI
+ 	(5170 - 5250 @ 80), (20), AUTO-BW
+ 	(5250 - 5330 @ 80), (20), DFS, AUTO-BW
+ 	(5490 - 5710 @ 160), (27), DFS
++	# 5 gHz Short Range Devices, ref:
++	# Etsi EN 300 440-1
++	# Etsi EN 300 440-2
++	# http://crc.bg/files/_bg/Spisak_2015.pdf
++	# http://crc.bg/files/_bg/Pravila_2015_resh24.pdf
++	(5725 - 5875 @ 80), (14)
+ 	# 60 gHz band channels 1-4, ref: Etsi En 302 567
+ 	(57000 - 66000 @ 2160), (40)
+ 
+ country BH: DFS-JP
+ 	(2402 - 2482 @ 40), (20)
+-	(5170 - 5250 @ 80), (20)
+-	(5250 - 5330 @ 80), (20), DFS
+-	(5735 - 5835 @ 80), (20)
++	(5170 - 5250 @ 20), (20)
++	(5250 - 5330 @ 20), (20), DFS
++	(5735 - 5835 @ 20), (20)
+ 
+ country BL: DFS-ETSI
+ 	(2402 - 2482 @ 40), (20)
+@@ -263,10 +269,10 @@ country CO: DFS-FCC
+ 
+ country CR: DFS-FCC
+ 	(2402 - 2482 @ 40), (20)
+-	(5170 - 5250 @ 80), (17)
+-	(5250 - 5330 @ 80), (24), DFS
+-	(5490 - 5730 @ 80), (24), DFS
+-	(5735 - 5835 @ 80), (30)
++	(5170 - 5250 @ 20), (17)
++	(5250 - 5330 @ 20), (24), DFS
++	(5490 - 5730 @ 20), (24), DFS
++	(5735 - 5835 @ 20), (30)
+ 
+ country CX: DFS-FCC
+ 	(2402 - 2482 @ 40), (20)
+@@ -349,10 +355,10 @@ country DZ: DFS-JP
+ 
+ country EC: DFS-FCC
+ 	(2402 - 2482 @ 40), (20)
+-	(5170 - 5250 @ 80), (17)
+-	(5250 - 5330 @ 80), (24), DFS
+-	(5490 - 5730 @ 80), (24), DFS
+-	(5735 - 5835 @ 80), (30)
++	(5170 - 5250 @ 20), (17)
++	(5250 - 5330 @ 20), (24), DFS
++	(5490 - 5730 @ 20), (24), DFS
++	(5735 - 5835 @ 20), (30)
+ 
+ country EE: DFS-ETSI
+ 	(2402 - 2482 @ 40), (20)
+@@ -364,8 +370,8 @@ country EE: DFS-ETSI
+ 
+ country EG: DFS-ETSI
+ 	(2402 - 2482 @ 40), (20)
+-	(5170 - 5250 @ 80), (20)
+-	(5250 - 5330 @ 80), (20), DFS
++	(5170 - 5250 @ 40), (20)
++	(5250 - 5330 @ 40), (20), DFS
+ 
+ # Orden IET/787/2013, de 25 de abril, por la que se aprueba
+ # el cuadro nacional de atribución de frecuencias.
+@@ -474,10 +480,10 @@ country GT: DFS-FCC
+ 
+ country GU: DFS-FCC
+ 	(2402 - 2472 @ 40), (30)
+-	(5170 - 5250 @ 80), (17)
+-	(5250 - 5330 @ 80), (24), DFS
+-	(5490 - 5730 @ 80), (24), DFS
+-	(5735 - 5835 @ 80), (30)
++	(5170 - 5250 @ 20), (17)
++	(5250 - 5330 @ 20), (24), DFS
++	(5490 - 5730 @ 20), (24), DFS
++	(5735 - 5835 @ 20), (30)
+ 
+ country GY:
+ 	(2402 - 2482 @ 40), (30)
+@@ -522,8 +528,8 @@ country HU: DFS-ETSI
+ 
+ country ID: DFS-JP
+ 	# ref: http://www.postel.go.id/content/ID/regulasi/standardisasi/kepdir/bwa%205,8%20ghz.pdf
+-	(2402 - 2482 @ 40), (20)
+-	(5735 - 5815 @ 80), (23)
++	(2402 - 2482 @ 20), (20)
++	(5735 - 5815 @ 20), (23)
+ 
+ country IE: DFS-ETSI
+ 	(2402 - 2482 @ 40), (20)
+@@ -584,6 +590,9 @@ country JP: DFS-JP
+ 	(5170 - 5250 @ 80), (20), AUTO-BW
+ 	(5250 - 5330 @ 80), (20), DFS, AUTO-BW
+ 	(5490 - 5710 @ 160), (23), DFS
++	# 60 GHz band channels 2-4 at 10mW,
++	# ref: http://www.arib.or.jp/english/html/overview/doc/1-STD-T74v1_1.pdf
++	(59000 - 66000 @ 2160), (10 mW)
+ 
+ country KE: DFS-JP
+ 	(2402 - 2482 @ 40), (20)
+@@ -607,11 +616,11 @@ country KN: DFS-ETSI
+ 	(5735 - 5815 @ 80), (30)
+ 
+ country KP: DFS-JP
+-	(2402 - 2482 @ 40), (20)
+-	(5170 - 5250 @ 80), (20), AUTO-BW
+-	(5250 - 5330 @ 80), (20), DFS, AUTO-BW
+-	(5490 - 5630 @ 80), (30), DFS
+-	(5735 - 5815 @ 80), (30)
++	(2402 - 2482 @ 20), (20)
++	(5170 - 5250 @ 20), (20)
++	(5250 - 5330 @ 20), (20), DFS
++	(5490 - 5630 @ 20), (30), DFS
++	(5735 - 5815 @ 20), (30)
+ 
+ country KR: DFS-JP
+ 	(2402 - 2482 @ 40), (20)
+@@ -659,10 +668,10 @@ country LI: DFS-ETSI
+ 
+ country LK: DFS-FCC
+ 	(2402 - 2482 @ 40), (20)
+-	(5170 - 5250 @ 80), (17)
+-	(5250 - 5330 @ 80), (24), DFS
+-	(5490 - 5730 @ 80), (24), DFS
+-	(5735 - 5835 @ 80), (30)
++	(5170 - 5250 @ 20), (17)
++	(5250 - 5330 @ 20), (24), DFS
++	(5490 - 5730 @ 20), (24), DFS
++	(5735 - 5835 @ 20), (30)
+ 
+ # Source:
+ # http://lca.org.ls/images/documents/lesotho_national_frequency_allocation_plan.pdf
+@@ -751,11 +760,12 @@ country MN: DFS-FCC
+ 	(5490 - 5730 @ 160), (24), DFS
+ 	(5735 - 5835 @ 80), (30)
+ 
+-country MO:
+-	(2402 - 2482 @ 40), (20)
+-	(5170 - 5250 @ 40), (23)
+-	(5250 - 5330 @ 40), (23), DFS
+-	(5735 - 5835 @ 40), (30)
++country MO: DFS-FCC
++	(2402 - 2482 @ 40), (23)
++	(5170 - 5250 @ 80), (23), AUTO-BW
++	(5250 - 5330 @ 80), (23), DFS, AUTO-BW
++	(5490 - 5730 @ 160), (30), DFS
++	(5735 - 5835 @ 80), (30)
+ 
+ country MP: DFS-FCC
+ 	(2402 - 2472 @ 40), (30)
+@@ -793,6 +803,14 @@ country MU: DFS-FCC
+ 	(5490 - 5730 @ 160), (24), DFS
+ 	(5735 - 5835 @ 80), (30)
+ 
++# Source:
++# http://www.cam.gov.mv/docs/tech_standards/TAM-TS-100-2004-WLAN.pdf
++country MV: DFS-ETSI
++	(2400 - 2483.5 @ 40), (100 mW)
++	(5150 - 5250 @ 80), (200 mW), AUTO-BW
++	(5250 - 5350 @ 80), (100 mW), DFS, AUTO-BW
++	(5725 - 5850 @ 80), (100 mW)
++
+ country MW: DFS-ETSI
+ 	(2402 - 2482 @ 40), (20)
+ 	(5170 - 5250 @ 80), (20), AUTO-BW
+@@ -812,6 +830,11 @@ country MY: DFS-FCC
+ 	(5250 - 5330 @ 80), (23), DFS, AUTO-BW
+ 	(5735 - 5835 @ 80), (30)
+ 
++country NG: DFS-ETSI
++	(2402 - 2482 @ 40), (20)
++	(5250 - 5330 @ 80), (30), DFS
++	(5735 - 5835 @ 80), (30)
++
+ country NI: DFS-FCC
+ 	(2402 - 2472 @ 40), (30)
+ 	(5170 - 5250 @ 80), (24), AUTO-BW
+@@ -848,7 +871,7 @@ country NP: DFS-JP
+ 	(5250 - 5330 @ 80), (20), DFS, AUTO-BW
+ 	(5735 - 5835 @ 80), (20)
+ 
+-country NZ: DFS-FCC
++country NZ: DFS-ETSI
+ 	(2402 - 2482 @ 40), (30)
+ 	(5170 - 5250 @ 80), (17), AUTO-BW
+ 	(5250 - 5330 @ 80), (24), DFS, AUTO-BW
+@@ -971,10 +994,12 @@ country RS: DFS-ETSI
+ 
+ country RU: DFS-ETSI
+ 	(2402 - 2482 @ 40), (20)
+-	(5170 - 5250 @ 80), (20)
+-	(5250 - 5330 @ 80), (20), DFS
+-	(5650 - 5730 @ 80), (30), DFS
+-	(5735 - 5835 @ 80), (30)
++	(5170 - 5250 @ 40), (20)
++	(5250 - 5330 @ 40), (20), DFS
++	(5650 - 5730 @ 40), (30), DFS
++	(5735 - 5835 @ 40), (30)
++	# 60 GHz band channels 1-4, ref: Changes to NLA 124_Order №129_22042015.pdf
++	(57000 - 66000 @ 2160), (40)
+ 
+ country RW: DFS-FCC
+ 	(2402 - 2482 @ 40), (20)
+@@ -1037,9 +1062,9 @@ country SR: DFS-ETSI
+ 
+ country SV: DFS-FCC
+ 	(2402 - 2482 @ 40), (20)
+-	(5170 - 5250 @ 80), (17)
+-	(5250 - 5330 @ 80), (23), DFS
+-	(5735 - 5835 @ 80), (30)
++	(5170 - 5250 @ 20), (17)
++	(5250 - 5330 @ 20), (23), DFS
++	(5735 - 5835 @ 20), (30)
+ 
+ country SY:
+ 	(2402 - 2482 @ 40), (20)
+@@ -1099,6 +1124,10 @@ country TW: DFS-JP
+ 	(5650 - 5710 @ 40), (30), DFS
+ 	(5735 - 5835 @ 80), (30)
+  
++country TZ:
++	(2402 - 2482 @ 40), (20)
++	(5735 - 5835 @ 80), (30)
++
+ # Source:
+ # #914 / 06 Sep 2007: http://www.ucrf.gov.ua/uk/doc/nkrz/1196068874
+ # #1174 / 23 Oct 2008: http://www.nkrz.gov.ua/uk/activities/ruling/1225269361
+@@ -1125,6 +1154,7 @@ country US: DFS-FCC
+ 	(2402 - 2472 @ 40), (30)
+ 	(5170 - 5250 @ 80), (17), AUTO-BW
+ 	(5250 - 5330 @ 80), (23), DFS, AUTO-BW
++	(5490 - 5730 @ 160), (23), DFS
+ 	(5735 - 5835 @ 80), (30)
+ 	# 60g band
+ 	# reference: http://cfr.regstoday.com/47cfr15.aspx#47_CFR_15p255
+@@ -1192,6 +1222,12 @@ country WF: DFS-ETSI
+ 	(5250 - 5330 @ 80), (20), DFS, AUTO-BW
+ 	(5490 - 5710 @ 160), (27), DFS
+ 
++country WS: DFS-ETSI
++	(2402 - 2482 @ 40), (20)
++	(5170 - 5250 @ 40), (20)
++	(5250 - 5330 @ 40), (20), DFS
++	(5490 - 5710 @ 40), (27), DFS
++
+ country YE:
+ 	(2402 - 2482 @ 40), (20)
+ 
+diff --git a/package/kernel/mac80211/patches/001-fix_build.patch b/package/kernel/mac80211/patches/001-fix_build.patch
+index 818983e..402649d 100644
+--- a/package/kernel/mac80211/patches/001-fix_build.patch
++++ b/package/kernel/mac80211/patches/001-fix_build.patch
+@@ -27,7 +27,7 @@
+  	@set -e ; test -f .local-symbols || (						\
+  	echo "/--------------"								;\
+  	echo "| You shouldn't run make in the backports tree, but only in"		;\
+-@@ -60,56 +62,60 @@ mrproper:
++@@ -60,57 +62,61 @@ mrproper:
+  	echo "| (that isn't currently running.)"					;\
+  	echo "\\--"									;\
+  	false)
+@@ -56,11 +56,12 @@
+ -			done								\
+ -		) > Kconfig.kernel							;\
+ -		kver=$$($(MAKE) --no-print-directory -C $(KLIB_BUILD) kernelversion |	\
+--			sed 's/^\(\(3\|2\.6\)\.[0-9]\+\).*/\1/;t;d')			;\
++-			sed 's/^\(\([3-4]\|2\.6\)\.[0-9]\+\).*/\1/;t;d')		;\
+ -		test "$$kver" != "" || echo "Kernel version parse failed!"		;\
+ -		test "$$kver" != ""							;\
+ -		kvers="$$(seq 14 39 | sed 's/^/2.6./')"					;\
+--		kvers="$$kvers $$(seq 0 99 | sed 's/^/3./')"				;\
++-		kvers="$$kvers $$(seq 0 19 | sed 's/^/3./')"				;\
++-		kvers="$$kvers $$(seq 0 99 | sed 's/^/4./')"				;\
+ -		print=0									;\
+ -		for v in $$kvers ; do							\
+ -			if [ "$$print" = "1" ] ; then					\
+@@ -111,11 +112,12 @@
+ +
+ +Kconfig.versions: Kconfig.kernel
+ +	@kver=$$($(MAKE) --no-print-directory -C $(KLIB_BUILD) kernelversion |	\
+-+		sed 's/^\(\(3\|2\.6\)\.[0-9]\+\).*/\1/;t;d')			;\
+++		sed 's/^\(\([3-4]\|2\.6\)\.[0-9]\+\).*/\1/;t;d')		;\
+ +	test "$$kver" != "" || echo "Kernel version parse failed!"		;\
+ +	test "$$kver" != ""							;\
+ +	kvers="$$(seq 14 39 | sed 's/^/2.6./')"					;\
+-+	kvers="$$kvers $$(seq 0 99 | sed 's/^/3./')"				;\
+++	kvers="$$kvers $$(seq 0 19 | sed 's/^/3./')"				;\
+++	kvers="$$kvers $$(seq 0 99 | sed 's/^/4./')"				;\
+ +	print=0									;\
+ +	for v in $$kvers ; do							\
+ +		if [ "$$print" = "1" ] ; then					\
+diff --git a/package/kernel/mac80211/patches/004-backports_debugfs_fix.patch b/package/kernel/mac80211/patches/004-backports_debugfs_fix.patch
+deleted file mode 100644
+index d48a723..0000000
+--- a/package/kernel/mac80211/patches/004-backports_debugfs_fix.patch
++++ /dev/null
+@@ -1,10 +0,0 @@
+---- a/backport-include/linux/debugfs.h
+-+++ b/backport-include/linux/debugfs.h
+-@@ -3,6 +3,7 @@
+- #include_next <linux/debugfs.h>
+- #include <linux/version.h>
+- #include <generated/utsrelease.h>
+-+#include <linux/device.h>
+- 
+- #if defined(CONFIG_DEBUG_FS)
+- struct dentry *debugfs_create_devm_seqfile(struct device *dev, const char *name,
+diff --git a/package/kernel/mac80211/patches/008-fix_netdev_unregister.patch b/package/kernel/mac80211/patches/008-fix_netdev_unregister.patch
+deleted file mode 100644
+index e07f323..0000000
+--- a/package/kernel/mac80211/patches/008-fix_netdev_unregister.patch
++++ /dev/null
+@@ -1,16 +0,0 @@
+---- a/net/mac80211/iface.c
+-+++ b/net/mac80211/iface.c
+-@@ -1858,6 +1858,13 @@ void ieee80211_remove_interfaces(struct
+- 	}
+- 	mutex_unlock(&local->iflist_mtx);
+- 	unregister_netdevice_many(&unreg_list);
+-+#if (!(LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,45) && \
+-+       LINUX_VERSION_CODE < KERNEL_VERSION(3,11,0)) && \
+-+     !(LINUX_VERSION_CODE >= KERNEL_VERSION(3,14,9) && \
+-+       LINUX_VERSION_CODE < KERNEL_VERSION(3,15,0)) && \
+-+     (LINUX_VERSION_CODE < KERNEL_VERSION(3,16,0)))
+-+	list_del(&unreg_list);
+-+#endif
+- 
+- 	list_for_each_entry_safe(sdata, tmp, &wdev_list, list) {
+- 		list_del(&sdata->list);
+diff --git a/package/kernel/mac80211/patches/020-add_mpls_h.patch b/package/kernel/mac80211/patches/020-add_mpls_h.patch
+deleted file mode 100644
+index e5310bc..0000000
+--- a/package/kernel/mac80211/patches/020-add_mpls_h.patch
++++ /dev/null
+@@ -1,37 +0,0 @@
+---- /dev/null
+-+++ b/include/uapi/linux/mpls.h
+-@@ -0,0 +1,34 @@
+-+#ifndef _UAPI_MPLS_H
+-+#define _UAPI_MPLS_H
+-+
+-+#include <linux/types.h>
+-+#include <asm/byteorder.h>
+-+
+-+/* Reference: RFC 5462, RFC 3032
+-+ *
+-+ *  0                   1                   2                   3
+-+ *  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+-+ * |                Label                  | TC  |S|       TTL     |
+-+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+-+ *
+-+ *	Label:  Label Value, 20 bits
+-+ *	TC:     Traffic Class field, 3 bits
+-+ *	S:      Bottom of Stack, 1 bit
+-+ *	TTL:    Time to Live, 8 bits
+-+ */
+-+
+-+struct mpls_label {
+-+	__be32 entry;
+-+};
+-+
+-+#define MPLS_LS_LABEL_MASK      0xFFFFF000
+-+#define MPLS_LS_LABEL_SHIFT     12
+-+#define MPLS_LS_TC_MASK         0x00000E00
+-+#define MPLS_LS_TC_SHIFT        9
+-+#define MPLS_LS_S_MASK          0x00000100
+-+#define MPLS_LS_S_SHIFT         8
+-+#define MPLS_LS_TTL_MASK        0x000000FF
+-+#define MPLS_LS_TTL_SHIFT       0
+-+
+-+#endif /* _UAPI_MPLS_H */
+diff --git a/package/kernel/mac80211/patches/020-backports-do-not-add-debugfs_create_devm_seqfile-on-.patch b/package/kernel/mac80211/patches/020-backports-do-not-add-debugfs_create_devm_seqfile-on-.patch
+new file mode 100644
+index 0000000..97f678c
+--- /dev/null
++++ b/package/kernel/mac80211/patches/020-backports-do-not-add-debugfs_create_devm_seqfile-on-.patch
+@@ -0,0 +1,33 @@
++From e15e9231e7a9f81f5264d294fd3fd96a20d92516 Mon Sep 17 00:00:00 2001
++From: Hauke Mehrtens <hauke@hauke-m.de>
++Date: Sat, 25 Jul 2015 15:19:17 +0200
++Subject: [PATCH 3/3] backports: do not add debugfs_create_devm_seqfile() on
++ recent kernel versions
++
++An #ifdef for the kernel version was missing around the header of
++debugfs_create_devm_seqfile() and the LINUX_BACKPORT() was also not
++done.
++
++Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
++---
++ backport/backport-include/linux/debugfs.h | 3 +++
++ 1 file changed, 3 insertions(+)
++
++--- a/backport-include/linux/debugfs.h
+++++ b/backport-include/linux/debugfs.h
++@@ -5,6 +5,8 @@
++ #include <linux/device.h>
++ #include <generated/utsrelease.h>
++ 
+++#if LINUX_VERSION_CODE < KERNEL_VERSION(3,19,0)
+++#define debugfs_create_devm_seqfile LINUX_BACKPORT(debugfs_create_devm_seqfile)
++ #if defined(CONFIG_DEBUG_FS)
++ struct dentry *debugfs_create_devm_seqfile(struct device *dev, const char *name,
++ 					   struct dentry *parent,
++@@ -20,5 +22,6 @@ static inline struct dentry *debugfs_cre
++ 	return ERR_PTR(-ENODEV);
++ }
++ #endif /* CONFIG_DEBUG_FS */
+++#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(3,19,0) */
++ 
++ #endif /* __BACKPORT_DEBUGFS_H_ */
+diff --git a/package/kernel/mac80211/patches/045-bcma-from-4.1.patch b/package/kernel/mac80211/patches/045-bcma-from-4.1.patch
+deleted file mode 100644
+index dce217f..0000000
+--- a/package/kernel/mac80211/patches/045-bcma-from-4.1.patch
++++ /dev/null
+@@ -1,104 +0,0 @@
+---- a/drivers/bcma/driver_pci.c
+-+++ b/drivers/bcma/driver_pci.c
+-@@ -282,39 +282,6 @@ void bcma_core_pci_power_save(struct bcm
+- }
+- EXPORT_SYMBOL_GPL(bcma_core_pci_power_save);
+- 
+--int bcma_core_pci_irq_ctl(struct bcma_bus *bus, struct bcma_device *core,
+--			  bool enable)
+--{
+--	struct pci_dev *pdev;
+--	u32 coremask, tmp;
+--	int err = 0;
+--
+--	if (bus->hosttype != BCMA_HOSTTYPE_PCI) {
+--		/* This bcma device is not on a PCI host-bus. So the IRQs are
+--		 * not routed through the PCI core.
+--		 * So we must not enable routing through the PCI core. */
+--		goto out;
+--	}
+--
+--	pdev = bus->host_pci;
+--
+--	err = pci_read_config_dword(pdev, BCMA_PCI_IRQMASK, &tmp);
+--	if (err)
+--		goto out;
+--
+--	coremask = BIT(core->core_index) << 8;
+--	if (enable)
+--		tmp |= coremask;
+--	else
+--		tmp &= ~coremask;
+--
+--	err = pci_write_config_dword(pdev, BCMA_PCI_IRQMASK, tmp);
+--
+--out:
+--	return err;
+--}
+--EXPORT_SYMBOL_GPL(bcma_core_pci_irq_ctl);
+--
+- static void bcma_core_pci_extend_L1timer(struct bcma_drv_pci *pc, bool extend)
+- {
+- 	u32 w;
+---- a/drivers/bcma/host_pci.c
+-+++ b/drivers/bcma/host_pci.c
+-@@ -351,3 +351,37 @@ void bcma_host_pci_down(struct bcma_bus
+- 		bcma_core_pci_down(&bus->drv_pci[0]);
+- }
+- EXPORT_SYMBOL_GPL(bcma_host_pci_down);
+-+
+-+/* See also si_pci_setup */
+-+int bcma_host_pci_irq_ctl(struct bcma_bus *bus, struct bcma_device *core,
+-+			  bool enable)
+-+{
+-+	struct pci_dev *pdev;
+-+	u32 coremask, tmp;
+-+	int err = 0;
+-+
+-+	if (bus->hosttype != BCMA_HOSTTYPE_PCI) {
+-+		/* This bcma device is not on a PCI host-bus. So the IRQs are
+-+		 * not routed through the PCI core.
+-+		 * So we must not enable routing through the PCI core. */
+-+		goto out;
+-+	}
+-+
+-+	pdev = bus->host_pci;
+-+
+-+	err = pci_read_config_dword(pdev, BCMA_PCI_IRQMASK, &tmp);
+-+	if (err)
+-+		goto out;
+-+
+-+	coremask = BIT(core->core_index) << 8;
+-+	if (enable)
+-+		tmp |= coremask;
+-+	else
+-+		tmp &= ~coremask;
+-+
+-+	err = pci_write_config_dword(pdev, BCMA_PCI_IRQMASK, tmp);
+-+
+-+out:
+-+	return err;
+-+}
+-+EXPORT_SYMBOL_GPL(bcma_host_pci_irq_ctl);
+---- a/drivers/net/wireless/b43/main.c
+-+++ b/drivers/net/wireless/b43/main.c
+-@@ -4866,7 +4866,7 @@ static int b43_wireless_core_init(struct
+- 	switch (dev->dev->bus_type) {
+- #ifdef CPTCFG_B43_BCMA
+- 	case B43_BUS_BCMA:
+--		bcma_core_pci_irq_ctl(dev->dev->bdev->bus,
+-+		bcma_host_pci_irq_ctl(dev->dev->bdev->bus,
+- 				      dev->dev->bdev, true);
+- 		bcma_host_pci_up(dev->dev->bdev->bus);
+- 		break;
+---- a/drivers/net/wireless/brcm80211/brcmsmac/main.c
+-+++ b/drivers/net/wireless/brcm80211/brcmsmac/main.c
+-@@ -4959,7 +4959,7 @@ static int brcms_b_up_prep(struct brcms_
+- 	 * Configure pci/pcmcia here instead of in brcms_c_attach()
+- 	 * to allow mfg hotswap:  down, hotswap (chip power cycle), up.
+- 	 */
+--	bcma_core_pci_irq_ctl(wlc_hw->d11core->bus, wlc_hw->d11core,
+-+	bcma_host_pci_irq_ctl(wlc_hw->d11core->bus, wlc_hw->d11core,
+- 			      true);
+- 
+- 	/*
+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 d307949..4fbab23 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 @@
+ --- a/.local-symbols
+ +++ b/.local-symbols
+-@@ -344,40 +344,3 @@ USB_CDC_PHONET=
++@@ -449,43 +449,6 @@ USB_CDC_PHONET=
+  USB_IPHETH=
+  USB_SIERRA_NET=
+  USB_VL600=
+@@ -32,26 +32,18 @@
+ -BCMA_BLOCKIO=
+ -BCMA_HOST_PCI_POSSIBLE=
+ -BCMA_HOST_PCI=
+--BCMA_DRIVER_PCI_HOSTMODE=
+ -BCMA_HOST_SOC=
+ -BCMA_DRIVER_PCI=
++-BCMA_DRIVER_PCI_HOSTMODE=
+ -BCMA_DRIVER_MIPS=
+ -BCMA_SFLASH=
+ -BCMA_NFLASH=
+ -BCMA_DRIVER_GMAC_CMN=
+ -BCMA_DRIVER_GPIO=
+ -BCMA_DEBUG=
+---- a/Makefile.kernel
+-+++ b/Makefile.kernel
+-@@ -38,8 +38,6 @@ obj-$(CPTCFG_MAC80211) += net/mac80211/
+- obj-$(CPTCFG_WLAN) += drivers/net/wireless/
+- #obj-$(CPTCFG_BT) += net/bluetooth/
+- #obj-$(CPTCFG_BT) += drivers/bluetooth/
+--obj-$(CPTCFG_SSB) += drivers/ssb/
+--obj-$(CPTCFG_BCMA) += drivers/bcma/
+- #obj-$(CPTCFG_ETHERNET) += drivers/net/ethernet/
+- obj-$(CPTCFG_USB_NET_RNDIS_WLAN) += drivers/net/usb/
+- #obj-$(CPTCFG_NFC) += net/nfc/
++ NFC=
++ NFC_DIGITAL=
++ NFC_NCI=
+ --- a/drivers/net/wireless/b43/main.c
+ +++ b/drivers/net/wireless/b43/main.c
+ @@ -2866,7 +2866,7 @@ static struct ssb_device *b43_ssb_gpio_d
+@@ -63,7 +55,7 @@
+  	return (bus->chipco.dev ? bus->chipco.dev : bus->pcicore.dev);
+  #else
+  	return bus->chipco.dev;
+-@@ -4907,7 +4907,7 @@ static int b43_wireless_core_init(struct
++@@ -4903,7 +4903,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. */
+@@ -116,12 +108,23 @@
+ --- a/Kconfig.sources
+ +++ b/Kconfig.sources
+ @@ -9,9 +9,6 @@ source "$BACKPORT_DIR/drivers/net/wirele
+- #source "$BACKPORT_DIR/drivers/net/ethernet/Kconfig"
++ source "$BACKPORT_DIR/drivers/net/ethernet/Kconfig"
+  source "$BACKPORT_DIR/drivers/net/usb/Kconfig"
+  
+ -source "$BACKPORT_DIR/drivers/ssb/Kconfig"
+ -source "$BACKPORT_DIR/drivers/bcma/Kconfig"
+ -
+- #source "$BACKPORT_DIR/net/nfc/Kconfig"
++ source "$BACKPORT_DIR/net/nfc/Kconfig"
+  
+- #source "$BACKPORT_DIR/drivers/media/Kconfig"
++ source "$BACKPORT_DIR/drivers/media/Kconfig"
++--- a/Makefile.kernel
+++++ b/Makefile.kernel
++@@ -38,8 +38,6 @@ obj-$(CPTCFG_MAC80211) += net/mac80211/
++ obj-$(CPTCFG_WLAN) += drivers/net/wireless/
++ obj-$(CPTCFG_BT) += net/bluetooth/
++ obj-$(CPTCFG_BT) += drivers/bluetooth/
++-obj-$(CPTCFG_SSB) += drivers/ssb/
++-obj-$(CPTCFG_BCMA) += drivers/bcma/
++ obj-$(CPTCFG_ETHERNET) += drivers/net/ethernet/
++ obj-$(CPTCFG_USB_NET_RNDIS_WLAN) += drivers/net/usb/
++ obj-$(CPTCFG_NFC) += net/nfc/
+diff --git a/package/kernel/mac80211/patches/090-linux_3_18_12_compat.patch b/package/kernel/mac80211/patches/090-linux_3_18_12_compat.patch
+deleted file mode 100644
+index 85c5280..0000000
+--- a/package/kernel/mac80211/patches/090-linux_3_18_12_compat.patch
++++ /dev/null
+@@ -1,29 +0,0 @@
+---- a/backport-include/linux/wait.h
+-+++ b/backport-include/linux/wait.h
+-@@ -23,7 +23,7 @@ backport_wait_on_bit_io(void *word, int
+- 
+- #endif
+- 
+--#if LINUX_VERSION_CODE < KERNEL_VERSION(3,19,0)
+-+#if LINUX_VERSION_CODE < KERNEL_VERSION(3,18,12)
+- #define WQ_FLAG_WOKEN		0x02
+- 
+- #define wait_woken LINUX_BACKPORT(wait_woken)
+---- a/compat/backport-3.19.c
+-+++ b/compat/backport-3.19.c
+-@@ -15,6 +15,7 @@
+- #include <linux/netdevice.h>
+- #include <linux/debugfs.h>
+- 
+-+#if LINUX_VERSION_CODE < KERNEL_VERSION(3,18,12)
+- static inline bool is_kthread_should_stop(void)
+- {
+- 	return (current->flags & PF_KTHREAD) && kthread_should_stop();
+-@@ -79,6 +80,7 @@ int woken_wake_function(wait_queue_t *wa
+- 	return default_wake_function(wait, mode, sync, key);
+- }
+- EXPORT_SYMBOL(woken_wake_function);
+-+#endif
+- 
+- #ifdef __BACKPORT_NETDEV_RSS_KEY_FILL
+- u8 netdev_rss_key[NETDEV_RSS_KEY_LEN];
+diff --git a/package/kernel/mac80211/patches/100-remove-cryptoapi-dependencies.patch b/package/kernel/mac80211/patches/100-remove-cryptoapi-dependencies.patch
+new file mode 100644
+index 0000000..07dde54
+--- /dev/null
++++ b/package/kernel/mac80211/patches/100-remove-cryptoapi-dependencies.patch
+@@ -0,0 +1,376 @@
++--- a/net/mac80211/Kconfig
+++++ b/net/mac80211/Kconfig
++@@ -5,8 +5,6 @@ config MAC80211
++ 	depends on CRYPTO
++ 	depends on CRYPTO_ARC4
++ 	depends on CRYPTO_AES
++-	select BPAUTO_CRYPTO_CCM
++-	depends on CRYPTO_GCM
++ 	depends on CRC32
++ 	select BPAUTO_AVERAGE
++ 	---help---
++--- a/net/mac80211/Makefile
+++++ b/net/mac80211/Makefile
++@@ -15,9 +15,7 @@ mac80211-y := \
++ 	michael.o \
++ 	tkip.o \
++ 	aes_ccm.o \
++-	aes_gcm.o \
++ 	aes_cmac.o \
++-	aes_gmac.o \
++ 	cfg.o \
++ 	ethtool.o \
++ 	rx.o \
++--- a/net/mac80211/aes_ccm.c
+++++ b/net/mac80211/aes_ccm.c
++@@ -13,89 +13,132 @@
++ #include <linux/types.h>
++ #include <linux/err.h>
++ #include <crypto/aead.h>
+++#include <crypto/aes.h>
++ 
++ #include <net/mac80211.h>
++ #include "key.h"
++ #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);
+++
+++	/* Extra Authenticate-only data (always two AES blocks) */
+++	for (i = 0; i < AES_BLOCK_SIZE; i++)
+++		aad[i] ^= b[i];
+++	crypto_cipher_encrypt_one(tfm, b, aad);
+++
+++	aad += AES_BLOCK_SIZE;
+++
+++	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)
+++{
+++	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;
+++
+++	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);
+++
+++	/* 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;
+++
+++		/* Authentication followed by encryption */
+++		for (i = 0; i < blen; i++)
+++			b[i] ^= pos[i];
+++		crypto_cipher_encrypt_one(tfm, b, b);
+++
+++		b_0[14] = (j >> 8) & 0xff;
+++		b_0[15] = j & 0xff;
+++		crypto_cipher_encrypt_one(tfm, e, b_0);
+++		for (i = 0; i < blen; i++)
+++			*cpos++ = *pos++ ^ e[i];
+++	}
++ 
++-	crypto_aead_encrypt(aead_req);
+++	for (i = 0; i < mic_len; i++)
+++		mic[i] = b[i] ^ s_0[i];
++ }
++ 
++-int ieee80211_aes_ccm_decrypt(struct crypto_aead *tfm, u8 *b_0, u8 *aad,
+++int ieee80211_aes_ccm_decrypt(struct crypto_cipher *tfm, u8 *b_0, u8 *aad,
++ 			      u8 *data, size_t data_len, u8 *mic,
++ 			      size_t mic_len)
++ {
++-	struct scatterlist sg[3];
++-	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;
++-
++-	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];
+++
+++	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);
+++
+++	/* 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;
+++
+++		/* Decryption followed by authentication */
+++		b_0[14] = (j >> 8) & 0xff;
+++		b_0[15] = j & 0xff;
+++		crypto_cipher_encrypt_one(tfm, b, b_0);
+++		for (i = 0; i < blen; i++) {
+++			*pos = *cpos++ ^ b[i];
+++			a[i] ^= *pos++;
+++		}
+++		crypto_cipher_encrypt_one(tfm, a, a);
+++	}
+++
+++	for (i = 0; i < mic_len; i++) {
+++		if ((mic[i] ^ s_0[i]) != a[i])
+++			return -1;
+++	}
++ 
++-	return crypto_aead_decrypt(aead_req);
+++	return 0;
++ }
++ 
++-struct crypto_aead *ieee80211_aes_key_setup_encrypt(const u8 key[],
++-						    size_t key_len,
++-						    size_t mic_len)
+++struct crypto_cipher *ieee80211_aes_key_setup_encrypt(const u8 key[],
+++						      size_t key_len,
+++						      size_t mic_len)
++ {
++-	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;
++-
++-	err = crypto_aead_setkey(tfm, key, key_len);
++-	if (err)
++-		goto free_aead;
++-	err = crypto_aead_setauthsize(tfm, mic_len);
++-	if (err)
++-		goto free_aead;
+++	tfm = crypto_alloc_cipher("aes", 0, CRYPTO_ALG_ASYNC);
+++	if (!IS_ERR(tfm))
+++		crypto_cipher_setkey(tfm, key, key_len);
++ 
++ 	return tfm;
++-
++-free_aead:
++-	crypto_free_aead(tfm);
++-	return ERR_PTR(err);
++ }
++ 
++-void ieee80211_aes_key_free(struct crypto_aead *tfm)
+++
+++void ieee80211_aes_key_free(struct crypto_cipher *tfm)
++ {
++-	crypto_free_aead(tfm);
+++	crypto_free_cipher(tfm);
++ }
++--- a/net/mac80211/aes_ccm.h
+++++ b/net/mac80211/aes_ccm.h
++@@ -12,15 +12,15 @@
++ 
++ #include <linux/crypto.h>
++ 
++-struct crypto_aead *ieee80211_aes_key_setup_encrypt(const u8 key[],
++-						    size_t key_len,
++-						    size_t mic_len);
++-void ieee80211_aes_ccm_encrypt(struct crypto_aead *tfm, u8 *b_0, u8 *aad,
+++struct crypto_cipher *ieee80211_aes_key_setup_encrypt(const u8 key[],
+++						      size_t key_len,
+++						      size_t mic_len);
+++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);
++-int ieee80211_aes_ccm_decrypt(struct crypto_aead *tfm, u8 *b_0, u8 *aad,
+++int ieee80211_aes_ccm_decrypt(struct crypto_cipher *tfm, u8 *b_0, u8 *aad,
++ 			      u8 *data, size_t data_len, u8 *mic,
++ 			      size_t mic_len);
++-void ieee80211_aes_key_free(struct crypto_aead *tfm);
+++void ieee80211_aes_key_free(struct crypto_cipher *tfm);
++ 
++ #endif /* AES_CCM_H */
++--- a/net/mac80211/aes_gcm.h
+++++ b/net/mac80211/aes_gcm.h
++@@ -11,12 +11,28 @@
++ 
++ #include <linux/crypto.h>
++ 
++-void ieee80211_aes_gcm_encrypt(struct crypto_aead *tfm, u8 *j_0, u8 *aad,
++-			       u8 *data, size_t data_len, u8 *mic);
++-int ieee80211_aes_gcm_decrypt(struct crypto_aead *tfm, u8 *j_0, u8 *aad,
++-			      u8 *data, size_t data_len, u8 *mic);
++-struct crypto_aead *ieee80211_aes_gcm_key_setup_encrypt(const u8 key[],
++-							size_t key_len);
++-void ieee80211_aes_gcm_key_free(struct crypto_aead *tfm);
+++static inline void
+++ieee80211_aes_gcm_encrypt(struct crypto_aead *tfm, u8 *j_0, u8 *aad,
+++			  u8 *data, size_t data_len, u8 *mic)
+++{
+++}
+++
+++static inline int
+++ieee80211_aes_gcm_decrypt(struct crypto_aead *tfm, u8 *j_0, u8 *aad,
+++			  u8 *data, size_t data_len, u8 *mic)
+++{
+++    return -EOPNOTSUPP;
+++}
+++
+++static inline struct crypto_aead *
+++ieee80211_aes_gcm_key_setup_encrypt(const u8 key[], size_t key_len)
+++{
+++    return NULL;
+++}
+++
+++static inline void
+++ieee80211_aes_gcm_key_free(struct crypto_aead *tfm)
+++{
+++}
++ 
++ #endif /* AES_GCM_H */
++--- a/net/mac80211/aes_gmac.h
+++++ b/net/mac80211/aes_gmac.h
++@@ -11,10 +11,22 @@
++ 
++ #include <linux/crypto.h>
++ 
++-struct crypto_aead *ieee80211_aes_gmac_key_setup(const u8 key[],
++-						 size_t key_len);
++-int ieee80211_aes_gmac(struct crypto_aead *tfm, const u8 *aad, u8 *nonce,
++-		       const u8 *data, size_t data_len, u8 *mic);
++-void ieee80211_aes_gmac_key_free(struct crypto_aead *tfm);
+++static inline struct crypto_aead *
+++ieee80211_aes_gmac_key_setup(const u8 key[], size_t key_len)
+++{
+++	return NULL;
+++}
+++
+++static inline int
+++ieee80211_aes_gmac(struct crypto_aead *tfm, const u8 *aad, u8 *nonce,
+++		   const u8 *data, size_t data_len, u8 *mic)
+++{
+++	return -EOPNOTSUPP;
+++}
+++
+++static inline void
+++ieee80211_aes_gmac_key_free(struct crypto_aead *tfm)
+++{
+++}
++ 
++ #endif /* AES_GMAC_H */
++--- a/net/mac80211/key.h
+++++ b/net/mac80211/key.h
++@@ -84,7 +84,7 @@ struct ieee80211_key {
++ 			 * Management frames.
++ 			 */
++ 			u8 rx_pn[IEEE80211_NUM_TIDS + 1][IEEE80211_CCMP_PN_LEN];
++-			struct crypto_aead *tfm;
+++			struct crypto_cipher *tfm;
++ 			u32 replays; /* dot11RSNAStatsCCMPReplays */
++ 		} ccmp;
++ 		struct {
++--- a/net/mac80211/wpa.c
+++++ b/net/mac80211/wpa.c
++@@ -304,7 +304,8 @@ ieee80211_crypto_tkip_decrypt(struct iee
++ }
++ 
++ 
++-static void ccmp_special_blocks(struct sk_buff *skb, u8 *pn, u8 *b_0, u8 *aad)
+++static void ccmp_special_blocks(struct sk_buff *skb, u8 *pn, u8 *b_0, u8 *aad,
+++				u16 data_len)
++ {
++ 	__le16 mask_fc;
++ 	int a4_included, mgmt;
++@@ -334,14 +335,8 @@ static void ccmp_special_blocks(struct s
++ 	else
++ 		qos_tid = 0;
++ 
++-	/* In CCM, the initial vectors (IV) used for CTR mode encryption and CBC
++-	 * mode authentication are not allowed to collide, yet both are derived
++-	 * from this vector b_0. We only set L := 1 here to indicate that the
++-	 * data size can be represented in (L+1) bytes. The CCM layer will take
++-	 * care of storing the data length in the top (L+1) bytes and setting
++-	 * and clearing the other bits as is required to derive the two IVs.
++-	 */
++-	b_0[0] = 0x1;
+++	/* First block, b_0 */
+++	b_0[0] = 0x59; /* flags: Adata: 1, M: 011, L: 001 */
++ 
++ 	/* Nonce: Nonce Flags | A2 | PN
++ 	 * Nonce Flags: Priority (b0..b3) | Management (b4) | Reserved (b5..b7)
++@@ -349,6 +344,8 @@ static void ccmp_special_blocks(struct s
++ 	b_0[1] = qos_tid | (mgmt << 4);
++ 	memcpy(&b_0[2], hdr->addr2, ETH_ALEN);
++ 	memcpy(&b_0[8], pn, IEEE80211_CCMP_PN_LEN);
+++	/* l(m) */
+++	put_unaligned_be16(data_len, &b_0[14]);
++ 
++ 	/* AAD (extra authenticate-only data) / masked 802.11 header
++ 	 * FC | A1 | A2 | A3 | SC | [A4] | [QC] */
++@@ -460,7 +457,7 @@ static int ccmp_encrypt_skb(struct ieee8
++ 		return 0;
++ 
++ 	pos += IEEE80211_CCMP_HDR_LEN;
++-	ccmp_special_blocks(skb, pn, b_0, aad);
+++	ccmp_special_blocks(skb, pn, b_0, aad, len);
++ 	ieee80211_aes_ccm_encrypt(key->u.ccmp.tfm, b_0, aad, pos, len,
++ 				  skb_put(skb, mic_len), mic_len);
++ 
++@@ -531,7 +528,7 @@ ieee80211_crypto_ccmp_decrypt(struct iee
++ 			u8 aad[2 * AES_BLOCK_SIZE];
++ 			u8 b_0[AES_BLOCK_SIZE];
++ 			/* hardware didn't decrypt/verify MIC */
++-			ccmp_special_blocks(skb, pn, b_0, aad);
+++			ccmp_special_blocks(skb, pn, b_0, aad, data_len);
++ 
++ 			if (ieee80211_aes_ccm_decrypt(
++ 				    key->u.ccmp.tfm, b_0, aad,
+diff --git a/package/kernel/mac80211/patches/100-revert-cryptoapi-ports.patch b/package/kernel/mac80211/patches/100-revert-cryptoapi-ports.patch
+deleted file mode 100644
+index ceca952..0000000
+--- a/package/kernel/mac80211/patches/100-revert-cryptoapi-ports.patch
++++ /dev/null
+@@ -1,2055 +0,0 @@
+-This patch reverts the following commits from wireless-testing:
+-
+-8ade538bf39b1ee53418528fdacd36b8e65621b9
+-56c52da2d554f081e8fce58ecbcf6a40c605b95b
+-2b2ba0db1c820d04d5143452d70012cd44d7b578
+-00b9cfa3ff38401bd70c34b250ca13e5ea347b4a
+-4f031fa9f188b2b0641ac20087d9e16bcfb4e49d
+-6e1ee5d2e9e411892b5d84e3ea93e3fc88ac786c
+-30ef7ef9672d92ab2cac37f60a31955c118321e7
+-f359d3fe832e49eeec2232b2af5a9e3aee6b4862 (only the changes in aes_cmac.{c,h})
+-7ec7c4a9a686c608315739ab6a2b0527a240883c
+----
+-
+---- a/include/linux/ieee80211.h
+-+++ b/include/linux/ieee80211.h
+-@@ -1017,15 +1017,6 @@ struct ieee80211_mmie {
+- 	u8 mic[8];
+- } __packed;
+- 
+--/* Management MIC information element (IEEE 802.11w) for GMAC and CMAC-256 */
+--struct ieee80211_mmie_16 {
+--	u8 element_id;
+--	u8 length;
+--	__le16 key_id;
+--	u8 sequence_number[6];
+--	u8 mic[16];
+--} __packed;
+--
+- struct ieee80211_vendor_ie {
+- 	u8 element_id;
+- 	u8 len;
+---- a/include/net/mac80211.h
+-+++ b/include/net/mac80211.h
+-@@ -1306,8 +1306,8 @@ struct ieee80211_vif *wdev_to_ieee80211_
+-  * @IEEE80211_KEY_FLAG_PAIRWISE: Set by mac80211, this flag indicates
+-  *	that the key is pairwise rather then a shared key.
+-  * @IEEE80211_KEY_FLAG_SW_MGMT_TX: This flag should be set by the driver for a
+-- *	CCMP/GCMP key if it requires CCMP/GCMP encryption of management frames
+-- *	(MFP) to be done in software.
+-+ *	CCMP key if it requires CCMP encryption of management frames (MFP) to
+-+ *	be done in software.
+-  * @IEEE80211_KEY_FLAG_PUT_IV_SPACE: This flag should be set by the driver
+-  *	if space should be prepared for the IV, but the IV
+-  *	itself should not be generated. Do not set together with
+-@@ -1322,7 +1322,7 @@ struct ieee80211_vif *wdev_to_ieee80211_
+-  *	RX, if your crypto engine can't deal with TX you can also set the
+-  *	%IEEE80211_KEY_FLAG_SW_MGMT_TX flag to encrypt such frames in SW.
+-  * @IEEE80211_KEY_FLAG_GENERATE_IV_MGMT: This flag should be set by the
+-- *	driver for a CCMP/GCMP key to indicate that is requires IV generation
+-+ *	driver for a CCMP key to indicate that is requires IV generation
+-  *	only for managment frames (MFP).
+-  * @IEEE80211_KEY_FLAG_RESERVE_TAILROOM: This flag should be set by the
+-  *	driver for a key to indicate that sufficient tailroom must always
+-@@ -4112,10 +4112,6 @@ void ieee80211_aes_cmac_calculate_k1_k2(
+-  *	reverse order than in packet)
+-  * @aes_cmac: PN data, most significant byte first (big endian,
+-  *	reverse order than in packet)
+-- * @aes_gmac: PN data, most significant byte first (big endian,
+-- *	reverse order than in packet)
+-- * @gcmp: PN data, most significant byte first (big endian,
+-- *	reverse order than in packet)
+-  */
+- struct ieee80211_key_seq {
+- 	union {
+-@@ -4129,12 +4125,6 @@ struct ieee80211_key_seq {
+- 		struct {
+- 			u8 pn[6];
+- 		} aes_cmac;
+--		struct {
+--			u8 pn[6];
+--		} aes_gmac;
+--		struct {
+--			u8 pn[6];
+--		} gcmp;
+- 	};
+- };
+- 
+-@@ -4159,7 +4149,7 @@ void ieee80211_get_key_tx_seq(struct iee
+-  * ieee80211_get_key_rx_seq - get key RX sequence counter
+-  *
+-  * @keyconf: the parameter passed with the set key
+-- * @tid: The TID, or -1 for the management frame value (CCMP/GCMP only);
+-+ * @tid: The TID, or -1 for the management frame value (CCMP only);
+-  *	the value on TID 0 is also used for non-QoS frames. For
+-  *	CMAC, only TID 0 is valid.
+-  * @seq: buffer to receive the sequence data
+-@@ -4195,7 +4185,7 @@ void ieee80211_set_key_tx_seq(struct iee
+-  * ieee80211_set_key_rx_seq - set key RX sequence counter
+-  *
+-  * @keyconf: the parameter passed with the set key
+-- * @tid: The TID, or -1 for the management frame value (CCMP/GCMP only);
+-+ * @tid: The TID, or -1 for the management frame value (CCMP only);
+-  *	the value on TID 0 is also used for non-QoS frames. For
+-  *	CMAC, only TID 0 is valid.
+-  * @seq: new sequence data
+---- a/net/mac80211/Kconfig
+-+++ b/net/mac80211/Kconfig
+-@@ -5,8 +5,6 @@ config MAC80211
+- 	depends on CRYPTO
+- 	depends on CRYPTO_ARC4
+- 	depends on CRYPTO_AES
+--	select BPAUTO_CRYPTO_CCM
+--	depends on CRYPTO_GCM
+- 	depends on CRC32
+- 	select BPAUTO_AVERAGE
+- 	---help---
+---- a/net/mac80211/Makefile
+-+++ b/net/mac80211/Makefile
+-@@ -15,9 +15,7 @@ mac80211-y := \
+- 	michael.o \
+- 	tkip.o \
+- 	aes_ccm.o \
+--	aes_gcm.o \
+- 	aes_cmac.o \
+--	aes_gmac.o \
+- 	cfg.o \
+- 	ethtool.o \
+- 	rx.o \
+---- a/net/mac80211/aes_ccm.c
+-+++ b/net/mac80211/aes_ccm.c
+-@@ -2,8 +2,6 @@
+-  * Copyright 2003-2004, Instant802 Networks, Inc.
+-  * Copyright 2005-2006, Devicescape Software, Inc.
+-  *
+-- * Rewrite: Copyright (C) 2013 Linaro Ltd <ard.biesheuvel@linaro.org>
+-- *
+-  * This program is free software; you can redistribute it and/or modify
+-  * it under the terms of the GNU General Public License version 2 as
+-  * published by the Free Software Foundation.
+-@@ -19,82 +17,134 @@
+- #include "key.h"
+- #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 *scratch, u8 *a)
+-+{
+-+	int i;
+-+	u8 *b_0, *aad, *b, *s_0;
+-+
+-+	b_0 = scratch + 3 * AES_BLOCK_SIZE;
+-+	aad = scratch + 4 * AES_BLOCK_SIZE;
+-+	b = scratch;
+-+	s_0 = scratch + AES_BLOCK_SIZE;
+-+
+-+	crypto_cipher_encrypt_one(tfm, b, b_0);
+-+
+-+	/* Extra Authenticate-only data (always two AES blocks) */
+-+	for (i = 0; i < AES_BLOCK_SIZE; i++)
+-+		aad[i] ^= b[i];
+-+	crypto_cipher_encrypt_one(tfm, b, aad);
+-+
+-+	aad += AES_BLOCK_SIZE;
+-+
+-+	for (i = 0; i < AES_BLOCK_SIZE; i++)
+-+		aad[i] ^= b[i];
+-+	crypto_cipher_encrypt_one(tfm, a, aad);
+-+
+-+	/* Mask out bits from auth-only-b_0 */
+-+	b_0[0] &= 0x07;
+-+
+-+	/* 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);
+-+}
+-+
+-+
+-+void ieee80211_aes_ccm_encrypt(struct crypto_cipher *tfm, u8 *scratch,
+-+			       u8 *data, size_t data_len,
+-+			       u8 *cdata, u8 *mic)
+- {
+--	struct scatterlist assoc, pt, ct[2];
+-+	int i, j, last_len, num_blocks;
+-+	u8 *pos, *cpos, *b, *s_0, *e, *b_0;
+- 
+--	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;
+--
+--	memset(aead_req, 0, sizeof(aead_req_data));
+--
+--	sg_init_one(&pt, data, data_len);
+--	sg_init_one(&assoc, &aad[2], be16_to_cpup((__be16 *)aad));
+--	sg_init_table(ct, 2);
+--	sg_set_buf(&ct[0], data, data_len);
+--	sg_set_buf(&ct[1], mic, mic_len);
+--
+--	aead_request_set_tfm(aead_req, tfm);
+--	aead_request_set_assoc(aead_req, &assoc, assoc.length);
+--	aead_request_set_crypt(aead_req, &pt, ct, data_len, b_0);
+-+	b = scratch;
+-+	s_0 = scratch + AES_BLOCK_SIZE;
+-+	e = scratch + 2 * AES_BLOCK_SIZE;
+-+	b_0 = scratch + 3 * AES_BLOCK_SIZE;
+-+
+-+	num_blocks = DIV_ROUND_UP(data_len, AES_BLOCK_SIZE);
+-+	last_len = data_len % AES_BLOCK_SIZE;
+-+	aes_ccm_prepare(tfm, scratch, b);
+-+
+-+	/* Process payload blocks */
+-+	pos = data;
+-+	cpos = cdata;
+-+	for (j = 1; j <= num_blocks; j++) {
+-+		int blen = (j == num_blocks && last_len) ?
+-+			last_len : AES_BLOCK_SIZE;
+-+
+-+		/* Authentication followed by encryption */
+-+		for (i = 0; i < blen; i++)
+-+			b[i] ^= pos[i];
+-+		crypto_cipher_encrypt_one(tfm, b, b);
+-+
+-+		b_0[14] = (j >> 8) & 0xff;
+-+		b_0[15] = j & 0xff;
+-+		crypto_cipher_encrypt_one(tfm, e, b_0);
+-+		for (i = 0; i < blen; i++)
+-+			*cpos++ = *pos++ ^ e[i];
+-+	}
+- 
+--	crypto_aead_encrypt(aead_req);
+-+	for (i = 0; i < IEEE80211_CCMP_MIC_LEN; i++)
+-+		mic[i] = b[i] ^ s_0[i];
+- }
+- 
+--int ieee80211_aes_ccm_decrypt(struct crypto_aead *tfm, u8 *b_0, u8 *aad,
+--			      u8 *data, size_t data_len, u8 *mic,
+--			      size_t mic_len)
+-+
+-+int ieee80211_aes_ccm_decrypt(struct crypto_cipher *tfm, u8 *scratch,
+-+			      u8 *cdata, size_t data_len, u8 *mic, u8 *data)
+- {
+--	struct scatterlist assoc, pt, ct[2];
+--	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;
+--
+--	if (data_len == 0)
+--		return -EINVAL;
+--
+--	memset(aead_req, 0, sizeof(aead_req_data));
+--
+--	sg_init_one(&pt, data, data_len);
+--	sg_init_one(&assoc, &aad[2], be16_to_cpup((__be16 *)aad));
+--	sg_init_table(ct, 2);
+--	sg_set_buf(&ct[0], data, data_len);
+--	sg_set_buf(&ct[1], mic, mic_len);
+--
+--	aead_request_set_tfm(aead_req, tfm);
+--	aead_request_set_assoc(aead_req, &assoc, assoc.length);
+--	aead_request_set_crypt(aead_req, ct, &pt, data_len + mic_len, b_0);
+-+	int i, j, last_len, num_blocks;
+-+	u8 *pos, *cpos, *b, *s_0, *a, *b_0;
+-+
+-+	b = scratch;
+-+	s_0 = scratch + AES_BLOCK_SIZE;
+-+	a = scratch + 2 * AES_BLOCK_SIZE;
+-+	b_0 = scratch + 3 * AES_BLOCK_SIZE;
+-+
+-+	num_blocks = DIV_ROUND_UP(data_len, AES_BLOCK_SIZE);
+-+	last_len = data_len % AES_BLOCK_SIZE;
+-+	aes_ccm_prepare(tfm, scratch, a);
+-+
+-+	/* Process payload blocks */
+-+	cpos = cdata;
+-+	pos = data;
+-+	for (j = 1; j <= num_blocks; j++) {
+-+		int blen = (j == num_blocks && last_len) ?
+-+			last_len : AES_BLOCK_SIZE;
+-+
+-+		/* Decryption followed by authentication */
+-+		b_0[14] = (j >> 8) & 0xff;
+-+		b_0[15] = j & 0xff;
+-+		crypto_cipher_encrypt_one(tfm, b, b_0);
+-+		for (i = 0; i < blen; i++) {
+-+			*pos = *cpos++ ^ b[i];
+-+			a[i] ^= *pos++;
+-+		}
+-+		crypto_cipher_encrypt_one(tfm, a, a);
+-+	}
+-+
+-+	for (i = 0; i < IEEE80211_CCMP_MIC_LEN; i++) {
+-+		if ((mic[i] ^ s_0[i]) != a[i])
+-+			return -1;
+-+	}
+- 
+--	return crypto_aead_decrypt(aead_req);
+-+	return 0;
+- }
+- 
+--struct crypto_aead *ieee80211_aes_key_setup_encrypt(const u8 key[],
+--						    size_t key_len,
+--						    size_t mic_len)
+-+
+-+struct crypto_cipher *ieee80211_aes_key_setup_encrypt(const u8 key[])
+- {
+--	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;
+--
+--	err = crypto_aead_setkey(tfm, key, key_len);
+--	if (!err)
+--		err = crypto_aead_setauthsize(tfm, mic_len);
+--	if (!err)
+--		return tfm;
+-+	tfm = crypto_alloc_cipher("aes", 0, CRYPTO_ALG_ASYNC);
+-+	if (!IS_ERR(tfm))
+-+		crypto_cipher_setkey(tfm, key, WLAN_KEY_LEN_CCMP);
+- 
+--	crypto_free_aead(tfm);
+--	return ERR_PTR(err);
+-+	return tfm;
+- }
+- 
+--void ieee80211_aes_key_free(struct crypto_aead *tfm)
+-+
+-+void ieee80211_aes_key_free(struct crypto_cipher *tfm)
+- {
+--	crypto_free_aead(tfm);
+-+	crypto_free_cipher(tfm);
+- }
+---- a/net/mac80211/aes_ccm.h
+-+++ b/net/mac80211/aes_ccm.h
+-@@ -12,15 +12,13 @@
+- 
+- #include <linux/crypto.h>
+- 
+--struct crypto_aead *ieee80211_aes_key_setup_encrypt(const u8 key[],
+--						    size_t key_len,
+--						    size_t mic_len);
+--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);
+--int ieee80211_aes_ccm_decrypt(struct crypto_aead *tfm, u8 *b_0, u8 *aad,
+--			      u8 *data, size_t data_len, u8 *mic,
+--			      size_t mic_len);
+--void ieee80211_aes_key_free(struct crypto_aead *tfm);
+-+struct crypto_cipher *ieee80211_aes_key_setup_encrypt(const u8 key[]);
+-+void ieee80211_aes_ccm_encrypt(struct crypto_cipher *tfm, u8 *scratch,
+-+			       u8 *data, size_t data_len,
+-+			       u8 *cdata, u8 *mic);
+-+int ieee80211_aes_ccm_decrypt(struct crypto_cipher *tfm, u8 *scratch,
+-+			      u8 *cdata, size_t data_len,
+-+			      u8 *mic, u8 *data);
+-+void ieee80211_aes_key_free(struct crypto_cipher *tfm);
+- 
+- #endif /* AES_CCM_H */
+---- a/net/mac80211/aes_cmac.c
+-+++ b/net/mac80211/aes_cmac.c
+-@@ -18,8 +18,8 @@
+- #include "key.h"
+- #include "aes_cmac.h"
+- 
+-+#define AES_CMAC_KEY_LEN 16
+- #define CMAC_TLEN 8 /* CMAC TLen = 64 bits (8 octets) */
+--#define CMAC_TLEN_256 16 /* CMAC TLen = 128 bits (16 octets) */
+- #define AAD_LEN 20
+- 
+- 
+-@@ -35,9 +35,9 @@ static void gf_mulx(u8 *pad)
+- 		pad[AES_BLOCK_SIZE - 1] ^= 0x87;
+- }
+- 
+--static void aes_cmac_vector(struct crypto_cipher *tfm, size_t num_elem,
+--			    const u8 *addr[], const size_t *len, u8 *mac,
+--			    size_t mac_len)
+-+
+-+static void aes_128_cmac_vector(struct crypto_cipher *tfm, size_t num_elem,
+-+				const u8 *addr[], const size_t *len, u8 *mac)
+- {
+- 	u8 cbc[AES_BLOCK_SIZE], pad[AES_BLOCK_SIZE];
+- 	const u8 *pos, *end;
+-@@ -88,7 +88,7 @@ static void aes_cmac_vector(struct crypt
+- 	for (i = 0; i < AES_BLOCK_SIZE; i++)
+- 		pad[i] ^= cbc[i];
+- 	crypto_cipher_encrypt_one(tfm, pad, pad);
+--	memcpy(mac, pad, mac_len);
+-+	memcpy(mac, pad, CMAC_TLEN);
+- }
+- 
+- 
+-@@ -107,35 +107,17 @@ void ieee80211_aes_cmac(struct crypto_ci
+- 	addr[2] = zero;
+- 	len[2] = CMAC_TLEN;
+- 
+--	aes_cmac_vector(tfm, 3, addr, len, mic, CMAC_TLEN);
+-+	aes_128_cmac_vector(tfm, 3, addr, len, mic);
+- }
+- 
+--void ieee80211_aes_cmac_256(struct crypto_cipher *tfm, const u8 *aad,
+--			    const u8 *data, size_t data_len, u8 *mic)
+--{
+--	const u8 *addr[3];
+--	size_t len[3];
+--	u8 zero[CMAC_TLEN_256];
+--
+--	memset(zero, 0, CMAC_TLEN_256);
+--	addr[0] = aad;
+--	len[0] = AAD_LEN;
+--	addr[1] = data;
+--	len[1] = data_len - CMAC_TLEN_256;
+--	addr[2] = zero;
+--	len[2] = CMAC_TLEN_256;
+--
+--	aes_cmac_vector(tfm, 3, addr, len, mic, CMAC_TLEN_256);
+--}
+- 
+--struct crypto_cipher *ieee80211_aes_cmac_key_setup(const u8 key[],
+--						   size_t key_len)
+-+struct crypto_cipher * ieee80211_aes_cmac_key_setup(const u8 key[])
+- {
+- 	struct crypto_cipher *tfm;
+- 
+- 	tfm = crypto_alloc_cipher("aes", 0, CRYPTO_ALG_ASYNC);
+- 	if (!IS_ERR(tfm))
+--		crypto_cipher_setkey(tfm, key, key_len);
+-+		crypto_cipher_setkey(tfm, key, AES_CMAC_KEY_LEN);
+- 
+- 	return tfm;
+- }
+---- a/net/mac80211/aes_cmac.h
+-+++ b/net/mac80211/aes_cmac.h
+-@@ -11,12 +11,9 @@
+- 
+- #include <linux/crypto.h>
+- 
+--struct crypto_cipher *ieee80211_aes_cmac_key_setup(const u8 key[],
+--						   size_t key_len);
+-+struct crypto_cipher * ieee80211_aes_cmac_key_setup(const u8 key[]);
+- void ieee80211_aes_cmac(struct crypto_cipher *tfm, const u8 *aad,
+- 			const u8 *data, size_t data_len, u8 *mic);
+--void ieee80211_aes_cmac_256(struct crypto_cipher *tfm, const u8 *aad,
+--			    const u8 *data, size_t data_len, u8 *mic);
+- void ieee80211_aes_cmac_key_free(struct crypto_cipher *tfm);
+- 
+- #endif /* AES_CMAC_H */
+---- a/net/mac80211/aes_gcm.c
+-+++ /dev/null
+-@@ -1,95 +0,0 @@
+--/*
+-- * Copyright 2014-2015, Qualcomm Atheros, Inc.
+-- *
+-- * This program is free software; you can redistribute it and/or modify
+-- * it under the terms of the GNU General Public License version 2 as
+-- * published by the Free Software Foundation.
+-- */
+--
+--#include <linux/kernel.h>
+--#include <linux/types.h>
+--#include <linux/crypto.h>
+--#include <linux/err.h>
+--#include <crypto/aes.h>
+--
+--#include <net/mac80211.h>
+--#include "key.h"
+--#include "aes_gcm.h"
+--
+--void ieee80211_aes_gcm_encrypt(struct crypto_aead *tfm, u8 *j_0, u8 *aad,
+--			       u8 *data, size_t data_len, u8 *mic)
+--{
+--	struct scatterlist assoc, pt, ct[2];
+--
+--	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;
+--
+--	memset(aead_req, 0, sizeof(aead_req_data));
+--
+--	sg_init_one(&pt, data, data_len);
+--	sg_init_one(&assoc, &aad[2], be16_to_cpup((__be16 *)aad));
+--	sg_init_table(ct, 2);
+--	sg_set_buf(&ct[0], data, data_len);
+--	sg_set_buf(&ct[1], mic, IEEE80211_GCMP_MIC_LEN);
+--
+--	aead_request_set_tfm(aead_req, tfm);
+--	aead_request_set_assoc(aead_req, &assoc, assoc.length);
+--	aead_request_set_crypt(aead_req, &pt, ct, data_len, j_0);
+--
+--	crypto_aead_encrypt(aead_req);
+--}
+--
+--int ieee80211_aes_gcm_decrypt(struct crypto_aead *tfm, u8 *j_0, u8 *aad,
+--			      u8 *data, size_t data_len, u8 *mic)
+--{
+--	struct scatterlist assoc, pt, ct[2];
+--	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;
+--
+--	if (data_len == 0)
+--		return -EINVAL;
+--
+--	memset(aead_req, 0, sizeof(aead_req_data));
+--
+--	sg_init_one(&pt, data, data_len);
+--	sg_init_one(&assoc, &aad[2], be16_to_cpup((__be16 *)aad));
+--	sg_init_table(ct, 2);
+--	sg_set_buf(&ct[0], data, data_len);
+--	sg_set_buf(&ct[1], mic, IEEE80211_GCMP_MIC_LEN);
+--
+--	aead_request_set_tfm(aead_req, tfm);
+--	aead_request_set_assoc(aead_req, &assoc, assoc.length);
+--	aead_request_set_crypt(aead_req, ct, &pt,
+--			       data_len + IEEE80211_GCMP_MIC_LEN, j_0);
+--
+--	return crypto_aead_decrypt(aead_req);
+--}
+--
+--struct crypto_aead *ieee80211_aes_gcm_key_setup_encrypt(const u8 key[],
+--							size_t key_len)
+--{
+--	struct crypto_aead *tfm;
+--	int err;
+--
+--	tfm = crypto_alloc_aead("gcm(aes)", 0, CRYPTO_ALG_ASYNC);
+--	if (IS_ERR(tfm))
+--		return tfm;
+--
+--	err = crypto_aead_setkey(tfm, key, key_len);
+--	if (!err)
+--		err = crypto_aead_setauthsize(tfm, IEEE80211_GCMP_MIC_LEN);
+--	if (!err)
+--		return tfm;
+--
+--	crypto_free_aead(tfm);
+--	return ERR_PTR(err);
+--}
+--
+--void ieee80211_aes_gcm_key_free(struct crypto_aead *tfm)
+--{
+--	crypto_free_aead(tfm);
+--}
+---- a/net/mac80211/aes_gcm.h
+-+++ /dev/null
+-@@ -1,22 +0,0 @@
+--/*
+-- * Copyright 2014-2015, Qualcomm Atheros, Inc.
+-- *
+-- * This program is free software; you can redistribute it and/or modify
+-- * it under the terms of the GNU General Public License version 2 as
+-- * published by the Free Software Foundation.
+-- */
+--
+--#ifndef AES_GCM_H
+--#define AES_GCM_H
+--
+--#include <linux/crypto.h>
+--
+--void ieee80211_aes_gcm_encrypt(struct crypto_aead *tfm, u8 *j_0, u8 *aad,
+--			       u8 *data, size_t data_len, u8 *mic);
+--int ieee80211_aes_gcm_decrypt(struct crypto_aead *tfm, u8 *j_0, u8 *aad,
+--			      u8 *data, size_t data_len, u8 *mic);
+--struct crypto_aead *ieee80211_aes_gcm_key_setup_encrypt(const u8 key[],
+--							size_t key_len);
+--void ieee80211_aes_gcm_key_free(struct crypto_aead *tfm);
+--
+--#endif /* AES_GCM_H */
+---- a/net/mac80211/aes_gmac.c
+-+++ /dev/null
+-@@ -1,84 +0,0 @@
+--/*
+-- * AES-GMAC for IEEE 802.11 BIP-GMAC-128 and BIP-GMAC-256
+-- * Copyright 2015, Qualcomm Atheros, Inc.
+-- *
+-- * This program is free software; you can redistribute it and/or modify
+-- * it under the terms of the GNU General Public License version 2 as
+-- * published by the Free Software Foundation.
+-- */
+--
+--#include <linux/kernel.h>
+--#include <linux/types.h>
+--#include <linux/crypto.h>
+--#include <linux/err.h>
+--#include <crypto/aes.h>
+--
+--#include <net/mac80211.h>
+--#include "key.h"
+--#include "aes_gmac.h"
+--
+--#define GMAC_MIC_LEN 16
+--#define GMAC_NONCE_LEN 12
+--#define AAD_LEN 20
+--
+--int ieee80211_aes_gmac(struct crypto_aead *tfm, const u8 *aad, u8 *nonce,
+--		       const u8 *data, size_t data_len, u8 *mic)
+--{
+--	struct scatterlist sg[3], ct[1];
+--	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;
+--	u8 zero[GMAC_MIC_LEN], iv[AES_BLOCK_SIZE];
+--
+--	if (data_len < GMAC_MIC_LEN)
+--		return -EINVAL;
+--
+--	memset(aead_req, 0, sizeof(aead_req_data));
+--
+--	memset(zero, 0, GMAC_MIC_LEN);
+--	sg_init_table(sg, 3);
+--	sg_set_buf(&sg[0], aad, AAD_LEN);
+--	sg_set_buf(&sg[1], data, data_len - GMAC_MIC_LEN);
+--	sg_set_buf(&sg[2], zero, GMAC_MIC_LEN);
+--
+--	memcpy(iv, nonce, GMAC_NONCE_LEN);
+--	memset(iv + GMAC_NONCE_LEN, 0, sizeof(iv) - GMAC_NONCE_LEN);
+--	iv[AES_BLOCK_SIZE - 1] = 0x01;
+--
+--	sg_init_table(ct, 1);
+--	sg_set_buf(&ct[0], mic, GMAC_MIC_LEN);
+--
+--	aead_request_set_tfm(aead_req, tfm);
+--	aead_request_set_assoc(aead_req, sg, AAD_LEN + data_len);
+--	aead_request_set_crypt(aead_req, NULL, ct, 0, iv);
+--
+--	crypto_aead_encrypt(aead_req);
+--
+--	return 0;
+--}
+--
+--struct crypto_aead *ieee80211_aes_gmac_key_setup(const u8 key[],
+--						 size_t key_len)
+--{
+--	struct crypto_aead *tfm;
+--	int err;
+--
+--	tfm = crypto_alloc_aead("gcm(aes)", 0, CRYPTO_ALG_ASYNC);
+--	if (IS_ERR(tfm))
+--		return tfm;
+--
+--	err = crypto_aead_setkey(tfm, key, key_len);
+--	if (!err)
+--		return tfm;
+--	if (!err)
+--		err = crypto_aead_setauthsize(tfm, GMAC_MIC_LEN);
+--
+--	crypto_free_aead(tfm);
+--	return ERR_PTR(err);
+--}
+--
+--void ieee80211_aes_gmac_key_free(struct crypto_aead *tfm)
+--{
+--	crypto_free_aead(tfm);
+--}
+---- a/net/mac80211/aes_gmac.h
+-+++ /dev/null
+-@@ -1,20 +0,0 @@
+--/*
+-- * Copyright 2015, Qualcomm Atheros, Inc.
+-- *
+-- * This program is free software; you can redistribute it and/or modify
+-- * it under the terms of the GNU General Public License version 2 as
+-- * published by the Free Software Foundation.
+-- */
+--
+--#ifndef AES_GMAC_H
+--#define AES_GMAC_H
+--
+--#include <linux/crypto.h>
+--
+--struct crypto_aead *ieee80211_aes_gmac_key_setup(const u8 key[],
+--						 size_t key_len);
+--int ieee80211_aes_gmac(struct crypto_aead *tfm, const u8 *aad, u8 *nonce,
+--		       const u8 *data, size_t data_len, u8 *mic);
+--void ieee80211_aes_gmac_key_free(struct crypto_aead *tfm);
+--
+--#endif /* AES_GMAC_H */
+---- a/net/mac80211/cfg.c
+-+++ b/net/mac80211/cfg.c
+-@@ -162,13 +162,8 @@ static int ieee80211_add_key(struct wiph
+- 			return -EINVAL;
+- 		break;
+- 	case WLAN_CIPHER_SUITE_CCMP:
+--	case WLAN_CIPHER_SUITE_CCMP_256:
+- 	case WLAN_CIPHER_SUITE_AES_CMAC:
+--	case WLAN_CIPHER_SUITE_BIP_CMAC_256:
+--	case WLAN_CIPHER_SUITE_BIP_GMAC_128:
+--	case WLAN_CIPHER_SUITE_BIP_GMAC_256:
+- 	case WLAN_CIPHER_SUITE_GCMP:
+--	case WLAN_CIPHER_SUITE_GCMP_256:
+- 		break;
+- 	default:
+- 		cs = ieee80211_cs_get(local, params->cipher, sdata->vif.type);
+-@@ -353,7 +348,6 @@ static int ieee80211_get_key(struct wiph
+- 		params.seq_len = 6;
+- 		break;
+- 	case WLAN_CIPHER_SUITE_CCMP:
+--	case WLAN_CIPHER_SUITE_CCMP_256:
+- 		pn64 = atomic64_read(&key->u.ccmp.tx_pn);
+- 		seq[0] = pn64;
+- 		seq[1] = pn64 >> 8;
+-@@ -365,35 +359,10 @@ static int ieee80211_get_key(struct wiph
+- 		params.seq_len = 6;
+- 		break;
+- 	case WLAN_CIPHER_SUITE_AES_CMAC:
+--	case WLAN_CIPHER_SUITE_BIP_CMAC_256:
+- 		pn64 = atomic64_read(&key->u.aes_cmac.tx_pn);
+- 		seq[0] = pn64;
+- 		seq[1] = pn64 >> 8;
+- 		seq[2] = pn64 >> 16;
+--		seq[3] = pn64 >> 24;
+--		seq[4] = pn64 >> 32;
+--		seq[5] = pn64 >> 40;
+--		params.seq = seq;
+--		params.seq_len = 6;
+--		break;
+--	case WLAN_CIPHER_SUITE_BIP_GMAC_128:
+--	case WLAN_CIPHER_SUITE_BIP_GMAC_256:
+--		pn64 = atomic64_read(&key->u.aes_gmac.tx_pn);
+--		seq[0] = pn64;
+--		seq[1] = pn64 >> 8;
+--		seq[2] = pn64 >> 16;
+--		seq[3] = pn64 >> 24;
+--		seq[4] = pn64 >> 32;
+--		seq[5] = pn64 >> 40;
+--		params.seq = seq;
+--		params.seq_len = 6;
+--		break;
+--	case WLAN_CIPHER_SUITE_GCMP:
+--	case WLAN_CIPHER_SUITE_GCMP_256:
+--		pn64 = atomic64_read(&key->u.gcmp.tx_pn);
+--		seq[0] = pn64;
+--		seq[1] = pn64 >> 8;
+--		seq[2] = pn64 >> 16;
+- 		seq[3] = pn64 >> 24;
+- 		seq[4] = pn64 >> 32;
+- 		seq[5] = pn64 >> 40;
+---- a/net/mac80211/debugfs_key.c
+-+++ b/net/mac80211/debugfs_key.c
+-@@ -94,33 +94,17 @@ static ssize_t key_tx_spec_read(struct f
+- 				key->u.tkip.tx.iv16);
+- 		break;
+- 	case WLAN_CIPHER_SUITE_CCMP:
+--	case WLAN_CIPHER_SUITE_CCMP_256:
+- 		pn = atomic64_read(&key->u.ccmp.tx_pn);
+- 		len = scnprintf(buf, sizeof(buf), "%02x%02x%02x%02x%02x%02x\n",
+- 				(u8)(pn >> 40), (u8)(pn >> 32), (u8)(pn >> 24),
+- 				(u8)(pn >> 16), (u8)(pn >> 8), (u8)pn);
+- 		break;
+- 	case WLAN_CIPHER_SUITE_AES_CMAC:
+--	case WLAN_CIPHER_SUITE_BIP_CMAC_256:
+- 		pn = atomic64_read(&key->u.aes_cmac.tx_pn);
+- 		len = scnprintf(buf, sizeof(buf), "%02x%02x%02x%02x%02x%02x\n",
+- 				(u8)(pn >> 40), (u8)(pn >> 32), (u8)(pn >> 24),
+- 				(u8)(pn >> 16), (u8)(pn >> 8), (u8)pn);
+- 		break;
+--	case WLAN_CIPHER_SUITE_BIP_GMAC_128:
+--	case WLAN_CIPHER_SUITE_BIP_GMAC_256:
+--		pn = atomic64_read(&key->u.aes_gmac.tx_pn);
+--		len = scnprintf(buf, sizeof(buf), "%02x%02x%02x%02x%02x%02x\n",
+--				(u8)(pn >> 40), (u8)(pn >> 32), (u8)(pn >> 24),
+--				(u8)(pn >> 16), (u8)(pn >> 8), (u8)pn);
+--		break;
+--	case WLAN_CIPHER_SUITE_GCMP:
+--	case WLAN_CIPHER_SUITE_GCMP_256:
+--		pn = atomic64_read(&key->u.gcmp.tx_pn);
+--		len = scnprintf(buf, sizeof(buf), "%02x%02x%02x%02x%02x%02x\n",
+--				(u8)(pn >> 40), (u8)(pn >> 32), (u8)(pn >> 24),
+--				(u8)(pn >> 16), (u8)(pn >> 8), (u8)pn);
+--		break;
+- 	default:
+- 		return 0;
+- 	}
+-@@ -150,7 +134,6 @@ static ssize_t key_rx_spec_read(struct f
+- 		len = p - buf;
+- 		break;
+- 	case WLAN_CIPHER_SUITE_CCMP:
+--	case WLAN_CIPHER_SUITE_CCMP_256:
+- 		for (i = 0; i < IEEE80211_NUM_TIDS + 1; i++) {
+- 			rpn = key->u.ccmp.rx_pn[i];
+- 			p += scnprintf(p, sizeof(buf)+buf-p,
+-@@ -161,7 +144,6 @@ static ssize_t key_rx_spec_read(struct f
+- 		len = p - buf;
+- 		break;
+- 	case WLAN_CIPHER_SUITE_AES_CMAC:
+--	case WLAN_CIPHER_SUITE_BIP_CMAC_256:
+- 		rpn = key->u.aes_cmac.rx_pn;
+- 		p += scnprintf(p, sizeof(buf)+buf-p,
+- 			       "%02x%02x%02x%02x%02x%02x\n",
+-@@ -169,26 +151,6 @@ static ssize_t key_rx_spec_read(struct f
+- 			       rpn[3], rpn[4], rpn[5]);
+- 		len = p - buf;
+- 		break;
+--	case WLAN_CIPHER_SUITE_BIP_GMAC_128:
+--	case WLAN_CIPHER_SUITE_BIP_GMAC_256:
+--		rpn = key->u.aes_gmac.rx_pn;
+--		p += scnprintf(p, sizeof(buf)+buf-p,
+--			       "%02x%02x%02x%02x%02x%02x\n",
+--			       rpn[0], rpn[1], rpn[2],
+--			       rpn[3], rpn[4], rpn[5]);
+--		len = p - buf;
+--		break;
+--	case WLAN_CIPHER_SUITE_GCMP:
+--	case WLAN_CIPHER_SUITE_GCMP_256:
+--		for (i = 0; i < IEEE80211_NUM_TIDS + 1; i++) {
+--			rpn = key->u.gcmp.rx_pn[i];
+--			p += scnprintf(p, sizeof(buf)+buf-p,
+--				       "%02x%02x%02x%02x%02x%02x\n",
+--				       rpn[0], rpn[1], rpn[2],
+--				       rpn[3], rpn[4], rpn[5]);
+--		}
+--		len = p - buf;
+--		break;
+- 	default:
+- 		return 0;
+- 	}
+-@@ -205,23 +167,12 @@ static ssize_t key_replays_read(struct f
+- 
+- 	switch (key->conf.cipher) {
+- 	case WLAN_CIPHER_SUITE_CCMP:
+--	case WLAN_CIPHER_SUITE_CCMP_256:
+- 		len = scnprintf(buf, sizeof(buf), "%u\n", key->u.ccmp.replays);
+- 		break;
+- 	case WLAN_CIPHER_SUITE_AES_CMAC:
+--	case WLAN_CIPHER_SUITE_BIP_CMAC_256:
+- 		len = scnprintf(buf, sizeof(buf), "%u\n",
+- 				key->u.aes_cmac.replays);
+- 		break;
+--	case WLAN_CIPHER_SUITE_BIP_GMAC_128:
+--	case WLAN_CIPHER_SUITE_BIP_GMAC_256:
+--		len = scnprintf(buf, sizeof(buf), "%u\n",
+--				key->u.aes_gmac.replays);
+--		break;
+--	case WLAN_CIPHER_SUITE_GCMP:
+--	case WLAN_CIPHER_SUITE_GCMP_256:
+--		len = scnprintf(buf, sizeof(buf), "%u\n", key->u.gcmp.replays);
+--		break;
+- 	default:
+- 		return 0;
+- 	}
+-@@ -238,15 +189,9 @@ static ssize_t key_icverrors_read(struct
+- 
+- 	switch (key->conf.cipher) {
+- 	case WLAN_CIPHER_SUITE_AES_CMAC:
+--	case WLAN_CIPHER_SUITE_BIP_CMAC_256:
+- 		len = scnprintf(buf, sizeof(buf), "%u\n",
+- 				key->u.aes_cmac.icverrors);
+- 		break;
+--	case WLAN_CIPHER_SUITE_BIP_GMAC_128:
+--	case WLAN_CIPHER_SUITE_BIP_GMAC_256:
+--		len = scnprintf(buf, sizeof(buf), "%u\n",
+--				key->u.aes_gmac.icverrors);
+--		break;
+- 	default:
+- 		return 0;
+- 	}
+---- a/net/mac80211/key.c
+-+++ b/net/mac80211/key.c
+-@@ -24,8 +24,6 @@
+- #include "debugfs_key.h"
+- #include "aes_ccm.h"
+- #include "aes_cmac.h"
+--#include "aes_gmac.h"
+--#include "aes_gcm.h"
+- 
+- 
+- /**
+-@@ -164,13 +162,7 @@ static int ieee80211_key_enable_hw_accel
+- 	case WLAN_CIPHER_SUITE_WEP104:
+- 	case WLAN_CIPHER_SUITE_TKIP:
+- 	case WLAN_CIPHER_SUITE_CCMP:
+--	case WLAN_CIPHER_SUITE_CCMP_256:
+- 	case WLAN_CIPHER_SUITE_AES_CMAC:
+--	case WLAN_CIPHER_SUITE_BIP_CMAC_256:
+--	case WLAN_CIPHER_SUITE_BIP_GMAC_128:
+--	case WLAN_CIPHER_SUITE_BIP_GMAC_256:
+--	case WLAN_CIPHER_SUITE_GCMP:
+--	case WLAN_CIPHER_SUITE_GCMP_256:
+- 		/* all of these we can do in software - if driver can */
+- 		if (ret == 1)
+- 			return 0;
+-@@ -394,26 +386,7 @@ ieee80211_key_alloc(u32 cipher, int idx,
+- 		 * Initialize AES key state here as an optimization so that
+- 		 * it does not need to be initialized for every packet.
+- 		 */
+--		key->u.ccmp.tfm = ieee80211_aes_key_setup_encrypt(
+--			key_data, key_len, IEEE80211_CCMP_MIC_LEN);
+--		if (IS_ERR(key->u.ccmp.tfm)) {
+--			err = PTR_ERR(key->u.ccmp.tfm);
+--			kfree(key);
+--			return ERR_PTR(err);
+--		}
+--		break;
+--	case WLAN_CIPHER_SUITE_CCMP_256:
+--		key->conf.iv_len = IEEE80211_CCMP_256_HDR_LEN;
+--		key->conf.icv_len = IEEE80211_CCMP_256_MIC_LEN;
+--		for (i = 0; seq && i < IEEE80211_NUM_TIDS + 1; i++)
+--			for (j = 0; j < IEEE80211_CCMP_256_PN_LEN; j++)
+--				key->u.ccmp.rx_pn[i][j] =
+--					seq[IEEE80211_CCMP_256_PN_LEN - j - 1];
+--		/* Initialize AES key state here as an optimization so that
+--		 * it does not need to be initialized for every packet.
+--		 */
+--		key->u.ccmp.tfm = ieee80211_aes_key_setup_encrypt(
+--			key_data, key_len, IEEE80211_CCMP_256_MIC_LEN);
+-+		key->u.ccmp.tfm = ieee80211_aes_key_setup_encrypt(key_data);
+- 		if (IS_ERR(key->u.ccmp.tfm)) {
+- 			err = PTR_ERR(key->u.ccmp.tfm);
+- 			kfree(key);
+-@@ -421,12 +394,8 @@ ieee80211_key_alloc(u32 cipher, int idx,
+- 		}
+- 		break;
+- 	case WLAN_CIPHER_SUITE_AES_CMAC:
+--	case WLAN_CIPHER_SUITE_BIP_CMAC_256:
+- 		key->conf.iv_len = 0;
+--		if (cipher == WLAN_CIPHER_SUITE_AES_CMAC)
+--			key->conf.icv_len = sizeof(struct ieee80211_mmie);
+--		else
+--			key->conf.icv_len = sizeof(struct ieee80211_mmie_16);
+-+		key->conf.icv_len = sizeof(struct ieee80211_mmie);
+- 		if (seq)
+- 			for (j = 0; j < IEEE80211_CMAC_PN_LEN; j++)
+- 				key->u.aes_cmac.rx_pn[j] =
+-@@ -436,51 +405,13 @@ ieee80211_key_alloc(u32 cipher, int idx,
+- 		 * it does not need to be initialized for every packet.
+- 		 */
+- 		key->u.aes_cmac.tfm =
+--			ieee80211_aes_cmac_key_setup(key_data, key_len);
+-+			ieee80211_aes_cmac_key_setup(key_data);
+- 		if (IS_ERR(key->u.aes_cmac.tfm)) {
+- 			err = PTR_ERR(key->u.aes_cmac.tfm);
+- 			kfree(key);
+- 			return ERR_PTR(err);
+- 		}
+- 		break;
+--	case WLAN_CIPHER_SUITE_BIP_GMAC_128:
+--	case WLAN_CIPHER_SUITE_BIP_GMAC_256:
+--		key->conf.iv_len = 0;
+--		key->conf.icv_len = sizeof(struct ieee80211_mmie_16);
+--		if (seq)
+--			for (j = 0; j < IEEE80211_GMAC_PN_LEN; j++)
+--				key->u.aes_gmac.rx_pn[j] =
+--					seq[IEEE80211_GMAC_PN_LEN - j - 1];
+--		/* Initialize AES key state here as an optimization so that
+--		 * it does not need to be initialized for every packet.
+--		 */
+--		key->u.aes_gmac.tfm =
+--			ieee80211_aes_gmac_key_setup(key_data, key_len);
+--		if (IS_ERR(key->u.aes_gmac.tfm)) {
+--			err = PTR_ERR(key->u.aes_gmac.tfm);
+--			kfree(key);
+--			return ERR_PTR(err);
+--		}
+--		break;
+--	case WLAN_CIPHER_SUITE_GCMP:
+--	case WLAN_CIPHER_SUITE_GCMP_256:
+--		key->conf.iv_len = IEEE80211_GCMP_HDR_LEN;
+--		key->conf.icv_len = IEEE80211_GCMP_MIC_LEN;
+--		for (i = 0; seq && i < IEEE80211_NUM_TIDS + 1; i++)
+--			for (j = 0; j < IEEE80211_GCMP_PN_LEN; j++)
+--				key->u.gcmp.rx_pn[i][j] =
+--					seq[IEEE80211_GCMP_PN_LEN - j - 1];
+--		/* Initialize AES key state here as an optimization so that
+--		 * it does not need to be initialized for every packet.
+--		 */
+--		key->u.gcmp.tfm = ieee80211_aes_gcm_key_setup_encrypt(key_data,
+--								      key_len);
+--		if (IS_ERR(key->u.gcmp.tfm)) {
+--			err = PTR_ERR(key->u.gcmp.tfm);
+--			kfree(key);
+--			return ERR_PTR(err);
+--		}
+--		break;
+- 	default:
+- 		if (cs) {
+- 			size_t len = (seq_len > MAX_PN_LEN) ?
+-@@ -502,24 +433,10 @@ ieee80211_key_alloc(u32 cipher, int idx,
+- 
+- static void ieee80211_key_free_common(struct ieee80211_key *key)
+- {
+--	switch (key->conf.cipher) {
+--	case WLAN_CIPHER_SUITE_CCMP:
+--	case WLAN_CIPHER_SUITE_CCMP_256:
+-+	if (key->conf.cipher == WLAN_CIPHER_SUITE_CCMP)
+- 		ieee80211_aes_key_free(key->u.ccmp.tfm);
+--		break;
+--	case WLAN_CIPHER_SUITE_AES_CMAC:
+--	case WLAN_CIPHER_SUITE_BIP_CMAC_256:
+-+	if (key->conf.cipher == WLAN_CIPHER_SUITE_AES_CMAC)
+- 		ieee80211_aes_cmac_key_free(key->u.aes_cmac.tfm);
+--		break;
+--	case WLAN_CIPHER_SUITE_BIP_GMAC_128:
+--	case WLAN_CIPHER_SUITE_BIP_GMAC_256:
+--		ieee80211_aes_gmac_key_free(key->u.aes_gmac.tfm);
+--		break;
+--	case WLAN_CIPHER_SUITE_GCMP:
+--	case WLAN_CIPHER_SUITE_GCMP_256:
+--		ieee80211_aes_gcm_key_free(key->u.gcmp.tfm);
+--		break;
+--	}
+- 	kzfree(key);
+- }
+- 
+-@@ -826,7 +743,6 @@ void ieee80211_get_key_tx_seq(struct iee
+- 		seq->tkip.iv16 = key->u.tkip.tx.iv16;
+- 		break;
+- 	case WLAN_CIPHER_SUITE_CCMP:
+--	case WLAN_CIPHER_SUITE_CCMP_256:
+- 		pn64 = atomic64_read(&key->u.ccmp.tx_pn);
+- 		seq->ccmp.pn[5] = pn64;
+- 		seq->ccmp.pn[4] = pn64 >> 8;
+-@@ -836,7 +752,6 @@ void ieee80211_get_key_tx_seq(struct iee
+- 		seq->ccmp.pn[0] = pn64 >> 40;
+- 		break;
+- 	case WLAN_CIPHER_SUITE_AES_CMAC:
+--	case WLAN_CIPHER_SUITE_BIP_CMAC_256:
+- 		pn64 = atomic64_read(&key->u.aes_cmac.tx_pn);
+- 		seq->ccmp.pn[5] = pn64;
+- 		seq->ccmp.pn[4] = pn64 >> 8;
+-@@ -845,26 +760,6 @@ void ieee80211_get_key_tx_seq(struct iee
+- 		seq->ccmp.pn[1] = pn64 >> 32;
+- 		seq->ccmp.pn[0] = pn64 >> 40;
+- 		break;
+--	case WLAN_CIPHER_SUITE_BIP_GMAC_128:
+--	case WLAN_CIPHER_SUITE_BIP_GMAC_256:
+--		pn64 = atomic64_read(&key->u.aes_gmac.tx_pn);
+--		seq->ccmp.pn[5] = pn64;
+--		seq->ccmp.pn[4] = pn64 >> 8;
+--		seq->ccmp.pn[3] = pn64 >> 16;
+--		seq->ccmp.pn[2] = pn64 >> 24;
+--		seq->ccmp.pn[1] = pn64 >> 32;
+--		seq->ccmp.pn[0] = pn64 >> 40;
+--		break;
+--	case WLAN_CIPHER_SUITE_GCMP:
+--	case WLAN_CIPHER_SUITE_GCMP_256:
+--		pn64 = atomic64_read(&key->u.gcmp.tx_pn);
+--		seq->gcmp.pn[5] = pn64;
+--		seq->gcmp.pn[4] = pn64 >> 8;
+--		seq->gcmp.pn[3] = pn64 >> 16;
+--		seq->gcmp.pn[2] = pn64 >> 24;
+--		seq->gcmp.pn[1] = pn64 >> 32;
+--		seq->gcmp.pn[0] = pn64 >> 40;
+--		break;
+- 	default:
+- 		WARN_ON(1);
+- 	}
+-@@ -887,7 +782,6 @@ void ieee80211_get_key_rx_seq(struct iee
+- 		seq->tkip.iv16 = key->u.tkip.rx[tid].iv16;
+- 		break;
+- 	case WLAN_CIPHER_SUITE_CCMP:
+--	case WLAN_CIPHER_SUITE_CCMP_256:
+- 		if (WARN_ON(tid < -1 || tid >= IEEE80211_NUM_TIDS))
+- 			return;
+- 		if (tid < 0)
+-@@ -897,29 +791,11 @@ void ieee80211_get_key_rx_seq(struct iee
+- 		memcpy(seq->ccmp.pn, pn, IEEE80211_CCMP_PN_LEN);
+- 		break;
+- 	case WLAN_CIPHER_SUITE_AES_CMAC:
+--	case WLAN_CIPHER_SUITE_BIP_CMAC_256:
+- 		if (WARN_ON(tid != 0))
+- 			return;
+- 		pn = key->u.aes_cmac.rx_pn;
+- 		memcpy(seq->aes_cmac.pn, pn, IEEE80211_CMAC_PN_LEN);
+- 		break;
+--	case WLAN_CIPHER_SUITE_BIP_GMAC_128:
+--	case WLAN_CIPHER_SUITE_BIP_GMAC_256:
+--		if (WARN_ON(tid != 0))
+--			return;
+--		pn = key->u.aes_gmac.rx_pn;
+--		memcpy(seq->aes_gmac.pn, pn, IEEE80211_GMAC_PN_LEN);
+--		break;
+--	case WLAN_CIPHER_SUITE_GCMP:
+--	case WLAN_CIPHER_SUITE_GCMP_256:
+--		if (WARN_ON(tid < -1 || tid >= IEEE80211_NUM_TIDS))
+--			return;
+--		if (tid < 0)
+--			pn = key->u.gcmp.rx_pn[IEEE80211_NUM_TIDS];
+--		else
+--			pn = key->u.gcmp.rx_pn[tid];
+--		memcpy(seq->gcmp.pn, pn, IEEE80211_GCMP_PN_LEN);
+--		break;
+- 	}
+- }
+- EXPORT_SYMBOL(ieee80211_get_key_rx_seq);
+-@@ -938,7 +814,6 @@ void ieee80211_set_key_tx_seq(struct iee
+- 		key->u.tkip.tx.iv16 = seq->tkip.iv16;
+- 		break;
+- 	case WLAN_CIPHER_SUITE_CCMP:
+--	case WLAN_CIPHER_SUITE_CCMP_256:
+- 		pn64 = (u64)seq->ccmp.pn[5] |
+- 		       ((u64)seq->ccmp.pn[4] << 8) |
+- 		       ((u64)seq->ccmp.pn[3] << 16) |
+-@@ -948,7 +823,6 @@ void ieee80211_set_key_tx_seq(struct iee
+- 		atomic64_set(&key->u.ccmp.tx_pn, pn64);
+- 		break;
+- 	case WLAN_CIPHER_SUITE_AES_CMAC:
+--	case WLAN_CIPHER_SUITE_BIP_CMAC_256:
+- 		pn64 = (u64)seq->aes_cmac.pn[5] |
+- 		       ((u64)seq->aes_cmac.pn[4] << 8) |
+- 		       ((u64)seq->aes_cmac.pn[3] << 16) |
+-@@ -957,26 +831,6 @@ void ieee80211_set_key_tx_seq(struct iee
+- 		       ((u64)seq->aes_cmac.pn[0] << 40);
+- 		atomic64_set(&key->u.aes_cmac.tx_pn, pn64);
+- 		break;
+--	case WLAN_CIPHER_SUITE_BIP_GMAC_128:
+--	case WLAN_CIPHER_SUITE_BIP_GMAC_256:
+--		pn64 = (u64)seq->aes_gmac.pn[5] |
+--		       ((u64)seq->aes_gmac.pn[4] << 8) |
+--		       ((u64)seq->aes_gmac.pn[3] << 16) |
+--		       ((u64)seq->aes_gmac.pn[2] << 24) |
+--		       ((u64)seq->aes_gmac.pn[1] << 32) |
+--		       ((u64)seq->aes_gmac.pn[0] << 40);
+--		atomic64_set(&key->u.aes_gmac.tx_pn, pn64);
+--		break;
+--	case WLAN_CIPHER_SUITE_GCMP:
+--	case WLAN_CIPHER_SUITE_GCMP_256:
+--		pn64 = (u64)seq->gcmp.pn[5] |
+--		       ((u64)seq->gcmp.pn[4] << 8) |
+--		       ((u64)seq->gcmp.pn[3] << 16) |
+--		       ((u64)seq->gcmp.pn[2] << 24) |
+--		       ((u64)seq->gcmp.pn[1] << 32) |
+--		       ((u64)seq->gcmp.pn[0] << 40);
+--		atomic64_set(&key->u.gcmp.tx_pn, pn64);
+--		break;
+- 	default:
+- 		WARN_ON(1);
+- 		break;
+-@@ -1000,7 +854,6 @@ void ieee80211_set_key_rx_seq(struct iee
+- 		key->u.tkip.rx[tid].iv16 = seq->tkip.iv16;
+- 		break;
+- 	case WLAN_CIPHER_SUITE_CCMP:
+--	case WLAN_CIPHER_SUITE_CCMP_256:
+- 		if (WARN_ON(tid < -1 || tid >= IEEE80211_NUM_TIDS))
+- 			return;
+- 		if (tid < 0)
+-@@ -1010,29 +863,11 @@ void ieee80211_set_key_rx_seq(struct iee
+- 		memcpy(pn, seq->ccmp.pn, IEEE80211_CCMP_PN_LEN);
+- 		break;
+- 	case WLAN_CIPHER_SUITE_AES_CMAC:
+--	case WLAN_CIPHER_SUITE_BIP_CMAC_256:
+- 		if (WARN_ON(tid != 0))
+- 			return;
+- 		pn = key->u.aes_cmac.rx_pn;
+- 		memcpy(pn, seq->aes_cmac.pn, IEEE80211_CMAC_PN_LEN);
+- 		break;
+--	case WLAN_CIPHER_SUITE_BIP_GMAC_128:
+--	case WLAN_CIPHER_SUITE_BIP_GMAC_256:
+--		if (WARN_ON(tid != 0))
+--			return;
+--		pn = key->u.aes_gmac.rx_pn;
+--		memcpy(pn, seq->aes_gmac.pn, IEEE80211_GMAC_PN_LEN);
+--		break;
+--	case WLAN_CIPHER_SUITE_GCMP:
+--	case WLAN_CIPHER_SUITE_GCMP_256:
+--		if (WARN_ON(tid < -1 || tid >= IEEE80211_NUM_TIDS))
+--			return;
+--		if (tid < 0)
+--			pn = key->u.gcmp.rx_pn[IEEE80211_NUM_TIDS];
+--		else
+--			pn = key->u.gcmp.rx_pn[tid];
+--		memcpy(pn, seq->gcmp.pn, IEEE80211_GCMP_PN_LEN);
+--		break;
+- 	default:
+- 		WARN_ON(1);
+- 		break;
+---- a/net/mac80211/key.h
+-+++ b/net/mac80211/key.h
+-@@ -84,7 +84,7 @@ struct ieee80211_key {
+- 			 * Management frames.
+- 			 */
+- 			u8 rx_pn[IEEE80211_NUM_TIDS + 1][IEEE80211_CCMP_PN_LEN];
+--			struct crypto_aead *tfm;
+-+			struct crypto_cipher *tfm;
+- 			u32 replays; /* dot11RSNAStatsCCMPReplays */
+- 		} ccmp;
+- 		struct {
+-@@ -95,24 +95,6 @@ struct ieee80211_key {
+- 			u32 icverrors; /* dot11RSNAStatsCMACICVErrors */
+- 		} aes_cmac;
+- 		struct {
+--			atomic64_t tx_pn;
+--			u8 rx_pn[IEEE80211_GMAC_PN_LEN];
+--			struct crypto_aead *tfm;
+--			u32 replays; /* dot11RSNAStatsCMACReplays */
+--			u32 icverrors; /* dot11RSNAStatsCMACICVErrors */
+--		} aes_gmac;
+--		struct {
+--			atomic64_t tx_pn;
+--			/* Last received packet number. The first
+--			 * IEEE80211_NUM_TIDS counters are used with Data
+--			 * frames and the last counter is used with Robust
+--			 * Management frames.
+--			 */
+--			u8 rx_pn[IEEE80211_NUM_TIDS + 1][IEEE80211_GCMP_PN_LEN];
+--			struct crypto_aead *tfm;
+--			u32 replays; /* dot11RSNAStatsGCMPReplays */
+--		} gcmp;
+--		struct {
+- 			/* generic cipher scheme */
+- 			u8 rx_pn[IEEE80211_NUM_TIDS + 1][MAX_PN_LEN];
+- 		} gen;
+---- a/net/mac80211/main.c
+-+++ b/net/mac80211/main.c
+-@@ -666,15 +666,9 @@ static int ieee80211_init_cipher_suites(
+- 		WLAN_CIPHER_SUITE_WEP104,
+- 		WLAN_CIPHER_SUITE_TKIP,
+- 		WLAN_CIPHER_SUITE_CCMP,
+--		WLAN_CIPHER_SUITE_CCMP_256,
+--		WLAN_CIPHER_SUITE_GCMP,
+--		WLAN_CIPHER_SUITE_GCMP_256,
+- 
+- 		/* keep last -- depends on hw flags! */
+--		WLAN_CIPHER_SUITE_AES_CMAC,
+--		WLAN_CIPHER_SUITE_BIP_CMAC_256,
+--		WLAN_CIPHER_SUITE_BIP_GMAC_128,
+--		WLAN_CIPHER_SUITE_BIP_GMAC_256,
+-+		WLAN_CIPHER_SUITE_AES_CMAC
+- 	};
+- 
+- 	if (local->hw.flags & IEEE80211_HW_SW_CRYPTO_CONTROL ||
+-@@ -713,7 +707,7 @@ static int ieee80211_init_cipher_suites(
+- 		local->hw.wiphy->n_cipher_suites = ARRAY_SIZE(cipher_suites);
+- 
+- 		if (!have_mfp)
+--			local->hw.wiphy->n_cipher_suites -= 4;
+-+			local->hw.wiphy->n_cipher_suites--;
+- 
+- 		if (!have_wep) {
+- 			local->hw.wiphy->cipher_suites += 2;
+-@@ -730,42 +724,32 @@ static int ieee80211_init_cipher_suites(
+- 		/* Driver specifies cipher schemes only (but not cipher suites
+- 		 * including the schemes)
+- 		 *
+--		 * We start counting ciphers defined by schemes, TKIP, CCMP,
+--		 * CCMP-256, GCMP, and GCMP-256
+-+		 * We start counting ciphers defined by schemes, TKIP and CCMP
+- 		 */
+--		n_suites = local->hw.n_cipher_schemes + 5;
+-+		n_suites = local->hw.n_cipher_schemes + 2;
+- 
+- 		/* check if we have WEP40 and WEP104 */
+- 		if (have_wep)
+- 			n_suites += 2;
+- 
+--		/* check if we have AES_CMAC, BIP-CMAC-256, BIP-GMAC-128,
+--		 * BIP-GMAC-256
+--		 */
+-+		/* check if we have AES_CMAC */
+- 		if (have_mfp)
+--			n_suites += 4;
+-+			n_suites++;
+- 
+- 		suites = kmalloc(sizeof(u32) * n_suites, GFP_KERNEL);
+- 		if (!suites)
+- 			return -ENOMEM;
+- 
+- 		suites[w++] = WLAN_CIPHER_SUITE_CCMP;
+--		suites[w++] = WLAN_CIPHER_SUITE_CCMP_256;
+- 		suites[w++] = WLAN_CIPHER_SUITE_TKIP;
+--		suites[w++] = WLAN_CIPHER_SUITE_GCMP;
+--		suites[w++] = WLAN_CIPHER_SUITE_GCMP_256;
+- 
+- 		if (have_wep) {
+- 			suites[w++] = WLAN_CIPHER_SUITE_WEP40;
+- 			suites[w++] = WLAN_CIPHER_SUITE_WEP104;
+- 		}
+- 
+--		if (have_mfp) {
+-+		if (have_mfp)
+- 			suites[w++] = WLAN_CIPHER_SUITE_AES_CMAC;
+--			suites[w++] = WLAN_CIPHER_SUITE_BIP_CMAC_256;
+--			suites[w++] = WLAN_CIPHER_SUITE_BIP_GMAC_128;
+--			suites[w++] = WLAN_CIPHER_SUITE_BIP_GMAC_256;
+--		}
+- 
+- 		for (r = 0; r < local->hw.n_cipher_schemes; r++)
+- 			suites[w++] = cs[r].cipher;
+---- a/net/mac80211/rx.c
+-+++ b/net/mac80211/rx.c
+-@@ -647,7 +647,6 @@ static int ieee80211_get_mmie_keyidx(str
+- {
+- 	struct ieee80211_mgmt *hdr = (struct ieee80211_mgmt *) skb->data;
+- 	struct ieee80211_mmie *mmie;
+--	struct ieee80211_mmie_16 *mmie16;
+- 
+- 	if (skb->len < 24 + sizeof(*mmie) || !is_multicast_ether_addr(hdr->da))
+- 		return -1;
+-@@ -657,18 +656,11 @@ static int ieee80211_get_mmie_keyidx(str
+- 
+- 	mmie = (struct ieee80211_mmie *)
+- 		(skb->data + skb->len - sizeof(*mmie));
+--	if (mmie->element_id == WLAN_EID_MMIE &&
+--	    mmie->length == sizeof(*mmie) - 2)
+--		return le16_to_cpu(mmie->key_id);
+--
+--	mmie16 = (struct ieee80211_mmie_16 *)
+--		(skb->data + skb->len - sizeof(*mmie16));
+--	if (skb->len >= 24 + sizeof(*mmie16) &&
+--	    mmie16->element_id == WLAN_EID_MMIE &&
+--	    mmie16->length == sizeof(*mmie16) - 2)
+--		return le16_to_cpu(mmie16->key_id);
+-+	if (mmie->element_id != WLAN_EID_MMIE ||
+-+	    mmie->length != sizeof(*mmie) - 2)
+-+		return -1;
+- 
+--	return -1;
+-+	return le16_to_cpu(mmie->key_id);
+- }
+- 
+- static int iwl80211_get_cs_keyid(const struct ieee80211_cipher_scheme *cs,
+-@@ -1658,27 +1650,11 @@ ieee80211_rx_h_decrypt(struct ieee80211_
+- 		result = ieee80211_crypto_tkip_decrypt(rx);
+- 		break;
+- 	case WLAN_CIPHER_SUITE_CCMP:
+--		result = ieee80211_crypto_ccmp_decrypt(
+--			rx, IEEE80211_CCMP_MIC_LEN);
+--		break;
+--	case WLAN_CIPHER_SUITE_CCMP_256:
+--		result = ieee80211_crypto_ccmp_decrypt(
+--			rx, IEEE80211_CCMP_256_MIC_LEN);
+-+		result = ieee80211_crypto_ccmp_decrypt(rx);
+- 		break;
+- 	case WLAN_CIPHER_SUITE_AES_CMAC:
+- 		result = ieee80211_crypto_aes_cmac_decrypt(rx);
+- 		break;
+--	case WLAN_CIPHER_SUITE_BIP_CMAC_256:
+--		result = ieee80211_crypto_aes_cmac_256_decrypt(rx);
+--		break;
+--	case WLAN_CIPHER_SUITE_BIP_GMAC_128:
+--	case WLAN_CIPHER_SUITE_BIP_GMAC_256:
+--		result = ieee80211_crypto_aes_gmac_decrypt(rx);
+--		break;
+--	case WLAN_CIPHER_SUITE_GCMP:
+--	case WLAN_CIPHER_SUITE_GCMP_256:
+--		result = ieee80211_crypto_gcmp_decrypt(rx);
+--		break;
+- 	default:
+- 		result = ieee80211_crypto_hw_decrypt(rx);
+- 	}
+-@@ -1805,9 +1781,7 @@ ieee80211_rx_h_defragment(struct ieee802
+- 		/* This is the first fragment of a new frame. */
+- 		entry = ieee80211_reassemble_add(rx->sdata, frag, seq,
+- 						 rx->seqno_idx, &(rx->skb));
+--		if (rx->key &&
+--		    (rx->key->conf.cipher == WLAN_CIPHER_SUITE_CCMP ||
+--		     rx->key->conf.cipher == WLAN_CIPHER_SUITE_CCMP_256) &&
+-+		if (rx->key && rx->key->conf.cipher == WLAN_CIPHER_SUITE_CCMP &&
+- 		    ieee80211_has_protected(fc)) {
+- 			int queue = rx->security_idx;
+- 			/* Store CCMP PN so that we can verify that the next
+-@@ -1836,9 +1810,7 @@ ieee80211_rx_h_defragment(struct ieee802
+- 		int i;
+- 		u8 pn[IEEE80211_CCMP_PN_LEN], *rpn;
+- 		int queue;
+--		if (!rx->key ||
+--		    (rx->key->conf.cipher != WLAN_CIPHER_SUITE_CCMP &&
+--		     rx->key->conf.cipher != WLAN_CIPHER_SUITE_CCMP_256))
+-+		if (!rx->key || rx->key->conf.cipher != WLAN_CIPHER_SUITE_CCMP)
+- 			return RX_DROP_UNUSABLE;
+- 		memcpy(pn, entry->last_pn, IEEE80211_CCMP_PN_LEN);
+- 		for (i = IEEE80211_CCMP_PN_LEN - 1; i >= 0; i--) {
+---- a/net/mac80211/tx.c
+-+++ b/net/mac80211/tx.c
+-@@ -626,9 +626,6 @@ ieee80211_tx_h_select_key(struct ieee802
+- 				tx->key = NULL;
+- 			break;
+- 		case WLAN_CIPHER_SUITE_CCMP:
+--		case WLAN_CIPHER_SUITE_CCMP_256:
+--		case WLAN_CIPHER_SUITE_GCMP:
+--		case WLAN_CIPHER_SUITE_GCMP_256:
+- 			if (!ieee80211_is_data_present(hdr->frame_control) &&
+- 			    !ieee80211_use_mfp(hdr->frame_control, tx->sta,
+- 					       tx->skb))
+-@@ -639,9 +636,6 @@ ieee80211_tx_h_select_key(struct ieee802
+- 					ieee80211_is_mgmt(hdr->frame_control);
+- 			break;
+- 		case WLAN_CIPHER_SUITE_AES_CMAC:
+--		case WLAN_CIPHER_SUITE_BIP_CMAC_256:
+--		case WLAN_CIPHER_SUITE_BIP_GMAC_128:
+--		case WLAN_CIPHER_SUITE_BIP_GMAC_256:
+- 			if (!ieee80211_is_mgmt(hdr->frame_control))
+- 				tx->key = NULL;
+- 			break;
+-@@ -1017,21 +1011,9 @@ ieee80211_tx_h_encrypt(struct ieee80211_
+- 	case WLAN_CIPHER_SUITE_TKIP:
+- 		return ieee80211_crypto_tkip_encrypt(tx);
+- 	case WLAN_CIPHER_SUITE_CCMP:
+--		return ieee80211_crypto_ccmp_encrypt(
+--			tx, IEEE80211_CCMP_MIC_LEN);
+--	case WLAN_CIPHER_SUITE_CCMP_256:
+--		return ieee80211_crypto_ccmp_encrypt(
+--			tx, IEEE80211_CCMP_256_MIC_LEN);
+-+		return ieee80211_crypto_ccmp_encrypt(tx);
+- 	case WLAN_CIPHER_SUITE_AES_CMAC:
+- 		return ieee80211_crypto_aes_cmac_encrypt(tx);
+--	case WLAN_CIPHER_SUITE_BIP_CMAC_256:
+--		return ieee80211_crypto_aes_cmac_256_encrypt(tx);
+--	case WLAN_CIPHER_SUITE_BIP_GMAC_128:
+--	case WLAN_CIPHER_SUITE_BIP_GMAC_256:
+--		return ieee80211_crypto_aes_gmac_encrypt(tx);
+--	case WLAN_CIPHER_SUITE_GCMP:
+--	case WLAN_CIPHER_SUITE_GCMP_256:
+--		return ieee80211_crypto_gcmp_encrypt(tx);
+- 	default:
+- 		return ieee80211_crypto_hw_encrypt(tx);
+- 	}
+---- a/net/mac80211/wpa.c
+-+++ b/net/mac80211/wpa.c
+-@@ -22,8 +22,6 @@
+- #include "tkip.h"
+- #include "aes_ccm.h"
+- #include "aes_cmac.h"
+--#include "aes_gmac.h"
+--#include "aes_gcm.h"
+- #include "wpa.h"
+- 
+- ieee80211_tx_result
+-@@ -304,15 +302,22 @@ ieee80211_crypto_tkip_decrypt(struct iee
+- }
+- 
+- 
+--static void ccmp_special_blocks(struct sk_buff *skb, u8 *pn, u8 *b_0, u8 *aad)
+-+static void ccmp_special_blocks(struct sk_buff *skb, u8 *pn, u8 *scratch,
+-+				int encrypted)
+- {
+- 	__le16 mask_fc;
+- 	int a4_included, mgmt;
+- 	u8 qos_tid;
+--	u16 len_a;
+-+	u8 *b_0, *aad;
+-+	u16 data_len, len_a;
+- 	unsigned int hdrlen;
+- 	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
+- 
+-+	memset(scratch, 0, 6 * AES_BLOCK_SIZE);
+-+
+-+	b_0 = scratch + 3 * AES_BLOCK_SIZE;
+-+	aad = scratch + 4 * AES_BLOCK_SIZE;
+-+
+- 	/*
+- 	 * Mask FC: zero subtype b4 b5 b6 (if not mgmt)
+- 	 * Retry, PwrMgt, MoreData; set Protected
+-@@ -334,21 +339,20 @@ static void ccmp_special_blocks(struct s
+- 	else
+- 		qos_tid = 0;
+- 
+--	/* In CCM, the initial vectors (IV) used for CTR mode encryption and CBC
+--	 * mode authentication are not allowed to collide, yet both are derived
+--	 * from this vector b_0. We only set L := 1 here to indicate that the
+--	 * data size can be represented in (L+1) bytes. The CCM layer will take
+--	 * care of storing the data length in the top (L+1) bytes and setting
+--	 * and clearing the other bits as is required to derive the two IVs.
+--	 */
+--	b_0[0] = 0x1;
+-+	data_len = skb->len - hdrlen - IEEE80211_CCMP_HDR_LEN;
+-+	if (encrypted)
+-+		data_len -= IEEE80211_CCMP_MIC_LEN;
+- 
+-+	/* First block, b_0 */
+-+	b_0[0] = 0x59; /* flags: Adata: 1, M: 011, L: 001 */
+- 	/* Nonce: Nonce Flags | A2 | PN
+- 	 * Nonce Flags: Priority (b0..b3) | Management (b4) | Reserved (b5..b7)
+- 	 */
+- 	b_0[1] = qos_tid | (mgmt << 4);
+- 	memcpy(&b_0[2], hdr->addr2, ETH_ALEN);
+- 	memcpy(&b_0[8], pn, IEEE80211_CCMP_PN_LEN);
+-+	/* l(m) */
+-+	put_unaligned_be16(data_len, &b_0[14]);
+- 
+- 	/* AAD (extra authenticate-only data) / masked 802.11 header
+- 	 * FC | A1 | A2 | A3 | SC | [A4] | [QC] */
+-@@ -395,8 +399,7 @@ static inline void ccmp_hdr2pn(u8 *pn, u
+- }
+- 
+- 
+--static int ccmp_encrypt_skb(struct ieee80211_tx_data *tx, struct sk_buff *skb,
+--			    unsigned int mic_len)
+-+static int ccmp_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;
+-@@ -405,8 +408,7 @@ static int ccmp_encrypt_skb(struct ieee8
+- 	u8 *pos;
+- 	u8 pn[6];
+- 	u64 pn64;
+--	u8 aad[2 * AES_BLOCK_SIZE];
+--	u8 b_0[AES_BLOCK_SIZE];
+-+	u8 scratch[6 * AES_BLOCK_SIZE];
+- 
+- 	if (info->control.hw_key &&
+- 	    !(info->control.hw_key->flags & IEEE80211_KEY_FLAG_GENERATE_IV) &&
+-@@ -427,7 +429,7 @@ static int ccmp_encrypt_skb(struct ieee8
+- 	if (info->control.hw_key)
+- 		tail = 0;
+- 	else
+--		tail = mic_len;
+-+		tail = IEEE80211_CCMP_MIC_LEN;
+- 
+- 	if (WARN_ON(skb_tailroom(skb) < tail ||
+- 		    skb_headroom(skb) < IEEE80211_CCMP_HDR_LEN))
+-@@ -460,24 +462,23 @@ static int ccmp_encrypt_skb(struct ieee8
+- 		return 0;
+- 
+- 	pos += IEEE80211_CCMP_HDR_LEN;
+--	ccmp_special_blocks(skb, pn, b_0, aad);
+--	ieee80211_aes_ccm_encrypt(key->u.ccmp.tfm, b_0, aad, pos, len,
+--				  skb_put(skb, mic_len), mic_len);
+-+	ccmp_special_blocks(skb, pn, scratch, 0);
+-+	ieee80211_aes_ccm_encrypt(key->u.ccmp.tfm, scratch, pos, len,
+-+				  pos, skb_put(skb, IEEE80211_CCMP_MIC_LEN));
+- 
+- 	return 0;
+- }
+- 
+- 
+- ieee80211_tx_result
+--ieee80211_crypto_ccmp_encrypt(struct ieee80211_tx_data *tx,
+--			      unsigned int mic_len)
+-+ieee80211_crypto_ccmp_encrypt(struct ieee80211_tx_data *tx)
+- {
+- 	struct sk_buff *skb;
+- 
+- 	ieee80211_tx_set_protected(tx);
+- 
+- 	skb_queue_walk(&tx->skbs, skb) {
+--		if (ccmp_encrypt_skb(tx, skb, mic_len) < 0)
+-+		if (ccmp_encrypt_skb(tx, skb) < 0)
+- 			return TX_DROP;
+- 	}
+- 
+-@@ -486,8 +487,7 @@ ieee80211_crypto_ccmp_encrypt(struct iee
+- 
+- 
+- ieee80211_rx_result
+--ieee80211_crypto_ccmp_decrypt(struct ieee80211_rx_data *rx,
+--			      unsigned int mic_len)
+-+ieee80211_crypto_ccmp_decrypt(struct ieee80211_rx_data *rx)
+- {
+- 	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data;
+- 	int hdrlen;
+-@@ -504,7 +504,8 @@ ieee80211_crypto_ccmp_decrypt(struct iee
+- 	    !ieee80211_is_robust_mgmt_frame(skb))
+- 		return RX_CONTINUE;
+- 
+--	data_len = skb->len - hdrlen - IEEE80211_CCMP_HDR_LEN - mic_len;
+-+	data_len = skb->len - hdrlen - IEEE80211_CCMP_HDR_LEN -
+-+		   IEEE80211_CCMP_MIC_LEN;
+- 	if (!rx->sta || data_len < 0)
+- 		return RX_DROP_UNUSABLE;
+- 
+-@@ -526,23 +527,23 @@ ieee80211_crypto_ccmp_decrypt(struct iee
+- 	}
+- 
+- 	if (!(status->flag & RX_FLAG_DECRYPTED)) {
+--		u8 aad[2 * AES_BLOCK_SIZE];
+--		u8 b_0[AES_BLOCK_SIZE];
+-+		u8 scratch[6 * AES_BLOCK_SIZE];
+- 		/* hardware didn't decrypt/verify MIC */
+--		ccmp_special_blocks(skb, pn, b_0, aad);
+-+		ccmp_special_blocks(skb, pn, scratch, 1);
+- 
+- 		if (ieee80211_aes_ccm_decrypt(
+--			    key->u.ccmp.tfm, b_0, aad,
+-+			    key->u.ccmp.tfm, scratch,
+- 			    skb->data + hdrlen + IEEE80211_CCMP_HDR_LEN,
+- 			    data_len,
+--			    skb->data + skb->len - mic_len, mic_len))
+-+			    skb->data + skb->len - IEEE80211_CCMP_MIC_LEN,
+-+			    skb->data + hdrlen + IEEE80211_CCMP_HDR_LEN))
+- 			return RX_DROP_UNUSABLE;
+- 	}
+- 
+- 	memcpy(key->u.ccmp.rx_pn[queue], pn, IEEE80211_CCMP_PN_LEN);
+- 
+- 	/* Remove CCMP header and MIC */
+--	if (pskb_trim(skb, skb->len - mic_len))
+-+	if (pskb_trim(skb, skb->len - IEEE80211_CCMP_MIC_LEN))
+- 		return RX_DROP_UNUSABLE;
+- 	memmove(skb->data + IEEE80211_CCMP_HDR_LEN, skb->data, hdrlen);
+- 	skb_pull(skb, IEEE80211_CCMP_HDR_LEN);
+-@@ -550,229 +551,6 @@ ieee80211_crypto_ccmp_decrypt(struct iee
+- 	return RX_CONTINUE;
+- }
+- 
+--static void gcmp_special_blocks(struct sk_buff *skb, u8 *pn, u8 *j_0, u8 *aad)
+--{
+--	__le16 mask_fc;
+--	u8 qos_tid;
+--	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
+--
+--	memcpy(j_0, hdr->addr2, ETH_ALEN);
+--	memcpy(&j_0[ETH_ALEN], pn, IEEE80211_GCMP_PN_LEN);
+--	j_0[13] = 0;
+--	j_0[14] = 0;
+--	j_0[AES_BLOCK_SIZE - 1] = 0x01;
+--
+--	/* AAD (extra authenticate-only data) / masked 802.11 header
+--	 * FC | A1 | A2 | A3 | SC | [A4] | [QC]
+--	 */
+--	put_unaligned_be16(ieee80211_hdrlen(hdr->frame_control) - 2, &aad[0]);
+--	/* Mask FC: zero subtype b4 b5 b6 (if not mgmt)
+--	 * Retry, PwrMgt, MoreData; set Protected
+--	 */
+--	mask_fc = hdr->frame_control;
+--	mask_fc &= ~cpu_to_le16(IEEE80211_FCTL_RETRY |
+--				IEEE80211_FCTL_PM | IEEE80211_FCTL_MOREDATA);
+--	if (!ieee80211_is_mgmt(hdr->frame_control))
+--		mask_fc &= ~cpu_to_le16(0x0070);
+--	mask_fc |= cpu_to_le16(IEEE80211_FCTL_PROTECTED);
+--
+--	put_unaligned(mask_fc, (__le16 *)&aad[2]);
+--	memcpy(&aad[4], &hdr->addr1, 3 * ETH_ALEN);
+--
+--	/* Mask Seq#, leave Frag# */
+--	aad[22] = *((u8 *)&hdr->seq_ctrl) & 0x0f;
+--	aad[23] = 0;
+--
+--	if (ieee80211_is_data_qos(hdr->frame_control))
+--		qos_tid = *ieee80211_get_qos_ctl(hdr) &
+--			IEEE80211_QOS_CTL_TID_MASK;
+--	else
+--		qos_tid = 0;
+--
+--	if (ieee80211_has_a4(hdr->frame_control)) {
+--		memcpy(&aad[24], hdr->addr4, ETH_ALEN);
+--		aad[30] = qos_tid;
+--		aad[31] = 0;
+--	} else {
+--		memset(&aad[24], 0, ETH_ALEN + IEEE80211_QOS_CTL_LEN);
+--		aad[24] = qos_tid;
+--	}
+--}
+--
+--static inline void gcmp_pn2hdr(u8 *hdr, const u8 *pn, int key_id)
+--{
+--	hdr[0] = pn[5];
+--	hdr[1] = pn[4];
+--	hdr[2] = 0;
+--	hdr[3] = 0x20 | (key_id << 6);
+--	hdr[4] = pn[3];
+--	hdr[5] = pn[2];
+--	hdr[6] = pn[1];
+--	hdr[7] = pn[0];
+--}
+--
+--static inline void gcmp_hdr2pn(u8 *pn, const u8 *hdr)
+--{
+--	pn[0] = hdr[7];
+--	pn[1] = hdr[6];
+--	pn[2] = hdr[5];
+--	pn[3] = hdr[4];
+--	pn[4] = hdr[1];
+--	pn[5] = hdr[0];
+--}
+--
+--static int gcmp_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);
+--	int hdrlen, len, tail;
+--	u8 *pos;
+--	u8 pn[6];
+--	u64 pn64;
+--	u8 aad[2 * AES_BLOCK_SIZE];
+--	u8 j_0[AES_BLOCK_SIZE];
+--
+--	if (info->control.hw_key &&
+--	    !(info->control.hw_key->flags & IEEE80211_KEY_FLAG_GENERATE_IV) &&
+--	    !(info->control.hw_key->flags & IEEE80211_KEY_FLAG_PUT_IV_SPACE) &&
+--	    !((info->control.hw_key->flags &
+--	       IEEE80211_KEY_FLAG_GENERATE_IV_MGMT) &&
+--	      ieee80211_is_mgmt(hdr->frame_control))) {
+--		/* hwaccel has no need for preallocated room for GCMP
+--		 * header or MIC fields
+--		 */
+--		return 0;
+--	}
+--
+--	hdrlen = ieee80211_hdrlen(hdr->frame_control);
+--	len = skb->len - hdrlen;
+--
+--	if (info->control.hw_key)
+--		tail = 0;
+--	else
+--		tail = IEEE80211_GCMP_MIC_LEN;
+--
+--	if (WARN_ON(skb_tailroom(skb) < tail ||
+--		    skb_headroom(skb) < IEEE80211_GCMP_HDR_LEN))
+--		return -1;
+--
+--	pos = skb_push(skb, IEEE80211_GCMP_HDR_LEN);
+--	memmove(pos, pos + IEEE80211_GCMP_HDR_LEN, hdrlen);
+--	skb_set_network_header(skb, skb_network_offset(skb) +
+--				    IEEE80211_GCMP_HDR_LEN);
+--
+--	/* the HW only needs room for the IV, but not the actual IV */
+--	if (info->control.hw_key &&
+--	    (info->control.hw_key->flags & IEEE80211_KEY_FLAG_PUT_IV_SPACE))
+--		return 0;
+--
+--	hdr = (struct ieee80211_hdr *)pos;
+--	pos += hdrlen;
+--
+--	pn64 = atomic64_inc_return(&key->u.gcmp.tx_pn);
+--
+--	pn[5] = pn64;
+--	pn[4] = pn64 >> 8;
+--	pn[3] = pn64 >> 16;
+--	pn[2] = pn64 >> 24;
+--	pn[1] = pn64 >> 32;
+--	pn[0] = pn64 >> 40;
+--
+--	gcmp_pn2hdr(pos, pn, key->conf.keyidx);
+--
+--	/* hwaccel - with software GCMP header */
+--	if (info->control.hw_key)
+--		return 0;
+--
+--	pos += IEEE80211_GCMP_HDR_LEN;
+--	gcmp_special_blocks(skb, pn, j_0, aad);
+--	ieee80211_aes_gcm_encrypt(key->u.gcmp.tfm, j_0, aad, pos, len,
+--				  skb_put(skb, IEEE80211_GCMP_MIC_LEN));
+--
+--	return 0;
+--}
+--
+--ieee80211_tx_result
+--ieee80211_crypto_gcmp_encrypt(struct ieee80211_tx_data *tx)
+--{
+--	struct sk_buff *skb;
+--
+--	ieee80211_tx_set_protected(tx);
+--
+--	skb_queue_walk(&tx->skbs, skb) {
+--		if (gcmp_encrypt_skb(tx, skb) < 0)
+--			return TX_DROP;
+--	}
+--
+--	return TX_CONTINUE;
+--}
+--
+--ieee80211_rx_result
+--ieee80211_crypto_gcmp_decrypt(struct ieee80211_rx_data *rx)
+--{
+--	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data;
+--	int hdrlen;
+--	struct ieee80211_key *key = rx->key;
+--	struct sk_buff *skb = rx->skb;
+--	struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb);
+--	u8 pn[IEEE80211_GCMP_PN_LEN];
+--	int data_len;
+--	int queue;
+--
+--	hdrlen = ieee80211_hdrlen(hdr->frame_control);
+--
+--	if (!ieee80211_is_data(hdr->frame_control) &&
+--	    !ieee80211_is_robust_mgmt_frame(skb))
+--		return RX_CONTINUE;
+--
+--	data_len = skb->len - hdrlen - IEEE80211_GCMP_HDR_LEN -
+--		   IEEE80211_GCMP_MIC_LEN;
+--	if (!rx->sta || data_len < 0)
+--		return RX_DROP_UNUSABLE;
+--
+--	if (status->flag & RX_FLAG_DECRYPTED) {
+--		if (!pskb_may_pull(rx->skb, hdrlen + IEEE80211_GCMP_HDR_LEN))
+--			return RX_DROP_UNUSABLE;
+--	} else {
+--		if (skb_linearize(rx->skb))
+--			return RX_DROP_UNUSABLE;
+--	}
+--
+--	gcmp_hdr2pn(pn, skb->data + hdrlen);
+--
+--	queue = rx->security_idx;
+--
+--	if (memcmp(pn, key->u.gcmp.rx_pn[queue], IEEE80211_GCMP_PN_LEN) <= 0) {
+--		key->u.gcmp.replays++;
+--		return RX_DROP_UNUSABLE;
+--	}
+--
+--	if (!(status->flag & RX_FLAG_DECRYPTED)) {
+--		u8 aad[2 * AES_BLOCK_SIZE];
+--		u8 j_0[AES_BLOCK_SIZE];
+--		/* hardware didn't decrypt/verify MIC */
+--		gcmp_special_blocks(skb, pn, j_0, aad);
+--
+--		if (ieee80211_aes_gcm_decrypt(
+--			    key->u.gcmp.tfm, j_0, aad,
+--			    skb->data + hdrlen + IEEE80211_GCMP_HDR_LEN,
+--			    data_len,
+--			    skb->data + skb->len - IEEE80211_GCMP_MIC_LEN))
+--			return RX_DROP_UNUSABLE;
+--	}
+--
+--	memcpy(key->u.gcmp.rx_pn[queue], pn, IEEE80211_GCMP_PN_LEN);
+--
+--	/* Remove GCMP header and MIC */
+--	if (pskb_trim(skb, skb->len - IEEE80211_GCMP_MIC_LEN))
+--		return RX_DROP_UNUSABLE;
+--	memmove(skb->data + IEEE80211_GCMP_HDR_LEN, skb->data, hdrlen);
+--	skb_pull(skb, IEEE80211_GCMP_HDR_LEN);
+--
+--	return RX_CONTINUE;
+--}
+--
+- static ieee80211_tx_result
+- ieee80211_crypto_cs_encrypt(struct ieee80211_tx_data *tx,
+- 			    struct sk_buff *skb)
+-@@ -956,48 +734,6 @@ ieee80211_crypto_aes_cmac_encrypt(struct
+- 	return TX_CONTINUE;
+- }
+- 
+--ieee80211_tx_result
+--ieee80211_crypto_aes_cmac_256_encrypt(struct ieee80211_tx_data *tx)
+--{
+--	struct sk_buff *skb;
+--	struct ieee80211_tx_info *info;
+--	struct ieee80211_key *key = tx->key;
+--	struct ieee80211_mmie_16 *mmie;
+--	u8 aad[20];
+--	u64 pn64;
+--
+--	if (WARN_ON(skb_queue_len(&tx->skbs) != 1))
+--		return TX_DROP;
+--
+--	skb = skb_peek(&tx->skbs);
+--
+--	info = IEEE80211_SKB_CB(skb);
+--
+--	if (info->control.hw_key)
+--		return TX_CONTINUE;
+--
+--	if (WARN_ON(skb_tailroom(skb) < sizeof(*mmie)))
+--		return TX_DROP;
+--
+--	mmie = (struct ieee80211_mmie_16 *)skb_put(skb, sizeof(*mmie));
+--	mmie->element_id = WLAN_EID_MMIE;
+--	mmie->length = sizeof(*mmie) - 2;
+--	mmie->key_id = cpu_to_le16(key->conf.keyidx);
+--
+--	/* PN = PN + 1 */
+--	pn64 = atomic64_inc_return(&key->u.aes_cmac.tx_pn);
+--
+--	bip_ipn_set64(mmie->sequence_number, pn64);
+--
+--	bip_aad(skb, aad);
+--
+--	/* MIC = AES-256-CMAC(IGTK, AAD || Management Frame Body || MMIE, 128)
+--	 */
+--	ieee80211_aes_cmac_256(key->u.aes_cmac.tfm, aad,
+--			       skb->data + 24, skb->len - 24, mmie->mic);
+--
+--	return TX_CONTINUE;
+--}
+- 
+- ieee80211_rx_result
+- ieee80211_crypto_aes_cmac_decrypt(struct ieee80211_rx_data *rx)
+-@@ -1045,160 +781,6 @@ ieee80211_crypto_aes_cmac_decrypt(struct
+- 
+- 	/* Remove MMIE */
+- 	skb_trim(skb, skb->len - sizeof(*mmie));
+--
+--	return RX_CONTINUE;
+--}
+--
+--ieee80211_rx_result
+--ieee80211_crypto_aes_cmac_256_decrypt(struct ieee80211_rx_data *rx)
+--{
+--	struct sk_buff *skb = rx->skb;
+--	struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb);
+--	struct ieee80211_key *key = rx->key;
+--	struct ieee80211_mmie_16 *mmie;
+--	u8 aad[20], mic[16], ipn[6];
+--	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
+--
+--	if (!ieee80211_is_mgmt(hdr->frame_control))
+--		return RX_CONTINUE;
+--
+--	/* management frames are already linear */
+--
+--	if (skb->len < 24 + sizeof(*mmie))
+--		return RX_DROP_UNUSABLE;
+--
+--	mmie = (struct ieee80211_mmie_16 *)
+--		(skb->data + skb->len - sizeof(*mmie));
+--	if (mmie->element_id != WLAN_EID_MMIE ||
+--	    mmie->length != sizeof(*mmie) - 2)
+--		return RX_DROP_UNUSABLE; /* Invalid MMIE */
+--
+--	bip_ipn_swap(ipn, mmie->sequence_number);
+--
+--	if (memcmp(ipn, key->u.aes_cmac.rx_pn, 6) <= 0) {
+--		key->u.aes_cmac.replays++;
+--		return RX_DROP_UNUSABLE;
+--	}
+--
+--	if (!(status->flag & RX_FLAG_DECRYPTED)) {
+--		/* hardware didn't decrypt/verify MIC */
+--		bip_aad(skb, aad);
+--		ieee80211_aes_cmac_256(key->u.aes_cmac.tfm, aad,
+--				       skb->data + 24, skb->len - 24, mic);
+--		if (memcmp(mic, mmie->mic, sizeof(mmie->mic)) != 0) {
+--			key->u.aes_cmac.icverrors++;
+--			return RX_DROP_UNUSABLE;
+--		}
+--	}
+--
+--	memcpy(key->u.aes_cmac.rx_pn, ipn, 6);
+--
+--	/* Remove MMIE */
+--	skb_trim(skb, skb->len - sizeof(*mmie));
+--
+--	return RX_CONTINUE;
+--}
+--
+--ieee80211_tx_result
+--ieee80211_crypto_aes_gmac_encrypt(struct ieee80211_tx_data *tx)
+--{
+--	struct sk_buff *skb;
+--	struct ieee80211_tx_info *info;
+--	struct ieee80211_key *key = tx->key;
+--	struct ieee80211_mmie_16 *mmie;
+--	struct ieee80211_hdr *hdr;
+--	u8 aad[20];
+--	u64 pn64;
+--	u8 nonce[12];
+--
+--	if (WARN_ON(skb_queue_len(&tx->skbs) != 1))
+--		return TX_DROP;
+--
+--	skb = skb_peek(&tx->skbs);
+--
+--	info = IEEE80211_SKB_CB(skb);
+--
+--	if (info->control.hw_key)
+--		return TX_CONTINUE;
+--
+--	if (WARN_ON(skb_tailroom(skb) < sizeof(*mmie)))
+--		return TX_DROP;
+--
+--	mmie = (struct ieee80211_mmie_16 *)skb_put(skb, sizeof(*mmie));
+--	mmie->element_id = WLAN_EID_MMIE;
+--	mmie->length = sizeof(*mmie) - 2;
+--	mmie->key_id = cpu_to_le16(key->conf.keyidx);
+--
+--	/* PN = PN + 1 */
+--	pn64 = atomic64_inc_return(&key->u.aes_gmac.tx_pn);
+--
+--	bip_ipn_set64(mmie->sequence_number, pn64);
+--
+--	bip_aad(skb, aad);
+--
+--	hdr = (struct ieee80211_hdr *)skb->data;
+--	memcpy(nonce, hdr->addr2, ETH_ALEN);
+--	bip_ipn_swap(nonce + ETH_ALEN, mmie->sequence_number);
+--
+--	/* MIC = AES-GMAC(IGTK, AAD || Management Frame Body || MMIE, 128) */
+--	if (ieee80211_aes_gmac(key->u.aes_gmac.tfm, aad, nonce,
+--			       skb->data + 24, skb->len - 24, mmie->mic) < 0)
+--		return TX_DROP;
+--
+--	return TX_CONTINUE;
+--}
+--
+--ieee80211_rx_result
+--ieee80211_crypto_aes_gmac_decrypt(struct ieee80211_rx_data *rx)
+--{
+--	struct sk_buff *skb = rx->skb;
+--	struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb);
+--	struct ieee80211_key *key = rx->key;
+--	struct ieee80211_mmie_16 *mmie;
+--	u8 aad[20], mic[16], ipn[6], nonce[12];
+--	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
+--
+--	if (!ieee80211_is_mgmt(hdr->frame_control))
+--		return RX_CONTINUE;
+--
+--	/* management frames are already linear */
+--
+--	if (skb->len < 24 + sizeof(*mmie))
+--		return RX_DROP_UNUSABLE;
+--
+--	mmie = (struct ieee80211_mmie_16 *)
+--		(skb->data + skb->len - sizeof(*mmie));
+--	if (mmie->element_id != WLAN_EID_MMIE ||
+--	    mmie->length != sizeof(*mmie) - 2)
+--		return RX_DROP_UNUSABLE; /* Invalid MMIE */
+--
+--	bip_ipn_swap(ipn, mmie->sequence_number);
+--
+--	if (memcmp(ipn, key->u.aes_gmac.rx_pn, 6) <= 0) {
+--		key->u.aes_gmac.replays++;
+--		return RX_DROP_UNUSABLE;
+--	}
+--
+--	if (!(status->flag & RX_FLAG_DECRYPTED)) {
+--		/* hardware didn't decrypt/verify MIC */
+--		bip_aad(skb, aad);
+--
+--		memcpy(nonce, hdr->addr2, ETH_ALEN);
+--		memcpy(nonce + ETH_ALEN, ipn, 6);
+--
+--		if (ieee80211_aes_gmac(key->u.aes_gmac.tfm, aad, nonce,
+--				       skb->data + 24, skb->len - 24,
+--				       mic) < 0 ||
+--		    memcmp(mic, mmie->mic, sizeof(mmie->mic)) != 0) {
+--			key->u.aes_gmac.icverrors++;
+--			return RX_DROP_UNUSABLE;
+--		}
+--	}
+--
+--	memcpy(key->u.aes_gmac.rx_pn, ipn, 6);
+--
+--	/* Remove MMIE */
+--	skb_trim(skb, skb->len - sizeof(*mmie));
+- 
+- 	return RX_CONTINUE;
+- }
+---- a/net/mac80211/wpa.h
+-+++ b/net/mac80211/wpa.h
+-@@ -24,32 +24,17 @@ ieee80211_rx_result
+- ieee80211_crypto_tkip_decrypt(struct ieee80211_rx_data *rx);
+- 
+- ieee80211_tx_result
+--ieee80211_crypto_ccmp_encrypt(struct ieee80211_tx_data *tx,
+--			      unsigned int mic_len);
+-+ieee80211_crypto_ccmp_encrypt(struct ieee80211_tx_data *tx);
+- ieee80211_rx_result
+--ieee80211_crypto_ccmp_decrypt(struct ieee80211_rx_data *rx,
+--			      unsigned int mic_len);
+-+ieee80211_crypto_ccmp_decrypt(struct ieee80211_rx_data *rx);
+- 
+- ieee80211_tx_result
+- ieee80211_crypto_aes_cmac_encrypt(struct ieee80211_tx_data *tx);
+--ieee80211_tx_result
+--ieee80211_crypto_aes_cmac_256_encrypt(struct ieee80211_tx_data *tx);
+- ieee80211_rx_result
+- ieee80211_crypto_aes_cmac_decrypt(struct ieee80211_rx_data *rx);
+--ieee80211_rx_result
+--ieee80211_crypto_aes_cmac_256_decrypt(struct ieee80211_rx_data *rx);
+--ieee80211_tx_result
+--ieee80211_crypto_aes_gmac_encrypt(struct ieee80211_tx_data *tx);
+--ieee80211_rx_result
+--ieee80211_crypto_aes_gmac_decrypt(struct ieee80211_rx_data *rx);
+- ieee80211_tx_result
+- ieee80211_crypto_hw_encrypt(struct ieee80211_tx_data *tx);
+- ieee80211_rx_result
+- ieee80211_crypto_hw_decrypt(struct ieee80211_rx_data *rx);
+- 
+--ieee80211_tx_result
+--ieee80211_crypto_gcmp_encrypt(struct ieee80211_tx_data *tx);
+--ieee80211_rx_result
+--ieee80211_crypto_gcmp_decrypt(struct ieee80211_rx_data *rx);
+--
+- #endif /* WPA_H */
+diff --git a/package/kernel/mac80211/patches/110-mac80211_keep_keys_on_stop_ap.patch b/package/kernel/mac80211/patches/110-mac80211_keep_keys_on_stop_ap.patch
+index 41a3c4f..cff6d89 100644
+--- a/package/kernel/mac80211/patches/110-mac80211_keep_keys_on_stop_ap.patch
++++ b/package/kernel/mac80211/patches/110-mac80211_keep_keys_on_stop_ap.patch
+@@ -2,7 +2,7 @@ Used for AP+STA support in OpenWrt - preserve AP mode keys across STA reconnects
+ 
+ --- a/net/mac80211/cfg.c
+ +++ b/net/mac80211/cfg.c
+-@@ -856,7 +856,6 @@ static int ieee80211_stop_ap(struct wiph
++@@ -886,7 +886,6 @@ static int ieee80211_stop_ap(struct wiph
+  	sdata->u.ap.driver_smps_mode = IEEE80211_SMPS_OFF;
+  
+  	__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 de79bd2..5fc9454 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 @@
+  static int ieee80211_ifa6_changed(struct notifier_block *nb,
+  				  unsigned long data, void *arg)
+  {
+-@@ -1057,14 +1057,14 @@ int ieee80211_register_hw(struct ieee802
++@@ -1086,14 +1086,14 @@ int ieee80211_register_hw(struct ieee802
+  	if (result)
+  		goto fail_pm_qos;
+  
+@@ -35,7 +35,7 @@
+  	local->ifa6_notifier.notifier_call = ieee80211_ifa6_changed;
+  	result = register_inet6addr_notifier(&local->ifa6_notifier);
+  	if (result)
+-@@ -1073,13 +1073,13 @@ int ieee80211_register_hw(struct ieee802
++@@ -1102,13 +1102,13 @@ int ieee80211_register_hw(struct ieee802
+  
+  	return 0;
+  
+@@ -52,7 +52,7 @@
+   fail_ifa:
+  	pm_qos_remove_notifier(PM_QOS_NETWORK_LATENCY,
+  			       &local->network_latency_notifier);
+-@@ -1124,10 +1124,10 @@ void ieee80211_unregister_hw(struct ieee
++@@ -1141,10 +1141,10 @@ void ieee80211_unregister_hw(struct ieee
+  
+  	pm_qos_remove_notifier(PM_QOS_NETWORK_LATENCY,
+  			       &local->network_latency_notifier);
+diff --git a/package/kernel/mac80211/patches/210-ap_scan.patch b/package/kernel/mac80211/patches/210-ap_scan.patch
+index 47dcec3..29f05c4 100644
+--- a/package/kernel/mac80211/patches/210-ap_scan.patch
++++ b/package/kernel/mac80211/patches/210-ap_scan.patch
+@@ -1,6 +1,6 @@
+ --- a/net/mac80211/cfg.c
+ +++ b/net/mac80211/cfg.c
+-@@ -1963,7 +1963,7 @@ static int ieee80211_scan(struct wiphy *
++@@ -2008,7 +2008,7 @@ static int ieee80211_scan(struct wiphy *
+  		 * the  frames sent while scanning on other channel will be
+  		 * lost)
+  		 */
+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
+new file mode 100644
+index 0000000..bddb15a
+--- /dev/null
++++ b/package/kernel/mac80211/patches/300-ath9k-force-rx_clear-when-disabling-rx.patch
+@@ -0,0 +1,31 @@
++From: Felix Fietkau <nbd@openwrt.org>
++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
++Rx related DMA stop warnings
++
++Cc: stable@vger.kernel.org
++Signed-off-by: Felix Fietkau <nbd@openwrt.org>
++---
++
++--- a/drivers/net/wireless/ath/ath9k/mac.c
+++++ b/drivers/net/wireless/ath/ath9k/mac.c
++@@ -677,13 +677,15 @@ void ath9k_hw_startpcureceive(struct ath
++ 
++ 	ath9k_ani_reset(ah, is_scanning);
++ 
++-	REG_CLR_BIT(ah, AR_DIAG_SW, (AR_DIAG_RX_DIS | AR_DIAG_RX_ABORT));
+++	REG_CLR_BIT(ah, AR_DIAG_SW,
+++		    AR_DIAG_RX_DIS | AR_DIAG_RX_ABORT | AR_DIAG_FORCE_RX_CLEAR);
++ }
++ EXPORT_SYMBOL(ath9k_hw_startpcureceive);
++ 
++ void ath9k_hw_abortpcurecv(struct ath_hw *ah)
++ {
++-	REG_SET_BIT(ah, AR_DIAG_SW, AR_DIAG_RX_ABORT | AR_DIAG_RX_DIS);
+++	REG_SET_BIT(ah, AR_DIAG_SW,
+++		    AR_DIAG_RX_DIS | AR_DIAG_RX_ABORT | AR_DIAG_FORCE_RX_CLEAR);
++ 
++ 	ath9k_hw_disable_mib_counters(ah);
++ }
+diff --git a/package/kernel/mac80211/patches/300-mac80211-add-an-intermediate-software-queue-implemen.patch b/package/kernel/mac80211/patches/300-mac80211-add-an-intermediate-software-queue-implemen.patch
+deleted file mode 100644
+index 237121b..0000000
+--- a/package/kernel/mac80211/patches/300-mac80211-add-an-intermediate-software-queue-implemen.patch
++++ /dev/null
+@@ -1,882 +0,0 @@
+-From: Felix Fietkau <nbd@openwrt.org>
+-Date: Tue, 18 Nov 2014 23:58:51 +0100
+-Subject: [PATCH] mac80211: add an intermediate software queue implementation
+-
+-This allows drivers to request per-vif and per-sta-tid queues from which
+-they can pull frames. This makes it easier to keep the hardware queues
+-short, and to improve fairness between clients and vifs.
+-
+-The task of scheduling packet transmission is left up to the driver -
+-queueing is controlled by mac80211. Drivers can only dequeue packets by
+-calling ieee80211_tx_dequeue. This makes it possible to add active queue
+-management later without changing drivers using this code.
+-
+-This can also be used as a starting point to implement A-MSDU
+-aggregation in a way that does not add artificially induced latency.
+-
+-Signed-off-by: Felix Fietkau <nbd@openwrt.org>
+----
+-
+---- a/include/net/mac80211.h
+-+++ b/include/net/mac80211.h
+-@@ -84,6 +84,39 @@
+-  *
+-  */
+- 
+-+/**
+-+ * DOC: mac80211 software tx queueing
+-+ *
+-+ * mac80211 provides an optional intermediate queueing implementation designed
+-+ * to allow the driver to keep hardware queues short and provide some fairness
+-+ * between different stations/interfaces.
+-+ * In this model, the driver pulls data frames from the mac80211 queue instead
+-+ * of letting mac80211 push them via drv_tx().
+-+ * Other frames (e.g. control or management) are still pushed using drv_tx().
+-+ *
+-+ * Drivers indicate that they use this model by implementing the .wake_tx_queue
+-+ * driver operation.
+-+ *
+-+ * Intermediate queues (struct ieee80211_txq) are kept per-sta per-tid, with a
+-+ * single per-vif queue for multicast data frames.
+-+ *
+-+ * The driver is expected to initialize its private per-queue data for stations
+-+ * and interfaces in the .add_interface and .sta_add ops.
+-+ *
+-+ * The driver can't access the queue directly. To dequeue a frame, it calls
+-+ * ieee80211_tx_dequeue(). Whenever mac80211 adds a new frame to a queue, it
+-+ * calls the .wake_tx_queue driver op.
+-+ *
+-+ * For AP powersave TIM handling, the driver only needs to indicate if it has
+-+ * buffered packets in the driver specific data structures by calling
+-+ * ieee80211_sta_set_buffered(). For frames buffered in the ieee80211_txq
+-+ * struct, mac80211 sets the appropriate TIM PVB bits and calls
+-+ * .release_buffered_frames().
+-+ * In that callback the driver is therefore expected to release its own
+-+ * buffered frames and afterwards also frames from the ieee80211_txq (obtained
+-+ * via the usual ieee80211_tx_dequeue).
+-+ */
+-+
+- struct device;
+- 
+- /**
+-@@ -1246,6 +1279,7 @@ enum ieee80211_vif_flags {
+-  *	monitor interface (if that is requested.)
+-  * @drv_priv: data area for driver use, will always be aligned to
+-  *	sizeof(void *).
+-+ * @txq: the multicast data TX queue (if driver uses the TXQ abstraction)
+-  */
+- struct ieee80211_vif {
+- 	enum nl80211_iftype type;
+-@@ -1257,6 +1291,8 @@ struct ieee80211_vif {
+- 	u8 cab_queue;
+- 	u8 hw_queue[IEEE80211_NUM_ACS];
+- 
+-+	struct ieee80211_txq *txq;
+-+
+- 	struct ieee80211_chanctx_conf __rcu *chanctx_conf;
+- 
+- 	u32 driver_flags;
+-@@ -1501,6 +1537,7 @@ struct ieee80211_sta_rates {
+-  * @tdls_initiator: indicates the STA is an initiator of the TDLS link. Only
+-  *	valid if the STA is a TDLS peer in the first place.
+-  * @mfp: indicates whether the STA uses management frame protection or not.
+-+ * @txq: per-TID data TX queues (if driver uses the TXQ abstraction)
+-  */
+- struct ieee80211_sta {
+- 	u32 supp_rates[IEEE80211_NUM_BANDS];
+-@@ -1519,6 +1556,8 @@ struct ieee80211_sta {
+- 	bool tdls_initiator;
+- 	bool mfp;
+- 
+-+	struct ieee80211_txq *txq[IEEE80211_NUM_TIDS];
+-+
+- 	/* must be last */
+- 	u8 drv_priv[0] __aligned(sizeof(void *));
+- };
+-@@ -1547,6 +1586,27 @@ struct ieee80211_tx_control {
+- };
+- 
+- /**
+-+ * struct ieee80211_txq - Software intermediate tx queue
+-+ *
+-+ * @vif: &struct ieee80211_vif pointer from the add_interface callback.
+-+ * @sta: station table entry, %NULL for per-vif queue
+-+ * @tid: the TID for this queue (unused for per-vif queue)
+-+ * @ac: the AC for this queue
+-+ *
+-+ * The driver can obtain packets from this queue by calling
+-+ * ieee80211_tx_dequeue().
+-+ */
+-+struct ieee80211_txq {
+-+	struct ieee80211_vif *vif;
+-+	struct ieee80211_sta *sta;
+-+	u8 tid;
+-+	u8 ac;
+-+
+-+	/* must be last */
+-+	u8 drv_priv[0] __aligned(sizeof(void *));
+-+};
+-+
+-+/**
+-  * enum ieee80211_hw_flags - hardware flags
+-  *
+-  * These flags are used to indicate hardware capabilities to
+-@@ -1770,6 +1830,8 @@ enum ieee80211_hw_flags {
+-  *	within &struct ieee80211_sta.
+-  * @chanctx_data_size: size (in bytes) of the drv_priv data area
+-  *	within &struct ieee80211_chanctx_conf.
+-+ * @txq_data_size: size (in bytes) of the drv_priv data area
+-+ *	within @struct ieee80211_txq.
+-  *
+-  * @max_rates: maximum number of alternate rate retry stages the hw
+-  *	can handle.
+-@@ -1818,6 +1880,9 @@ enum ieee80211_hw_flags {
+-  * @n_cipher_schemes: a size of an array of cipher schemes definitions.
+-  * @cipher_schemes: a pointer to an array of cipher scheme definitions
+-  *	supported by HW.
+-+ *
+-+ * @txq_ac_max_pending: maximum number of frames per AC pending in all txq
+-+ *	entries for a vif.
+-  */
+- struct ieee80211_hw {
+- 	struct ieee80211_conf conf;
+-@@ -1830,6 +1895,7 @@ struct ieee80211_hw {
+- 	int vif_data_size;
+- 	int sta_data_size;
+- 	int chanctx_data_size;
+-+	int txq_data_size;
+- 	u16 queues;
+- 	u16 max_listen_interval;
+- 	s8 max_signal;
+-@@ -1846,6 +1912,7 @@ struct ieee80211_hw {
+- 	u8 uapsd_max_sp_len;
+- 	u8 n_cipher_schemes;
+- 	const struct ieee80211_cipher_scheme *cipher_schemes;
+-+	int txq_ac_max_pending;
+- };
+- 
+- /**
+-@@ -3007,6 +3074,8 @@ enum ieee80211_reconfig_type {
+-  *	response template is provided, together with the location of the
+-  *	switch-timing IE within the template. The skb can only be used within
+-  *	the function call.
+-+ *
+-+ * @wake_tx_queue: Called when new packets have been added to the queue.
+-  */
+- struct ieee80211_ops {
+- 	void (*tx)(struct ieee80211_hw *hw,
+-@@ -3238,6 +3307,9 @@ struct ieee80211_ops {
+- 	void (*tdls_recv_channel_switch)(struct ieee80211_hw *hw,
+- 					 struct ieee80211_vif *vif,
+- 					 struct ieee80211_tdls_ch_sw_params *params);
+-+
+-+	void (*wake_tx_queue)(struct ieee80211_hw *hw,
+-+			      struct ieee80211_txq *txq);
+- };
+- 
+- /**
+-@@ -5249,4 +5321,15 @@ void ieee80211_unreserve_tid(struct ieee
+-  */
+- size_t ieee80211_ie_split(const u8 *ies, size_t ielen,
+- 			  const u8 *ids, int n_ids, size_t offset);
+-+
+-+/**
+-+ * ieee80211_tx_dequeue - dequeue a packet from a software tx queue
+-+ *
+-+ * @hw: pointer as obtained from ieee80211_alloc_hw()
+-+ * @txq: pointer obtained from station or virtual interface
+-+ *
+-+ * Returns the skb if successful, %NULL if no frame was available.
+-+ */
+-+struct sk_buff *ieee80211_tx_dequeue(struct ieee80211_hw *hw,
+-+				     struct ieee80211_txq *txq);
+- #endif /* MAC80211_H */
+---- a/net/mac80211/driver-ops.h
+-+++ b/net/mac80211/driver-ops.h
+-@@ -1367,4 +1367,16 @@ drv_tdls_recv_channel_switch(struct ieee
+- 	trace_drv_return_void(local);
+- }
+- 
+-+static inline void drv_wake_tx_queue(struct ieee80211_local *local,
+-+				     struct txq_info *txq)
+-+{
+-+	struct ieee80211_sub_if_data *sdata = vif_to_sdata(txq->txq.vif);
+-+
+-+	if (!check_sdata_in_driver(sdata))
+-+		return;
+-+
+-+	trace_drv_wake_tx_queue(local, sdata, txq);
+-+	local->ops->wake_tx_queue(&local->hw, &txq->txq);
+-+}
+-+
+- #endif /* __MAC80211_DRIVER_OPS */
+---- a/net/mac80211/ieee80211_i.h
+-+++ b/net/mac80211/ieee80211_i.h
+-@@ -809,6 +809,19 @@ struct mac80211_qos_map {
+- 	struct rcu_head rcu_head;
+- };
+- 
+-+enum txq_info_flags {
+-+	IEEE80211_TXQ_STOP,
+-+	IEEE80211_TXQ_AMPDU,
+-+};
+-+
+-+struct txq_info {
+-+	struct sk_buff_head queue;
+-+	unsigned long flags;
+-+
+-+	/* keep last! */
+-+	struct ieee80211_txq txq;
+-+};
+-+
+- struct ieee80211_sub_if_data {
+- 	struct list_head list;
+- 
+-@@ -853,6 +866,7 @@ struct ieee80211_sub_if_data {
+- 	bool control_port_no_encrypt;
+- 	int encrypt_headroom;
+- 
+-+	atomic_t txqs_len[IEEE80211_NUM_ACS];
+- 	struct ieee80211_tx_queue_params tx_conf[IEEE80211_NUM_ACS];
+- 	struct mac80211_qos_map __rcu *qos_map;
+- 
+-@@ -1453,6 +1467,10 @@ static inline struct ieee80211_local *hw
+- 	return container_of(hw, struct ieee80211_local, hw);
+- }
+- 
+-+static inline struct txq_info *to_txq_info(struct ieee80211_txq *txq)
+-+{
+-+	return container_of(txq, struct txq_info, txq);
+-+}
+- 
+- static inline int ieee80211_bssid_match(const u8 *raddr, const u8 *addr)
+- {
+-@@ -1905,6 +1923,9 @@ static inline bool ieee80211_can_run_wor
+- 	return true;
+- }
+- 
+-+void ieee80211_init_tx_queue(struct ieee80211_sub_if_data *sdata,
+-+			     struct sta_info *sta,
+-+			     struct txq_info *txq, int tid);
+- void ieee80211_send_auth(struct ieee80211_sub_if_data *sdata,
+- 			 u16 transaction, u16 auth_alg, u16 status,
+- 			 const u8 *extra, size_t extra_len, const u8 *bssid,
+---- a/net/mac80211/iface.c
+-+++ b/net/mac80211/iface.c
+-@@ -969,6 +969,13 @@ static void ieee80211_do_stop(struct iee
+- 	}
+- 	spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags);
+- 
+-+	if (sdata->vif.txq) {
+-+		struct txq_info *txqi = to_txq_info(sdata->vif.txq);
+-+
+-+		ieee80211_purge_tx_queue(&local->hw, &txqi->queue);
+-+		atomic_set(&sdata->txqs_len[txqi->txq.ac], 0);
+-+	}
+-+
+- 	if (local->open_count == 0)
+- 		ieee80211_clear_tx_pending(local);
+- 
+-@@ -1674,6 +1681,7 @@ int ieee80211_if_add(struct ieee80211_lo
+- {
+- 	struct net_device *ndev = NULL;
+- 	struct ieee80211_sub_if_data *sdata = NULL;
+-+	struct txq_info *txqi;
+- 	int ret, i;
+- 	int txqs = 1;
+- 
+-@@ -1693,10 +1701,18 @@ int ieee80211_if_add(struct ieee80211_lo
+- 		ieee80211_assign_perm_addr(local, wdev->address, type);
+- 		memcpy(sdata->vif.addr, wdev->address, ETH_ALEN);
+- 	} else {
+-+		int size = ALIGN(sizeof(*sdata) + local->hw.vif_data_size,
+-+				 sizeof(void *));
+-+		int txq_size = 0;
+-+
+-+		if (local->ops->wake_tx_queue)
+-+			txq_size += sizeof(struct txq_info) +
+-+				    local->hw.txq_data_size;
+-+
+- 		if (local->hw.queues >= IEEE80211_NUM_ACS)
+- 			txqs = IEEE80211_NUM_ACS;
+- 
+--		ndev = alloc_netdev_mqs(sizeof(*sdata) + local->hw.vif_data_size,
+-+		ndev = alloc_netdev_mqs(size + txq_size,
+- 					name, NET_NAME_UNKNOWN,
+- 					ieee80211_if_setup, txqs, 1);
+- 		if (!ndev)
+-@@ -1731,6 +1747,11 @@ int ieee80211_if_add(struct ieee80211_lo
+- 		memcpy(sdata->vif.addr, ndev->dev_addr, ETH_ALEN);
+- 		memcpy(sdata->name, ndev->name, IFNAMSIZ);
+- 
+-+		if (txq_size) {
+-+			txqi = netdev_priv(ndev) + size;
+-+			ieee80211_init_tx_queue(sdata, NULL, txqi, 0);
+-+		}
+-+
+- 		sdata->dev = ndev;
+- 	}
+- 
+---- a/net/mac80211/main.c
+-+++ b/net/mac80211/main.c
+-@@ -1019,6 +1019,9 @@ int ieee80211_register_hw(struct ieee802
+- 
+- 	local->dynamic_ps_forced_timeout = -1;
+- 
+-+	if (!local->hw.txq_ac_max_pending)
+-+		local->hw.txq_ac_max_pending = 64;
+-+
+- 	result = ieee80211_wep_init(local);
+- 	if (result < 0)
+- 		wiphy_debug(local->hw.wiphy, "Failed to initialize wep: %d\n",
+---- a/net/mac80211/sta_info.c
+-+++ b/net/mac80211/sta_info.c
+-@@ -118,6 +118,16 @@ static void __cleanup_single_sta(struct
+- 		atomic_dec(&ps->num_sta_ps);
+- 	}
+- 
+-+	if (sta->sta.txq[0]) {
+-+		for (i = 0; i < ARRAY_SIZE(sta->sta.txq); i++) {
+-+			struct txq_info *txqi = to_txq_info(sta->sta.txq[i]);
+-+			int n = skb_queue_len(&txqi->queue);
+-+
+-+			ieee80211_purge_tx_queue(&local->hw, &txqi->queue);
+-+			atomic_sub(n, &sdata->txqs_len[txqi->txq.ac]);
+-+		}
+-+	}
+-+
+- 	for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) {
+- 		local->total_ps_buffered -= skb_queue_len(&sta->ps_tx_buf[ac]);
+- 		ieee80211_purge_tx_queue(&local->hw, &sta->ps_tx_buf[ac]);
+-@@ -234,6 +244,8 @@ void sta_info_free(struct ieee80211_loca
+- 
+- 	sta_dbg(sta->sdata, "Destroyed STA %pM\n", sta->sta.addr);
+- 
+-+	if (sta->sta.txq[0])
+-+		kfree(to_txq_info(sta->sta.txq[0]));
+- 	kfree(rcu_dereference_raw(sta->sta.rates));
+- 	kfree(sta);
+- }
+-@@ -285,11 +297,12 @@ struct sta_info *sta_info_alloc(struct i
+- 				const u8 *addr, gfp_t gfp)
+- {
+- 	struct ieee80211_local *local = sdata->local;
+-+	struct ieee80211_hw *hw = &local->hw;
+- 	struct sta_info *sta;
+- 	struct timespec uptime;
+- 	int i;
+- 
+--	sta = kzalloc(sizeof(*sta) + local->hw.sta_data_size, gfp);
+-+	sta = kzalloc(sizeof(*sta) + hw->sta_data_size, gfp);
+- 	if (!sta)
+- 		return NULL;
+- 
+-@@ -321,11 +334,25 @@ struct sta_info *sta_info_alloc(struct i
+- 	for (i = 0; i < ARRAY_SIZE(sta->chain_signal_avg); i++)
+- 		ewma_init(&sta->chain_signal_avg[i], 1024, 8);
+- 
+--	if (sta_prepare_rate_control(local, sta, gfp)) {
+--		kfree(sta);
+--		return NULL;
+-+	if (local->ops->wake_tx_queue) {
+-+		void *txq_data;
+-+		int size = sizeof(struct txq_info) +
+-+			   ALIGN(hw->txq_data_size, sizeof(void *));
+-+
+-+		txq_data = kcalloc(ARRAY_SIZE(sta->sta.txq), size, gfp);
+-+		if (!txq_data)
+-+			goto free;
+-+
+-+		for (i = 0; i < ARRAY_SIZE(sta->sta.txq); i++) {
+-+			struct txq_info *txq = txq_data + i * size;
+-+
+-+			ieee80211_init_tx_queue(sdata, sta, txq, i);
+-+		}
+- 	}
+- 
+-+	if (sta_prepare_rate_control(local, sta, gfp))
+-+		goto free_txq;
+-+
+- 	for (i = 0; i < IEEE80211_NUM_TIDS; i++) {
+- 		/*
+- 		 * timer_to_tid must be initialized with identity mapping
+-@@ -346,7 +373,7 @@ struct sta_info *sta_info_alloc(struct i
+- 	if (sdata->vif.type == NL80211_IFTYPE_AP ||
+- 	    sdata->vif.type == NL80211_IFTYPE_AP_VLAN) {
+- 		struct ieee80211_supported_band *sband =
+--			local->hw.wiphy->bands[ieee80211_get_sdata_band(sdata)];
+-+			hw->wiphy->bands[ieee80211_get_sdata_band(sdata)];
+- 		u8 smps = (sband->ht_cap.cap & IEEE80211_HT_CAP_SM_PS) >>
+- 				IEEE80211_HT_CAP_SM_PS_SHIFT;
+- 		/*
+-@@ -371,6 +398,13 @@ struct sta_info *sta_info_alloc(struct i
+- 	sta_dbg(sdata, "Allocated STA %pM\n", sta->sta.addr);
+- 
+- 	return sta;
+-+
+-+free_txq:
+-+	if (sta->sta.txq[0])
+-+		kfree(to_txq_info(sta->sta.txq[0]));
+-+free:
+-+	kfree(sta);
+-+	return NULL;
+- }
+- 
+- static int sta_info_insert_check(struct sta_info *sta)
+-@@ -640,6 +674,8 @@ static void __sta_info_recalc_tim(struct
+- 
+- 		indicate_tim |=
+- 			sta->driver_buffered_tids & tids;
+-+		indicate_tim |=
+-+			sta->txq_buffered_tids & tids;
+- 	}
+- 
+-  done:
+-@@ -1071,7 +1107,7 @@ void ieee80211_sta_ps_deliver_wakeup(str
+- 	struct ieee80211_sub_if_data *sdata = sta->sdata;
+- 	struct ieee80211_local *local = sdata->local;
+- 	struct sk_buff_head pending;
+--	int filtered = 0, buffered = 0, ac;
+-+	int filtered = 0, buffered = 0, ac, i;
+- 	unsigned long flags;
+- 	struct ps_data *ps;
+- 
+-@@ -1090,10 +1126,22 @@ void ieee80211_sta_ps_deliver_wakeup(str
+- 
+- 	BUILD_BUG_ON(BITS_TO_LONGS(IEEE80211_NUM_TIDS) > 1);
+- 	sta->driver_buffered_tids = 0;
+-+	sta->txq_buffered_tids = 0;
+- 
+- 	if (!(local->hw.flags & IEEE80211_HW_AP_LINK_PS))
+- 		drv_sta_notify(local, sdata, STA_NOTIFY_AWAKE, &sta->sta);
+- 
+-+	if (sta->sta.txq[0]) {
+-+		for (i = 0; i < ARRAY_SIZE(sta->sta.txq); i++) {
+-+			struct txq_info *txqi = to_txq_info(sta->sta.txq[i]);
+-+
+-+			if (!skb_queue_len(&txqi->queue))
+-+				continue;
+-+
+-+			drv_wake_tx_queue(local, txqi);
+-+		}
+-+	}
+-+
+- 	skb_queue_head_init(&pending);
+- 
+- 	/* sync with ieee80211_tx_h_unicast_ps_buf */
+-@@ -1275,8 +1323,10 @@ ieee80211_sta_ps_deliver_response(struct
+- 		/* if we already have frames from software, then we can't also
+- 		 * release from hardware queues
+- 		 */
+--		if (skb_queue_empty(&frames))
+-+		if (skb_queue_empty(&frames)) {
+- 			driver_release_tids |= sta->driver_buffered_tids & tids;
+-+			driver_release_tids |= sta->txq_buffered_tids & tids;
+-+		}
+- 
+- 		if (driver_release_tids) {
+- 			/* If the driver has data on more than one TID then
+-@@ -1447,6 +1497,9 @@ ieee80211_sta_ps_deliver_response(struct
+- 
+- 		sta_info_recalc_tim(sta);
+- 	} else {
+-+		unsigned long tids = sta->txq_buffered_tids & driver_release_tids;
+-+		int tid;
+-+
+- 		/*
+- 		 * We need to release a frame that is buffered somewhere in the
+- 		 * driver ... it'll have to handle that.
+-@@ -1466,8 +1519,22 @@ ieee80211_sta_ps_deliver_response(struct
+- 		 * that the TID(s) became empty before returning here from the
+- 		 * release function.
+- 		 * Either way, however, when the driver tells us that the TID(s)
+--		 * became empty we'll do the TIM recalculation.
+-+		 * became empty or we find that a txq became empty, we'll do the
+-+		 * TIM recalculation.
+- 		 */
+-+
+-+		if (!sta->sta.txq[0])
+-+			return;
+-+
+-+		for (tid = 0; tid < ARRAY_SIZE(sta->sta.txq); tid++) {
+-+			struct txq_info *txqi = to_txq_info(sta->sta.txq[tid]);
+-+
+-+			if (!(tids & BIT(tid)) || skb_queue_len(&txqi->queue))
+-+				continue;
+-+
+-+			sta_info_recalc_tim(sta);
+-+			break;
+-+		}
+- 	}
+- }
+- 
+---- a/net/mac80211/sta_info.h
+-+++ b/net/mac80211/sta_info.h
+-@@ -274,6 +274,7 @@ struct sta_ampdu_mlme {
+-  *	entered power saving state, these are also delivered to
+-  *	the station when it leaves powersave or polls for frames
+-  * @driver_buffered_tids: bitmap of TIDs the driver has data buffered on
+-+ * @txq_buffered_tids: bitmap of TIDs that mac80211 has txq data buffered on
+-  * @rx_packets: Number of MSDUs received from this STA
+-  * @rx_bytes: Number of bytes received from this STA
+-  * @last_rx: time (in jiffies) when last frame was received from this STA
+-@@ -368,6 +369,7 @@ struct sta_info {
+- 	struct sk_buff_head ps_tx_buf[IEEE80211_NUM_ACS];
+- 	struct sk_buff_head tx_filtered[IEEE80211_NUM_ACS];
+- 	unsigned long driver_buffered_tids;
+-+	unsigned long txq_buffered_tids;
+- 
+- 	/* Updated from RX path only, no locking requirements */
+- 	unsigned long rx_packets;
+---- a/net/mac80211/trace.h
+-+++ b/net/mac80211/trace.h
+-@@ -2312,6 +2312,37 @@ TRACE_EVENT(drv_tdls_recv_channel_switch
+- 	)
+- );
+- 
+-+TRACE_EVENT(drv_wake_tx_queue,
+-+	TP_PROTO(struct ieee80211_local *local,
+-+		 struct ieee80211_sub_if_data *sdata,
+-+		 struct txq_info *txq),
+-+
+-+	TP_ARGS(local, sdata, txq),
+-+
+-+	TP_STRUCT__entry(
+-+		LOCAL_ENTRY
+-+		VIF_ENTRY
+-+		STA_ENTRY
+-+		__field(u8, ac)
+-+		__field(u8, tid)
+-+	),
+-+
+-+	TP_fast_assign(
+-+		struct ieee80211_sta *sta = txq->txq.sta;
+-+
+-+		LOCAL_ASSIGN;
+-+		VIF_ASSIGN;
+-+		STA_ASSIGN;
+-+		__entry->ac = txq->txq.ac;
+-+		__entry->tid = txq->txq.tid;
+-+	),
+-+
+-+	TP_printk(
+-+		LOCAL_PR_FMT  VIF_PR_FMT  STA_PR_FMT " ac:%d tid:%d",
+-+		LOCAL_PR_ARG, VIF_PR_ARG, STA_PR_ARG, __entry->ac, __entry->tid
+-+	)
+-+);
+-+
+- #ifdef CPTCFG_MAC80211_MESSAGE_TRACING
+- #undef TRACE_SYSTEM
+- #define TRACE_SYSTEM mac80211_msg
+---- a/net/mac80211/tx.c
+-+++ b/net/mac80211/tx.c
+-@@ -776,12 +776,22 @@ ieee80211_tx_h_rate_ctrl(struct ieee8021
+- 	return TX_CONTINUE;
+- }
+- 
+-+static __le16 ieee80211_tx_next_seq(struct sta_info *sta, int tid)
+-+{
+-+	u16 *seq = &sta->tid_seq[tid];
+-+	__le16 ret = cpu_to_le16(*seq);
+-+
+-+	/* Increase the sequence number. */
+-+	*seq = (*seq + 0x10) & IEEE80211_SCTL_SEQ;
+-+
+-+	return ret;
+-+}
+-+
+- static ieee80211_tx_result debug_noinline
+- ieee80211_tx_h_sequence(struct ieee80211_tx_data *tx)
+- {
+- 	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx->skb);
+- 	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)tx->skb->data;
+--	u16 *seq;
+- 	u8 *qc;
+- 	int tid;
+- 
+-@@ -832,13 +842,10 @@ ieee80211_tx_h_sequence(struct ieee80211
+- 
+- 	qc = ieee80211_get_qos_ctl(hdr);
+- 	tid = *qc & IEEE80211_QOS_CTL_TID_MASK;
+--	seq = &tx->sta->tid_seq[tid];
+- 	tx->sta->tx_msdu[tid]++;
+- 
+--	hdr->seq_ctrl = cpu_to_le16(*seq);
+--
+--	/* Increase the sequence number. */
+--	*seq = (*seq + 0x10) & IEEE80211_SCTL_SEQ;
+-+	if (!tx->sta->sta.txq[0])
+-+		hdr->seq_ctrl = ieee80211_tx_next_seq(tx->sta, tid);
+- 
+- 	return TX_CONTINUE;
+- }
+-@@ -1067,7 +1074,7 @@ static bool ieee80211_tx_prep_agg(struct
+- 		 * nothing -- this aggregation session is being started
+- 		 * but that might still fail with the driver
+- 		 */
+--	} else {
+-+	} else if (!tx->sta->sta.txq[tid]) {
+- 		spin_lock(&tx->sta->lock);
+- 		/*
+- 		 * Need to re-check now, because we may get here
+-@@ -1201,13 +1208,102 @@ ieee80211_tx_prepare(struct ieee80211_su
+- 	return TX_CONTINUE;
+- }
+- 
+-+static void ieee80211_drv_tx(struct ieee80211_local *local,
+-+			     struct ieee80211_vif *vif,
+-+			     struct ieee80211_sta *pubsta,
+-+			     struct sk_buff *skb)
+-+{
+-+	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
+-+	struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
+-+	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
+-+	struct ieee80211_tx_control control = {
+-+		.sta = pubsta,
+-+	};
+-+	struct ieee80211_txq *txq = NULL;
+-+	struct txq_info *txqi;
+-+	u8 ac;
+-+
+-+	if (info->control.flags & IEEE80211_TX_CTRL_PS_RESPONSE)
+-+		goto tx_normal;
+-+
+-+	if (!ieee80211_is_data(hdr->frame_control))
+-+		goto tx_normal;
+-+
+-+	if (pubsta) {
+-+		u8 tid = skb->priority & IEEE80211_QOS_CTL_TID_MASK;
+-+
+-+		txq = pubsta->txq[tid];
+-+	} else if (vif) {
+-+		txq = vif->txq;
+-+	}
+-+
+-+	if (!txq)
+-+		goto tx_normal;
+-+
+-+	ac = txq->ac;
+-+	txqi = to_txq_info(txq);
+-+	atomic_inc(&sdata->txqs_len[ac]);
+-+	if (atomic_read(&sdata->txqs_len[ac]) >= local->hw.txq_ac_max_pending)
+-+		netif_stop_subqueue(sdata->dev, ac);
+-+
+-+	skb_queue_tail(&txqi->queue, skb);
+-+	drv_wake_tx_queue(local, txqi);
+-+
+-+	return;
+-+
+-+tx_normal:
+-+	drv_tx(local, &control, skb);
+-+}
+-+
+-+struct sk_buff *ieee80211_tx_dequeue(struct ieee80211_hw *hw,
+-+				     struct ieee80211_txq *txq)
+-+{
+-+	struct ieee80211_local *local = hw_to_local(hw);
+-+	struct ieee80211_sub_if_data *sdata = vif_to_sdata(txq->vif);
+-+	struct txq_info *txqi = container_of(txq, struct txq_info, txq);
+-+	struct ieee80211_hdr *hdr;
+-+	struct sk_buff *skb = NULL;
+-+	u8 ac = txq->ac;
+-+
+-+	spin_lock_bh(&txqi->queue.lock);
+-+
+-+	if (test_bit(IEEE80211_TXQ_STOP, &txqi->flags))
+-+		goto out;
+-+
+-+	skb = __skb_dequeue(&txqi->queue);
+-+	if (!skb)
+-+		goto out;
+-+
+-+	atomic_dec(&sdata->txqs_len[ac]);
+-+	if (__netif_subqueue_stopped(sdata->dev, ac))
+-+		ieee80211_propagate_queue_wake(local, sdata->vif.hw_queue[ac]);
+-+
+-+	hdr = (struct ieee80211_hdr *)skb->data;
+-+	if (txq->sta && ieee80211_is_data_qos(hdr->frame_control)) {
+-+		struct sta_info *sta = container_of(txq->sta, struct sta_info,
+-+						    sta);
+-+		struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
+-+
+-+		hdr->seq_ctrl = ieee80211_tx_next_seq(sta, txq->tid);
+-+		if (test_bit(IEEE80211_TXQ_AMPDU, &txqi->flags))
+-+			info->flags |= IEEE80211_TX_CTL_AMPDU;
+-+		else
+-+			info->flags &= ~IEEE80211_TX_CTL_AMPDU;
+-+	}
+-+
+-+out:
+-+	spin_unlock_bh(&txqi->queue.lock);
+-+
+-+	return skb;
+-+}
+-+EXPORT_SYMBOL(ieee80211_tx_dequeue);
+-+
+- static bool ieee80211_tx_frags(struct ieee80211_local *local,
+- 			       struct ieee80211_vif *vif,
+- 			       struct ieee80211_sta *sta,
+- 			       struct sk_buff_head *skbs,
+- 			       bool txpending)
+- {
+--	struct ieee80211_tx_control control;
+- 	struct sk_buff *skb, *tmp;
+- 	unsigned long flags;
+- 
+-@@ -1265,10 +1361,9 @@ static bool ieee80211_tx_frags(struct ie
+- 		spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags);
+- 
+- 		info->control.vif = vif;
+--		control.sta = sta;
+- 
+- 		__skb_unlink(skb, skbs);
+--		drv_tx(local, &control, skb);
+-+		ieee80211_drv_tx(local, vif, sta, skb);
+- 	}
+- 
+- 	return true;
+---- a/net/mac80211/util.c
+-+++ b/net/mac80211/util.c
+-@@ -308,6 +308,11 @@ void ieee80211_propagate_queue_wake(stru
+- 		for (ac = 0; ac < n_acs; ac++) {
+- 			int ac_queue = sdata->vif.hw_queue[ac];
+- 
+-+			if (local->ops->wake_tx_queue &&
+-+			    (atomic_read(&sdata->txqs_len[ac]) >
+-+			     local->hw.txq_ac_max_pending))
+-+				continue;
+-+
+- 			if (ac_queue == queue ||
+- 			    (sdata->vif.cab_queue == queue &&
+- 			     local->queue_stop_reasons[ac_queue] == 0 &&
+-@@ -3307,3 +3312,20 @@ u8 *ieee80211_add_wmm_info_ie(u8 *buf, u
+- 
+- 	return buf;
+- }
+-+
+-+void ieee80211_init_tx_queue(struct ieee80211_sub_if_data *sdata,
+-+			     struct sta_info *sta,
+-+			     struct txq_info *txqi, int tid)
+-+{
+-+	skb_queue_head_init(&txqi->queue);
+-+	txqi->txq.vif = &sdata->vif;
+-+
+-+	if (sta) {
+-+		txqi->txq.sta = &sta->sta;
+-+		sta->sta.txq[tid] = &txqi->txq;
+-+		txqi->txq.ac = ieee802_1d_to_ac[tid & 7];
+-+	} else {
+-+		sdata->vif.txq = &txqi->txq;
+-+		txqi->txq.ac = IEEE80211_AC_BE;
+-+	}
+-+}
+---- a/net/mac80211/rx.c
+-+++ b/net/mac80211/rx.c
+-@@ -1176,6 +1176,7 @@ static void sta_ps_start(struct sta_info
+- 	struct ieee80211_sub_if_data *sdata = sta->sdata;
+- 	struct ieee80211_local *local = sdata->local;
+- 	struct ps_data *ps;
+-+	int tid;
+- 
+- 	if (sta->sdata->vif.type == NL80211_IFTYPE_AP ||
+- 	    sta->sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
+-@@ -1189,6 +1190,18 @@ static void sta_ps_start(struct sta_info
+- 		drv_sta_notify(local, sdata, STA_NOTIFY_SLEEP, &sta->sta);
+- 	ps_dbg(sdata, "STA %pM aid %d enters power save mode\n",
+- 	       sta->sta.addr, sta->sta.aid);
+-+
+-+	if (!sta->sta.txq[0])
+-+		return;
+-+
+-+	for (tid = 0; tid < ARRAY_SIZE(sta->sta.txq); tid++) {
+-+		struct txq_info *txqi = to_txq_info(sta->sta.txq[tid]);
+-+
+-+		if (!skb_queue_len(&txqi->queue))
+-+			set_bit(tid, &sta->txq_buffered_tids);
+-+		else
+-+			clear_bit(tid, &sta->txq_buffered_tids);
+-+	}
+- }
+- 
+- static void sta_ps_end(struct sta_info *sta)
+---- a/net/mac80211/agg-tx.c
+-+++ b/net/mac80211/agg-tx.c
+-@@ -188,6 +188,43 @@ ieee80211_wake_queue_agg(struct ieee8021
+- 	__release(agg_queue);
+- }
+- 
+-+static void
+-+ieee80211_agg_stop_txq(struct sta_info *sta, int tid)
+-+{
+-+	struct ieee80211_txq *txq = sta->sta.txq[tid];
+-+	struct txq_info *txqi;
+-+
+-+	if (!txq)
+-+		return;
+-+
+-+	txqi = to_txq_info(txq);
+-+
+-+	/* Lock here to protect against further seqno updates on dequeue */
+-+	spin_lock_bh(&txqi->queue.lock);
+-+	set_bit(IEEE80211_TXQ_STOP, &txqi->flags);
+-+	spin_unlock_bh(&txqi->queue.lock);
+-+}
+-+
+-+static void
+-+ieee80211_agg_start_txq(struct sta_info *sta, int tid, bool enable)
+-+{
+-+	struct ieee80211_txq *txq = sta->sta.txq[tid];
+-+	struct txq_info *txqi;
+-+
+-+	if (!txq)
+-+		return;
+-+
+-+	txqi = to_txq_info(txq);
+-+
+-+	if (enable)
+-+		set_bit(IEEE80211_TXQ_AMPDU, &txqi->flags);
+-+	else
+-+		clear_bit(IEEE80211_TXQ_AMPDU, &txqi->flags);
+-+
+-+	clear_bit(IEEE80211_TXQ_STOP, &txqi->flags);
+-+	drv_wake_tx_queue(sta->sdata->local, txqi);
+-+}
+-+
+- /*
+-  * splice packets from the STA's pending to the local pending,
+-  * requires a call to ieee80211_agg_splice_finish later
+-@@ -247,6 +284,7 @@ static void ieee80211_remove_tid_tx(stru
+- 	ieee80211_assign_tid_tx(sta, tid, NULL);
+- 
+- 	ieee80211_agg_splice_finish(sta->sdata, tid);
+-+	ieee80211_agg_start_txq(sta, tid, false);
+- 
+- 	kfree_rcu(tid_tx, rcu_head);
+- }
+-@@ -418,6 +456,8 @@ void ieee80211_tx_ba_session_handle_star
+- 	 */
+- 	clear_bit(HT_AGG_STATE_WANT_START, &tid_tx->state);
+- 
+-+	ieee80211_agg_stop_txq(sta, tid);
+-+
+- 	/*
+- 	 * Make sure no packets are being processed. This ensures that
+- 	 * we have a valid starting sequence number and that in-flight
+-@@ -440,6 +480,8 @@ void ieee80211_tx_ba_session_handle_star
+- 		ieee80211_agg_splice_finish(sdata, tid);
+- 		spin_unlock_bh(&sta->lock);
+- 
+-+		ieee80211_agg_start_txq(sta, tid, false);
+-+
+- 		kfree_rcu(tid_tx, rcu_head);
+- 		return;
+- 	}
+-@@ -666,6 +708,8 @@ static void ieee80211_agg_tx_operational
+- 	ieee80211_agg_splice_finish(sta->sdata, tid);
+- 
+- 	spin_unlock_bh(&sta->lock);
+-+
+-+	ieee80211_agg_start_txq(sta, tid, true);
+- }
+- 
+- void ieee80211_start_tx_ba_cb(struct ieee80211_vif *vif, u8 *ra, u16 tid)
+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
+new file mode 100644
+index 0000000..4faac0d
+--- /dev/null
++++ b/package/kernel/mac80211/patches/301-ath9k-limit-retries-for-powersave-response-frames.patch
+@@ -0,0 +1,121 @@
++From: Felix Fietkau <nbd@openwrt.org>
++Date: Thu, 2 Jul 2015 15:20:56 +0200
++Subject: [PATCH] ath9k: limit retries for powersave response frames
++
++In some cases, the channel might be busy enough that an ath9k AP's
++response to PS-Poll frames might be too slow and the station has already
++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>
++---
++
++--- a/drivers/net/wireless/ath/ath9k/xmit.c
+++++ b/drivers/net/wireless/ath/ath9k/xmit.c
++@@ -147,10 +147,25 @@ static void ath_send_bar(struct ath_atx_
++ }
++ 
++ static void ath_set_rates(struct ieee80211_vif *vif, struct ieee80211_sta *sta,
++-			  struct ath_buf *bf)
+++			  struct ath_buf *bf, bool ps)
++ {
+++	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(bf->bf_mpdu);
+++
+++	if (ps) {
+++		/* Clear the first rate to avoid using a sample rate for PS frames */
+++		info->control.rates[0].idx = -1;
+++		info->control.rates[0].count = 0;
+++	}
+++
++ 	ieee80211_get_tx_rates(vif, sta, bf->bf_mpdu, bf->rates,
++ 			       ARRAY_SIZE(bf->rates));
+++	if (!ps)
+++		return;
+++
+++	if (bf->rates[0].count > 2)
+++		bf->rates[0].count = 2;
+++
+++	bf->rates[1].idx = -1;
++ }
++ 
++ static void ath_txq_skb_done(struct ath_softc *sc, struct ath_txq *txq,
++@@ -1430,7 +1445,7 @@ ath_tx_form_burst(struct ath_softc *sc,
++ 		if (tx_info->flags & IEEE80211_TX_CTL_AMPDU)
++ 			break;
++ 
++-		ath_set_rates(tid->an->vif, tid->an->sta, bf);
+++		ath_set_rates(tid->an->vif, tid->an->sta, bf, false);
++ 	} while (1);
++ }
++ 
++@@ -1461,7 +1476,7 @@ static bool ath_tx_sched_aggr(struct ath
++ 		return false;
++ 	}
++ 
++-	ath_set_rates(tid->an->vif, tid->an->sta, bf);
+++	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);
++@@ -1653,7 +1668,7 @@ void ath9k_release_buffered_frames(struc
++ 
++ 			__skb_unlink(bf->bf_mpdu, tid_q);
++ 			list_add_tail(&bf->list, &bf_q);
++-			ath_set_rates(tid->an->vif, tid->an->sta, bf);
+++			ath_set_rates(tid->an->vif, tid->an->sta, bf, true);
++ 			if (bf_isampdu(bf)) {
++ 				ath_tx_addto_baw(sc, tid, bf);
++ 				bf->bf_state.bf_type &= ~BUF_AGGR;
++@@ -2318,7 +2333,7 @@ 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, skip_uapsd = false, ps_resp;
+++	bool queue, ps_resp;
++ 	int q, ret;
++ 
++ 	if (vif)
++@@ -2365,13 +2380,13 @@ int ath_tx_start(struct ieee80211_hw *hw
++ 		if (!txctl->an)
++ 			txctl->an = &avp->mcast_node;
++ 		queue = true;
++-		skip_uapsd = true;
+++		ps_resp = false;
++ 	}
++ 
++ 	if (txctl->an && queue)
++ 		tid = ath_get_skb_tid(sc, txctl->an, skb);
++ 
++-	if (!skip_uapsd && ps_resp) {
+++	if (ps_resp) {
++ 		ath_txq_unlock(sc, txq);
++ 		txq = sc->tx.uapsdq;
++ 		ath_txq_lock(sc, txq);
++@@ -2409,7 +2424,7 @@ int ath_tx_start(struct ieee80211_hw *hw
++ 	if (txctl->paprd)
++ 		bf->bf_state.bfs_paprd_timestamp = jiffies;
++ 
++-	ath_set_rates(vif, sta, bf);
+++	ath_set_rates(vif, sta, bf, ps_resp);
++ 	ath_tx_send_normal(sc, txq, tid, skb);
++ 
++ out:
++@@ -2448,7 +2463,7 @@ void ath_tx_cabq(struct ieee80211_hw *hw
++ 			break;
++ 
++ 		bf->bf_lastbf = bf;
++-		ath_set_rates(vif, NULL, bf);
+++		ath_set_rates(vif, NULL, bf, false);
++ 		ath_buf_set_rate(sc, bf, &info, fi->framelen, false);
++ 		duration += info.rates[0].PktDuration;
++ 		if (bf_tail)
++@@ -2968,7 +2983,7 @@ int ath9k_tx99_send(struct ath_softc *sc
++ 		return -EINVAL;
++ 	}
++ 
++-	ath_set_rates(sc->tx99_vif, NULL, bf);
+++	ath_set_rates(sc->tx99_vif, NULL, bf, false);
++ 
++ 	ath9k_hw_set_desc_link(sc->sc_ah, bf->bf_desc, bf->bf_daddr);
++ 	ath9k_hw_tx99_start(sc->sc_ah, txctl->txq->axq_qnum);
+diff --git a/package/kernel/mac80211/patches/301-mac80211-lock-rate-control.patch b/package/kernel/mac80211/patches/301-mac80211-lock-rate-control.patch
+deleted file mode 100644
+index 465d943..0000000
+--- a/package/kernel/mac80211/patches/301-mac80211-lock-rate-control.patch
++++ /dev/null
+@@ -1,125 +0,0 @@
+-From: Johannes Berg <johannes.berg@intel.com>
+-Date: Wed, 11 Mar 2015 09:14:15 +0100
+-Subject: [PATCH] mac80211: lock rate control
+-
+-Both minstrel (reported by Sven Eckelmann) and the iwlwifi rate
+-control aren't properly taking concurrency into account. It's
+-likely that the same is true for other rate control algorithms.
+-
+-In the case of minstrel this manifests itself in crashes when an
+-update and other data access are run concurrently, for example
+-when the stations change bandwidth or similar. In iwlwifi, this
+-can cause firmware crashes.
+-
+-Since fixing all rate control algorithms will be very difficult,
+-just provide locking for invocations. This protects the internal
+-data structures the algorithms maintain.
+-
+-I've manipulated hostapd to test this, by having it change its
+-advertised bandwidth roughly ever 150ms. At the same time, I'm
+-running a flood ping between the client and the AP, which causes
+-this race of update vs. get_rate/status to easily happen on the
+-client. With this change, the system survives this test.
+-
+-Reported-by: Sven Eckelmann <sven@open-mesh.com>
+-Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+----
+-
+---- a/net/mac80211/rate.c
+-+++ b/net/mac80211/rate.c
+-@@ -683,7 +683,13 @@ void rate_control_get_rate(struct ieee80
+- 	if (sdata->local->hw.flags & IEEE80211_HW_HAS_RATE_CONTROL)
+- 		return;
+- 
+--	ref->ops->get_rate(ref->priv, ista, priv_sta, txrc);
+-+	if (ista) {
+-+		spin_lock_bh(&sta->rate_ctrl_lock);
+-+		ref->ops->get_rate(ref->priv, ista, priv_sta, txrc);
+-+		spin_unlock_bh(&sta->rate_ctrl_lock);
+-+	} else {
+-+		ref->ops->get_rate(ref->priv, NULL, NULL, txrc);
+-+	}
+- 
+- 	if (sdata->local->hw.flags & IEEE80211_HW_SUPPORTS_RC_TABLE)
+- 		return;
+---- a/net/mac80211/rate.h
+-+++ b/net/mac80211/rate.h
+-@@ -42,10 +42,12 @@ static inline void rate_control_tx_statu
+- 	if (!ref || !test_sta_flag(sta, WLAN_STA_RATE_CONTROL))
+- 		return;
+- 
+-+	spin_lock_bh(&sta->rate_ctrl_lock);
+- 	if (ref->ops->tx_status)
+- 		ref->ops->tx_status(ref->priv, sband, ista, priv_sta, skb);
+- 	else
+- 		ref->ops->tx_status_noskb(ref->priv, sband, ista, priv_sta, info);
+-+	spin_unlock_bh(&sta->rate_ctrl_lock);
+- }
+- 
+- static inline void
+-@@ -64,7 +66,9 @@ rate_control_tx_status_noskb(struct ieee
+- 	if (WARN_ON_ONCE(!ref->ops->tx_status_noskb))
+- 		return;
+- 
+-+	spin_lock_bh(&sta->rate_ctrl_lock);
+- 	ref->ops->tx_status_noskb(ref->priv, sband, ista, priv_sta, info);
+-+	spin_unlock_bh(&sta->rate_ctrl_lock);
+- }
+- 
+- static inline void rate_control_rate_init(struct sta_info *sta)
+-@@ -91,8 +95,10 @@ static inline void rate_control_rate_ini
+- 
+- 	sband = local->hw.wiphy->bands[chanctx_conf->def.chan->band];
+- 
+-+	spin_lock_bh(&sta->rate_ctrl_lock);
+- 	ref->ops->rate_init(ref->priv, sband, &chanctx_conf->def, ista,
+- 			    priv_sta);
+-+	spin_unlock_bh(&sta->rate_ctrl_lock);
+- 	rcu_read_unlock();
+- 	set_sta_flag(sta, WLAN_STA_RATE_CONTROL);
+- }
+-@@ -115,18 +121,20 @@ static inline void rate_control_rate_upd
+- 			return;
+- 		}
+- 
+-+		spin_lock_bh(&sta->rate_ctrl_lock);
+- 		ref->ops->rate_update(ref->priv, sband, &chanctx_conf->def,
+- 				      ista, priv_sta, changed);
+-+		spin_unlock_bh(&sta->rate_ctrl_lock);
+- 		rcu_read_unlock();
+- 	}
+- 	drv_sta_rc_update(local, sta->sdata, &sta->sta, changed);
+- }
+- 
+- static inline void *rate_control_alloc_sta(struct rate_control_ref *ref,
+--					   struct ieee80211_sta *sta,
+--					   gfp_t gfp)
+-+					   struct sta_info *sta, gfp_t gfp)
+- {
+--	return ref->ops->alloc_sta(ref->priv, sta, gfp);
+-+	spin_lock_init(&sta->rate_ctrl_lock);
+-+	return ref->ops->alloc_sta(ref->priv, &sta->sta, gfp);
+- }
+- 
+- static inline void rate_control_free_sta(struct sta_info *sta)
+---- a/net/mac80211/sta_info.c
+-+++ b/net/mac80211/sta_info.c
+-@@ -286,7 +286,7 @@ static int sta_prepare_rate_control(stru
+- 
+- 	sta->rate_ctrl = local->rate_ctrl;
+- 	sta->rate_ctrl_priv = rate_control_alloc_sta(sta->rate_ctrl,
+--						     &sta->sta, gfp);
+-+						     sta, gfp);
+- 	if (!sta->rate_ctrl_priv)
+- 		return -ENOMEM;
+- 
+---- a/net/mac80211/sta_info.h
+-+++ b/net/mac80211/sta_info.h
+-@@ -349,6 +349,7 @@ struct sta_info {
+- 	u8 ptk_idx;
+- 	struct rate_control_ref *rate_ctrl;
+- 	void *rate_ctrl_priv;
+-+	spinlock_t rate_ctrl_lock;
+- 	spinlock_t lock;
+- 
+- 	struct work_struct drv_deliver_wk;
+diff --git a/package/kernel/mac80211/patches/302-ath10k-Delay-device-access-after-cold-reset.patch b/package/kernel/mac80211/patches/302-ath10k-Delay-device-access-after-cold-reset.patch
+new file mode 100644
+index 0000000..820aa9a
+--- /dev/null
++++ b/package/kernel/mac80211/patches/302-ath10k-Delay-device-access-after-cold-reset.patch
+@@ -0,0 +1,56 @@
++From: Vasanthakumar Thiagarajan <vthiagar@qti.qualcomm.com>
++Date: Fri, 3 Jul 2015 11:45:42 +0530
++Subject: [PATCH] ath10k: Delay device access after cold reset
++
++It is observed that during cold reset pcie access right
++after a write operation to SOC_GLOBAL_RESET_ADDRESS causes
++Data Bus Error and system hard lockup. The reason
++for bus error is that pcie needs some time to get
++back to stable state for any transaction during cold reset. Add
++delay of 20 msecs after write of SOC_GLOBAL_RESET_ADDRESS
++to fix this issue.
++
++Signed-off-by: Vasanthakumar Thiagarajan <vthiagar@qti.qualcomm.com>
++---
++
++--- a/drivers/net/wireless/ath/ath10k/pci.c
+++++ b/drivers/net/wireless/ath/ath10k/pci.c
++@@ -2761,7 +2761,6 @@ static int ath10k_pci_wait_for_target_in
++ 
++ static int ath10k_pci_cold_reset(struct ath10k *ar)
++ {
++-	int i;
++ 	u32 val;
++ 
++ 	ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot cold reset\n");
++@@ -2777,23 +2776,18 @@ static int ath10k_pci_cold_reset(struct
++ 	val |= 1;
++ 	ath10k_pci_reg_write32(ar, SOC_GLOBAL_RESET_ADDRESS, val);
++ 
++-	for (i = 0; i < ATH_PCI_RESET_WAIT_MAX; i++) {
++-		if (ath10k_pci_reg_read32(ar, RTC_STATE_ADDRESS) &
++-					  RTC_STATE_COLD_RESET_MASK)
++-			break;
++-		msleep(1);
++-	}
+++	/* After writing into SOC_GLOBAL_RESET to put device into
+++	 * reset and pulling out of reset pcie may not be stable
+++	 * for any immediate pcie register access and cause bus error,
+++	 * add delay before any pcie access request to fix this issue.
+++	 */
+++	msleep(20);
++ 
++ 	/* Pull Target, including PCIe, out of RESET. */
++ 	val &= ~1;
++ 	ath10k_pci_reg_write32(ar, SOC_GLOBAL_RESET_ADDRESS, val);
++ 
++-	for (i = 0; i < ATH_PCI_RESET_WAIT_MAX; i++) {
++-		if (!(ath10k_pci_reg_read32(ar, RTC_STATE_ADDRESS) &
++-					    RTC_STATE_COLD_RESET_MASK))
++-			break;
++-		msleep(1);
++-	}
+++	msleep(20);
++ 
++ 	ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot cold reset complete\n");
++ 
+diff --git a/package/kernel/mac80211/patches/302-ath9k-restart-only-triggering-DFS-detector-line.patch b/package/kernel/mac80211/patches/302-ath9k-restart-only-triggering-DFS-detector-line.patch
+deleted file mode 100644
+index e54e16e..0000000
+--- a/package/kernel/mac80211/patches/302-ath9k-restart-only-triggering-DFS-detector-line.patch
++++ /dev/null
+@@ -1,21 +0,0 @@
+-From: Zefir Kurtisi <zefir.kurtisi@neratec.com>
+-Date: Tue, 10 Mar 2015 17:49:29 +0100
+-Subject: [PATCH] ath9k: restart only triggering DFS detector line
+-
+-To support HT40 DFS mode, a triggering detector must
+-reset only itself but not other detector lines.
+-
+-Signed-off-by: Zefir Kurtisi <zefir.kurtisi@neratec.com>
+----
+-
+---- a/drivers/net/wireless/ath/dfs_pattern_detector.c
+-+++ b/drivers/net/wireless/ath/dfs_pattern_detector.c
+-@@ -289,7 +289,7 @@ dpd_add_pulse(struct dfs_pattern_detecto
+- 				"count=%d, count_false=%d\n",
+- 				event->freq, pd->rs->type_id,
+- 				ps->pri, ps->count, ps->count_falses);
+--			channel_detector_reset(dpd, cd);
+-+			pd->reset(pd, dpd->last_pulse_ts);
+- 			return true;
+- 		}
+- 	}
+diff --git a/package/kernel/mac80211/patches/303-ath9k-add-DFS-support-for-extension-channel.patch b/package/kernel/mac80211/patches/303-ath9k-add-DFS-support-for-extension-channel.patch
+deleted file mode 100644
+index ed268ea..0000000
+--- a/package/kernel/mac80211/patches/303-ath9k-add-DFS-support-for-extension-channel.patch
++++ /dev/null
+@@ -1,76 +0,0 @@
+-From: Zefir Kurtisi <zefir.kurtisi@neratec.com>
+-Date: Tue, 10 Mar 2015 17:49:30 +0100
+-Subject: [PATCH] ath9k: add DFS support for extension channel
+-
+-In HT40 modes, pulse events on primary and extension
+-channel are processed individually. If valid, a pulse
+-event will be fed into the detector
+-* for primary frequency, or
+-* for extension frequency (+/-20MHz based on HT40-mode)
+-* or both
+-
+-With that, a 40MHz radar will result in two individual
+-radar events.
+-
+-Signed-off-by: Zefir Kurtisi <zefir.kurtisi@neratec.com>
+----
+-
+---- a/drivers/net/wireless/ath/ath9k/dfs.c
+-+++ b/drivers/net/wireless/ath/ath9k/dfs.c
+-@@ -126,8 +126,19 @@ ath9k_postprocess_radar_event(struct ath
+- 	DFS_STAT_INC(sc, pulses_detected);
+- 	return true;
+- }
+--#undef PRI_CH_RADAR_FOUND
+--#undef EXT_CH_RADAR_FOUND
+-+
+-+static void
+-+ath9k_dfs_process_radar_pulse(struct ath_softc *sc, struct pulse_event *pe)
+-+{
+-+	struct dfs_pattern_detector *pd = sc->dfs_detector;
+-+	DFS_STAT_INC(sc, pulses_processed);
+-+	if (pd == NULL)
+-+		return;
+-+	if (!pd->add_pulse(pd, pe))
+-+		return;
+-+	DFS_STAT_INC(sc, radar_detected);
+-+	ieee80211_radar_detected(sc->hw);
+-+}
+- 
+- /*
+-  * DFS: check PHY-error for radar pulse and feed the detector
+-@@ -176,18 +187,21 @@ void ath9k_dfs_process_phyerr(struct ath
+- 	ard.pulse_length_pri = vdata_end[-3];
+- 	pe.freq = ah->curchan->channel;
+- 	pe.ts = mactime;
+--	if (ath9k_postprocess_radar_event(sc, &ard, &pe)) {
+--		struct dfs_pattern_detector *pd = sc->dfs_detector;
+--		ath_dbg(common, DFS,
+--			"ath9k_dfs_process_phyerr: channel=%d, ts=%llu, "
+--			"width=%d, rssi=%d, delta_ts=%llu\n",
+--			pe.freq, pe.ts, pe.width, pe.rssi,
+--			pe.ts - sc->dfs_prev_pulse_ts);
+--		sc->dfs_prev_pulse_ts = pe.ts;
+--		DFS_STAT_INC(sc, pulses_processed);
+--		if (pd != NULL && pd->add_pulse(pd, &pe)) {
+--			DFS_STAT_INC(sc, radar_detected);
+--			ieee80211_radar_detected(sc->hw);
+--		}
+-+	if (!ath9k_postprocess_radar_event(sc, &ard, &pe))
+-+		return;
+-+
+-+	ath_dbg(common, DFS,
+-+		"ath9k_dfs_process_phyerr: type=%d, freq=%d, ts=%llu, "
+-+		"width=%d, rssi=%d, delta_ts=%llu\n",
+-+		ard.pulse_bw_info, pe.freq, pe.ts, pe.width, pe.rssi,
+-+		pe.ts - sc->dfs_prev_pulse_ts);
+-+	sc->dfs_prev_pulse_ts = pe.ts;
+-+	if (ard.pulse_bw_info & PRI_CH_RADAR_FOUND)
+-+		ath9k_dfs_process_radar_pulse(sc, &pe);
+-+	if (ard.pulse_bw_info & EXT_CH_RADAR_FOUND) {
+-+		pe.freq += IS_CHAN_HT40PLUS(ah->curchan) ? 20 : -20;
+-+		ath9k_dfs_process_radar_pulse(sc, &pe);
+- 	}
+- }
+-+#undef PRI_CH_RADAR_FOUND
+-+#undef EXT_CH_RADAR_FOUND
+diff --git a/package/kernel/mac80211/patches/303-ath9k-add-fast-xmit-support.patch b/package/kernel/mac80211/patches/303-ath9k-add-fast-xmit-support.patch
+new file mode 100644
+index 0000000..139015c
+--- /dev/null
++++ b/package/kernel/mac80211/patches/303-ath9k-add-fast-xmit-support.patch
+@@ -0,0 +1,17 @@
++From: Felix Fietkau <nbd@openwrt.org>
++Date: Mon, 11 May 2015 18:35:20 +0200
++Subject: [PATCH] ath9k: add fast-xmit support
++
++Signed-off-by: Felix Fietkau <nbd@openwrt.org>
++---
++
++--- a/drivers/net/wireless/ath/ath9k/init.c
+++++ b/drivers/net/wireless/ath/ath9k/init.c
++@@ -826,6 +826,7 @@ static void ath9k_set_hw_capab(struct at
++ 	ieee80211_hw_set(hw, SIGNAL_DBM);
++ 	ieee80211_hw_set(hw, RX_INCLUDES_FCS);
++ 	ieee80211_hw_set(hw, HOST_BROADCAST_PS_BUFFERING);
+++	ieee80211_hw_set(hw, SUPPORT_FAST_XMIT);
++ 
++ 	if (ath9k_ps_enable)
++ 		ieee80211_hw_set(hw, SUPPORTS_PS);
+diff --git a/package/kernel/mac80211/patches/304-ath9k-allow-40MHz-radar-detection-width.patch b/package/kernel/mac80211/patches/304-ath9k-allow-40MHz-radar-detection-width.patch
+deleted file mode 100644
+index e1eab64..0000000
+--- a/package/kernel/mac80211/patches/304-ath9k-allow-40MHz-radar-detection-width.patch
++++ /dev/null
+@@ -1,19 +0,0 @@
+-From: Zefir Kurtisi <zefir.kurtisi@neratec.com>
+-Date: Tue, 10 Mar 2015 17:49:31 +0100
+-Subject: [PATCH] ath9k: allow 40MHz radar detection width
+-
+-Signed-off-by: Zefir Kurtisi <zefir.kurtisi@neratec.com>
+----
+-
+---- a/drivers/net/wireless/ath/ath9k/init.c
+-+++ b/drivers/net/wireless/ath/ath9k/init.c
+-@@ -763,7 +763,8 @@ static const struct ieee80211_iface_comb
+- 		.num_different_channels = 1,
+- 		.beacon_int_infra_match = true,
+- 		.radar_detect_widths =	BIT(NL80211_CHAN_WIDTH_20_NOHT) |
+--					BIT(NL80211_CHAN_WIDTH_20),
+-+					BIT(NL80211_CHAN_WIDTH_20) |
+-+					BIT(NL80211_CHAN_WIDTH_40),
+- 	}
+- #endif
+- };
+diff --git a/package/kernel/mac80211/patches/304-ath9k-remove-struct-ath_atx_ac.patch b/package/kernel/mac80211/patches/304-ath9k-remove-struct-ath_atx_ac.patch
+new file mode 100644
+index 0000000..9f04276
+--- /dev/null
++++ b/package/kernel/mac80211/patches/304-ath9k-remove-struct-ath_atx_ac.patch
+@@ -0,0 +1,385 @@
++From: Felix Fietkau <nbd@openwrt.org>
++Date: Sat, 4 Apr 2015 18:39:06 +0200
++Subject: [PATCH] ath9k: remove struct ath_atx_ac
++
++struct ath_atx_ac contains a list of active TIDs belonging to one WMM AC.
++This patch changes the code to track active station TIDs in the txq directly.
++
++Signed-off-by: Felix Fietkau <nbd@openwrt.org>
++---
++
++--- a/drivers/net/wireless/ath/ath9k/ath9k.h
+++++ b/drivers/net/wireless/ath/ath9k/ath9k.h
++@@ -173,14 +173,6 @@ struct ath_txq {
++ 	struct sk_buff_head complete_q;
++ };
++ 
++-struct ath_atx_ac {
++-	struct ath_txq *txq;
++-	struct list_head list;
++-	struct list_head tid_q;
++-	bool clear_ps_filter;
++-	bool sched;
++-};
++-
++ struct ath_frame_info {
++ 	struct ath_buf *bf;
++ 	u16 framelen;
++@@ -243,7 +235,7 @@ struct ath_atx_tid {
++ 	struct sk_buff_head buf_q;
++ 	struct sk_buff_head retry_q;
++ 	struct ath_node *an;
++-	struct ath_atx_ac *ac;
+++	struct ath_txq *txq;
++ 	unsigned long tx_buf[BITS_TO_LONGS(ATH_TID_MAX_BUFS)];
++ 	u16 seq_start;
++ 	u16 seq_next;
++@@ -255,6 +247,7 @@ struct ath_atx_tid {
++ 	s8 bar_index;
++ 	bool sched;
++ 	bool active;
+++	bool clear_ps_filter;
++ };
++ 
++ struct ath_node {
++@@ -262,7 +255,6 @@ struct ath_node {
++ 	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];
++-	struct ath_atx_ac ac[IEEE80211_NUM_ACS];
++ 
++ 	u16 maxampdu;
++ 	u8 mpdudensity;
++--- a/drivers/net/wireless/ath/ath9k/xmit.c
+++++ b/drivers/net/wireless/ath/ath9k/xmit.c
++@@ -106,7 +106,6 @@ void ath_txq_unlock_complete(struct ath_
++ static void ath_tx_queue_tid(struct ath_softc *sc, struct ath_txq *txq,
++ 			     struct ath_atx_tid *tid)
++ {
++-	struct ath_atx_ac *ac = tid->ac;
++ 	struct list_head *list;
++ 	struct ath_vif *avp = (struct ath_vif *) tid->an->vif->drv_priv;
++ 	struct ath_chanctx *ctx = avp->chanctx;
++@@ -118,15 +117,8 @@ static void ath_tx_queue_tid(struct ath_
++ 		return;
++ 
++ 	tid->sched = true;
++-	list_add_tail(&tid->list, &ac->tid_q);
++-
++-	if (ac->sched)
++-		return;
++-
++-	ac->sched = true;
++-
++ 	list = &ctx->acq[TID_TO_WME_AC(tid->tidno)];
++-	list_add_tail(&ac->list, list);
+++	list_add_tail(&tid->list, list);
++ }
++ 
++ static struct ath_frame_info *get_frame_info(struct sk_buff *skb)
++@@ -223,7 +215,7 @@ static struct sk_buff *ath_tid_dequeue(s
++ static void
++ ath_tx_tid_change_state(struct ath_softc *sc, struct ath_atx_tid *tid)
++ {
++-	struct ath_txq *txq = tid->ac->txq;
+++	struct ath_txq *txq = tid->txq;
++ 	struct ieee80211_tx_info *tx_info;
++ 	struct sk_buff *skb, *tskb;
++ 	struct ath_buf *bf;
++@@ -252,7 +244,7 @@ ath_tx_tid_change_state(struct ath_softc
++ 
++ static void ath_tx_flush_tid(struct ath_softc *sc, struct ath_atx_tid *tid)
++ {
++-	struct ath_txq *txq = tid->ac->txq;
+++	struct ath_txq *txq = tid->txq;
++ 	struct sk_buff *skb;
++ 	struct ath_buf *bf;
++ 	struct list_head bf_head;
++@@ -659,7 +651,7 @@ static void ath_tx_complete_aggr(struct
++ 			ath_tx_queue_tid(sc, txq, tid);
++ 
++ 			if (ts->ts_status & (ATH9K_TXERR_FILT | ATH9K_TXERR_XRETRY))
++-				tid->ac->clear_ps_filter = true;
+++				tid->clear_ps_filter = true;
++ 		}
++ 	}
++ 
++@@ -749,7 +741,7 @@ static u32 ath_lookup_rate(struct ath_so
++ 	struct ieee80211_tx_rate *rates;
++ 	u32 max_4ms_framelen, frmlen;
++ 	u16 aggr_limit, bt_aggr_limit, legacy = 0;
++-	int q = tid->ac->txq->mac80211_qnum;
+++	int q = tid->txq->mac80211_qnum;
++ 	int i;
++ 
++ 	skb = bf->bf_mpdu;
++@@ -1486,8 +1478,8 @@ static bool ath_tx_sched_aggr(struct ath
++ 	if (list_empty(&bf_q))
++ 		return false;
++ 
++-	if (tid->ac->clear_ps_filter || tid->an->no_ps_filter) {
++-		tid->ac->clear_ps_filter = false;
+++	if (tid->clear_ps_filter || tid->an->no_ps_filter) {
+++		tid->clear_ps_filter = false;
++ 		tx_info->flags |= IEEE80211_TX_CTL_CLEAR_PS_FILT;
++ 	}
++ 
++@@ -1506,7 +1498,7 @@ int ath_tx_aggr_start(struct ath_softc *
++ 
++ 	an = (struct ath_node *)sta->drv_priv;
++ 	txtid = ATH_AN_2_TID(an, tid);
++-	txq = txtid->ac->txq;
+++	txq = txtid->txq;
++ 
++ 	ath_txq_lock(sc, txq);
++ 
++@@ -1540,7 +1532,7 @@ void ath_tx_aggr_stop(struct ath_softc *
++ {
++ 	struct ath_node *an = (struct ath_node *)sta->drv_priv;
++ 	struct ath_atx_tid *txtid = ATH_AN_2_TID(an, tid);
++-	struct ath_txq *txq = txtid->ac->txq;
+++	struct ath_txq *txq = txtid->txq;
++ 
++ 	ath_txq_lock(sc, txq);
++ 	txtid->active = false;
++@@ -1553,7 +1545,6 @@ void ath_tx_aggr_sleep(struct ieee80211_
++ 		       struct ath_node *an)
++ {
++ 	struct ath_atx_tid *tid;
++-	struct ath_atx_ac *ac;
++ 	struct ath_txq *txq;
++ 	bool buffered;
++ 	int tidno;
++@@ -1561,8 +1552,7 @@ void ath_tx_aggr_sleep(struct ieee80211_
++ 	for (tidno = 0, tid = &an->tid[tidno];
++ 	     tidno < IEEE80211_NUM_TIDS; tidno++, tid++) {
++ 
++-		ac = tid->ac;
++-		txq = ac->txq;
+++		txq = tid->txq;
++ 
++ 		ath_txq_lock(sc, txq);
++ 
++@@ -1576,11 +1566,6 @@ void ath_tx_aggr_sleep(struct ieee80211_
++ 		tid->sched = false;
++ 		list_del(&tid->list);
++ 
++-		if (ac->sched) {
++-			ac->sched = false;
++-			list_del(&ac->list);
++-		}
++-
++ 		ath_txq_unlock(sc, txq);
++ 
++ 		ieee80211_sta_set_buffered(sta, tidno, buffered);
++@@ -1590,18 +1575,16 @@ void ath_tx_aggr_sleep(struct ieee80211_
++ void ath_tx_aggr_wakeup(struct ath_softc *sc, struct ath_node *an)
++ {
++ 	struct ath_atx_tid *tid;
++-	struct ath_atx_ac *ac;
++ 	struct ath_txq *txq;
++ 	int tidno;
++ 
++ 	for (tidno = 0, tid = &an->tid[tidno];
++ 	     tidno < IEEE80211_NUM_TIDS; tidno++, tid++) {
++ 
++-		ac = tid->ac;
++-		txq = ac->txq;
+++		txq = tid->txq;
++ 
++ 		ath_txq_lock(sc, txq);
++-		ac->clear_ps_filter = true;
+++		tid->clear_ps_filter = true;
++ 
++ 		if (ath_tid_has_buffered(tid)) {
++ 			ath_tx_queue_tid(sc, txq, tid);
++@@ -1621,7 +1604,7 @@ void ath_tx_aggr_resume(struct ath_softc
++ 
++ 	an = (struct ath_node *)sta->drv_priv;
++ 	tid = ATH_AN_2_TID(an, tidno);
++-	txq = tid->ac->txq;
+++	txq = tid->txq;
++ 
++ 	ath_txq_lock(sc, txq);
++ 
++@@ -1660,7 +1643,7 @@ void ath9k_release_buffered_frames(struc
++ 
++ 		tid = ATH_AN_2_TID(an, i);
++ 
++-		ath_txq_lock(sc, tid->ac->txq);
+++		ath_txq_lock(sc, tid->txq);
++ 		while (nframes > 0) {
++ 			bf = ath_tx_get_tid_subframe(sc, sc->tx.uapsdq, tid, &tid_q);
++ 			if (!bf)
++@@ -1684,7 +1667,7 @@ void ath9k_release_buffered_frames(struc
++ 			if (an->sta && !ath_tid_has_buffered(tid))
++ 				ieee80211_sta_set_buffered(an->sta, i, false);
++ 		}
++-		ath_txq_unlock_complete(sc, tid->ac->txq);
+++		ath_txq_unlock_complete(sc, tid->txq);
++ 	}
++ 
++ 	if (list_empty(&bf_q))
++@@ -1933,9 +1916,8 @@ void ath_tx_cleanupq(struct ath_softc *s
++ void ath_txq_schedule(struct ath_softc *sc, struct ath_txq *txq)
++ {
++ 	struct ath_common *common = ath9k_hw_common(sc->sc_ah);
++-	struct ath_atx_ac *ac, *last_ac;
++ 	struct ath_atx_tid *tid, *last_tid;
++-	struct list_head *ac_list;
+++	struct list_head *tid_list;
++ 	bool sent = false;
++ 
++ 	if (txq->mac80211_qnum < 0)
++@@ -1945,63 +1927,46 @@ void ath_txq_schedule(struct ath_softc *
++ 		return;
++ 
++ 	spin_lock_bh(&sc->chan_lock);
++-	ac_list = &sc->cur_chan->acq[txq->mac80211_qnum];
+++	tid_list = &sc->cur_chan->acq[txq->mac80211_qnum];
++ 
++-	if (list_empty(ac_list)) {
+++	if (list_empty(tid_list)) {
++ 		spin_unlock_bh(&sc->chan_lock);
++ 		return;
++ 	}
++ 
++ 	rcu_read_lock();
++ 
++-	last_ac = list_entry(ac_list->prev, struct ath_atx_ac, list);
++-	while (!list_empty(ac_list)) {
+++	last_tid = list_entry(tid_list->prev, struct ath_atx_tid, list);
+++	while (!list_empty(tid_list)) {
++ 		bool stop = false;
++ 
++ 		if (sc->cur_chan->stopped)
++ 			break;
++ 
++-		ac = list_first_entry(ac_list, struct ath_atx_ac, list);
++-		last_tid = list_entry(ac->tid_q.prev, struct ath_atx_tid, list);
++-		list_del(&ac->list);
++-		ac->sched = false;
++-
++-		while (!list_empty(&ac->tid_q)) {
++-
++-			tid = list_first_entry(&ac->tid_q, struct ath_atx_tid,
++-					       list);
++-			list_del(&tid->list);
++-			tid->sched = false;
++-
++-			if (ath_tx_sched_aggr(sc, txq, tid, &stop))
++-				sent = true;
++-
++-			/*
++-			 * add tid to round-robin queue if more frames
++-			 * are pending for the tid
++-			 */
++-			if (ath_tid_has_buffered(tid))
++-				ath_tx_queue_tid(sc, txq, tid);
+++		tid = list_first_entry(tid_list, struct ath_atx_tid, list);
+++		list_del(&tid->list);
+++		tid->sched = false;
++ 
++-			if (stop || tid == last_tid)
++-				break;
++-		}
+++		if (ath_tx_sched_aggr(sc, txq, tid, &stop))
+++			sent = true;
++ 
++-		if (!list_empty(&ac->tid_q) && !ac->sched) {
++-			ac->sched = true;
++-			list_add_tail(&ac->list, ac_list);
++-		}
+++		/*
+++		 * add tid to round-robin queue if more frames
+++		 * are pending for the tid
+++		 */
+++		if (ath_tid_has_buffered(tid))
+++			ath_tx_queue_tid(sc, txq, tid);
++ 
++ 		if (stop)
++ 			break;
++ 
++-		if (ac == last_ac) {
+++		if (tid == last_tid) {
++ 			if (!sent)
++ 				break;
++ 
++ 			sent = false;
++-			last_ac = list_entry(ac_list->prev,
++-					     struct ath_atx_ac, list);
+++			last_tid = list_entry(tid_list->prev,
+++					      struct ath_atx_tid, list);
++ 		}
++ 	}
++ 
++@@ -2391,10 +2356,10 @@ int ath_tx_start(struct ieee80211_hw *hw
++ 		txq = sc->tx.uapsdq;
++ 		ath_txq_lock(sc, txq);
++ 	} else if (txctl->an && queue) {
++-		WARN_ON(tid->ac->txq != txctl->txq);
+++		WARN_ON(tid->txq != txctl->txq);
++ 
++ 		if (info->flags & IEEE80211_TX_CTL_CLEAR_PS_FILT)
++-			tid->ac->clear_ps_filter = true;
+++			tid->clear_ps_filter = true;
++ 
++ 		/*
++ 		 * Add this frame to software queue for scheduling later
++@@ -2888,7 +2853,6 @@ int ath_tx_init(struct ath_softc *sc, in
++ void ath_tx_node_init(struct ath_softc *sc, struct ath_node *an)
++ {
++ 	struct ath_atx_tid *tid;
++-	struct ath_atx_ac *ac;
++ 	int tidno, acno;
++ 
++ 	for (tidno = 0, tid = &an->tid[tidno];
++@@ -2901,24 +2865,16 @@ void ath_tx_node_init(struct ath_softc *
++ 		tid->baw_head  = tid->baw_tail = 0;
++ 		tid->sched     = false;
++ 		tid->active	   = false;
+++		tid->clear_ps_filter = true;
++ 		__skb_queue_head_init(&tid->buf_q);
++ 		__skb_queue_head_init(&tid->retry_q);
++ 		acno = TID_TO_WME_AC(tidno);
++-		tid->ac = &an->ac[acno];
++-	}
++-
++-	for (acno = 0, ac = &an->ac[acno];
++-	     acno < IEEE80211_NUM_ACS; acno++, ac++) {
++-		ac->sched    = false;
++-		ac->clear_ps_filter = true;
++-		ac->txq = sc->tx.txq_map[acno];
++-		INIT_LIST_HEAD(&ac->tid_q);
+++		tid->txq = sc->tx.txq_map[acno];
++ 	}
++ }
++ 
++ void ath_tx_node_cleanup(struct ath_softc *sc, struct ath_node *an)
++ {
++-	struct ath_atx_ac *ac;
++ 	struct ath_atx_tid *tid;
++ 	struct ath_txq *txq;
++ 	int tidno;
++@@ -2926,8 +2882,7 @@ void ath_tx_node_cleanup(struct ath_soft
++ 	for (tidno = 0, tid = &an->tid[tidno];
++ 	     tidno < IEEE80211_NUM_TIDS; tidno++, tid++) {
++ 
++-		ac = tid->ac;
++-		txq = ac->txq;
+++		txq = tid->txq;
++ 
++ 		ath_txq_lock(sc, txq);
++ 
++@@ -2936,11 +2891,6 @@ void ath_tx_node_cleanup(struct ath_soft
++ 			tid->sched = false;
++ 		}
++ 
++-		if (ac->sched) {
++-			list_del(&ac->list);
++-			tid->ac->sched = false;
++-		}
++-
++ 		ath_tid_drain(sc, txq, tid);
++ 		tid->active = false;
++ 
+diff --git a/package/kernel/mac80211/patches/305-ath5k-channel-change-fix.patch b/package/kernel/mac80211/patches/305-ath5k-channel-change-fix.patch
+deleted file mode 100644
+index 4cfa53f..0000000
+--- a/package/kernel/mac80211/patches/305-ath5k-channel-change-fix.patch
++++ /dev/null
+@@ -1,137 +0,0 @@
+-From: Sergey Ryazanov <ryazanov.s.a@gmail.com>
+-Date: Wed, 4 Mar 2015 05:12:10 +0300
+-Subject: [PATCH] ath5k: channel change fix
+-
+-ath5k updates the channel pointer and after that it stops the Rx logic
+-and apply channel to HW. In case of channel switch, such sequence
+-creates a small window when a frame, which is received on the old
+-channel is considered as a frame received on the new one.
+-
+-The most notable consequence of this situation occurs during the switch
+-from 2 GHz band (CCK+OFDM) to the 5GHz band (OFDM-only). Frame received
+-with CCK rate, e.g. beacon received at the 1mbps, causes the following
+-warning:
+-
+-  WARNING: at ath5k/base.c:589 ath5k_tasklet_rx+0x318/0x6ec [ath5k]()
+-  invalid hw_rix: 1a
+-  [..]
+-  Call Trace:
+-  [<802656a8>] show_stack+0x48/0x70
+-  [<802dd92c>] warn_slowpath_common+0x88/0xbc
+-  [<802dd98c>] warn_slowpath_fmt+0x2c/0x38
+-  [<81b51be8>] ath5k_tasklet_rx+0x318/0x6ec [ath5k]
+-  [<8028ac64>] tasklet_action+0x8c/0xf0
+-  [<80075804>] __do_softirq+0x180/0x32c
+-  [<80196ce8>] irq_exit+0x54/0x70
+-  [<80041848>] ret_from_irq+0x0/0x4
+-  [<80182fdc>] ioread32+0x4/0xc
+-  [<81b4c42c>] ath5k_hw_set_sleep_clock+0x2ec/0x474 [ath5k]
+-  [<81b4cf28>] ath5k_hw_reset+0x50/0xeb8 [ath5k]
+-  [<81b50900>] ath5k_reset+0xd4/0x310 [ath5k]
+-  [<81b557e8>] ath5k_config+0x4c/0x104 [ath5k]
+-  [<80d01770>] ieee80211_hw_config+0x2f4/0x35c [mac80211]
+-  [<80d09aa8>] ieee80211_scan_work+0x2e4/0x414 [mac80211]
+-  [<8022c3f4>] process_one_work+0x28c/0x400
+-  [<802df8f8>] worker_thread+0x258/0x3c0
+-  [<801b5710>] kthread+0xe0/0xec
+-  [<800418a8>] ret_from_kernel_thread+0x14/0x1c
+-
+-The easiest way to reproduce this warning is to run scan with dualband
+-NIC in noisy environments, when the channel 11 runs multiple APs. In my
+-tests if the APs num >= 12, the warning appears in the first few
+-seconds of scanning.
+-
+-In order to fix this, the Rx disable code moved to a higher level and
+-placed before the channel pointer update. This is also makes the code a
+-bit more symmetrical, since we disable and enable the Rx in the same
+-function.
+-
+-In fact, at the pointer update time new frames should not appear,
+-because interrupt generation at this point should already be disabled.
+-The next patch should address this issue.
+-
+-CC: Jiri Slaby <jirislaby@gmail.com>
+-CC: Nick Kossifidis <mickflemm@gmail.com>
+-CC: Luis R. Rodriguez <mcgrof@do-not-panic.com>
+-Reported-by: Christophe Prevotaux <cprevotaux@nltinc.com>
+-Tested-by: Christophe Prevotaux <cprevotaux@nltinc.com>
+-Tested-by: Eric Bree <ebree@nltinc.com>
+-Signed-off-by: Sergey Ryazanov <ryazanov.s.a@gmail.com>
+----
+-
+---- a/drivers/net/wireless/ath/ath5k/base.c
+-+++ b/drivers/net/wireless/ath/ath5k/base.c
+-@@ -2858,7 +2858,7 @@ ath5k_reset(struct ath5k_hw *ah, struct
+- {
+- 	struct ath_common *common = ath5k_hw_common(ah);
+- 	int ret, ani_mode;
+--	bool fast;
+-+	bool fast = chan && modparam_fastchanswitch ? 1 : 0;
+- 
+- 	ATH5K_DBG(ah, ATH5K_DEBUG_RESET, "resetting\n");
+- 
+-@@ -2876,11 +2876,29 @@ ath5k_reset(struct ath5k_hw *ah, struct
+- 	 * so we should also free any remaining
+- 	 * tx buffers */
+- 	ath5k_drain_tx_buffs(ah);
+-+
+-+	/* Stop PCU */
+-+	ath5k_hw_stop_rx_pcu(ah);
+-+
+-+	/* Stop DMA
+-+	 *
+-+	 * Note: If DMA didn't stop continue
+-+	 * since only a reset will fix it.
+-+	 */
+-+	ret = ath5k_hw_dma_stop(ah);
+-+
+-+	/* RF Bus grant won't work if we have pending
+-+	 * frames
+-+	 */
+-+	if (ret && fast) {
+-+		ATH5K_DBG(ah, ATH5K_DEBUG_RESET,
+-+			  "DMA didn't stop, falling back to normal reset\n");
+-+		fast = false;
+-+	}
+-+
+- 	if (chan)
+- 		ah->curchan = chan;
+- 
+--	fast = ((chan != NULL) && modparam_fastchanswitch) ? 1 : 0;
+--
+- 	ret = ath5k_hw_reset(ah, ah->opmode, ah->curchan, fast, skip_pcu);
+- 	if (ret) {
+- 		ATH5K_ERR(ah, "can't reset hardware (%d)\n", ret);
+---- a/drivers/net/wireless/ath/ath5k/reset.c
+-+++ b/drivers/net/wireless/ath/ath5k/reset.c
+-@@ -1169,30 +1169,6 @@ ath5k_hw_reset(struct ath5k_hw *ah, enum
+- 	if (ah->ah_version == AR5K_AR5212)
+- 		ath5k_hw_set_sleep_clock(ah, false);
+- 
+--	/*
+--	 * Stop PCU
+--	 */
+--	ath5k_hw_stop_rx_pcu(ah);
+--
+--	/*
+--	 * Stop DMA
+--	 *
+--	 * Note: If DMA didn't stop continue
+--	 * since only a reset will fix it.
+--	 */
+--	ret = ath5k_hw_dma_stop(ah);
+--
+--	/* RF Bus grant won't work if we have pending
+--	 * frames */
+--	if (ret && fast) {
+--		ATH5K_DBG(ah, ATH5K_DEBUG_RESET,
+--			"DMA didn't stop, falling back to normal reset\n");
+--		fast = false;
+--		/* Non fatal, just continue with
+--		 * normal reset */
+--		ret = 0;
+--	}
+--
+- 	mode = channel->hw_value;
+- 	switch (mode) {
+- 	case AR5K_MODE_11A:
+diff --git a/package/kernel/mac80211/patches/305-ath9k-remove-the-sched-field-in-struct-ath_atx_tid.patch b/package/kernel/mac80211/patches/305-ath9k-remove-the-sched-field-in-struct-ath_atx_tid.patch
+new file mode 100644
+index 0000000..ec860dc
+--- /dev/null
++++ b/package/kernel/mac80211/patches/305-ath9k-remove-the-sched-field-in-struct-ath_atx_tid.patch
+@@ -0,0 +1,90 @@
++From: Felix Fietkau <nbd@openwrt.org>
++Date: Sat, 4 Apr 2015 18:42:33 +0200
++Subject: [PATCH] ath9k: remove the sched field in struct ath_atx_tid
++
++Use list_empty(&tid->list) instead
++
++Signed-off-by: Felix Fietkau <nbd@openwrt.org>
++---
++
++--- a/drivers/net/wireless/ath/ath9k/ath9k.h
+++++ b/drivers/net/wireless/ath/ath9k/ath9k.h
++@@ -245,7 +245,6 @@ struct ath_atx_tid {
++ 	int baw_tail;   /* next unused tx buffer slot */
++ 
++ 	s8 bar_index;
++-	bool sched;
++ 	bool active;
++ 	bool clear_ps_filter;
++ };
++--- a/drivers/net/wireless/ath/ath9k/xmit.c
+++++ b/drivers/net/wireless/ath/ath9k/xmit.c
++@@ -113,12 +113,9 @@ static void ath_tx_queue_tid(struct ath_
++ 	if (!ctx)
++ 		return;
++ 
++-	if (tid->sched)
++-		return;
++-
++-	tid->sched = true;
++ 	list = &ctx->acq[TID_TO_WME_AC(tid->tidno)];
++-	list_add_tail(&tid->list, list);
+++	if (list_empty(&tid->list))
+++		list_add_tail(&tid->list, list);
++ }
++ 
++ static struct ath_frame_info *get_frame_info(struct sk_buff *skb)
++@@ -1556,15 +1553,14 @@ void ath_tx_aggr_sleep(struct ieee80211_
++ 
++ 		ath_txq_lock(sc, txq);
++ 
++-		if (!tid->sched) {
+++		if (list_empty(&tid->list)) {
++ 			ath_txq_unlock(sc, txq);
++ 			continue;
++ 		}
++ 
++ 		buffered = ath_tid_has_buffered(tid);
++ 
++-		tid->sched = false;
++-		list_del(&tid->list);
+++		list_del_init(&tid->list);
++ 
++ 		ath_txq_unlock(sc, txq);
++ 
++@@ -1944,8 +1940,7 @@ void ath_txq_schedule(struct ath_softc *
++ 			break;
++ 
++ 		tid = list_first_entry(tid_list, struct ath_atx_tid, list);
++-		list_del(&tid->list);
++-		tid->sched = false;
+++		list_del_init(&tid->list);
++ 
++ 		if (ath_tx_sched_aggr(sc, txq, tid, &stop))
++ 			sent = true;
++@@ -2863,11 +2858,11 @@ void ath_tx_node_init(struct ath_softc *
++ 		tid->seq_start = tid->seq_next = 0;
++ 		tid->baw_size  = WME_MAX_BA;
++ 		tid->baw_head  = tid->baw_tail = 0;
++-		tid->sched     = false;
++ 		tid->active	   = false;
++ 		tid->clear_ps_filter = true;
++ 		__skb_queue_head_init(&tid->buf_q);
++ 		__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];
++ 	}
++@@ -2886,10 +2881,8 @@ void ath_tx_node_cleanup(struct ath_soft
++ 
++ 		ath_txq_lock(sc, txq);
++ 
++-		if (tid->sched) {
++-			list_del(&tid->list);
++-			tid->sched = false;
++-		}
+++		if (!list_empty(&tid->list))
+++			list_del_init(&tid->list);
++ 
++ 		ath_tid_drain(sc, txq, tid);
++ 		tid->active = false;
+diff --git a/package/kernel/mac80211/patches/306-ath5k-fix-reset-race.patch b/package/kernel/mac80211/patches/306-ath5k-fix-reset-race.patch
+deleted file mode 100644
+index 85a1904..0000000
+--- a/package/kernel/mac80211/patches/306-ath5k-fix-reset-race.patch
++++ /dev/null
+@@ -1,96 +0,0 @@
+-From: Sergey Ryazanov <ryazanov.s.a@gmail.com>
+-Date: Wed, 4 Mar 2015 05:12:11 +0300
+-Subject: [PATCH] ath5k: fix reset race
+-
+-To prepare for reset ath5k should finish all asynchronous tasks. At
+-first, it disables the interrupt generation, then it waits for the
+-interrupt handler and tasklets completion, and then proceeds to the HW
+-configuration update. But it does not consider that the interrupt
+-handler or tasklet re-enables the interrupt generation. And we fall in a
+-situation when ath5k assumes that interrupts are disabled, but it is
+-not.
+-
+-This can lead to different consequences, such as reception of the frame,
+-when we do not expect it. Under certain circumstances, this can lead to
+-the following warning:
+-
+-  WARNING: at ath5k/base.c:589 ath5k_tasklet_rx+0x318/0x6ec [ath5k]()
+-  invalid hw_rix: 1a
+-  [..]
+-  Call Trace:
+-  [<802656a8>] show_stack+0x48/0x70
+-  [<802dd92c>] warn_slowpath_common+0x88/0xbc
+-  [<802dd98c>] warn_slowpath_fmt+0x2c/0x38
+-  [<81b51be8>] ath5k_tasklet_rx+0x318/0x6ec [ath5k]
+-  [<8028ac64>] tasklet_action+0x8c/0xf0
+-  [<80075804>] __do_softirq+0x180/0x32c
+-  [<80196ce8>] irq_exit+0x54/0x70
+-  [<80041848>] ret_from_irq+0x0/0x4
+-  [<80182fdc>] ioread32+0x4/0xc
+-  [<81b4c42c>] ath5k_hw_set_sleep_clock+0x2ec/0x474 [ath5k]
+-  [<81b4cf28>] ath5k_hw_reset+0x50/0xeb8 [ath5k]
+-  [<81b50900>] ath5k_reset+0xd4/0x310 [ath5k]
+-  [<81b557e8>] ath5k_config+0x4c/0x104 [ath5k]
+-  [<80d01770>] ieee80211_hw_config+0x2f4/0x35c [mac80211]
+-  [<80d09aa8>] ieee80211_scan_work+0x2e4/0x414 [mac80211]
+-  [<8022c3f4>] process_one_work+0x28c/0x400
+-  [<802df8f8>] worker_thread+0x258/0x3c0
+-  [<801b5710>] kthread+0xe0/0xec
+-  [<800418a8>] ret_from_kernel_thread+0x14/0x1c
+-
+-Fix this issue by adding a new status flag, which forbids to re-enable
+-the interrupt generation until the HW configuration is completed.
+-
+-Note: previous patch, which reorders the Rx disable code helps to avoid
+-the above warning, but not fixes the root cause of unexpected frame
+-receiving.
+-
+-CC: Jiri Slaby <jirislaby@gmail.com>
+-CC: Nick Kossifidis <mickflemm@gmail.com>
+-CC: Luis R. Rodriguez <mcgrof@do-not-panic.com>
+-Reported-by: Christophe Prevotaux <cprevotaux@nltinc.com>
+-Tested-by: Christophe Prevotaux <cprevotaux@nltinc.com>
+-Tested-by: Eric Bree <ebree@nltinc.com>
+-Signed-off-by: Sergey Ryazanov <ryazanov.s.a@gmail.com>
+----
+-
+---- a/drivers/net/wireless/ath/ath5k/ath5k.h
+-+++ b/drivers/net/wireless/ath/ath5k/ath5k.h
+-@@ -1283,6 +1283,7 @@ struct ath5k_hw {
+- #define ATH_STAT_PROMISC	1
+- #define ATH_STAT_LEDSOFT	2		/* enable LED gpio status */
+- #define ATH_STAT_STARTED	3		/* opened & irqs enabled */
+-+#define ATH_STAT_RESET		4		/* hw reset */
+- 
+- 	unsigned int		filter_flags;	/* HW flags, AR5K_RX_FILTER_* */
+- 	unsigned int		fif_filter_flags; /* Current FIF_* filter flags */
+---- a/drivers/net/wireless/ath/ath5k/base.c
+-+++ b/drivers/net/wireless/ath/ath5k/base.c
+-@@ -1523,6 +1523,9 @@ ath5k_set_current_imask(struct ath5k_hw
+- 	enum ath5k_int imask;
+- 	unsigned long flags;
+- 
+-+	if (test_bit(ATH_STAT_RESET, ah->status))
+-+		return;
+-+
+- 	spin_lock_irqsave(&ah->irqlock, flags);
+- 	imask = ah->imask;
+- 	if (ah->rx_pending)
+-@@ -2862,6 +2865,8 @@ ath5k_reset(struct ath5k_hw *ah, struct
+- 
+- 	ATH5K_DBG(ah, ATH5K_DEBUG_RESET, "resetting\n");
+- 
+-+	__set_bit(ATH_STAT_RESET, ah->status);
+-+
+- 	ath5k_hw_set_imr(ah, 0);
+- 	synchronize_irq(ah->irq);
+- 	ath5k_stop_tasklets(ah);
+-@@ -2952,6 +2957,8 @@ ath5k_reset(struct ath5k_hw *ah, struct
+- 	 */
+- /*	ath5k_chan_change(ah, c); */
+- 
+-+	__clear_bit(ATH_STAT_RESET, ah->status);
+-+
+- 	ath5k_beacon_config(ah);
+- 	/* intrs are enabled by ath5k_beacon_config */
+- 
+diff --git a/package/kernel/mac80211/patches/306-mac80211-Deinline-rate_control_rate_init-rate_contro.patch b/package/kernel/mac80211/patches/306-mac80211-Deinline-rate_control_rate_init-rate_contro.patch
+new file mode 100644
+index 0000000..928c93b
+--- /dev/null
++++ b/package/kernel/mac80211/patches/306-mac80211-Deinline-rate_control_rate_init-rate_contro.patch
+@@ -0,0 +1,161 @@
++From: Denys Vlasenko <dvlasenk@redhat.com>
++Date: Wed, 15 Jul 2015 14:56:06 +0200
++Subject: [PATCH] mac80211: Deinline rate_control_rate_init,
++ rate_control_rate_update
++
++With this .config: http://busybox.net/~vda/kernel_config,
++after deinlining these functions have sizes and callsite counts
++as follows:
++
++rate_control_rate_init: 554 bytes, 8 calls
++rate_control_rate_update: 1596 bytes, 5 calls
++
++Total size reduction: about 11 kbytes.
++
++Signed-off-by: Denys Vlasenko <dvlasenk@redhat.com>
++CC: John Linville <linville@tuxdriver.com>
++CC: Michal Kazior <michal.kazior@tieto.com>
++CC: Johannes Berg <johannes.berg@intel.com>
++Cc: linux-wireless@vger.kernel.org
++Cc: netdev@vger.kernel.org
++CC: linux-kernel@vger.kernel.org
++---
++
++--- a/net/mac80211/rate.c
+++++ b/net/mac80211/rate.c
++@@ -29,6 +29,65 @@ module_param(ieee80211_default_rc_algo,
++ MODULE_PARM_DESC(ieee80211_default_rc_algo,
++ 		 "Default rate control algorithm for mac80211 to use");
++ 
+++void rate_control_rate_init(struct sta_info *sta)
+++{
+++	struct ieee80211_local *local = sta->sdata->local;
+++	struct rate_control_ref *ref = sta->rate_ctrl;
+++	struct ieee80211_sta *ista = &sta->sta;
+++	void *priv_sta = sta->rate_ctrl_priv;
+++	struct ieee80211_supported_band *sband;
+++	struct ieee80211_chanctx_conf *chanctx_conf;
+++
+++	ieee80211_sta_set_rx_nss(sta);
+++
+++	if (!ref)
+++		return;
+++
+++	rcu_read_lock();
+++
+++	chanctx_conf = rcu_dereference(sta->sdata->vif.chanctx_conf);
+++	if (WARN_ON(!chanctx_conf)) {
+++		rcu_read_unlock();
+++		return;
+++	}
+++
+++	sband = local->hw.wiphy->bands[chanctx_conf->def.chan->band];
+++
+++	spin_lock_bh(&sta->rate_ctrl_lock);
+++	ref->ops->rate_init(ref->priv, sband, &chanctx_conf->def, ista,
+++			    priv_sta);
+++	spin_unlock_bh(&sta->rate_ctrl_lock);
+++	rcu_read_unlock();
+++	set_sta_flag(sta, WLAN_STA_RATE_CONTROL);
+++}
+++
+++void rate_control_rate_update(struct ieee80211_local *local,
+++				    struct ieee80211_supported_band *sband,
+++				    struct sta_info *sta, u32 changed)
+++{
+++	struct rate_control_ref *ref = local->rate_ctrl;
+++	struct ieee80211_sta *ista = &sta->sta;
+++	void *priv_sta = sta->rate_ctrl_priv;
+++	struct ieee80211_chanctx_conf *chanctx_conf;
+++
+++	if (ref && ref->ops->rate_update) {
+++		rcu_read_lock();
+++
+++		chanctx_conf = rcu_dereference(sta->sdata->vif.chanctx_conf);
+++		if (WARN_ON(!chanctx_conf)) {
+++			rcu_read_unlock();
+++			return;
+++		}
+++
+++		spin_lock_bh(&sta->rate_ctrl_lock);
+++		ref->ops->rate_update(ref->priv, sband, &chanctx_conf->def,
+++				      ista, priv_sta, changed);
+++		spin_unlock_bh(&sta->rate_ctrl_lock);
+++		rcu_read_unlock();
+++	}
+++	drv_sta_rc_update(local, sta->sdata, &sta->sta, changed);
+++}
+++
++ int ieee80211_rate_control_register(const struct rate_control_ops *ops)
++ {
++ 	struct rate_control_alg *alg;
++--- a/net/mac80211/rate.h
+++++ b/net/mac80211/rate.h
++@@ -71,64 +71,10 @@ rate_control_tx_status_noskb(struct ieee
++ 	spin_unlock_bh(&sta->rate_ctrl_lock);
++ }
++ 
++-static inline void rate_control_rate_init(struct sta_info *sta)
++-{
++-	struct ieee80211_local *local = sta->sdata->local;
++-	struct rate_control_ref *ref = sta->rate_ctrl;
++-	struct ieee80211_sta *ista = &sta->sta;
++-	void *priv_sta = sta->rate_ctrl_priv;
++-	struct ieee80211_supported_band *sband;
++-	struct ieee80211_chanctx_conf *chanctx_conf;
++-
++-	ieee80211_sta_set_rx_nss(sta);
++-
++-	if (!ref)
++-		return;
++-
++-	rcu_read_lock();
++-
++-	chanctx_conf = rcu_dereference(sta->sdata->vif.chanctx_conf);
++-	if (WARN_ON(!chanctx_conf)) {
++-		rcu_read_unlock();
++-		return;
++-	}
++-
++-	sband = local->hw.wiphy->bands[chanctx_conf->def.chan->band];
++-
++-	spin_lock_bh(&sta->rate_ctrl_lock);
++-	ref->ops->rate_init(ref->priv, sband, &chanctx_conf->def, ista,
++-			    priv_sta);
++-	spin_unlock_bh(&sta->rate_ctrl_lock);
++-	rcu_read_unlock();
++-	set_sta_flag(sta, WLAN_STA_RATE_CONTROL);
++-}
++-
++-static inline void rate_control_rate_update(struct ieee80211_local *local,
+++void rate_control_rate_init(struct sta_info *sta);
+++void rate_control_rate_update(struct ieee80211_local *local,
++ 				    struct ieee80211_supported_band *sband,
++-				    struct sta_info *sta, u32 changed)
++-{
++-	struct rate_control_ref *ref = local->rate_ctrl;
++-	struct ieee80211_sta *ista = &sta->sta;
++-	void *priv_sta = sta->rate_ctrl_priv;
++-	struct ieee80211_chanctx_conf *chanctx_conf;
++-
++-	if (ref && ref->ops->rate_update) {
++-		rcu_read_lock();
++-
++-		chanctx_conf = rcu_dereference(sta->sdata->vif.chanctx_conf);
++-		if (WARN_ON(!chanctx_conf)) {
++-			rcu_read_unlock();
++-			return;
++-		}
++-
++-		spin_lock_bh(&sta->rate_ctrl_lock);
++-		ref->ops->rate_update(ref->priv, sband, &chanctx_conf->def,
++-				      ista, priv_sta, changed);
++-		spin_unlock_bh(&sta->rate_ctrl_lock);
++-		rcu_read_unlock();
++-	}
++-	drv_sta_rc_update(local, sta->sdata, &sta->sta, changed);
++-}
+++				    struct sta_info *sta, u32 changed);
++ 
++ static inline void *rate_control_alloc_sta(struct rate_control_ref *ref,
++ 					   struct sta_info *sta, gfp_t gfp)
+diff --git a/package/kernel/mac80211/patches/307-ath9k-fix-tracking-of-enabled-AP-beacons.patch b/package/kernel/mac80211/patches/307-ath9k-fix-tracking-of-enabled-AP-beacons.patch
+deleted file mode 100644
+index ab9771e..0000000
+--- a/package/kernel/mac80211/patches/307-ath9k-fix-tracking-of-enabled-AP-beacons.patch
++++ /dev/null
+@@ -1,76 +0,0 @@
+-From: Felix Fietkau <nbd@openwrt.org>
+-Date: Thu, 12 Mar 2015 17:10:50 +0100
+-Subject: [PATCH] ath9k: fix tracking of enabled AP beacons
+-
+-sc->nbcnvifs tracks assigned beacon slots, not enabled beacons.
+-Therefore, it cannot be used to decide if cur_conf->enable_beacon (bool)
+-should be updated, or if beacons have been enabled already.
+-With the current code (depending on the order of calls), beacons often
+-do not get enabled in an AP+STA setup.
+-To fix tracking of enabled beacons, convert cur_conf->enable_beacon to a
+-bitmask of enabled beacon slots.
+-
+-Cc: stable@vger.kernel.org
+-Signed-off-by: Felix Fietkau <nbd@openwrt.org>
+----
+-
+---- a/drivers/net/wireless/ath/ath9k/beacon.c
+-+++ b/drivers/net/wireless/ath/ath9k/beacon.c
+-@@ -219,12 +219,15 @@ 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,
+-@@ -521,8 +524,7 @@ static bool ath9k_allow_beacon_config(st
+- 	}
+- 
+- 	if (sc->sc_ah->opmode == NL80211_IFTYPE_AP) {
+--		if ((vif->type != NL80211_IFTYPE_AP) ||
+--		    (sc->nbcnvifs > 1)) {
+-+		if (vif->type != NL80211_IFTYPE_AP) {
+- 			ath_dbg(common, CONFIG,
+- 				"An AP interface is already present !\n");
+- 			return false;
+-@@ -616,12 +618,14 @@ void ath9k_beacon_config(struct ath_soft
+- 	 * enabling/disabling SWBA.
+- 	 */
+- 	if (changed & BSS_CHANGED_BEACON_ENABLED) {
+--		if (!bss_conf->enable_beacon &&
+--		    (sc->nbcnvifs <= 1)) {
+--			cur_conf->enable_beacon = false;
+--		} else if (bss_conf->enable_beacon) {
+--			cur_conf->enable_beacon = true;
+--			ath9k_cache_beacon_config(sc, ctx, bss_conf);
+-+		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);
+- 		}
+- 	}
+- 
+---- a/drivers/net/wireless/ath/ath9k/common.h
+-+++ b/drivers/net/wireless/ath/ath9k/common.h
+-@@ -54,7 +54,7 @@ struct ath_beacon_config {
+- 	u16 dtim_period;
+- 	u16 bmiss_timeout;
+- 	u8 dtim_count;
+--	bool enable_beacon;
+-+	u8 enable_beacon;
+- 	bool ibss_creator;
+- 	u32 nexttbtt;
+- 	u32 intval;
+diff --git a/package/kernel/mac80211/patches/307-mac80211-Deinline-drv_sta_state.patch b/package/kernel/mac80211/patches/307-mac80211-Deinline-drv_sta_state.patch
+new file mode 100644
+index 0000000..474c409
+--- /dev/null
++++ b/package/kernel/mac80211/patches/307-mac80211-Deinline-drv_sta_state.patch
+@@ -0,0 +1,116 @@
++From: Denys Vlasenko <dvlasenk@redhat.com>
++Date: Wed, 15 Jul 2015 14:56:05 +0200
++Subject: [PATCH] mac80211: Deinline drv_sta_state
++
++With this .config: http://busybox.net/~vda/kernel_config,
++after deinlining the function size is 3132 bytes and there are
++7 callsites.
++
++Total size reduction: about 20 kbytes.
++
++Signed-off-by: Denys Vlasenko <dvlasenk@redhat.com>
++CC: John Linville <linville@tuxdriver.com>
++CC: Michal Kazior <michal.kazior@tieto.com>
++Cc: Johannes Berg <johannes.berg@intel.com>
++Cc: linux-wireless@vger.kernel.org
++Cc: netdev@vger.kernel.org
++CC: linux-kernel@vger.kernel.org
++---
++ create mode 100644 net/mac80211/driver-ops.c
++
++--- a/net/mac80211/Makefile
+++++ b/net/mac80211/Makefile
++@@ -3,6 +3,7 @@ obj-$(CPTCFG_MAC80211) += mac80211.o
++ # mac80211 objects
++ mac80211-y := \
++ 	main.o status.o \
+++	driver-ops.o \
++ 	sta_info.o \
++ 	wep.o \
++ 	wpa.o \
++--- /dev/null
+++++ b/net/mac80211/driver-ops.c
++@@ -0,0 +1,41 @@
+++/*
+++ * This program is free software; you can redistribute it and/or modify
+++ * it under the terms of the GNU General Public License version 2 as
+++ * published by the Free Software Foundation.
+++ */
+++#include <net/mac80211.h>
+++#include "ieee80211_i.h"
+++#include "trace.h"
+++#include "driver-ops.h"
+++
+++__must_check
+++int drv_sta_state(struct ieee80211_local *local,
+++		  struct ieee80211_sub_if_data *sdata,
+++		  struct sta_info *sta,
+++		  enum ieee80211_sta_state old_state,
+++		  enum ieee80211_sta_state new_state)
+++{
+++	int ret = 0;
+++
+++	might_sleep();
+++
+++	sdata = get_bss_sdata(sdata);
+++	if (!check_sdata_in_driver(sdata))
+++		return -EIO;
+++
+++	trace_drv_sta_state(local, sdata, &sta->sta, old_state, new_state);
+++	if (local->ops->sta_state) {
+++		ret = local->ops->sta_state(&local->hw, &sdata->vif, &sta->sta,
+++					    old_state, new_state);
+++	} else if (old_state == IEEE80211_STA_AUTH &&
+++		   new_state == IEEE80211_STA_ASSOC) {
+++		ret = drv_sta_add(local, sdata, &sta->sta);
+++		if (ret == 0)
+++			sta->uploaded = true;
+++	} else if (old_state == IEEE80211_STA_ASSOC &&
+++		   new_state == IEEE80211_STA_AUTH) {
+++		drv_sta_remove(local, sdata, &sta->sta);
+++	}
+++	trace_drv_return_int(local, ret);
+++	return ret;
+++}
++--- a/net/mac80211/driver-ops.h
+++++ b/net/mac80211/driver-ops.h
++@@ -573,37 +573,12 @@ static inline void drv_sta_pre_rcu_remov
++ 	trace_drv_return_void(local);
++ }
++ 
++-static inline __must_check
+++__must_check
++ int drv_sta_state(struct ieee80211_local *local,
++ 		  struct ieee80211_sub_if_data *sdata,
++ 		  struct sta_info *sta,
++ 		  enum ieee80211_sta_state old_state,
++-		  enum ieee80211_sta_state new_state)
++-{
++-	int ret = 0;
++-
++-	might_sleep();
++-
++-	sdata = get_bss_sdata(sdata);
++-	if (!check_sdata_in_driver(sdata))
++-		return -EIO;
++-
++-	trace_drv_sta_state(local, sdata, &sta->sta, old_state, new_state);
++-	if (local->ops->sta_state) {
++-		ret = local->ops->sta_state(&local->hw, &sdata->vif, &sta->sta,
++-					    old_state, new_state);
++-	} else if (old_state == IEEE80211_STA_AUTH &&
++-		   new_state == IEEE80211_STA_ASSOC) {
++-		ret = drv_sta_add(local, sdata, &sta->sta);
++-		if (ret == 0)
++-			sta->uploaded = true;
++-	} else if (old_state == IEEE80211_STA_ASSOC &&
++-		   new_state == IEEE80211_STA_AUTH) {
++-		drv_sta_remove(local, sdata, &sta->sta);
++-	}
++-	trace_drv_return_int(local, ret);
++-	return ret;
++-}
+++		  enum ieee80211_sta_state new_state);
++ 
++ static inline void drv_sta_rc_update(struct ieee80211_local *local,
++ 				     struct ieee80211_sub_if_data *sdata,
+diff --git a/package/kernel/mac80211/patches/308-ath9k-Fix-NF-CCA-limits-for-AR9287-and-AR9227.patch b/package/kernel/mac80211/patches/308-ath9k-Fix-NF-CCA-limits-for-AR9287-and-AR9227.patch
+new file mode 100644
+index 0000000..1a3a9d4
+--- /dev/null
++++ b/package/kernel/mac80211/patches/308-ath9k-Fix-NF-CCA-limits-for-AR9287-and-AR9227.patch
+@@ -0,0 +1,30 @@
++From: Martin Blumenstingl <martin.blumenstingl@googlemail.com>
++Date: Wed, 22 Jul 2015 10:42:43 +0200
++Subject: [PATCH] ath9k: Fix NF CCA limits for AR9287 and AR9227
++
++The FreeBSD driver [0] uses the same 2G values as for the AR9280 chips.
++Using the same values in ath9k results in much better throughput for me.
++
++Before this patch I had a huge amount of packet loss (sometimes up to
++40%) and the max transfer speed was somewhere around 5Mbit/s. With this
++patch applied I have zero packet loss and ten times the throughput.
++My device uses a AR9227 which is the PCI variant of the AR9287.
++
++[0] http://bxr.su/FreeBSD/sys/dev/ath/ath_hal/ar9002/ar9287.h
++
++Signed-off-by: Martin Blumenstingl <martin.blumenstingl@googlemail.com>
++---
++
++--- a/drivers/net/wireless/ath/ath9k/ar9002_phy.h
+++++ b/drivers/net/wireless/ath/ath9k/ar9002_phy.h
++@@ -610,8 +610,8 @@
++ #define AR_PHY_CCA_MIN_GOOD_VAL_9271_2GHZ      -127
++ #define AR_PHY_CCA_MAX_GOOD_VAL_9271_2GHZ      -116
++ 
++-#define AR_PHY_CCA_NOM_VAL_9287_2GHZ           -120
+++#define AR_PHY_CCA_NOM_VAL_9287_2GHZ           -112
++ #define AR_PHY_CCA_MIN_GOOD_VAL_9287_2GHZ    -127
++-#define AR_PHY_CCA_MAX_GOOD_VAL_9287_2GHZ    -110
+++#define AR_PHY_CCA_MAX_GOOD_VAL_9287_2GHZ    -97
++ 
++ #endif
+diff --git a/package/kernel/mac80211/patches/308-mac80211-minstrel_ht-fix-rounding-issue-in-MCS-durat.patch b/package/kernel/mac80211/patches/308-mac80211-minstrel_ht-fix-rounding-issue-in-MCS-durat.patch
+deleted file mode 100644
+index d132636..0000000
+--- a/package/kernel/mac80211/patches/308-mac80211-minstrel_ht-fix-rounding-issue-in-MCS-durat.patch
++++ /dev/null
+@@ -1,43 +0,0 @@
+-From: Felix Fietkau <nbd@openwrt.org>
+-Date: Fri, 13 Mar 2015 10:49:40 +0100
+-Subject: [PATCH] mac80211: minstrel_ht: fix rounding issue in MCS duration
+- calculation
+-
+-On very high MCS bitrates, the calculated duration of rates that are
+-next to each other can be very imprecise, due to the small packet size
+-used as reference (1200 bytes).
+-This is most visible in VHT80 nss=2 MCS8/9, for which minstrel shows the
+-same throughput when the probability is also the same. This leads to a
+-bad rate selection for such rates.
+-
+-Fix this issue by introducing an average A-MPDU size factor into the
+-calculation.
+-
+-Signed-off-by: Felix Fietkau <nbd@openwrt.org>
+----
+-
+---- a/net/mac80211/rc80211_minstrel_ht.c
+-+++ b/net/mac80211/rc80211_minstrel_ht.c
+-@@ -17,10 +17,11 @@
+- #include "rc80211_minstrel.h"
+- #include "rc80211_minstrel_ht.h"
+- 
+-+#define AVG_AMPDU_SIZE	16
+- #define AVG_PKT_SIZE	1200
+- 
+- /* Number of bits for an average sized packet */
+--#define MCS_NBITS (AVG_PKT_SIZE << 3)
+-+#define MCS_NBITS ((AVG_PKT_SIZE * AVG_AMPDU_SIZE) << 3)
+- 
+- /* Number of symbols for a packet with (bps) bits per symbol */
+- #define MCS_NSYMS(bps) DIV_ROUND_UP(MCS_NBITS, (bps))
+-@@ -33,7 +34,8 @@
+- 	)
+- 
+- /* Transmit duration for the raw data part of an average sized packet */
+--#define MCS_DURATION(streams, sgi, bps) MCS_SYMBOL_TIME(sgi, MCS_NSYMS((streams) * (bps)))
+-+#define MCS_DURATION(streams, sgi, bps) \
+-+	(MCS_SYMBOL_TIME(sgi, MCS_NSYMS((streams) * (bps))) / AVG_AMPDU_SIZE)
+- 
+- #define BW_20			0
+- #define BW_40			1
+diff --git a/package/kernel/mac80211/patches/309-ath9k-disable-TPC-support-again-for-now.patch b/package/kernel/mac80211/patches/309-ath9k-disable-TPC-support-again-for-now.patch
+deleted file mode 100644
+index 945fbce..0000000
+--- a/package/kernel/mac80211/patches/309-ath9k-disable-TPC-support-again-for-now.patch
++++ /dev/null
+@@ -1,22 +0,0 @@
+-From: Felix Fietkau <nbd@openwrt.org>
+-Date: Sun, 15 Mar 2015 08:02:37 +0100
+-Subject: [PATCH] ath9k: disable TPC support again (for now)
+-
+-TPC support has been observed to cause some tx power fluctuations on
+-some devices with at least AR934x and AR938x chips.
+-Disable it for now until the bugs have been found and fixed
+-
+-Signed-off-by: Felix Fietkau <nbd@openwrt.org>
+----
+-
+---- a/drivers/net/wireless/ath/ath9k/hw.c
+-+++ b/drivers/net/wireless/ath/ath9k/hw.c
+-@@ -424,7 +424,7 @@ static void ath9k_hw_init_defaults(struc
+- 	ah->power_mode = ATH9K_PM_UNDEFINED;
+- 	ah->htc_reset_init = true;
+- 
+--	ah->tpc_enabled = true;
+-+	ah->tpc_enabled = false;
+- 
+- 	ah->ani_function = ATH9K_ANI_ALL;
+- 	if (!AR_SREV_9300_20_OR_LATER(ah))
+diff --git a/package/kernel/mac80211/patches/309-mac80211-make-local-tx_headroom-a-multiple-of-4.patch b/package/kernel/mac80211/patches/309-mac80211-make-local-tx_headroom-a-multiple-of-4.patch
+new file mode 100644
+index 0000000..e8e9617
+--- /dev/null
++++ b/package/kernel/mac80211/patches/309-mac80211-make-local-tx_headroom-a-multiple-of-4.patch
+@@ -0,0 +1,20 @@
++From: Felix Fietkau <nbd@openwrt.org>
++Date: Thu, 30 Jul 2015 14:12:25 +0200
++Subject: [PATCH] mac80211: make local->tx_headroom a multiple of 4
++
++This ensures that mac80211 generated management frames and beacons are
++aligned before being passed to the driver
++
++Signed-off-by: Felix Fietkau <nbd@openwrt.org>
++---
++
++--- a/net/mac80211/main.c
+++++ b/net/mac80211/main.c
++@@ -1031,6 +1031,7 @@ int ieee80211_register_hw(struct ieee802
++ 	 */
++ 	local->tx_headroom = max_t(unsigned int , local->hw.extra_tx_headroom,
++ 				   IEEE80211_TX_STATUS_HEADROOM);
+++	local->tx_headroom = ALIGN(local->tx_headroom, 4);
++ 
++ 	debugfs_hw_add(local);
++ 
+diff --git a/package/kernel/mac80211/patches/310-mac80211-don-t-look-up-stations-for-multicast-addres.patch b/package/kernel/mac80211/patches/310-mac80211-don-t-look-up-stations-for-multicast-addres.patch
+deleted file mode 100644
+index bd3050e..0000000
+--- a/package/kernel/mac80211/patches/310-mac80211-don-t-look-up-stations-for-multicast-addres.patch
++++ /dev/null
+@@ -1,21 +0,0 @@
+-From: Johannes Berg <johannes.berg@intel.com>
+-Date: Tue, 24 Feb 2015 00:28:18 +0100
+-Subject: [PATCH] mac80211: don't look up stations for multicast addresses
+-
+-Since multicast addresses don't exist as stations, don't attempt
+-to look them up in the hashtable on TX.
+-
+-Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+----
+-
+---- a/net/mac80211/tx.c
+-+++ b/net/mac80211/tx.c
+-@@ -1161,7 +1161,7 @@ ieee80211_tx_prepare(struct ieee80211_su
+- 		   tx->sdata->control_port_protocol == tx->skb->protocol) {
+- 		tx->sta = sta_info_get_bss(sdata, hdr->addr1);
+- 	}
+--	if (!tx->sta)
+-+	if (!tx->sta && !is_multicast_ether_addr(hdr->addr1))
+- 		tx->sta = sta_info_get(sdata, hdr->addr1);
+- 
+- 	if (tx->sta && ieee80211_is_data_qos(hdr->frame_control) &&
+diff --git a/package/kernel/mac80211/patches/310-mac80211-fix-invalid-read-in-minstrel_sort_best_tp_r.patch b/package/kernel/mac80211/patches/310-mac80211-fix-invalid-read-in-minstrel_sort_best_tp_r.patch
+new file mode 100644
+index 0000000..51a315c
+--- /dev/null
++++ b/package/kernel/mac80211/patches/310-mac80211-fix-invalid-read-in-minstrel_sort_best_tp_r.patch
+@@ -0,0 +1,34 @@
++From: Adrien Schildknecht <adrien+dev@schischi.me>
++Date: Tue, 28 Jul 2015 10:30:16 +0200
++Subject: [PATCH] mac80211: fix invalid read in minstrel_sort_best_tp_rates()
++
++At the last iteration of the loop, j may equal zero and thus
++tp_list[j - 1] causes an invalid read.
++Changed the logic of the loop so that j - 1 is always >= 0.
++
++Signed-off-by: Adrien Schildknecht <adrien+dev@schischi.me>
++---
++
++--- a/net/mac80211/rc80211_minstrel.c
+++++ b/net/mac80211/rc80211_minstrel.c
++@@ -92,14 +92,15 @@ int minstrel_get_tp_avg(struct minstrel_
++ static inline void
++ minstrel_sort_best_tp_rates(struct minstrel_sta_info *mi, int i, u8 *tp_list)
++ {
++-	int j = MAX_THR_RATES;
++-	struct minstrel_rate_stats *tmp_mrs = &mi->r[j - 1].stats;
+++	int j;
+++	struct minstrel_rate_stats *tmp_mrs;
++ 	struct minstrel_rate_stats *cur_mrs = &mi->r[i].stats;
++ 
++-	while (j > 0 && (minstrel_get_tp_avg(&mi->r[i], cur_mrs->prob_ewma) >
++-	       minstrel_get_tp_avg(&mi->r[tp_list[j - 1]], tmp_mrs->prob_ewma))) {
++-		j--;
+++	for (j = MAX_THR_RATES; j > 0; --j) {
++ 		tmp_mrs = &mi->r[tp_list[j - 1]].stats;
+++		if (minstrel_get_tp_avg(&mi->r[i], cur_mrs->prob_ewma) <=
+++		    minstrel_get_tp_avg(&mi->r[tp_list[j - 1]], tmp_mrs->prob_ewma))
+++			break;
++ 	}
++ 
++ 	if (j < MAX_THR_RATES - 1)
+diff --git a/package/kernel/mac80211/patches/311-brcmfmac-dhd_sdio.c-use-existing-atomic_or-primitive.patch b/package/kernel/mac80211/patches/311-brcmfmac-dhd_sdio.c-use-existing-atomic_or-primitive.patch
+new file mode 100644
+index 0000000..e44f121
+--- /dev/null
++++ b/package/kernel/mac80211/patches/311-brcmfmac-dhd_sdio.c-use-existing-atomic_or-primitive.patch
+@@ -0,0 +1,45 @@
++From: Vineet Gupta <Vineet.Gupta1@synopsys.com>
++Date: Thu, 9 Jul 2015 13:43:18 +0530
++Subject: [PATCH] brcmfmac: dhd_sdio.c: use existing atomic_or primitive
++
++There's already a generic implementation so use that instead.
++
++Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
++---
++
++--- a/drivers/net/wireless/brcm80211/brcmfmac/sdio.c
+++++ b/drivers/net/wireless/brcm80211/brcmfmac/sdio.c
++@@ -2564,15 +2564,6 @@ static inline void brcmf_sdio_clrintr(st
++ 	}
++ }
++ 
++-static void atomic_orr(int val, atomic_t *v)
++-{
++-	int old_val;
++-
++-	old_val = atomic_read(v);
++-	while (atomic_cmpxchg(v, old_val, val | old_val) != old_val)
++-		old_val = atomic_read(v);
++-}
++-
++ static int brcmf_sdio_intr_rstatus(struct brcmf_sdio *bus)
++ {
++ 	struct brcmf_core *buscore;
++@@ -2595,7 +2586,7 @@ static int brcmf_sdio_intr_rstatus(struc
++ 	if (val) {
++ 		brcmf_sdiod_regwl(bus->sdiodev, addr, val, &ret);
++ 		bus->sdcnt.f1regdata++;
++-		atomic_orr(val, &bus->intstatus);
+++		atomic_or(val, &bus->intstatus);
++ 	}
++ 
++ 	return ret;
++@@ -2712,7 +2703,7 @@ static void brcmf_sdio_dpc(struct brcmf_
++ 
++ 	/* Keep still-pending events for next scheduling */
++ 	if (intstatus)
++-		atomic_orr(intstatus, &bus->intstatus);
+++		atomic_or(intstatus, &bus->intstatus);
++ 
++ 	brcmf_sdio_clrintr(bus);
++ 
+diff --git a/package/kernel/mac80211/patches/311-mac80211-remove-drop_unencrypted-code.patch b/package/kernel/mac80211/patches/311-mac80211-remove-drop_unencrypted-code.patch
+deleted file mode 100644
+index b2475b9..0000000
+--- a/package/kernel/mac80211/patches/311-mac80211-remove-drop_unencrypted-code.patch
++++ /dev/null
+@@ -1,130 +0,0 @@
+-From: Johannes Berg <johannes.berg@intel.com>
+-Date: Fri, 20 Mar 2015 11:41:58 +0100
+-Subject: [PATCH] mac80211: remove drop_unencrypted code
+-
+-This mechanism was historic, and only ever used by IBSS, which
+-also doesn't need to have it as it properly manages station's
+-802.1X PAE state (or, with WEP, always has a key.)
+-
+-Remove the mechanism to clean up the code.
+-
+-Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+----
+-
+---- a/net/mac80211/debugfs.c
+-+++ b/net/mac80211/debugfs.c
+-@@ -274,8 +274,6 @@ void debugfs_hw_add(struct ieee80211_loc
+- #ifdef CPTCFG_MAC80211_DEBUG_COUNTERS
+- 	DEBUGFS_STATS_ADD(tx_handlers_drop, local->tx_handlers_drop);
+- 	DEBUGFS_STATS_ADD(tx_handlers_queued, local->tx_handlers_queued);
+--	DEBUGFS_STATS_ADD(tx_handlers_drop_unencrypted,
+--		local->tx_handlers_drop_unencrypted);
+- 	DEBUGFS_STATS_ADD(tx_handlers_drop_fragment,
+- 		local->tx_handlers_drop_fragment);
+- 	DEBUGFS_STATS_ADD(tx_handlers_drop_wep,
+---- a/net/mac80211/debugfs_netdev.c
+-+++ b/net/mac80211/debugfs_netdev.c
+-@@ -177,7 +177,6 @@ static ssize_t ieee80211_if_write_##name
+- 	IEEE80211_IF_FILE_R(name)
+- 
+- /* common attributes */
+--IEEE80211_IF_FILE(drop_unencrypted, drop_unencrypted, DEC);
+- IEEE80211_IF_FILE(rc_rateidx_mask_2ghz, rc_rateidx_mask[IEEE80211_BAND_2GHZ],
+- 		  HEX);
+- IEEE80211_IF_FILE(rc_rateidx_mask_5ghz, rc_rateidx_mask[IEEE80211_BAND_5GHZ],
+-@@ -562,7 +561,6 @@ IEEE80211_IF_FILE(dot11MeshAwakeWindowDu
+- 
+- static void add_common_files(struct ieee80211_sub_if_data *sdata)
+- {
+--	DEBUGFS_ADD(drop_unencrypted);
+- 	DEBUGFS_ADD(rc_rateidx_mask_2ghz);
+- 	DEBUGFS_ADD(rc_rateidx_mask_5ghz);
+- 	DEBUGFS_ADD(rc_rateidx_mcs_mask_2ghz);
+---- a/net/mac80211/ibss.c
+-+++ b/net/mac80211/ibss.c
+-@@ -249,8 +249,6 @@ static void __ieee80211_sta_join_ibss(st
+- 	if (presp)
+- 		kfree_rcu(presp, rcu_head);
+- 
+--	sdata->drop_unencrypted = capability & WLAN_CAPABILITY_PRIVACY ? 1 : 0;
+--
+- 	/* make a copy of the chandef, it could be modified below. */
+- 	chandef = *req_chandef;
+- 	chan = chandef.chan;
+-@@ -1289,8 +1287,6 @@ static void ieee80211_sta_create_ibss(st
+- 
+- 	if (ifibss->privacy)
+- 		capability |= WLAN_CAPABILITY_PRIVACY;
+--	else
+--		sdata->drop_unencrypted = 0;
+- 
+- 	__ieee80211_sta_join_ibss(sdata, bssid, sdata->vif.bss_conf.beacon_int,
+- 				  &ifibss->chandef, ifibss->basic_rates,
+---- a/net/mac80211/ieee80211_i.h
+-+++ b/net/mac80211/ieee80211_i.h
+-@@ -842,8 +842,6 @@ struct ieee80211_sub_if_data {
+- 
+- 	unsigned long state;
+- 
+--	int drop_unencrypted;
+--
+- 	char name[IFNAMSIZ];
+- 
+- 	/* Fragment table for host-based reassembly */
+-@@ -1289,7 +1287,6 @@ struct ieee80211_local {
+- 	/* TX/RX handler statistics */
+- 	unsigned int tx_handlers_drop;
+- 	unsigned int tx_handlers_queued;
+--	unsigned int tx_handlers_drop_unencrypted;
+- 	unsigned int tx_handlers_drop_fragment;
+- 	unsigned int tx_handlers_drop_wep;
+- 	unsigned int tx_handlers_drop_not_assoc;
+---- a/net/mac80211/iface.c
+-+++ b/net/mac80211/iface.c
+-@@ -1535,7 +1535,6 @@ int ieee80211_if_change_type(struct ieee
+- 	}
+- 
+- 	/* reset some values that shouldn't be kept across type changes */
+--	sdata->drop_unencrypted = 0;
+- 	if (type == NL80211_IFTYPE_STATION)
+- 		sdata->u.mgd.use_4addr = false;
+- 
+---- a/net/mac80211/rx.c
+-+++ b/net/mac80211/rx.c
+-@@ -1897,8 +1897,7 @@ static int ieee80211_drop_unencrypted(st
+- 	/* Drop unencrypted frames if key is set. */
+- 	if (unlikely(!ieee80211_has_protected(fc) &&
+- 		     !ieee80211_is_nullfunc(fc) &&
+--		     ieee80211_is_data(fc) &&
+--		     (rx->key || rx->sdata->drop_unencrypted)))
+-+		     ieee80211_is_data(fc) && rx->key))
+- 		return -EACCES;
+- 
+- 	return 0;
+---- a/net/mac80211/tx.c
+-+++ b/net/mac80211/tx.c
+-@@ -594,23 +594,8 @@ ieee80211_tx_h_select_key(struct ieee802
+- 	else if (!is_multicast_ether_addr(hdr->addr1) &&
+- 		 (key = rcu_dereference(tx->sdata->default_unicast_key)))
+- 		tx->key = key;
+--	else if (info->flags & IEEE80211_TX_CTL_INJECTED)
+-+	else
+- 		tx->key = NULL;
+--	else if (!tx->sdata->drop_unencrypted)
+--		tx->key = NULL;
+--	else if (tx->skb->protocol == tx->sdata->control_port_protocol)
+--		tx->key = NULL;
+--	else if (ieee80211_is_robust_mgmt_frame(tx->skb) &&
+--		 !(ieee80211_is_action(hdr->frame_control) &&
+--		   tx->sta && test_sta_flag(tx->sta, WLAN_STA_MFP)))
+--		tx->key = NULL;
+--	else if (ieee80211_is_mgmt(hdr->frame_control) &&
+--		 !ieee80211_is_robust_mgmt_frame(tx->skb))
+--		tx->key = NULL;
+--	else {
+--		I802_DEBUG_INC(tx->local->tx_handlers_drop_unencrypted);
+--		return TX_DROP;
+--	}
+- 
+- 	if (tx->key) {
+- 		bool skip_hw = false;
+diff --git a/package/kernel/mac80211/patches/312-brcmfmac-check-all-combinations-when-setting-wiphy-s.patch b/package/kernel/mac80211/patches/312-brcmfmac-check-all-combinations-when-setting-wiphy-s.patch
+new file mode 100644
+index 0000000..bb27115
+--- /dev/null
++++ b/package/kernel/mac80211/patches/312-brcmfmac-check-all-combinations-when-setting-wiphy-s.patch
+@@ -0,0 +1,46 @@
++From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <zajec5@gmail.com>
++Date: Thu, 20 Aug 2015 00:16:42 +0200
++Subject: [PATCH] brcmfmac: check all combinations when setting wiphy's
++ addresses
++MIME-Version: 1.0
++Content-Type: text/plain; charset=UTF-8
++Content-Transfer-Encoding: 8bit
++
++Broadcom is working on better reflection of interface combinations. With
++upcoming patches we may have 1st combination supporting less interfaces
++than others.
++To don't run out of addresses check all combinations to find the one
++with the greatest max_interfaces value.
++
++Signed-off-by: Rafał Miłecki <zajec5@gmail.com>
++Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
++---
++
++--- a/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c
+++++ b/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c
++@@ -5786,7 +5786,9 @@ static void brcmf_wiphy_wowl_params(stru
++ static int brcmf_setup_wiphy(struct wiphy *wiphy, struct brcmf_if *ifp)
++ {
++ 	struct brcmf_pub *drvr = ifp->drvr;
+++	const struct ieee80211_iface_combination *combo;
++ 	struct ieee80211_supported_band *band;
+++	u16 max_interfaces = 0;
++ 	__le32 bandlist[3];
++ 	u32 n_bands;
++ 	int err, i;
++@@ -5799,8 +5801,13 @@ static int brcmf_setup_wiphy(struct wiph
++ 	if (err)
++ 		return err;
++ 
++-	for (i = 0; i < wiphy->iface_combinations->max_interfaces &&
++-	     i < ARRAY_SIZE(drvr->addresses); i++) {
+++	for (i = 0, combo = wiphy->iface_combinations;
+++	     i < wiphy->n_iface_combinations; i++, combo++) {
+++		max_interfaces = max(max_interfaces, combo->max_interfaces);
+++	}
+++
+++	for (i = 0; i < max_interfaces && i < ARRAY_SIZE(drvr->addresses);
+++	     i++) {
++ 		u8 *addr = drvr->addresses[i].addr;
++ 
++ 		memcpy(addr, drvr->mac, ETH_ALEN);
+diff --git a/package/kernel/mac80211/patches/312-mac80211-don-t-look-up-destination-station-twice.patch b/package/kernel/mac80211/patches/312-mac80211-don-t-look-up-destination-station-twice.patch
+deleted file mode 100644
+index 02a7fab..0000000
+--- a/package/kernel/mac80211/patches/312-mac80211-don-t-look-up-destination-station-twice.patch
++++ /dev/null
+@@ -1,71 +0,0 @@
+-From: Johannes Berg <johannes.berg@intel.com>
+-Date: Fri, 20 Mar 2015 16:24:21 +0100
+-Subject: [PATCH] mac80211: don't look up destination station twice
+-
+-There's no need to look up the destination station twice while
+-building the 802.11 header for a given frame if the frame will
+-actually be transmitted to the station we initially looked up.
+-
+-This happens for 4-addr VLAN interfaces and TDLS connections, which
+-both directly send the frame to the station they looked up, though
+-in the case of TDLS some station conditions need to be checked.
+-
+-To avoid that, add a variable indicating that we've looked up the
+-station that the frame is going to be transmitted to, and avoid the
+-lookup/flag checking if it already has been done.
+-
+-In the TDLS case, also move the authorized/wme_sta flag assignment
+-to the correct place, i.e. only when that station is really used.
+-Before this change, the new lookup should always have succeeded so
+-that the potentially erroneous data would be overwritten.
+-
+-Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+----
+-
+---- a/net/mac80211/tx.c
+-+++ b/net/mac80211/tx.c
+-@@ -1894,6 +1894,7 @@ static struct sk_buff *ieee80211_build_h
+- 	bool wme_sta = false, authorized = false, tdls_auth = false;
+- 	bool tdls_peer = false, tdls_setup_frame = false;
+- 	bool multicast;
+-+	bool have_station = false;
+- 	u16 info_id = 0;
+- 	struct ieee80211_chanctx_conf *chanctx_conf;
+- 	struct ieee80211_sub_if_data *ap_sdata;
+-@@ -1918,6 +1919,7 @@ static struct sk_buff *ieee80211_build_h
+- 			hdrlen = 30;
+- 			authorized = test_sta_flag(sta, WLAN_STA_AUTHORIZED);
+- 			wme_sta = sta->sta.wme;
+-+			have_station = true;
+- 		}
+- 		ap_sdata = container_of(sdata->bss, struct ieee80211_sub_if_data,
+- 					u.ap);
+-@@ -2034,9 +2036,6 @@ static struct sk_buff *ieee80211_build_h
+- 		if (sdata->wdev.wiphy->flags & WIPHY_FLAG_SUPPORTS_TDLS) {
+- 			sta = sta_info_get(sdata, skb->data);
+- 			if (sta) {
+--				authorized = test_sta_flag(sta,
+--							WLAN_STA_AUTHORIZED);
+--				wme_sta = sta->sta.wme;
+- 				tdls_peer = test_sta_flag(sta,
+- 							  WLAN_STA_TDLS_PEER);
+- 				tdls_auth = test_sta_flag(sta,
+-@@ -2068,6 +2067,9 @@ static struct sk_buff *ieee80211_build_h
+- 			memcpy(hdr.addr2, skb->data + ETH_ALEN, ETH_ALEN);
+- 			memcpy(hdr.addr3, sdata->u.mgd.bssid, ETH_ALEN);
+- 			hdrlen = 24;
+-+			have_station = true;
+-+			authorized = test_sta_flag(sta, WLAN_STA_AUTHORIZED);
+-+			wme_sta = sta->sta.wme;
+- 		}  else if (sdata->u.mgd.use_4addr &&
+- 			    cpu_to_be16(ethertype) != sdata->control_port_protocol) {
+- 			fc |= cpu_to_le16(IEEE80211_FCTL_FROMDS |
+-@@ -2130,7 +2132,7 @@ static struct sk_buff *ieee80211_build_h
+- 	 * in AP mode)
+- 	 */
+- 	multicast = is_multicast_ether_addr(hdr.addr1);
+--	if (!multicast) {
+-+	if (!multicast && !have_station) {
+- 		sta = sta_info_get(sdata, hdr.addr1);
+- 		if (sta) {
+- 			authorized = test_sta_flag(sta, WLAN_STA_AUTHORIZED);
+diff --git a/package/kernel/mac80211/patches/313-brcmfmac-correct-interface-combination-info.patch b/package/kernel/mac80211/patches/313-brcmfmac-correct-interface-combination-info.patch
+new file mode 100644
+index 0000000..baee295
+--- /dev/null
++++ b/package/kernel/mac80211/patches/313-brcmfmac-correct-interface-combination-info.patch
+@@ -0,0 +1,204 @@
++From: Arend van Spriel <arend@broadcom.com>
++Date: Thu, 20 Aug 2015 22:06:03 +0200
++Subject: [PATCH] brcmfmac: correct interface combination info
++
++The interface combination provided by brcmfmac did not truly reflect
++the combinations supported by driver and/or firmware.
++
++Reviewed-by: Hante Meuleman <meuleman@broadcom.com>
++Reviewed-by: Franky (Zhenhui) Lin <frankyl@broadcom.com>
++Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
++Reviewed-by: Pontus Fuchs <pontusf@broadcom.com>
++Signed-off-by: Arend van Spriel <arend@broadcom.com>
++Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
++---
++
++--- a/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c
+++++ b/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c
++@@ -5695,63 +5695,132 @@ brcmf_txrx_stypes[NUM_NL80211_IFTYPES] =
++ 	}
++ };
++ 
+++/**
+++ * brcmf_setup_ifmodes() - determine interface modes and combinations.
+++ *
+++ * @wiphy: wiphy object.
+++ * @ifp: interface object needed for feat module api.
+++ *
+++ * The interface modes and combinations are determined dynamically here
+++ * based on firmware functionality.
+++ *
+++ * no p2p and no mbss:
+++ *
+++ *	#STA <= 1, #AP <= 1, channels = 1, 2 total
+++ *
+++ * no p2p and mbss:
+++ *
+++ *	#STA <= 1, #AP <= 1, channels = 1, 2 total
+++ *	#AP <= 4, matching BI, channels = 1, 4 total
+++ *
+++ * p2p, no mchan, and mbss:
+++ *
+++ *	#STA <= 1, #P2P-DEV <= 1, #{P2P-CL, P2P-GO} <= 1, channels = 1, 3 total
+++ *	#STA <= 1, #P2P-DEV <= 1, #AP <= 1, #P2P-CL <= 1, channels = 1, 4 total
+++ *	#AP <= 4, matching BI, channels = 1, 4 total
+++ *
+++ * p2p, mchan, and mbss:
+++ *
+++ *	#STA <= 1, #P2P-DEV <= 1, #{P2P-CL, P2P-GO} <= 1, channels = 2, 3 total
+++ *	#STA <= 1, #P2P-DEV <= 1, #AP <= 1, #P2P-CL <= 1, channels = 1, 4 total
+++ *	#AP <= 4, matching BI, channels = 1, 4 total
+++ */
++ static int brcmf_setup_ifmodes(struct wiphy *wiphy, struct brcmf_if *ifp)
++ {
++ 	struct ieee80211_iface_combination *combo = NULL;
++-	struct ieee80211_iface_limit *limits = NULL;
++-	int i = 0, max_iface_cnt;
+++	struct ieee80211_iface_limit *c0_limits = NULL;
+++	struct ieee80211_iface_limit *p2p_limits = NULL;
+++	struct ieee80211_iface_limit *mbss_limits = NULL;
+++	bool mbss, p2p;
+++	int i, c, n_combos;
++ 
++-	combo = kzalloc(sizeof(*combo), GFP_KERNEL);
+++	mbss = brcmf_feat_is_enabled(ifp, BRCMF_FEAT_MBSS);
+++	p2p = brcmf_feat_is_enabled(ifp, BRCMF_FEAT_P2P);
+++
+++	n_combos = 1 + !!p2p + !!mbss;
+++	combo = kcalloc(n_combos, sizeof(*combo), GFP_KERNEL);
++ 	if (!combo)
++ 		goto err;
++ 
++-	limits = kzalloc(sizeof(*limits) * 4, GFP_KERNEL);
++-	if (!limits)
+++	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);
++ 
++-	if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_MCHAN))
++-		combo->num_different_channels = 2;
++-	else
++-		combo->num_different_channels = 1;
++-
++-	if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_MBSS)) {
++-		limits[i].max = 1;
++-		limits[i++].types = BIT(NL80211_IFTYPE_STATION);
++-		limits[i].max = 4;
++-		limits[i++].types = BIT(NL80211_IFTYPE_AP);
++-		max_iface_cnt = 5;
++-	} else {
++-		limits[i].max = 2;
++-		limits[i++].types = BIT(NL80211_IFTYPE_STATION) |
++-				    BIT(NL80211_IFTYPE_AP);
++-		max_iface_cnt = 2;
++-	}
++-
++-	if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_P2P)) {
+++	c = 0;
+++	i = 0;
+++	combo[c].num_different_channels = 1;
+++	c0_limits[i].max = 1;
+++	c0_limits[i++].types = BIT(NL80211_IFTYPE_STATION);
+++	if (p2p) {
+++		if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_MCHAN))
+++			combo[c].num_different_channels = 2;
++ 		wiphy->interface_modes |= BIT(NL80211_IFTYPE_P2P_CLIENT) |
++ 					  BIT(NL80211_IFTYPE_P2P_GO) |
++ 					  BIT(NL80211_IFTYPE_P2P_DEVICE);
++-		limits[i].max = 1;
++-		limits[i++].types = BIT(NL80211_IFTYPE_P2P_CLIENT) |
++-				    BIT(NL80211_IFTYPE_P2P_GO);
++-		limits[i].max = 1;
++-		limits[i++].types = BIT(NL80211_IFTYPE_P2P_DEVICE);
++-		max_iface_cnt += 2;
++-	}
++-	combo->max_interfaces = max_iface_cnt;
++-	combo->limits = limits;
++-	combo->n_limits = i;
+++		c0_limits[i].max = 1;
+++		c0_limits[i++].types = BIT(NL80211_IFTYPE_P2P_DEVICE);
+++		c0_limits[i].max = 1;
+++		c0_limits[i++].types = BIT(NL80211_IFTYPE_P2P_CLIENT) |
+++				       BIT(NL80211_IFTYPE_P2P_GO);
+++	} else {
+++		c0_limits[i].max = 1;
+++		c0_limits[i++].types = BIT(NL80211_IFTYPE_AP);
+++	}
+++	combo[c].max_interfaces = i;
+++	combo[c].n_limits = i;
+++	combo[c].limits = c0_limits;
+++
+++	if (p2p) {
+++		c++;
+++		i = 0;
+++		combo[c].num_different_channels = 1;
+++		p2p_limits[i].max = 1;
+++		p2p_limits[i++].types = BIT(NL80211_IFTYPE_STATION);
+++		p2p_limits[i].max = 1;
+++		p2p_limits[i++].types = BIT(NL80211_IFTYPE_AP);
+++		p2p_limits[i].max = 1;
+++		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].max_interfaces = i;
+++		combo[c].n_limits = i;
+++		combo[c].limits = p2p_limits;
+++	}
++ 
+++	if (mbss) {
+++		c++;
+++		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].limits = mbss_limits;
+++	}
+++	wiphy->n_iface_combinations = n_combos;
++ 	wiphy->iface_combinations = combo;
++-	wiphy->n_iface_combinations = 1;
++ 	return 0;
++ 
++ err:
++-	kfree(limits);
+++	kfree(c0_limits);
+++	kfree(p2p_limits);
+++	kfree(mbss_limits);
++ 	kfree(combo);
++ 	return -ENOMEM;
++ }
++@@ -6080,11 +6149,15 @@ static void brcmf_cfg80211_reg_notifier(
++ 
++ static void brcmf_free_wiphy(struct wiphy *wiphy)
++ {
+++	int i;
+++
++ 	if (!wiphy)
++ 		return;
++ 
++-	if (wiphy->iface_combinations)
++-		kfree(wiphy->iface_combinations->limits);
+++	if (wiphy->iface_combinations) {
+++		for (i = 0; i < wiphy->n_iface_combinations; i++)
+++			kfree(wiphy->iface_combinations[i].limits);
+++	}
++ 	kfree(wiphy->iface_combinations);
++ 	if (wiphy->bands[IEEE80211_BAND_2GHZ]) {
++ 		kfree(wiphy->bands[IEEE80211_BAND_2GHZ]->channels);
+diff --git a/package/kernel/mac80211/patches/313-mac80211-drop-4-addr-VLAN-frames-earlier-if-not-conn.patch b/package/kernel/mac80211/patches/313-mac80211-drop-4-addr-VLAN-frames-earlier-if-not-conn.patch
+deleted file mode 100644
+index 4125351..0000000
+--- a/package/kernel/mac80211/patches/313-mac80211-drop-4-addr-VLAN-frames-earlier-if-not-conn.patch
++++ /dev/null
+@@ -1,27 +0,0 @@
+-From: Johannes Berg <johannes.berg@intel.com>
+-Date: Fri, 20 Mar 2015 16:24:22 +0100
+-Subject: [PATCH] mac80211: drop 4-addr VLAN frames earlier if not
+- connected
+-
+-If there's no station on the 4-addr VLAN interface, then frames
+-cannot be transmitted. Drop such frames earlier, before setting
+-up all the information for them.
+-
+-We should keep the old check though since that code might be used
+-for other internally-generated frames.
+-
+-Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+----
+-
+---- a/net/mac80211/tx.c
+-+++ b/net/mac80211/tx.c
+-@@ -1920,6 +1920,9 @@ static struct sk_buff *ieee80211_build_h
+- 			authorized = test_sta_flag(sta, WLAN_STA_AUTHORIZED);
+- 			wme_sta = sta->sta.wme;
+- 			have_station = true;
+-+		} else if (sdata->wdev.use_4addr) {
+-+			ret = -ENOLINK;
+-+			goto free;
+- 		}
+- 		ap_sdata = container_of(sdata->bss, struct ieee80211_sub_if_data,
+- 					u.ap);
+diff --git a/package/kernel/mac80211/patches/314-brcmfmac-add-debugfs-entry-for-msgbuf-statistics.patch b/package/kernel/mac80211/patches/314-brcmfmac-add-debugfs-entry-for-msgbuf-statistics.patch
+new file mode 100644
+index 0000000..9768ef2
+--- /dev/null
++++ b/package/kernel/mac80211/patches/314-brcmfmac-add-debugfs-entry-for-msgbuf-statistics.patch
+@@ -0,0 +1,87 @@
++From: Franky Lin <frankyl@broadcom.com>
++Date: Thu, 20 Aug 2015 22:06:04 +0200
++Subject: [PATCH] brcmfmac: add debugfs entry for msgbuf statistics
++
++Expose ring buffer read/write pointers and other useful statistics
++through debugfs.
++
++Reviewed-by: Arend Van Spriel <arend@broadcom.com>
++Reviewed-by: Hante Meuleman <meuleman@broadcom.com>
++Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
++Signed-off-by: Franky Lin <frankyl@broadcom.com>
++Signed-off-by: Arend van Spriel <arend@broadcom.com>
++Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
++---
++
++--- a/drivers/net/wireless/brcm80211/brcmfmac/msgbuf.c
+++++ b/drivers/net/wireless/brcm80211/brcmfmac/msgbuf.c
++@@ -1360,6 +1360,60 @@ void brcmf_msgbuf_delete_flowring(struct
++ 	}
++ }
++ 
+++#ifdef DEBUG
+++static int brcmf_msgbuf_stats_read(struct seq_file *seq, void *data)
+++{
+++	struct brcmf_bus *bus_if = dev_get_drvdata(seq->private);
+++	struct brcmf_pub *drvr = bus_if->drvr;
+++	struct brcmf_msgbuf *msgbuf = (struct brcmf_msgbuf *)drvr->proto->pd;
+++	struct brcmf_commonring *commonring;
+++	u16 i;
+++	struct brcmf_flowring_ring *ring;
+++	struct brcmf_flowring_hash *hash;
+++
+++	commonring = msgbuf->commonrings[BRCMF_H2D_MSGRING_CONTROL_SUBMIT];
+++	seq_printf(seq, "h2d_ctl_submit: rp %4u, wp %4u, depth %4u\n",
+++		   commonring->r_ptr, commonring->w_ptr, commonring->depth);
+++	commonring = msgbuf->commonrings[BRCMF_H2D_MSGRING_RXPOST_SUBMIT];
+++	seq_printf(seq, "h2d_rx_submit:  rp %4u, wp %4u, depth %4u\n",
+++		   commonring->r_ptr, commonring->w_ptr, commonring->depth);
+++	commonring = msgbuf->commonrings[BRCMF_D2H_MSGRING_CONTROL_COMPLETE];
+++	seq_printf(seq, "d2h_ctl_cmplt:  rp %4u, wp %4u, depth %4u\n",
+++		   commonring->r_ptr, commonring->w_ptr, commonring->depth);
+++	commonring = msgbuf->commonrings[BRCMF_D2H_MSGRING_TX_COMPLETE];
+++	seq_printf(seq, "d2h_tx_cmplt:   rp %4u, wp %4u, depth %4u\n",
+++		   commonring->r_ptr, commonring->w_ptr, commonring->depth);
+++	commonring = msgbuf->commonrings[BRCMF_D2H_MSGRING_RX_COMPLETE];
+++	seq_printf(seq, "d2h_rx_cmplt:   rp %4u, wp %4u, depth %4u\n",
+++		   commonring->r_ptr, commonring->w_ptr, commonring->depth);
+++
+++	seq_printf(seq, "\nh2d_flowrings: depth %u\n",
+++		   BRCMF_H2D_TXFLOWRING_MAX_ITEM);
+++	seq_puts(seq, "Active flowrings:\n");
+++	hash = msgbuf->flow->hash;
+++	for (i = 0; i < msgbuf->flow->nrofrings; i++) {
+++		if (!msgbuf->flow->rings[i])
+++			continue;
+++		ring = msgbuf->flow->rings[i];
+++		if (ring->status != RING_OPEN)
+++			continue;
+++		commonring = msgbuf->flowrings[i];
+++		hash = &msgbuf->flow->hash[ring->hash_id];
+++		seq_printf(seq, "id %3u: rp %4u, wp %4u, qlen %4u, blocked %u\n"
+++				"        ifidx %u, fifo %u, da %pM\n",
+++				i, commonring->r_ptr, commonring->w_ptr,
+++				skb_queue_len(&ring->skblist), ring->blocked,
+++				hash->ifidx, hash->fifo, hash->mac);
+++	}
+++
+++	return 0;
+++}
+++#else
+++static int brcmf_msgbuf_stats_read(struct seq_file *seq, void *data)
+++{
+++	return 0;
+++}
+++#endif
++ 
++ int brcmf_proto_msgbuf_attach(struct brcmf_pub *drvr)
++ {
++@@ -1460,6 +1514,8 @@ int brcmf_proto_msgbuf_attach(struct brc
++ 	spin_lock_init(&msgbuf->flowring_work_lock);
++ 	INIT_LIST_HEAD(&msgbuf->work_queue);
++ 
+++	brcmf_debugfs_add_entry(drvr, "msgbuf_stats", brcmf_msgbuf_stats_read);
+++
++ 	return 0;
++ 
++ fail:
+diff --git a/package/kernel/mac80211/patches/314-mac80211-mesh-avoid-pointless-station-lookup.patch b/package/kernel/mac80211/patches/314-mac80211-mesh-avoid-pointless-station-lookup.patch
+deleted file mode 100644
+index 9105a64..0000000
+--- a/package/kernel/mac80211/patches/314-mac80211-mesh-avoid-pointless-station-lookup.patch
++++ /dev/null
+@@ -1,33 +0,0 @@
+-From: Johannes Berg <johannes.berg@intel.com>
+-Date: Fri, 20 Mar 2015 16:24:23 +0100
+-Subject: [PATCH] mac80211: mesh: avoid pointless station lookup
+-
+-In ieee80211_build_hdr(), the station is looked up to build the
+-header correctly (QoS field) and to check for authorization. For
+-mesh, authorization isn't checked here, and QoS capability is
+-mandatory, so the station lookup can be avoided.
+-
+-Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+----
+-
+---- a/net/mac80211/tx.c
+-+++ b/net/mac80211/tx.c
+-@@ -2130,12 +2130,14 @@ static struct sk_buff *ieee80211_build_h
+- 	}
+- 
+- 	/*
+--	 * There's no need to try to look up the destination
+--	 * if it is a multicast address (which can only happen
+--	 * in AP mode)
+-+	 * There's no need to try to look up the destination station
+-+	 * if it is a multicast address. In mesh, there's no need to
+-+	 * look up the station at all as it always must be QoS capable
+-+	 * and mesh mode checks authorization later.
+- 	 */
+- 	multicast = is_multicast_ether_addr(hdr.addr1);
+--	if (!multicast && !have_station) {
+-+	if (!multicast && !have_station &&
+-+	    !ieee80211_vif_is_mesh(&sdata->vif)) {
+- 		sta = sta_info_get(sdata, hdr.addr1);
+- 		if (sta) {
+- 			authorized = test_sta_flag(sta, WLAN_STA_AUTHORIZED);
+diff --git a/package/kernel/mac80211/patches/315-brcmfmac-make-use-of-cfg80211_check_combinations.patch b/package/kernel/mac80211/patches/315-brcmfmac-make-use-of-cfg80211_check_combinations.patch
+new file mode 100644
+index 0000000..281f02b
+--- /dev/null
++++ b/package/kernel/mac80211/patches/315-brcmfmac-make-use-of-cfg80211_check_combinations.patch
+@@ -0,0 +1,83 @@
++From: Arend van Spriel <arend@broadcom.com>
++Date: Thu, 20 Aug 2015 22:06:05 +0200
++Subject: [PATCH] brcmfmac: make use of cfg80211_check_combinations()
++
++Use cfg80211_check_combinations() so we can bail out early when an
++interface add or change results in an invalid combination.
++
++Reviewed-by: Hante Meuleman <meuleman@broadcom.com>
++Reviewed-by: Franky (Zhenhui) Lin <frankyl@broadcom.com>
++Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
++Signed-off-by: Arend van Spriel <arend@broadcom.com>
++Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
++---
++
++--- a/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c
+++++ b/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c
++@@ -469,6 +469,36 @@ brcmf_find_wpsie(const u8 *parse, u32 le
++ 	return NULL;
++ }
++ 
+++static int brcmf_vif_change_validate(struct brcmf_cfg80211_info *cfg,
+++				     struct brcmf_cfg80211_vif *vif,
+++				     enum nl80211_iftype new_type)
+++{
+++	int iftype_num[NUM_NL80211_IFTYPES];
+++	struct brcmf_cfg80211_vif *pos;
+++
+++	memset(&iftype_num[0], 0, sizeof(iftype_num));
+++	list_for_each_entry(pos, &cfg->vif_list, list)
+++		if (pos == vif)
+++			iftype_num[new_type]++;
+++		else
+++			iftype_num[pos->wdev.iftype]++;
+++
+++	return cfg80211_check_combinations(cfg->wiphy, 1, 0, iftype_num);
+++}
+++
+++static int brcmf_vif_add_validate(struct brcmf_cfg80211_info *cfg,
+++				  enum nl80211_iftype new_type)
+++{
+++	int iftype_num[NUM_NL80211_IFTYPES];
+++	struct brcmf_cfg80211_vif *pos;
+++
+++	memset(&iftype_num[0], 0, sizeof(iftype_num));
+++	list_for_each_entry(pos, &cfg->vif_list, list)
+++		iftype_num[pos->wdev.iftype]++;
+++
+++	iftype_num[new_type]++;
+++	return cfg80211_check_combinations(cfg->wiphy, 1, 0, iftype_num);
+++}
++ 
++ static void convert_key_from_CPU(struct brcmf_wsec_key *key,
++ 				 struct brcmf_wsec_key_le *key_le)
++@@ -663,8 +693,14 @@ static struct wireless_dev *brcmf_cfg802
++ 						     struct vif_params *params)
++ {
++ 	struct wireless_dev *wdev;
+++	int err;
++ 
++ 	brcmf_dbg(TRACE, "enter: %s type %d\n", name, type);
+++	err = brcmf_vif_add_validate(wiphy_to_cfg(wiphy), type);
+++	if (err) {
+++		brcmf_err("iface validation failed: err=%d\n", err);
+++		return ERR_PTR(err);
+++	}
++ 	switch (type) {
++ 	case NL80211_IFTYPE_ADHOC:
++ 	case NL80211_IFTYPE_STATION:
++@@ -823,8 +859,12 @@ brcmf_cfg80211_change_iface(struct wiphy
++ 	s32 ap = 0;
++ 	s32 err = 0;
++ 
++-	brcmf_dbg(TRACE, "Enter, ndev=%p, type=%d\n", ndev, type);
++-
+++	brcmf_dbg(TRACE, "Enter, idx=%d, type=%d\n", ifp->bssidx, type);
+++	err = brcmf_vif_change_validate(wiphy_to_cfg(wiphy), vif, type);
+++	if (err) {
+++		brcmf_err("iface validation failed: err=%d\n", err);
+++		return err;
+++	}
++ 	switch (type) {
++ 	case NL80211_IFTYPE_MONITOR:
++ 	case NL80211_IFTYPE_WDS:
+diff --git a/package/kernel/mac80211/patches/315-mac80211-avoid-duplicate-TX-path-station-lookup.patch b/package/kernel/mac80211/patches/315-mac80211-avoid-duplicate-TX-path-station-lookup.patch
+deleted file mode 100644
+index d143025..0000000
+--- a/package/kernel/mac80211/patches/315-mac80211-avoid-duplicate-TX-path-station-lookup.patch
++++ /dev/null
+@@ -1,267 +0,0 @@
+-From: Johannes Berg <johannes.berg@intel.com>
+-Date: Fri, 20 Mar 2015 14:18:27 +0100
+-Subject: [PATCH] mac80211: avoid duplicate TX path station lookup
+-
+-Instead of looking up the destination station twice in the TX path
+-(first to build the header, and then for control processing), save
+-it when building the header and use it later in the TX path.
+-
+-To avoid having to look up the station in the many callers, allow
+-those to pass %NULL which keeps the existing lookup.
+-
+-Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+----
+-
+---- a/net/mac80211/cfg.c
+-+++ b/net/mac80211/cfg.c
+-@@ -3565,7 +3565,7 @@ static int ieee80211_probe_client(struct
+- 		nullfunc->qos_ctrl = cpu_to_le16(7);
+- 
+- 	local_bh_disable();
+--	ieee80211_xmit(sdata, skb);
+-+	ieee80211_xmit(sdata, sta, skb);
+- 	local_bh_enable();
+- 	rcu_read_unlock();
+- 
+---- a/net/mac80211/ieee80211_i.h
+-+++ b/net/mac80211/ieee80211_i.h
+-@@ -1775,7 +1775,8 @@ void mac80211_ev_michael_mic_failure(str
+- 				     gfp_t gfp);
+- void ieee80211_set_wmm_default(struct ieee80211_sub_if_data *sdata,
+- 			       bool bss_notify);
+--void ieee80211_xmit(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb);
+-+void ieee80211_xmit(struct ieee80211_sub_if_data *sdata,
+-+		    struct sta_info *sta, struct sk_buff *skb);
+- 
+- void __ieee80211_tx_skb_tid_band(struct ieee80211_sub_if_data *sdata,
+- 				 struct sk_buff *skb, int tid,
+---- a/net/mac80211/sta_info.c
+-+++ b/net/mac80211/sta_info.c
+-@@ -1279,7 +1279,7 @@ static void ieee80211_send_null_response
+- 	}
+- 
+- 	info->band = chanctx_conf->def.chan->band;
+--	ieee80211_xmit(sdata, skb);
+-+	ieee80211_xmit(sdata, sta, skb);
+- 	rcu_read_unlock();
+- }
+- 
+---- a/net/mac80211/tx.c
+-+++ b/net/mac80211/tx.c
+-@@ -1110,11 +1110,13 @@ static bool ieee80211_tx_prep_agg(struct
+- 
+- /*
+-  * initialises @tx
+-+ * pass %NULL for the station if unknown, a valid pointer if known
+-+ * or an ERR_PTR() if the station is known not to exist
+-  */
+- static ieee80211_tx_result
+- ieee80211_tx_prepare(struct ieee80211_sub_if_data *sdata,
+- 		     struct ieee80211_tx_data *tx,
+--		     struct sk_buff *skb)
+-+		     struct sta_info *sta, struct sk_buff *skb)
+- {
+- 	struct ieee80211_local *local = sdata->local;
+- 	struct ieee80211_hdr *hdr;
+-@@ -1137,17 +1139,22 @@ ieee80211_tx_prepare(struct ieee80211_su
+- 
+- 	hdr = (struct ieee80211_hdr *) skb->data;
+- 
+--	if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) {
+--		tx->sta = rcu_dereference(sdata->u.vlan.sta);
+--		if (!tx->sta && sdata->dev->ieee80211_ptr->use_4addr)
+--			return TX_DROP;
+--	} else if (info->flags & (IEEE80211_TX_CTL_INJECTED |
+--				  IEEE80211_TX_INTFL_NL80211_FRAME_TX) ||
+--		   tx->sdata->control_port_protocol == tx->skb->protocol) {
+--		tx->sta = sta_info_get_bss(sdata, hdr->addr1);
+-+	if (likely(sta)) {
+-+		if (!IS_ERR(sta))
+-+			tx->sta = sta;
+-+	} else {
+-+		if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) {
+-+			tx->sta = rcu_dereference(sdata->u.vlan.sta);
+-+			if (!tx->sta && sdata->wdev.use_4addr)
+-+				return TX_DROP;
+-+		} else if (info->flags & (IEEE80211_TX_INTFL_NL80211_FRAME_TX |
+-+					  IEEE80211_TX_CTL_INJECTED) ||
+-+			   tx->sdata->control_port_protocol == tx->skb->protocol) {
+-+			tx->sta = sta_info_get_bss(sdata, hdr->addr1);
+-+		}
+-+		if (!tx->sta && !is_multicast_ether_addr(hdr->addr1))
+-+			tx->sta = sta_info_get(sdata, hdr->addr1);
+- 	}
+--	if (!tx->sta && !is_multicast_ether_addr(hdr->addr1))
+--		tx->sta = sta_info_get(sdata, hdr->addr1);
+- 
+- 	if (tx->sta && ieee80211_is_data_qos(hdr->frame_control) &&
+- 	    !ieee80211_is_qos_nullfunc(hdr->frame_control) &&
+-@@ -1485,7 +1492,7 @@ bool ieee80211_tx_prepare_skb(struct iee
+- 	struct ieee80211_tx_data tx;
+- 	struct sk_buff *skb2;
+- 
+--	if (ieee80211_tx_prepare(sdata, &tx, skb) == TX_DROP)
+-+	if (ieee80211_tx_prepare(sdata, &tx, NULL, skb) == TX_DROP)
+- 		return false;
+- 
+- 	info->band = band;
+-@@ -1518,7 +1525,8 @@ EXPORT_SYMBOL(ieee80211_tx_prepare_skb);
+-  * Returns false if the frame couldn't be transmitted but was queued instead.
+-  */
+- static bool ieee80211_tx(struct ieee80211_sub_if_data *sdata,
+--			 struct sk_buff *skb, bool txpending)
+-+			 struct sta_info *sta, struct sk_buff *skb,
+-+			 bool txpending)
+- {
+- 	struct ieee80211_local *local = sdata->local;
+- 	struct ieee80211_tx_data tx;
+-@@ -1534,7 +1542,7 @@ static bool ieee80211_tx(struct ieee8021
+- 
+- 	/* initialises tx */
+- 	led_len = skb->len;
+--	res_prepare = ieee80211_tx_prepare(sdata, &tx, skb);
+-+	res_prepare = ieee80211_tx_prepare(sdata, &tx, sta, skb);
+- 
+- 	if (unlikely(res_prepare == TX_DROP)) {
+- 		ieee80211_free_txskb(&local->hw, skb);
+-@@ -1590,7 +1598,8 @@ static int ieee80211_skb_resize(struct i
+- 	return 0;
+- }
+- 
+--void ieee80211_xmit(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb)
+-+void ieee80211_xmit(struct ieee80211_sub_if_data *sdata,
+-+		    struct sta_info *sta, struct sk_buff *skb)
+- {
+- 	struct ieee80211_local *local = sdata->local;
+- 	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
+-@@ -1625,7 +1634,7 @@ void ieee80211_xmit(struct ieee80211_sub
+- 	}
+- 
+- 	ieee80211_set_qos_hdr(sdata, skb);
+--	ieee80211_tx(sdata, skb, false);
+-+	ieee80211_tx(sdata, sta, skb, false);
+- }
+- 
+- static bool ieee80211_parse_tx_radiotap(struct sk_buff *skb)
+-@@ -1846,7 +1855,7 @@ netdev_tx_t ieee80211_monitor_start_xmit
+- 		goto fail_rcu;
+- 
+- 	info->band = chandef->chan->band;
+--	ieee80211_xmit(sdata, skb);
+-+	ieee80211_xmit(sdata, NULL, skb);
+- 	rcu_read_unlock();
+- 
+- 	return NETDEV_TX_OK;
+-@@ -1877,7 +1886,8 @@ fail:
+-  * Returns: the (possibly reallocated) skb or an ERR_PTR() code
+-  */
+- static struct sk_buff *ieee80211_build_hdr(struct ieee80211_sub_if_data *sdata,
+--					   struct sk_buff *skb, u32 info_flags)
+-+					   struct sk_buff *skb, u32 info_flags,
+-+					   struct sta_info **sta_out)
+- {
+- 	struct ieee80211_local *local = sdata->local;
+- 	struct ieee80211_tx_info *info;
+-@@ -1920,6 +1930,7 @@ static struct sk_buff *ieee80211_build_h
+- 			authorized = test_sta_flag(sta, WLAN_STA_AUTHORIZED);
+- 			wme_sta = sta->sta.wme;
+- 			have_station = true;
+-+			*sta_out = sta;
+- 		} else if (sdata->wdev.use_4addr) {
+- 			ret = -ENOLINK;
+- 			goto free;
+-@@ -2073,6 +2084,7 @@ static struct sk_buff *ieee80211_build_h
+- 			have_station = true;
+- 			authorized = test_sta_flag(sta, WLAN_STA_AUTHORIZED);
+- 			wme_sta = sta->sta.wme;
+-+			*sta_out = sta;
+- 		}  else if (sdata->u.mgd.use_4addr &&
+- 			    cpu_to_be16(ethertype) != sdata->control_port_protocol) {
+- 			fc |= cpu_to_le16(IEEE80211_FCTL_FROMDS |
+-@@ -2136,13 +2148,18 @@ static struct sk_buff *ieee80211_build_h
+- 	 * and mesh mode checks authorization later.
+- 	 */
+- 	multicast = is_multicast_ether_addr(hdr.addr1);
+--	if (!multicast && !have_station &&
+--	    !ieee80211_vif_is_mesh(&sdata->vif)) {
+--		sta = sta_info_get(sdata, hdr.addr1);
+-+	if (multicast) {
+-+		*sta_out = ERR_PTR(-ENOENT);
+-+	} else if (!have_station && !ieee80211_vif_is_mesh(&sdata->vif)) {
+-+		if (sdata->control_port_protocol == skb->protocol)
+-+			sta = sta_info_get_bss(sdata, hdr.addr1);
+-+		else
+-+			sta = sta_info_get(sdata, hdr.addr1);
+- 		if (sta) {
+- 			authorized = test_sta_flag(sta, WLAN_STA_AUTHORIZED);
+- 			wme_sta = sta->sta.wme;
+- 		}
+-+		*sta_out = sta ?: ERR_PTR(-ENOENT);
+- 	}
+- 
+- 	/* For mesh, the use of the QoS header is mandatory */
+-@@ -2320,6 +2337,7 @@ void __ieee80211_subif_start_xmit(struct
+- 				  u32 info_flags)
+- {
+- 	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+-+	struct sta_info *sta = NULL;
+- 
+- 	if (unlikely(skb->len < ETH_HLEN)) {
+- 		kfree_skb(skb);
+-@@ -2328,7 +2346,7 @@ void __ieee80211_subif_start_xmit(struct
+- 
+- 	rcu_read_lock();
+- 
+--	skb = ieee80211_build_hdr(sdata, skb, info_flags);
+-+	skb = ieee80211_build_hdr(sdata, skb, info_flags, &sta);
+- 	if (IS_ERR(skb))
+- 		goto out;
+- 
+-@@ -2336,7 +2354,7 @@ void __ieee80211_subif_start_xmit(struct
+- 	dev->stats.tx_bytes += skb->len;
+- 	dev->trans_start = jiffies;
+- 
+--	ieee80211_xmit(sdata, skb);
+-+	ieee80211_xmit(sdata, sta, skb);
+-  out:
+- 	rcu_read_unlock();
+- }
+-@@ -2364,10 +2382,11 @@ ieee80211_build_data_template(struct iee
+- 		.local = sdata->local,
+- 		.sdata = sdata,
+- 	};
+-+	struct sta_info *sta_ignore;
+- 
+- 	rcu_read_lock();
+- 
+--	skb = ieee80211_build_hdr(sdata, skb, info_flags);
+-+	skb = ieee80211_build_hdr(sdata, skb, info_flags, &sta_ignore);
+- 	if (IS_ERR(skb))
+- 		goto out;
+- 
+-@@ -2425,7 +2444,7 @@ static bool ieee80211_tx_pending_skb(str
+- 			return true;
+- 		}
+- 		info->band = chanctx_conf->def.chan->band;
+--		result = ieee80211_tx(sdata, skb, true);
+-+		result = ieee80211_tx(sdata, NULL, skb, true);
+- 	} else {
+- 		struct sk_buff_head skbs;
+- 
+-@@ -3163,7 +3182,7 @@ ieee80211_get_buffered_bc(struct ieee802
+- 
+- 		if (sdata->vif.type == NL80211_IFTYPE_AP)
+- 			sdata = IEEE80211_DEV_TO_SUB_IF(skb->dev);
+--		if (!ieee80211_tx_prepare(sdata, &tx, skb))
+-+		if (!ieee80211_tx_prepare(sdata, &tx, NULL, skb))
+- 			break;
+- 		dev_kfree_skb_any(skb);
+- 	}
+-@@ -3295,6 +3314,6 @@ void __ieee80211_tx_skb_tid_band(struct
+- 	 */
+- 	local_bh_disable();
+- 	IEEE80211_SKB_CB(skb)->band = band;
+--	ieee80211_xmit(sdata, skb);
+-+	ieee80211_xmit(sdata, NULL, skb);
+- 	local_bh_enable();
+- }
+diff --git a/package/kernel/mac80211/patches/316-brcmfmac-block-the-correct-flowring-when-backup-queu.patch b/package/kernel/mac80211/patches/316-brcmfmac-block-the-correct-flowring-when-backup-queu.patch
+new file mode 100644
+index 0000000..2d5f7b9
+--- /dev/null
++++ b/package/kernel/mac80211/patches/316-brcmfmac-block-the-correct-flowring-when-backup-queu.patch
+@@ -0,0 +1,48 @@
++From: Franky Lin <frankyl@broadcom.com>
++Date: Thu, 20 Aug 2015 22:06:06 +0200
++Subject: [PATCH] brcmfmac: block the correct flowring when backup queue
++ overflow
++
++brcmf_flowring_block blocks the last active flowring under the same
++interface instead of the one provided by caller. This could lead to a
++dead lock of netif stop if there are more than one flowring under the
++interface and the traffic is high enough so brcmf_flowring_enqueue can
++not unblock the ring right away.
++
++Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
++Reviewed-by: Hante Meuleman <meuleman@broadcom.com>
++Signed-off-by: Franky Lin <frankyl@broadcom.com>
++Signed-off-by: Arend van Spriel <arend@broadcom.com>
++Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
++---
++
++--- a/drivers/net/wireless/brcm80211/brcmfmac/flowring.c
+++++ b/drivers/net/wireless/brcm80211/brcmfmac/flowring.c
++@@ -194,11 +194,15 @@ static void brcmf_flowring_block(struct
++ 	spin_lock_irqsave(&flow->block_lock, flags);
++ 
++ 	ring = flow->rings[flowid];
+++	if (ring->blocked == blocked) {
+++		spin_unlock_irqrestore(&flow->block_lock, flags);
+++		return;
+++	}
++ 	ifidx = brcmf_flowring_ifidx_get(flow, flowid);
++ 
++ 	currently_blocked = false;
++ 	for (i = 0; i < flow->nrofrings; i++) {
++-		if (flow->rings[i]) {
+++		if ((flow->rings[i]) && (i != flowid)) {
++ 			ring = flow->rings[i];
++ 			if ((ring->status == RING_OPEN) &&
++ 			    (brcmf_flowring_ifidx_get(flow, i) == ifidx)) {
++@@ -209,8 +213,8 @@ static void brcmf_flowring_block(struct
++ 			}
++ 		}
++ 	}
++-	ring->blocked = blocked;
++-	if (currently_blocked == blocked) {
+++	flow->rings[flowid]->blocked = blocked;
+++	if (currently_blocked) {
++ 		spin_unlock_irqrestore(&flow->block_lock, flags);
++ 		return;
++ 	}
+diff --git a/package/kernel/mac80211/patches/316-mac80211-reduce-log-spam-from-ieee80211_handle_pwr_c.patch b/package/kernel/mac80211/patches/316-mac80211-reduce-log-spam-from-ieee80211_handle_pwr_c.patch
+deleted file mode 100644
+index 77a82c2..0000000
+--- a/package/kernel/mac80211/patches/316-mac80211-reduce-log-spam-from-ieee80211_handle_pwr_c.patch
++++ /dev/null
+@@ -1,38 +0,0 @@
+-From: John Linville <linville@tuxdriver.com>
+-Date: Tue, 31 Mar 2015 10:49:14 -0400
+-Subject: [PATCH] mac80211: reduce log spam from ieee80211_handle_pwr_constr
+-
+-This changes a couple of messages from sdata_info to sdata_dbg.
+-This should reduce some log spam, as reported here:
+-
+-	https://bugzilla.redhat.com/show_bug.cgi?id=1206468
+-
+-Signed-off-by: John W. Linville <linville@tuxdriver.com>
+-Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+----
+-
+---- a/net/mac80211/mlme.c
+-+++ b/net/mac80211/mlme.c
+-@@ -1347,15 +1347,15 @@ static u32 ieee80211_handle_pwr_constr(s
+- 	 */
+- 	if (has_80211h_pwr &&
+- 	    (!has_cisco_pwr || pwr_level_80211h <= pwr_level_cisco)) {
+--		sdata_info(sdata,
+--			   "Limiting TX power to %d (%d - %d) dBm as advertised by %pM\n",
+--			   pwr_level_80211h, chan_pwr, pwr_reduction_80211h,
+--			   sdata->u.mgd.bssid);
+-+		sdata_dbg(sdata,
+-+			  "Limiting TX power to %d (%d - %d) dBm as advertised by %pM\n",
+-+			  pwr_level_80211h, chan_pwr, pwr_reduction_80211h,
+-+			  sdata->u.mgd.bssid);
+- 		new_ap_level = pwr_level_80211h;
+- 	} else {  /* has_cisco_pwr is always true here. */
+--		sdata_info(sdata,
+--			   "Limiting TX power to %d dBm as advertised by %pM\n",
+--			   pwr_level_cisco, sdata->u.mgd.bssid);
+-+		sdata_dbg(sdata,
+-+			  "Limiting TX power to %d dBm as advertised by %pM\n",
+-+			  pwr_level_cisco, sdata->u.mgd.bssid);
+- 		new_ap_level = pwr_level_cisco;
+- 	}
+- 
+diff --git a/package/kernel/mac80211/patches/317-brcmfmac-Fix-race-condition-in-msgbuf-ioctl-processi.patch b/package/kernel/mac80211/patches/317-brcmfmac-Fix-race-condition-in-msgbuf-ioctl-processi.patch
+deleted file mode 100644
+index e005fe7..0000000
+--- a/package/kernel/mac80211/patches/317-brcmfmac-Fix-race-condition-in-msgbuf-ioctl-processi.patch
++++ /dev/null
+@@ -1,35 +0,0 @@
+-From: Hante Meuleman <meuleman@broadcom.com>
+-Date: Fri, 6 Mar 2015 18:40:41 +0100
+-Subject: [PATCH] brcmfmac: Fix race condition in msgbuf ioctl processing.
+-
+-Msgbuf is using a wait_event_timeout to wait for the response on
+-an ioctl. The wakeup routine uses waitqueue_active to see if
+-wait_event_timeout has been called. There is a chance that the
+-response arrives before wait_event_timeout is called, this
+-will result in situation that wait_event_timeout never gets
+-woken again and assumed result will be a timeout. This patch
+-removes that errornous situation by always setting the
+-ctl_completed var before checking for queue active.
+-
+-Reviewed-by: Arend Van Spriel <arend@broadcom.com>
+-Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
+-Signed-off-by: Hante Meuleman <meuleman@broadcom.com>
+-Signed-off-by: Arend van Spriel <arend@broadcom.com>
+-Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
+----
+-
+---- a/drivers/net/wireless/brcm80211/brcmfmac/msgbuf.c
+-+++ b/drivers/net/wireless/brcm80211/brcmfmac/msgbuf.c
+-@@ -481,10 +481,9 @@ static int brcmf_msgbuf_ioctl_resp_wait(
+- 
+- static void brcmf_msgbuf_ioctl_resp_wake(struct brcmf_msgbuf *msgbuf)
+- {
+--	if (waitqueue_active(&msgbuf->ioctl_resp_wait)) {
+--		msgbuf->ctl_completed = true;
+-+	msgbuf->ctl_completed = true;
+-+	if (waitqueue_active(&msgbuf->ioctl_resp_wait))
+- 		wake_up(&msgbuf->ioctl_resp_wait);
+--	}
+- }
+- 
+- 
+diff --git a/package/kernel/mac80211/patches/317-brcmfmac-bump-highest-event-number-for-4339-firmware.patch b/package/kernel/mac80211/patches/317-brcmfmac-bump-highest-event-number-for-4339-firmware.patch
+new file mode 100644
+index 0000000..7378401
+--- /dev/null
++++ b/package/kernel/mac80211/patches/317-brcmfmac-bump-highest-event-number-for-4339-firmware.patch
+@@ -0,0 +1,52 @@
++From: Arend van Spriel <arend@broadcom.com>
++Date: Thu, 20 Aug 2015 22:06:07 +0200
++Subject: [PATCH] brcmfmac: bump highest event number for 4339 firmware
++
++The event mask length is determined by the highest event number
++that is specified in the driver. When this length is shorter than
++firmware expects setting event mask will fail and device becomes
++pretty useless. This issue was reported with bcm4339 firmware that
++was recently released.
++
++Reported-by: Pontus Fuchs <pontusf@broadcom.com>
++Reviewed-by: Hante Meuleman <meuleman@broadcom.com>
++Reviewed-by: Franky (Zhenhui) Lin <frankyl@broadcom.com>
++Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
++Reviewed-by: Pontus Fuchs <pontusf@broadcom.com>
++Signed-off-by: Arend van Spriel <arend@broadcom.com>
++Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
++---
++
++--- a/drivers/net/wireless/brcm80211/brcmfmac/fweh.h
+++++ b/drivers/net/wireless/brcm80211/brcmfmac/fweh.h
++@@ -85,7 +85,6 @@ struct brcmf_event;
++ 	BRCMF_ENUM_DEF(IF, 54) \
++ 	BRCMF_ENUM_DEF(P2P_DISC_LISTEN_COMPLETE, 55) \
++ 	BRCMF_ENUM_DEF(RSSI, 56) \
++-	BRCMF_ENUM_DEF(PFN_SCAN_COMPLETE, 57) \
++ 	BRCMF_ENUM_DEF(EXTLOG_MSG, 58) \
++ 	BRCMF_ENUM_DEF(ACTION_FRAME, 59) \
++ 	BRCMF_ENUM_DEF(ACTION_FRAME_COMPLETE, 60) \
++@@ -103,8 +102,7 @@ struct brcmf_event;
++ 	BRCMF_ENUM_DEF(FIFO_CREDIT_MAP, 74) \
++ 	BRCMF_ENUM_DEF(ACTION_FRAME_RX, 75) \
++ 	BRCMF_ENUM_DEF(TDLS_PEER_EVENT, 92) \
++-	BRCMF_ENUM_DEF(BCMC_CREDIT_SUPPORT, 127) \
++-	BRCMF_ENUM_DEF(PSTA_PRIMARY_INTF_IND, 128)
+++	BRCMF_ENUM_DEF(BCMC_CREDIT_SUPPORT, 127)
++ 
++ #define BRCMF_ENUM_DEF(id, val) \
++ 	BRCMF_E_##id = (val),
++@@ -112,7 +110,11 @@ struct brcmf_event;
++ /* firmware event codes sent by the dongle */
++ enum brcmf_fweh_event_code {
++ 	BRCMF_FWEH_EVENT_ENUM_DEFLIST
++-	BRCMF_E_LAST
+++	/* this determines event mask length which must match
+++	 * minimum length check in device firmware so it is
+++	 * hard-coded here.
+++	 */
+++	BRCMF_E_LAST = 139
++ };
++ #undef BRCMF_ENUM_DEF
++ 
+diff --git a/package/kernel/mac80211/patches/318-brcmfmac-Update-msgbuf-commonring-size-for-improved-.patch b/package/kernel/mac80211/patches/318-brcmfmac-Update-msgbuf-commonring-size-for-improved-.patch
+deleted file mode 100644
+index c2cd1c5..0000000
+--- a/package/kernel/mac80211/patches/318-brcmfmac-Update-msgbuf-commonring-size-for-improved-.patch
++++ /dev/null
+@@ -1,30 +0,0 @@
+-From: Hante Meuleman <meuleman@broadcom.com>
+-Date: Wed, 18 Mar 2015 13:25:23 +0100
+-Subject: [PATCH] brcmfmac: Update msgbuf commonring size for improved
+- throughput.
+-
+-Reviewed-by: Arend Van Spriel <arend@broadcom.com>
+-Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
+-Signed-off-by: Hante Meuleman <meuleman@broadcom.com>
+-Signed-off-by: Arend van Spriel <arend@broadcom.com>
+-Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
+----
+-
+---- a/drivers/net/wireless/brcm80211/brcmfmac/msgbuf.h
+-+++ b/drivers/net/wireless/brcm80211/brcmfmac/msgbuf.h
+-@@ -17,11 +17,11 @@
+- 
+- #ifdef CPTCFG_BRCMFMAC_PROTO_MSGBUF
+- 
+--#define BRCMF_H2D_MSGRING_CONTROL_SUBMIT_MAX_ITEM	20
+--#define BRCMF_H2D_MSGRING_RXPOST_SUBMIT_MAX_ITEM	256
+--#define BRCMF_D2H_MSGRING_CONTROL_COMPLETE_MAX_ITEM	20
+-+#define BRCMF_H2D_MSGRING_CONTROL_SUBMIT_MAX_ITEM	64
+-+#define BRCMF_H2D_MSGRING_RXPOST_SUBMIT_MAX_ITEM	512
+-+#define BRCMF_D2H_MSGRING_CONTROL_COMPLETE_MAX_ITEM	64
+- #define BRCMF_D2H_MSGRING_TX_COMPLETE_MAX_ITEM		1024
+--#define BRCMF_D2H_MSGRING_RX_COMPLETE_MAX_ITEM		256
+-+#define BRCMF_D2H_MSGRING_RX_COMPLETE_MAX_ITEM		512
+- #define BRCMF_H2D_TXFLOWRING_MAX_ITEM			512
+- 
+- #define BRCMF_H2D_MSGRING_CONTROL_SUBMIT_ITEMSIZE	40
+diff --git a/package/kernel/mac80211/patches/319-ath9k_htc-add-new-WMI_REG_RMW_CMDID-command.patch b/package/kernel/mac80211/patches/319-ath9k_htc-add-new-WMI_REG_RMW_CMDID-command.patch
+deleted file mode 100644
+index 6af69eb..0000000
+--- a/package/kernel/mac80211/patches/319-ath9k_htc-add-new-WMI_REG_RMW_CMDID-command.patch
++++ /dev/null
+@@ -1,307 +0,0 @@
+-From: Oleksij Rempel <linux@rempel-privat.de>
+-Date: Sun, 22 Mar 2015 19:29:46 +0100
+-Subject: [PATCH] ath9k_htc: add new WMI_REG_RMW_CMDID command
+-
+-Since usb bus add extra delay on each request, a command
+-with read + write requests is too expensive. We can dramtically
+-reduce usb load by moving this command to firmware.
+-
+-In my tests, this patch will reduce channel scan time
+-for about 5-10 seconds.
+-
+-Signed-off-by: Oleksij Rempel <linux@rempel-privat.de>
+-Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
+----
+-
+---- a/drivers/net/wireless/ath/ath.h
+-+++ b/drivers/net/wireless/ath/ath.h
+-@@ -131,6 +131,9 @@ struct ath_ops {
+- 	void (*enable_write_buffer)(void *);
+- 	void (*write_flush) (void *);
+- 	u32 (*rmw)(void *, u32 reg_offset, u32 set, u32 clr);
+-+	void (*enable_rmw_buffer)(void *);
+-+	void (*rmw_flush) (void *);
+-+
+- };
+- 
+- struct ath_common;
+---- a/drivers/net/wireless/ath/ath9k/htc.h
+-+++ b/drivers/net/wireless/ath/ath9k/htc.h
+-@@ -444,6 +444,10 @@ static inline void ath9k_htc_stop_btcoex
+- #define OP_BT_SCAN                 BIT(4)
+- #define OP_TSF_RESET               BIT(6)
+- 
+-+enum htc_op_flags {
+-+	HTC_FWFLAG_NO_RMW,
+-+};
+-+
+- struct ath9k_htc_priv {
+- 	struct device *dev;
+- 	struct ieee80211_hw *hw;
+-@@ -482,6 +486,7 @@ struct ath9k_htc_priv {
+- 	bool reconfig_beacon;
+- 	unsigned int rxfilter;
+- 	unsigned long op_flags;
+-+	unsigned long fw_flags;
+- 
+- 	struct ath9k_hw_cal_data caldata;
+- 	struct ath_spec_scan_priv spec_priv;
+---- a/drivers/net/wireless/ath/ath9k/htc_drv_init.c
+-+++ b/drivers/net/wireless/ath/ath9k/htc_drv_init.c
+-@@ -376,17 +376,139 @@ static void ath9k_regwrite_flush(void *h
+- 	mutex_unlock(&priv->wmi->multi_write_mutex);
+- }
+- 
+--static u32 ath9k_reg_rmw(void *hw_priv, u32 reg_offset, u32 set, u32 clr)
+-+static void ath9k_reg_rmw_buffer(void *hw_priv,
+-+				 u32 reg_offset, u32 set, u32 clr)
+-+{
+-+	struct ath_hw *ah = (struct ath_hw *) hw_priv;
+-+	struct ath_common *common = ath9k_hw_common(ah);
+-+	struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *) common->priv;
+-+	u32 rsp_status;
+-+	int r;
+-+
+-+	mutex_lock(&priv->wmi->multi_rmw_mutex);
+-+
+-+	/* Store the register/value */
+-+	priv->wmi->multi_rmw[priv->wmi->multi_rmw_idx].reg =
+-+		cpu_to_be32(reg_offset);
+-+	priv->wmi->multi_rmw[priv->wmi->multi_rmw_idx].set =
+-+		cpu_to_be32(set);
+-+	priv->wmi->multi_rmw[priv->wmi->multi_rmw_idx].clr =
+-+		cpu_to_be32(clr);
+-+
+-+	priv->wmi->multi_rmw_idx++;
+-+
+-+	/* If the buffer is full, send it out. */
+-+	if (priv->wmi->multi_rmw_idx == MAX_RMW_CMD_NUMBER) {
+-+		r = ath9k_wmi_cmd(priv->wmi, WMI_REG_RMW_CMDID,
+-+			  (u8 *) &priv->wmi->multi_rmw,
+-+			  sizeof(struct register_write) * priv->wmi->multi_rmw_idx,
+-+			  (u8 *) &rsp_status, sizeof(rsp_status),
+-+			  100);
+-+		if (unlikely(r)) {
+-+			ath_dbg(common, WMI,
+-+				"REGISTER RMW FAILED, multi len: %d\n",
+-+				priv->wmi->multi_rmw_idx);
+-+		}
+-+		priv->wmi->multi_rmw_idx = 0;
+-+	}
+-+
+-+	mutex_unlock(&priv->wmi->multi_rmw_mutex);
+-+}
+-+
+-+static void ath9k_reg_rmw_flush(void *hw_priv)
+- {
+--	u32 val;
+-+	struct ath_hw *ah = (struct ath_hw *) hw_priv;
+-+	struct ath_common *common = ath9k_hw_common(ah);
+-+	struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *) common->priv;
+-+	u32 rsp_status;
+-+	int r;
+-+
+-+	if (test_bit(HTC_FWFLAG_NO_RMW, &priv->fw_flags))
+-+		return;
+-+
+-+	atomic_dec(&priv->wmi->m_rmw_cnt);
+-+
+-+	mutex_lock(&priv->wmi->multi_rmw_mutex);
+-+
+-+	if (priv->wmi->multi_rmw_idx) {
+-+		r = ath9k_wmi_cmd(priv->wmi, WMI_REG_RMW_CMDID,
+-+			  (u8 *) &priv->wmi->multi_rmw,
+-+			  sizeof(struct register_rmw) * priv->wmi->multi_rmw_idx,
+-+			  (u8 *) &rsp_status, sizeof(rsp_status),
+-+			  100);
+-+		if (unlikely(r)) {
+-+			ath_dbg(common, WMI,
+-+				"REGISTER RMW FAILED, multi len: %d\n",
+-+				priv->wmi->multi_rmw_idx);
+-+		}
+-+		priv->wmi->multi_rmw_idx = 0;
+-+	}
+- 
+--	val = ath9k_regread(hw_priv, reg_offset);
+--	val &= ~clr;
+--	val |= set;
+--	ath9k_regwrite(hw_priv, val, reg_offset);
+-+	mutex_unlock(&priv->wmi->multi_rmw_mutex);
+-+}
+-+
+-+static void ath9k_enable_rmw_buffer(void *hw_priv)
+-+{
+-+	struct ath_hw *ah = (struct ath_hw *) hw_priv;
+-+	struct ath_common *common = ath9k_hw_common(ah);
+-+	struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *) common->priv;
+-+
+-+	if (test_bit(HTC_FWFLAG_NO_RMW, &priv->fw_flags))
+-+		return;
+-+
+-+	atomic_inc(&priv->wmi->m_rmw_cnt);
+-+}
+-+
+-+static u32 ath9k_reg_rmw_single(void *hw_priv,
+-+				 u32 reg_offset, u32 set, u32 clr)
+-+{
+-+	struct ath_hw *ah = (struct ath_hw *) hw_priv;
+-+	struct ath_common *common = ath9k_hw_common(ah);
+-+	struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *) common->priv;
+-+	struct register_rmw buf, buf_ret;
+-+	int ret;
+-+	u32 val = 0;
+-+
+-+	buf.reg = cpu_to_be32(reg_offset);
+-+	buf.set = cpu_to_be32(set);
+-+	buf.clr = cpu_to_be32(clr);
+-+
+-+	ret = ath9k_wmi_cmd(priv->wmi, WMI_REG_RMW_CMDID,
+-+			  (u8 *) &buf, sizeof(buf),
+-+			  (u8 *) &buf_ret, sizeof(buf_ret),
+-+			  100);
+-+	if (unlikely(ret)) {
+-+		ath_dbg(common, WMI, "REGISTER RMW FAILED:(0x%04x, %d)\n",
+-+			reg_offset, ret);
+-+	}
+- 	return val;
+- }
+- 
+-+static u32 ath9k_reg_rmw(void *hw_priv, u32 reg_offset, u32 set, u32 clr)
+-+{
+-+	struct ath_hw *ah = (struct ath_hw *) hw_priv;
+-+	struct ath_common *common = ath9k_hw_common(ah);
+-+	struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *) common->priv;
+-+
+-+	if (test_bit(HTC_FWFLAG_NO_RMW, &priv->fw_flags)) {
+-+		u32 val;
+-+
+-+		val = REG_READ(ah, reg_offset);
+-+		val &= ~clr;
+-+		val |= set;
+-+		REG_WRITE(ah, reg_offset, val);
+-+
+-+		return 0;
+-+	}
+-+
+-+	if (atomic_read(&priv->wmi->m_rmw_cnt))
+-+		ath9k_reg_rmw_buffer(hw_priv, reg_offset, set, clr);
+-+	else
+-+		ath9k_reg_rmw_single(hw_priv, reg_offset, set, clr);
+-+
+-+	return 0;
+-+}
+-+
+- static void ath_usb_read_cachesize(struct ath_common *common, int *csz)
+- {
+- 	*csz = L1_CACHE_BYTES >> 2;
+-@@ -501,6 +623,8 @@ static int ath9k_init_priv(struct ath9k_
+- 	ah->reg_ops.write = ath9k_regwrite;
+- 	ah->reg_ops.enable_write_buffer = ath9k_enable_regwrite_buffer;
+- 	ah->reg_ops.write_flush = ath9k_regwrite_flush;
+-+	ah->reg_ops.enable_rmw_buffer = ath9k_enable_rmw_buffer;
+-+	ah->reg_ops.rmw_flush = ath9k_reg_rmw_flush;
+- 	ah->reg_ops.rmw = ath9k_reg_rmw;
+- 	priv->ah = ah;
+- 
+-@@ -686,6 +810,12 @@ static int ath9k_init_firmware_version(s
+- 		return -EINVAL;
+- 	}
+- 
+-+	if (priv->fw_version_major == 1 && priv->fw_version_minor < 4)
+-+		set_bit(HTC_FWFLAG_NO_RMW, &priv->fw_flags);
+-+
+-+	dev_info(priv->dev, "FW RMW support: %s\n",
+-+		test_bit(HTC_FWFLAG_NO_RMW, &priv->fw_flags) ? "Off" : "On");
+-+
+- 	return 0;
+- }
+- 
+---- a/drivers/net/wireless/ath/ath9k/hw.h
+-+++ b/drivers/net/wireless/ath/ath9k/hw.h
+-@@ -100,6 +100,18 @@
+- 			(_ah)->reg_ops.write_flush((_ah));	\
+- 	} while (0)
+- 
+-+#define ENABLE_REG_RMW_BUFFER(_ah)					\
+-+	do {								\
+-+		if ((_ah)->reg_ops.enable_rmw_buffer)	\
+-+			(_ah)->reg_ops.enable_rmw_buffer((_ah)); \
+-+	} while (0)
+-+
+-+#define REG_RMW_BUFFER_FLUSH(_ah)					\
+-+	do {								\
+-+		if ((_ah)->reg_ops.rmw_flush)		\
+-+			(_ah)->reg_ops.rmw_flush((_ah));	\
+-+	} while (0)
+-+
+- #define PR_EEP(_s, _val)						\
+- 	do {								\
+- 		len += scnprintf(buf + len, size - len, "%20s : %10d\n",\
+---- a/drivers/net/wireless/ath/ath9k/wmi.c
+-+++ b/drivers/net/wireless/ath/ath9k/wmi.c
+-@@ -61,6 +61,8 @@ static const char *wmi_cmd_to_name(enum
+- 		return "WMI_REG_READ_CMDID";
+- 	case WMI_REG_WRITE_CMDID:
+- 		return "WMI_REG_WRITE_CMDID";
+-+	case WMI_REG_RMW_CMDID:
+-+		return "WMI_REG_RMW_CMDID";
+- 	case WMI_RC_STATE_CHANGE_CMDID:
+- 		return "WMI_RC_STATE_CHANGE_CMDID";
+- 	case WMI_RC_RATE_UPDATE_CMDID:
+-@@ -101,6 +103,7 @@ struct wmi *ath9k_init_wmi(struct ath9k_
+- 	spin_lock_init(&wmi->event_lock);
+- 	mutex_init(&wmi->op_mutex);
+- 	mutex_init(&wmi->multi_write_mutex);
+-+	mutex_init(&wmi->multi_rmw_mutex);
+- 	init_completion(&wmi->cmd_wait);
+- 	INIT_LIST_HEAD(&wmi->pending_tx_events);
+- 	tasklet_init(&wmi->wmi_event_tasklet, ath9k_wmi_event_tasklet,
+---- a/drivers/net/wireless/ath/ath9k/wmi.h
+-+++ b/drivers/net/wireless/ath/ath9k/wmi.h
+-@@ -112,6 +112,7 @@ enum wmi_cmd_id {
+- 	WMI_TX_STATS_CMDID,
+- 	WMI_RX_STATS_CMDID,
+- 	WMI_BITRATE_MASK_CMDID,
+-+	WMI_REG_RMW_CMDID,
+- };
+- 
+- enum wmi_event_id {
+-@@ -125,12 +126,19 @@ enum wmi_event_id {
+- };
+- 
+- #define MAX_CMD_NUMBER 62
+-+#define MAX_RMW_CMD_NUMBER 15
+- 
+- struct register_write {
+- 	__be32 reg;
+- 	__be32 val;
+- };
+- 
+-+struct register_rmw {
+-+	__be32 reg;
+-+	__be32 set;
+-+	__be32 clr;
+-+} __packed;
+-+
+- struct ath9k_htc_tx_event {
+- 	int count;
+- 	struct __wmi_event_txstatus txs;
+-@@ -156,10 +164,18 @@ struct wmi {
+- 
+- 	spinlock_t wmi_lock;
+- 
+-+	/* multi write section */
+- 	atomic_t mwrite_cnt;
+- 	struct register_write multi_write[MAX_CMD_NUMBER];
+- 	u32 multi_write_idx;
+- 	struct mutex multi_write_mutex;
+-+
+-+	/* multi rmw section */
+-+	atomic_t m_rmw_cnt;
+-+	struct register_rmw multi_rmw[MAX_RMW_CMD_NUMBER];
+-+	u32 multi_rmw_idx;
+-+	struct mutex multi_rmw_mutex;
+-+
+- };
+- 
+- struct wmi *ath9k_init_wmi(struct ath9k_htc_priv *priv);
+diff --git a/package/kernel/mac80211/patches/319-brcmfmac-consolidate-ifp-lookup-in-driver-core.patch b/package/kernel/mac80211/patches/319-brcmfmac-consolidate-ifp-lookup-in-driver-core.patch
+new file mode 100644
+index 0000000..97444b3
+--- /dev/null
++++ b/package/kernel/mac80211/patches/319-brcmfmac-consolidate-ifp-lookup-in-driver-core.patch
+@@ -0,0 +1,138 @@
++From: Arend van Spriel <arend@broadcom.com>
++Date: Wed, 26 Aug 2015 22:14:53 +0200
++Subject: [PATCH] brcmfmac: consolidate ifp lookup in driver core
++
++In rx path the firmware provide an interface index which is used to
++map to a struct brcmf_if instance. However, this involves some trick
++that is done in two places. This is changed by having driver core
++providing brcmf_get_ifp() function.
++
++Reviewed-by: Hante Meuleman <meuleman@broadcom.com>
++Reviewed-by: Franky (Zhenhui) Lin <frankyl@broadcom.com>
++Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
++Signed-off-by: Arend van Spriel <arend@broadcom.com>
++---
++
++--- a/drivers/net/wireless/brcm80211/brcmfmac/bcdc.c
+++++ b/drivers/net/wireless/brcm80211/brcmfmac/bcdc.c
++@@ -276,6 +276,7 @@ brcmf_proto_bcdc_hdrpull(struct brcmf_pu
++ 			 struct sk_buff *pktbuf)
++ {
++ 	struct brcmf_proto_bcdc_header *h;
+++	struct brcmf_if *ifp;
++ 
++ 	brcmf_dbg(BCDC, "Enter\n");
++ 
++@@ -289,30 +290,21 @@ brcmf_proto_bcdc_hdrpull(struct brcmf_pu
++ 	trace_brcmf_bcdchdr(pktbuf->data);
++ 	h = (struct brcmf_proto_bcdc_header *)(pktbuf->data);
++ 
++-	*ifidx = BCDC_GET_IF_IDX(h);
++-	if (*ifidx >= BRCMF_MAX_IFS) {
++-		brcmf_err("rx data ifnum out of range (%d)\n", *ifidx);
+++	ifp = brcmf_get_ifp(drvr, BCDC_GET_IF_IDX(h));
+++	if (IS_ERR_OR_NULL(ifp)) {
+++		brcmf_dbg(INFO, "no matching ifp found\n");
++ 		return -EBADE;
++ 	}
++-	/* The ifidx is the idx to map to matching netdev/ifp. When receiving
++-	 * events this is easy because it contains the bssidx which maps
++-	 * 1-on-1 to the netdev/ifp. But for data frames the ifidx is rcvd.
++-	 * bssidx 1 is used for p2p0 and no data can be received or
++-	 * transmitted on it. Therefor bssidx is ifidx + 1 if ifidx > 0
++-	 */
++-	if (*ifidx)
++-		(*ifidx)++;
++-
++ 	if (((h->flags & BCDC_FLAG_VER_MASK) >> BCDC_FLAG_VER_SHIFT) !=
++ 	    BCDC_PROTO_VER) {
++ 		brcmf_err("%s: non-BCDC packet received, flags 0x%x\n",
++-			  brcmf_ifname(drvr, *ifidx), h->flags);
+++			  brcmf_ifname(drvr, ifp->ifidx), h->flags);
++ 		return -EBADE;
++ 	}
++ 
++ 	if (h->flags & BCDC_FLAG_SUM_GOOD) {
++ 		brcmf_dbg(BCDC, "%s: BDC rcv, good checksum, flags 0x%x\n",
++-			  brcmf_ifname(drvr, *ifidx), h->flags);
+++			  brcmf_ifname(drvr, ifp->ifidx), h->flags);
++ 		pktbuf->ip_summed = CHECKSUM_UNNECESSARY;
++ 	}
++ 
++@@ -320,12 +312,15 @@ brcmf_proto_bcdc_hdrpull(struct brcmf_pu
++ 
++ 	skb_pull(pktbuf, BCDC_HEADER_LEN);
++ 	if (do_fws)
++-		brcmf_fws_hdrpull(drvr, *ifidx, h->data_offset << 2, pktbuf);
+++		brcmf_fws_hdrpull(drvr, ifp->ifidx, h->data_offset << 2,
+++				  pktbuf);
++ 	else
++ 		skb_pull(pktbuf, h->data_offset << 2);
++ 
++ 	if (pktbuf->len == 0)
++ 		return -ENODATA;
+++
+++	*ifidx = ifp->ifidx;
++ 	return 0;
++ }
++ 
++--- a/drivers/net/wireless/brcm80211/brcmfmac/core.c
+++++ b/drivers/net/wireless/brcm80211/brcmfmac/core.c
++@@ -83,6 +83,25 @@ char *brcmf_ifname(struct brcmf_pub *drv
++ 	return "<if_none>";
++ }
++ 
+++struct brcmf_if *brcmf_get_ifp(struct brcmf_pub *drvr, int ifidx)
+++{
+++	if (ifidx < 0 || ifidx >= BRCMF_MAX_IFS) {
+++		brcmf_err("ifidx %d out of range\n", ifidx);
+++		return ERR_PTR(-ERANGE);
+++	}
+++
+++	/* The ifidx is the idx to map to matching netdev/ifp. When receiving
+++	 * events this is easy because it contains the bssidx which maps
+++	 * 1-on-1 to the netdev/ifp. But for data frames the ifidx is rcvd.
+++	 * bssidx 1 is used for p2p0 and no data can be received or
+++	 * transmitted on it. Therefor bssidx is ifidx + 1 if ifidx > 0
+++	 */
+++	if (ifidx)
+++		ifidx++;
+++
+++	return drvr->iflist[ifidx];
+++}
+++
++ static void _brcmf_set_multicast_list(struct work_struct *work)
++ {
++ 	struct brcmf_if *ifp;
++--- a/drivers/net/wireless/brcm80211/brcmfmac/core.h
+++++ b/drivers/net/wireless/brcm80211/brcmfmac/core.h
++@@ -202,7 +202,7 @@ int brcmf_netdev_wait_pend8021x(struct b
++ 
++ /* Return pointer to interface name */
++ char *brcmf_ifname(struct brcmf_pub *drvr, int idx);
++-
+++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 bssidx, s32 ifidx,
++ 			      char *name, u8 *mac_addr);
++--- a/drivers/net/wireless/brcm80211/brcmfmac/msgbuf.c
+++++ b/drivers/net/wireless/brcm80211/brcmfmac/msgbuf.c
++@@ -1081,16 +1081,8 @@ brcmf_msgbuf_rx_skb(struct brcmf_msgbuf
++ {
++ 	struct brcmf_if *ifp;
++ 
++-	/* The ifidx is the idx to map to matching netdev/ifp. When receiving
++-	 * events this is easy because it contains the bssidx which maps
++-	 * 1-on-1 to the netdev/ifp. But for data frames the ifidx is rcvd.
++-	 * bssidx 1 is used for p2p0 and no data can be received or
++-	 * transmitted on it. Therefor bssidx is ifidx + 1 if ifidx > 0
++-	 */
++-	if (ifidx)
++-		(ifidx)++;
++-	ifp = msgbuf->drvr->iflist[ifidx];
++-	if (!ifp || !ifp->ndev) {
+++	ifp = brcmf_get_ifp(msgbuf->drvr, ifidx);
+++	if (IS_ERR_OR_NULL(ifp) || !ifp->ndev) {
++ 		brcmf_err("Received pkt for invalid ifidx %d\n", ifidx);
++ 		brcmu_pkt_buf_free_skb(skb);
++ 		return;
+diff --git a/package/kernel/mac80211/patches/320-ath9k-ar9271_hw_pa_cal-use-defs-instead-of-magin-num.patch b/package/kernel/mac80211/patches/320-ath9k-ar9271_hw_pa_cal-use-defs-instead-of-magin-num.patch
+deleted file mode 100644
+index c4dd1af..0000000
+--- a/package/kernel/mac80211/patches/320-ath9k-ar9271_hw_pa_cal-use-defs-instead-of-magin-num.patch
++++ /dev/null
+@@ -1,89 +0,0 @@
+-From: Oleksij Rempel <linux@rempel-privat.de>
+-Date: Sun, 22 Mar 2015 19:29:47 +0100
+-Subject: [PATCH] ath9k: ar9271_hw_pa_cal - use defs instead of magin
+- numbers
+-
+-This function uses mixed styles for register names/numbers which
+-is make harder reading and optimisation.
+-
+-Signed-off-by: Oleksij Rempel <linux@rempel-privat.de>
+-Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
+----
+-
+---- a/drivers/net/wireless/ath/ath9k/ar9002_calib.c
+-+++ b/drivers/net/wireless/ath/ath9k/ar9002_calib.c
+-@@ -430,22 +430,22 @@ static void ar9271_hw_pa_cal(struct ath_
+- 	u32 regVal;
+- 	unsigned int i;
+- 	u32 regList[][2] = {
+--		{ 0x786c, 0 },
+--		{ 0x7854, 0 },
+--		{ 0x7820, 0 },
+--		{ 0x7824, 0 },
+--		{ 0x7868, 0 },
+--		{ 0x783c, 0 },
+--		{ 0x7838, 0 } ,
+--		{ 0x7828, 0 } ,
+-+		{ AR9285_AN_TOP3, 0 },
+-+		{ AR9285_AN_RXTXBB1, 0 },
+-+		{ AR9285_AN_RF2G1, 0 },
+-+		{ AR9285_AN_RF2G2, 0 },
+-+		{ AR9285_AN_TOP2, 0 },
+-+		{ AR9285_AN_RF2G8, 0 },
+-+		{ AR9285_AN_RF2G7, 0 } ,
+-+		{ AR9285_AN_RF2G3, 0 } ,
+- 	};
+- 
+- 	for (i = 0; i < ARRAY_SIZE(regList); i++)
+- 		regList[i][1] = REG_READ(ah, regList[i][0]);
+- 
+--	regVal = REG_READ(ah, 0x7834);
+-+	regVal = REG_READ(ah, AR9285_AN_RF2G6);
+- 	regVal &= (~(0x1));
+--	REG_WRITE(ah, 0x7834, regVal);
+-+	REG_WRITE(ah, AR9285_AN_RF2G6, regVal);
+- 	regVal = REG_READ(ah, 0x9808);
+- 	regVal |= (0x1 << 27);
+- 	REG_WRITE(ah, 0x9808, regVal);
+-@@ -477,7 +477,7 @@ static void ar9271_hw_pa_cal(struct ath_
+- 	 * does not matter since we turn it off
+- 	 */
+- 	REG_RMW_FIELD(ah, AR9285_AN_RF2G7, AR9285_AN_RF2G7_PADRVGN2TAB0, 0);
+--
+-+	/* 7828, b0-11, ccom=fff */
+- 	REG_RMW_FIELD(ah, AR9285_AN_RF2G3, AR9271_AN_RF2G3_CCOMP, 0xfff);
+- 
+- 	/* Set:
+-@@ -490,15 +490,16 @@ static void ar9271_hw_pa_cal(struct ath_
+- 
+- 	/* find off_6_1; */
+- 	for (i = 6; i > 0; i--) {
+--		regVal = REG_READ(ah, 0x7834);
+-+		regVal = REG_READ(ah, AR9285_AN_RF2G6);
+- 		regVal |= (1 << (20 + i));
+--		REG_WRITE(ah, 0x7834, regVal);
+-+		REG_WRITE(ah, AR9285_AN_RF2G6, regVal);
+- 		udelay(1);
+- 		/* regVal = REG_READ(ah, 0x7834); */
+- 		regVal &= (~(0x1 << (20 + i)));
+--		regVal |= (MS(REG_READ(ah, 0x7840), AR9285_AN_RXTXBB1_SPARE9)
+-+		regVal |= (MS(REG_READ(ah, AR9285_AN_RF2G9),
+-+			      AR9285_AN_RXTXBB1_SPARE9)
+- 			    << (20 + i));
+--		REG_WRITE(ah, 0x7834, regVal);
+-+		REG_WRITE(ah, AR9285_AN_RF2G6, regVal);
+- 	}
+- 
+- 	regVal = (regVal >> 20) & 0x7f;
+-@@ -517,9 +518,9 @@ static void ar9271_hw_pa_cal(struct ath_
+- 
+- 	ENABLE_REGWRITE_BUFFER(ah);
+- 
+--	regVal = REG_READ(ah, 0x7834);
+-+	regVal = REG_READ(ah, AR_AN_RF2G1_CH1);
+- 	regVal |= 0x1;
+--	REG_WRITE(ah, 0x7834, regVal);
+-+	REG_WRITE(ah, AR_AN_RF2G1_CH1, regVal);
+- 	regVal = REG_READ(ah, 0x9808);
+- 	regVal &= (~(0x1 << 27));
+- 	REG_WRITE(ah, 0x9808, regVal);
+diff --git a/package/kernel/mac80211/patches/320-brcmfmac-make-brcmf_proto_hdrpull-return-struct-brcm.patch b/package/kernel/mac80211/patches/320-brcmfmac-make-brcmf_proto_hdrpull-return-struct-brcm.patch
+new file mode 100644
+index 0000000..632714c
+--- /dev/null
++++ b/package/kernel/mac80211/patches/320-brcmfmac-make-brcmf_proto_hdrpull-return-struct-brcm.patch
+@@ -0,0 +1,222 @@
++From: Arend van Spriel <arend@broadcom.com>
++Date: Wed, 26 Aug 2015 22:14:54 +0200
++Subject: [PATCH] brcmfmac: make brcmf_proto_hdrpull() return struct
++ brcmf_if instance
++
++Avoid spreading the ifidx in the driver, but have it return the
++struct brcmf_if instance.
++
++Reviewed-by: Hante Meuleman <meuleman@broadcom.com>
++Reviewed-by: Franky (Zhenhui) Lin <frankyl@broadcom.com>
++Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
++Signed-off-by: Arend van Spriel <arend@broadcom.com>
++---
++
++--- a/drivers/net/wireless/brcm80211/brcmfmac/bcdc.c
+++++ b/drivers/net/wireless/brcm80211/brcmfmac/bcdc.c
++@@ -272,11 +272,11 @@ brcmf_proto_bcdc_hdrpush(struct brcmf_pu
++ }
++ 
++ static int
++-brcmf_proto_bcdc_hdrpull(struct brcmf_pub *drvr, bool do_fws, u8 *ifidx,
++-			 struct sk_buff *pktbuf)
+++brcmf_proto_bcdc_hdrpull(struct brcmf_pub *drvr, bool do_fws,
+++			 struct sk_buff *pktbuf, struct brcmf_if **ifp)
++ {
++ 	struct brcmf_proto_bcdc_header *h;
++-	struct brcmf_if *ifp;
+++	struct brcmf_if *tmp_if;
++ 
++ 	brcmf_dbg(BCDC, "Enter\n");
++ 
++@@ -290,21 +290,21 @@ brcmf_proto_bcdc_hdrpull(struct brcmf_pu
++ 	trace_brcmf_bcdchdr(pktbuf->data);
++ 	h = (struct brcmf_proto_bcdc_header *)(pktbuf->data);
++ 
++-	ifp = brcmf_get_ifp(drvr, BCDC_GET_IF_IDX(h));
++-	if (IS_ERR_OR_NULL(ifp)) {
+++	tmp_if = brcmf_get_ifp(drvr, BCDC_GET_IF_IDX(h));
+++	if (!tmp_if) {
++ 		brcmf_dbg(INFO, "no matching ifp found\n");
++ 		return -EBADE;
++ 	}
++ 	if (((h->flags & BCDC_FLAG_VER_MASK) >> BCDC_FLAG_VER_SHIFT) !=
++ 	    BCDC_PROTO_VER) {
++ 		brcmf_err("%s: non-BCDC packet received, flags 0x%x\n",
++-			  brcmf_ifname(drvr, ifp->ifidx), h->flags);
+++			  brcmf_ifname(drvr, tmp_if->ifidx), h->flags);
++ 		return -EBADE;
++ 	}
++ 
++ 	if (h->flags & BCDC_FLAG_SUM_GOOD) {
++ 		brcmf_dbg(BCDC, "%s: BDC rcv, good checksum, flags 0x%x\n",
++-			  brcmf_ifname(drvr, ifp->ifidx), h->flags);
+++			  brcmf_ifname(drvr, tmp_if->ifidx), h->flags);
++ 		pktbuf->ip_summed = CHECKSUM_UNNECESSARY;
++ 	}
++ 
++@@ -312,7 +312,7 @@ brcmf_proto_bcdc_hdrpull(struct brcmf_pu
++ 
++ 	skb_pull(pktbuf, BCDC_HEADER_LEN);
++ 	if (do_fws)
++-		brcmf_fws_hdrpull(drvr, ifp->ifidx, h->data_offset << 2,
+++		brcmf_fws_hdrpull(drvr, tmp_if->ifidx, h->data_offset << 2,
++ 				  pktbuf);
++ 	else
++ 		skb_pull(pktbuf, h->data_offset << 2);
++@@ -320,7 +320,7 @@ brcmf_proto_bcdc_hdrpull(struct brcmf_pu
++ 	if (pktbuf->len == 0)
++ 		return -ENODATA;
++ 
++-	*ifidx = ifp->ifidx;
+++	*ifp = tmp_if;
++ 	return 0;
++ }
++ 
++--- a/drivers/net/wireless/brcm80211/brcmfmac/core.c
+++++ b/drivers/net/wireless/brcm80211/brcmfmac/core.c
++@@ -87,7 +87,7 @@ struct brcmf_if *brcmf_get_ifp(struct br
++ {
++ 	if (ifidx < 0 || ifidx >= BRCMF_MAX_IFS) {
++ 		brcmf_err("ifidx %d out of range\n", ifidx);
++-		return ERR_PTR(-ERANGE);
+++		return NULL;
++ 	}
++ 
++ 	/* The ifidx is the idx to map to matching netdev/ifp. When receiving
++@@ -539,17 +539,15 @@ void brcmf_rx_frame(struct device *dev,
++ 	struct brcmf_bus *bus_if = dev_get_drvdata(dev);
++ 	struct brcmf_pub *drvr = bus_if->drvr;
++ 	struct brcmf_skb_reorder_data *rd;
++-	u8 ifidx;
++ 	int ret;
++ 
++ 	brcmf_dbg(DATA, "Enter: %s: rxp=%p\n", dev_name(dev), skb);
++ 
++ 	/* process and remove protocol-specific header */
++-	ret = brcmf_proto_hdrpull(drvr, true, &ifidx, skb);
++-	ifp = drvr->iflist[ifidx];
+++	ret = brcmf_proto_hdrpull(drvr, true, skb, &ifp);
++ 
++ 	if (ret || !ifp || !ifp->ndev) {
++-		if ((ret != -ENODATA) && ifp)
+++		if (ret != -ENODATA && ifp)
++ 			ifp->stats.rx_errors++;
++ 		brcmu_pkt_buf_free_skb(skb);
++ 		return;
++@@ -592,17 +590,17 @@ void brcmf_txcomplete(struct device *dev
++ {
++ 	struct brcmf_bus *bus_if = dev_get_drvdata(dev);
++ 	struct brcmf_pub *drvr = bus_if->drvr;
++-	u8 ifidx;
+++	struct brcmf_if *ifp;
++ 
++ 	/* await txstatus signal for firmware if active */
++ 	if (brcmf_fws_fc_active(drvr->fws)) {
++ 		if (!success)
++ 			brcmf_fws_bustxfail(drvr->fws, txp);
++ 	} else {
++-		if (brcmf_proto_hdrpull(drvr, false, &ifidx, txp))
+++		if (brcmf_proto_hdrpull(drvr, false, txp, &ifp))
++ 			brcmu_pkt_buf_free_skb(txp);
++ 		else
++-			brcmf_txfinalize(drvr, txp, ifidx, success);
+++			brcmf_txfinalize(drvr, txp, ifp->ifidx, success);
++ 	}
++ }
++ 
++--- a/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c
+++++ b/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c
++@@ -1448,7 +1448,7 @@ brcmf_fws_txs_process(struct brcmf_fws_i
++ 	struct sk_buff *skb;
++ 	struct brcmf_skbuff_cb *skcb;
++ 	struct brcmf_fws_mac_descriptor *entry = NULL;
++-	u8 ifidx;
+++	struct brcmf_if *ifp;
++ 
++ 	brcmf_dbg(DATA, "flags %d\n", flags);
++ 
++@@ -1497,15 +1497,16 @@ brcmf_fws_txs_process(struct brcmf_fws_i
++ 	}
++ 	brcmf_fws_macdesc_return_req_credit(skb);
++ 
++-	if (brcmf_proto_hdrpull(fws->drvr, false, &ifidx, skb)) {
+++	ret = brcmf_proto_hdrpull(fws->drvr, false, skb, &ifp);
+++	if (ret) {
++ 		brcmu_pkt_buf_free_skb(skb);
++ 		return -EINVAL;
++ 	}
++ 	if (!remove_from_hanger)
++-		ret = brcmf_fws_txstatus_suppressed(fws, fifo, skb, ifidx,
+++		ret = brcmf_fws_txstatus_suppressed(fws, fifo, skb, ifp->ifidx,
++ 						    genbit, seq);
++ 	if (remove_from_hanger || ret)
++-		brcmf_txfinalize(fws->drvr, skb, ifidx, true);
+++		brcmf_txfinalize(fws->drvr, skb, ifp->ifidx, true);
++ 
++ 	return 0;
++ }
++@@ -1848,7 +1849,7 @@ static int brcmf_fws_commit_skb(struct b
++ 		entry->transit_count--;
++ 		if (entry->suppressed)
++ 			entry->suppr_transit_count--;
++-		brcmf_proto_hdrpull(fws->drvr, false, &ifidx, skb);
+++		(void)brcmf_proto_hdrpull(fws->drvr, false, skb, NULL);
++ 		goto rollback;
++ 	}
++ 
++--- a/drivers/net/wireless/brcm80211/brcmfmac/msgbuf.c
+++++ b/drivers/net/wireless/brcm80211/brcmfmac/msgbuf.c
++@@ -522,7 +522,7 @@ static int brcmf_msgbuf_set_dcmd(struct
++ 
++ 
++ static int brcmf_msgbuf_hdrpull(struct brcmf_pub *drvr, bool do_fws,
++-				u8 *ifidx, struct sk_buff *skb)
+++				struct sk_buff *skb, struct brcmf_if **ifp)
++ {
++ 	return -ENODEV;
++ }
++@@ -1082,7 +1082,7 @@ brcmf_msgbuf_rx_skb(struct brcmf_msgbuf
++ 	struct brcmf_if *ifp;
++ 
++ 	ifp = brcmf_get_ifp(msgbuf->drvr, ifidx);
++-	if (IS_ERR_OR_NULL(ifp) || !ifp->ndev) {
+++	if (!ifp || !ifp->ndev) {
++ 		brcmf_err("Received pkt for invalid ifidx %d\n", ifidx);
++ 		brcmu_pkt_buf_free_skb(skb);
++ 		return;
++--- a/drivers/net/wireless/brcm80211/brcmfmac/proto.h
+++++ b/drivers/net/wireless/brcm80211/brcmfmac/proto.h
++@@ -24,8 +24,8 @@ enum proto_addr_mode {
++ 
++ 
++ struct brcmf_proto {
++-	int (*hdrpull)(struct brcmf_pub *drvr, bool do_fws, u8 *ifidx,
++-		       struct sk_buff *skb);
+++	int (*hdrpull)(struct brcmf_pub *drvr, bool do_fws,
+++		       struct sk_buff *skb, struct brcmf_if **ifp);
++ 	int (*query_dcmd)(struct brcmf_pub *drvr, int ifidx, uint cmd,
++ 			  void *buf, uint len);
++ 	int (*set_dcmd)(struct brcmf_pub *drvr, int ifidx, uint cmd, void *buf,
++@@ -46,9 +46,19 @@ int brcmf_proto_attach(struct brcmf_pub
++ void brcmf_proto_detach(struct brcmf_pub *drvr);
++ 
++ static inline int brcmf_proto_hdrpull(struct brcmf_pub *drvr, bool do_fws,
++-				      u8 *ifidx, struct sk_buff *skb)
+++				      struct sk_buff *skb,
+++				      struct brcmf_if **ifp)
++ {
++-	return drvr->proto->hdrpull(drvr, do_fws, ifidx, skb);
+++	struct brcmf_if *tmp = NULL;
+++
+++	/* assure protocol is always called with
+++	 * non-null initialized pointer.
+++	 */
+++	if (ifp)
+++		*ifp = NULL;
+++	else
+++		ifp = &tmp;
+++	return drvr->proto->hdrpull(drvr, do_fws, skb, ifp);
++ }
++ static inline int brcmf_proto_query_dcmd(struct brcmf_pub *drvr, int ifidx,
++ 					 uint cmd, void *buf, uint len)
+diff --git a/package/kernel/mac80211/patches/321-ath9k-ar9271_hw_pa_cal-use-proper-makroses.patch b/package/kernel/mac80211/patches/321-ath9k-ar9271_hw_pa_cal-use-proper-makroses.patch
+deleted file mode 100644
+index f05287d..0000000
+--- a/package/kernel/mac80211/patches/321-ath9k-ar9271_hw_pa_cal-use-proper-makroses.patch
++++ /dev/null
+@@ -1,79 +0,0 @@
+-From: Oleksij Rempel <linux@rempel-privat.de>
+-Date: Sun, 22 Mar 2015 19:29:48 +0100
+-Subject: [PATCH] ath9k: ar9271_hw_pa_cal: use proper makroses.
+-
+-Signed-off-by: Oleksij Rempel <linux@rempel-privat.de>
+-Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
+----
+-
+---- a/drivers/net/wireless/ath/ath9k/ar9002_calib.c
+-+++ b/drivers/net/wireless/ath/ath9k/ar9002_calib.c
+-@@ -443,33 +443,30 @@ static void ar9271_hw_pa_cal(struct ath_
+- 	for (i = 0; i < ARRAY_SIZE(regList); i++)
+- 		regList[i][1] = REG_READ(ah, regList[i][0]);
+- 
+--	regVal = REG_READ(ah, AR9285_AN_RF2G6);
+--	regVal &= (~(0x1));
+--	REG_WRITE(ah, AR9285_AN_RF2G6, regVal);
+--	regVal = REG_READ(ah, 0x9808);
+--	regVal |= (0x1 << 27);
+--	REG_WRITE(ah, 0x9808, regVal);
+--
+-+	/* 7834, b1=0 */
+-+	REG_CLR_BIT(ah, AR9285_AN_RF2G6, 1 << 0);
+-+	/* 9808, b27=1 */
+-+	REG_SET_BIT(ah, 0x9808, 1 << 27);
+- 	/* 786c,b23,1, pwddac=1 */
+--	REG_RMW_FIELD(ah, AR9285_AN_TOP3, AR9285_AN_TOP3_PWDDAC, 1);
+-+	REG_SET_BIT(ah, AR9285_AN_TOP3, AR9285_AN_TOP3_PWDDAC);
+- 	/* 7854, b5,1, pdrxtxbb=1 */
+--	REG_RMW_FIELD(ah, AR9285_AN_RXTXBB1, AR9285_AN_RXTXBB1_PDRXTXBB1, 1);
+-+	REG_SET_BIT(ah, AR9285_AN_RXTXBB1, AR9285_AN_RXTXBB1_PDRXTXBB1);
+- 	/* 7854, b7,1, pdv2i=1 */
+--	REG_RMW_FIELD(ah, AR9285_AN_RXTXBB1, AR9285_AN_RXTXBB1_PDV2I, 1);
+-+	REG_SET_BIT(ah, AR9285_AN_RXTXBB1, AR9285_AN_RXTXBB1_PDV2I);
+- 	/* 7854, b8,1, pddacinterface=1 */
+--	REG_RMW_FIELD(ah, AR9285_AN_RXTXBB1, AR9285_AN_RXTXBB1_PDDACIF, 1);
+-+	REG_SET_BIT(ah, AR9285_AN_RXTXBB1, AR9285_AN_RXTXBB1_PDDACIF);
+- 	/* 7824,b12,0, offcal=0 */
+--	REG_RMW_FIELD(ah, AR9285_AN_RF2G2, AR9285_AN_RF2G2_OFFCAL, 0);
+-+	REG_CLR_BIT(ah, AR9285_AN_RF2G2, AR9285_AN_RF2G2_OFFCAL);
+- 	/* 7838, b1,0, pwddb=0 */
+--	REG_RMW_FIELD(ah, AR9285_AN_RF2G7, AR9285_AN_RF2G7_PWDDB, 0);
+-+	REG_CLR_BIT(ah, AR9285_AN_RF2G7, AR9285_AN_RF2G7_PWDDB);
+- 	/* 7820,b11,0, enpacal=0 */
+--	REG_RMW_FIELD(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_ENPACAL, 0);
+-+	REG_CLR_BIT(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_ENPACAL);
+- 	/* 7820,b25,1, pdpadrv1=0 */
+--	REG_RMW_FIELD(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_PDPADRV1, 0);
+-+	REG_CLR_BIT(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_PDPADRV1);
+- 	/* 7820,b24,0, pdpadrv2=0 */
+--	REG_RMW_FIELD(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_PDPADRV2, 0);
+-+	REG_CLR_BIT(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_PDPADRV2);
+- 	/* 7820,b23,0, pdpaout=0 */
+--	REG_RMW_FIELD(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_PDPAOUT, 0);
+-+	REG_CLR_BIT(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_PDPAOUT);
+- 	/* 783c,b14-16,7, padrvgn2tab_0=7 */
+- 	REG_RMW_FIELD(ah, AR9285_AN_RF2G8, AR9285_AN_RF2G8_PADRVGN2TAB0, 7);
+- 	/*
+-@@ -516,15 +513,13 @@ static void ar9271_hw_pa_cal(struct ath_
+- 		ah->pacal_info.prev_offset = regVal;
+- 	}
+- 
+--	ENABLE_REGWRITE_BUFFER(ah);
+- 
+--	regVal = REG_READ(ah, AR_AN_RF2G1_CH1);
+--	regVal |= 0x1;
+--	REG_WRITE(ah, AR_AN_RF2G1_CH1, regVal);
+--	regVal = REG_READ(ah, 0x9808);
+--	regVal &= (~(0x1 << 27));
+--	REG_WRITE(ah, 0x9808, regVal);
+-+	/* 7834, b1=1 */
+-+	REG_SET_BIT(ah, AR9285_AN_RF2G6, 1 << 0);
+-+	/* 9808, b27=0 */
+-+	REG_CLR_BIT(ah, 0x9808, 1 << 27);
+- 
+-+	ENABLE_REGWRITE_BUFFER(ah);
+- 	for (i = 0; i < ARRAY_SIZE(regList); i++)
+- 		REG_WRITE(ah, regList[i][0], regList[i][1]);
+- 
+diff --git a/package/kernel/mac80211/patches/321-brcmfmac-change-parameters-for-brcmf_remove_interfac.patch b/package/kernel/mac80211/patches/321-brcmfmac-change-parameters-for-brcmf_remove_interfac.patch
+new file mode 100644
+index 0000000..3360cbc
+--- /dev/null
++++ b/package/kernel/mac80211/patches/321-brcmfmac-change-parameters-for-brcmf_remove_interfac.patch
+@@ -0,0 +1,87 @@
++From: Arend van Spriel <arend@broadcom.com>
++Date: Wed, 26 Aug 2015 22:14:55 +0200
++Subject: [PATCH] brcmfmac: change parameters for
++ brcmf_remove_interface()
++
++Just pass the interface to be removed, ie. the struct brcmf_if instance.
++
++Reviewed-by: Hante Meuleman <meuleman@broadcom.com>
++Reviewed-by: Franky (Zhenhui) Lin <frankyl@broadcom.com>
++Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
++Signed-off-by: Arend van Spriel <arend@broadcom.com>
++---
++
++--- a/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c
+++++ b/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c
++@@ -4983,7 +4983,7 @@ brcmf_notify_connect_status_ap(struct br
++ 		brcmf_dbg(CONN, "AP mode link down\n");
++ 		complete(&cfg->vif_disabled);
++ 		if (ifp->vif->mbss)
++-			brcmf_remove_interface(ifp->drvr, ifp->bssidx);
+++			brcmf_remove_interface(ifp);
++ 		return 0;
++ 	}
++ 
++--- a/drivers/net/wireless/brcm80211/brcmfmac/core.c
+++++ b/drivers/net/wireless/brcm80211/brcmfmac/core.c
++@@ -887,12 +887,13 @@ static void brcmf_del_if(struct brcmf_pu
++ 	}
++ }
++ 
++-void brcmf_remove_interface(struct brcmf_pub *drvr, u32 bssidx)
+++void brcmf_remove_interface(struct brcmf_if *ifp)
++ {
++-	if (drvr->iflist[bssidx]) {
++-		brcmf_fws_del_interface(drvr->iflist[bssidx]);
++-		brcmf_del_if(drvr, bssidx);
++-	}
+++	if (!ifp || WARN_ON(ifp->drvr->iflist[ifp->bssidx] != ifp))
+++		return;
+++
+++	brcmf_fws_del_interface(ifp);
+++	brcmf_del_if(ifp->drvr, ifp->bssidx);
++ }
++ 
++ int brcmf_get_next_free_bsscfgidx(struct brcmf_pub *drvr)
++@@ -1122,7 +1123,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, i);
+++		brcmf_remove_interface(drvr->iflist[i]);
++ 
++ 	brcmf_cfg80211_detach(drvr->config);
++ 
++--- a/drivers/net/wireless/brcm80211/brcmfmac/core.h
+++++ b/drivers/net/wireless/brcm80211/brcmfmac/core.h
++@@ -206,7 +206,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 bssidx, s32 ifidx,
++ 			      char *name, u8 *mac_addr);
++-void brcmf_remove_interface(struct brcmf_pub *drvr, u32 bssidx);
+++void brcmf_remove_interface(struct brcmf_if *ifp);
++ int brcmf_get_next_free_bsscfgidx(struct brcmf_pub *drvr);
++ void brcmf_txflowblock_if(struct brcmf_if *ifp,
++ 			  enum brcmf_netif_stop_reason reason, bool state);
++--- a/drivers/net/wireless/brcm80211/brcmfmac/fweh.c
+++++ b/drivers/net/wireless/brcm80211/brcmfmac/fweh.c
++@@ -222,7 +222,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(drvr, ifevent->bssidx);
+++		brcmf_remove_interface(ifp);
++ }
++ 
++ /**
++--- a/drivers/net/wireless/brcm80211/brcmfmac/p2p.c
+++++ b/drivers/net/wireless/brcm80211/brcmfmac/p2p.c
++@@ -2140,7 +2140,7 @@ static void brcmf_p2p_delete_p2pdev(stru
++ {
++ 	cfg80211_unregister_wdev(&vif->wdev);
++ 	p2p->bss_idx[P2PAPI_BSSCFG_DEVICE].vif = NULL;
++-	brcmf_remove_interface(vif->ifp->drvr, vif->ifp->bssidx);
+++	brcmf_remove_interface(vif->ifp);
++ 	brcmf_free_vif(vif);
++ }
++ 
+diff --git a/package/kernel/mac80211/patches/322-ath9k-ar9271_hw_pa_cal-use-RMW-buffer.patch b/package/kernel/mac80211/patches/322-ath9k-ar9271_hw_pa_cal-use-RMW-buffer.patch
+deleted file mode 100644
+index 7247369..0000000
+--- a/package/kernel/mac80211/patches/322-ath9k-ar9271_hw_pa_cal-use-RMW-buffer.patch
++++ /dev/null
+@@ -1,48 +0,0 @@
+-From: Oleksij Rempel <linux@rempel-privat.de>
+-Date: Sun, 22 Mar 2015 19:29:49 +0100
+-Subject: [PATCH] ath9k: ar9271_hw_pa_cal: use RMW buffer
+-
+-Signed-off-by: Oleksij Rempel <linux@rempel-privat.de>
+-Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
+----
+-
+---- a/drivers/net/wireless/ath/ath9k/ar9002_calib.c
+-+++ b/drivers/net/wireless/ath/ath9k/ar9002_calib.c
+-@@ -436,13 +436,14 @@ static void ar9271_hw_pa_cal(struct ath_
+- 		{ AR9285_AN_RF2G2, 0 },
+- 		{ AR9285_AN_TOP2, 0 },
+- 		{ AR9285_AN_RF2G8, 0 },
+--		{ AR9285_AN_RF2G7, 0 } ,
+--		{ AR9285_AN_RF2G3, 0 } ,
+-+		{ AR9285_AN_RF2G7, 0 },
+-+		{ AR9285_AN_RF2G3, 0 },
+- 	};
+- 
+- 	for (i = 0; i < ARRAY_SIZE(regList); i++)
+- 		regList[i][1] = REG_READ(ah, regList[i][0]);
+- 
+-+	ENABLE_REG_RMW_BUFFER(ah);
+- 	/* 7834, b1=0 */
+- 	REG_CLR_BIT(ah, AR9285_AN_RF2G6, 1 << 0);
+- 	/* 9808, b27=1 */
+-@@ -476,6 +477,7 @@ static void ar9271_hw_pa_cal(struct ath_
+- 	REG_RMW_FIELD(ah, AR9285_AN_RF2G7, AR9285_AN_RF2G7_PADRVGN2TAB0, 0);
+- 	/* 7828, b0-11, ccom=fff */
+- 	REG_RMW_FIELD(ah, AR9285_AN_RF2G3, AR9271_AN_RF2G3_CCOMP, 0xfff);
+-+	REG_RMW_BUFFER_FLUSH(ah);
+- 
+- 	/* Set:
+- 	 * localmode=1,bmode=1,bmoderxtx=1,synthon=1,
+-@@ -514,10 +516,12 @@ static void ar9271_hw_pa_cal(struct ath_
+- 	}
+- 
+- 
+-+	ENABLE_REG_RMW_BUFFER(ah);
+- 	/* 7834, b1=1 */
+- 	REG_SET_BIT(ah, AR9285_AN_RF2G6, 1 << 0);
+- 	/* 9808, b27=0 */
+- 	REG_CLR_BIT(ah, 0x9808, 1 << 27);
+-+	REG_RMW_BUFFER_FLUSH(ah);
+- 
+- 	ENABLE_REGWRITE_BUFFER(ah);
+- 	for (i = 0; i < ARRAY_SIZE(regList); i++)
+diff --git a/package/kernel/mac80211/patches/322-brcmfmac-only-call-brcmf_cfg80211_detach-when-attach.patch b/package/kernel/mac80211/patches/322-brcmfmac-only-call-brcmf_cfg80211_detach-when-attach.patch
+new file mode 100644
+index 0000000..2b61f4e
+--- /dev/null
++++ b/package/kernel/mac80211/patches/322-brcmfmac-only-call-brcmf_cfg80211_detach-when-attach.patch
+@@ -0,0 +1,92 @@
++From: Arend van Spriel <arend@broadcom.com>
++Date: Wed, 26 Aug 2015 22:14:56 +0200
++Subject: [PATCH] brcmfmac: only call brcmf_cfg80211_detach() when attach
++ was successful
++
++In brcmf_bus_start() the function brcmf_cfg80211_attach() is called which
++may fail. If this happens we should not call brcmf_cfg80211_detach() in
++the failure path as it will result in NULL pointer dereference:
++
++  brcmf_fweh_activate_events: Set event_msgs error (-5)
++  brcmf_bus_start: failed: -5
++  brcmf_sdio_firmware_callback: dongle is not responding
++  BUG: unable to handle kernel NULL pointer dereference at 0000000000000068
++  IP: [<ffffffff811e8f08>] kernfs_find_ns+0x18/0xd0
++  PGD 0
++  Oops: 0000 [#1] SMP
++  Modules linked in: brcmfmac(O) brcmutil(O) cfg80211 auth_rpcgss
++  CPU: 1 PID: 45 Comm: kworker/1:1 Tainted: G           O
++  Hardware name: Dell Inc. Latitude E6410/07XJP9, BIOS A07 02/15/2011
++  Workqueue: events request_firmware_work_func
++  task: ffff880036c09ac0 ti: ffff880036dd4000 task.ti: ffff880036dd4000
++  RIP: 0010:[<ffffffff811e8f08>]  [<ffffffff811e8f08>] kernfs_find_ns+0x18/0xd0
++  RSP: 0018:ffff880036dd7a28  EFLAGS: 00010246
++  RAX: ffff880036c09ac0 RBX: 0000000000000000 RCX: 000000007fffffff
++  RDX: 0000000000000000 RSI: ffffffff816578b9 RDI: 0000000000000000
++  RBP: ffff880036dd7a48 R08: 0000000000000000 R09: ffff880036c0b340
++  R10: 00000000000002ec R11: ffff880036dd7b08 R12: ffffffff816578b9
++  R13: 0000000000000000 R14: ffffffff816578b9 R15: ffff8800c6c87000
++  FS:  0000000000000000(0000) GS:ffff88012bc40000(0000) knlGS:0000000000000000
++  CS:  0010 DS: 0000 ES: 0000 CR0: 000000008005003b
++  CR2: 0000000000000068 CR3: 0000000001a0b000 CR4: 00000000000006e0
++  Stack:
++   0000000000000000 ffffffff816578b9 0000000000000000 ffff8800c0d003c8
++   ffff880036dd7a78 ffffffff811e8ff5 0000000ffffffff1 ffffffff81a9b060
++   ffff8800c789f880 ffff8800c0d00000 ffff880036dd7a98 ffffffff811ebe0d
++  Call Trace:
++   [<ffffffff811e8ff5>] kernfs_find_and_get_ns+0x35/0x60
++   [<ffffffff811ebe0d>] sysfs_unmerge_group+0x1d/0x60
++   [<ffffffff81404ef2>] dpm_sysfs_remove+0x22/0x60
++   [<ffffffff813f9db9>] device_del+0x49/0x240
++   [<ffffffff815da768>] rfkill_unregister+0x58/0xc0
++   [<ffffffffa06bd91b>] wiphy_unregister+0xab/0x2f0 [cfg80211]
++   [<ffffffffa0742fe3>] brcmf_cfg80211_detach+0x23/0x50 [brcmfmac]
++   [<ffffffffa074d986>] brcmf_detach+0x86/0xe0 [brcmfmac]
++   [<ffffffffa0757de8>] brcmf_sdio_remove+0x48/0x120 [brcmfmac]
++   [<ffffffffa0758ed9>] brcmf_sdiod_remove+0x29/0xd0 [brcmfmac]
++   [<ffffffffa0759031>] brcmf_ops_sdio_remove+0xb1/0x110 [brcmfmac]
++   [<ffffffffa001c267>] sdio_bus_remove+0x37/0x100 [mmc_core]
++   [<ffffffff813fe026>] __device_release_driver+0x96/0x130
++   [<ffffffff813fe0e3>] device_release_driver+0x23/0x30
++   [<ffffffffa0754bc8>] brcmf_sdio_firmware_callback+0x2a8/0x5d0 [brcmfmac]
++   [<ffffffffa074deaf>] brcmf_fw_request_nvram_done+0x15f/0x5e0 [brcmfmac]
++   [<ffffffff8140142f>] ? devres_add+0x3f/0x50
++   [<ffffffff810642b5>] ? usermodehelper_read_unlock+0x15/0x20
++   [<ffffffff81400000>] ? platform_match+0x70/0xa0
++   [<ffffffff8140f400>] request_firmware_work_func+0x30/0x60
++   [<ffffffff8106828c>] process_one_work+0x14c/0x3d0
++   [<ffffffff8106862a>] worker_thread+0x11a/0x450
++   [<ffffffff81068510>] ? process_one_work+0x3d0/0x3d0
++   [<ffffffff8106d692>] kthread+0xd2/0xf0
++   [<ffffffff8106d5c0>] ? kthread_create_on_node+0x180/0x180
++   [<ffffffff815ed35f>] ret_from_fork+0x3f/0x70
++   [<ffffffff8106d5c0>] ? kthread_create_on_node+0x180/0x180
++  Code: e9 40 fe ff ff 48 89 d8 eb 87 66 0f 1f 84 00 00 00 00 00 66 66 66 66
++	90 55 48 89 e5 41 56 49 89 f6 41 55 49 89 d5 31 d2 41 54 53 <0f> b7
++	47 68 48 8b 5f 48 66 c1 e8 05 83 e0 01 4d 85 ed 0f b6 c8
++  RIP  [<ffffffff811e8f08>] kernfs_find_ns+0x18/0xd0
++   RSP <ffff880036dd7a28>
++  CR2: 0000000000000068
++  ---[ end trace 87d6ec0d3fe46740 ]---
++
++Reported-by: Daniel (Deognyoun) Kim <dekim@broadcom.com>
++Reviewed-by: Hante Meuleman <meuleman@broadcom.com>
++Reviewed-by: Franky (Zhenhui) Lin <frankyl@broadcom.com>
++Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
++Signed-off-by: Arend van Spriel <arend@broadcom.com>
++---
++
++--- a/drivers/net/wireless/brcm80211/brcmfmac/core.c
+++++ b/drivers/net/wireless/brcm80211/brcmfmac/core.c
++@@ -1049,7 +1049,10 @@ int brcmf_bus_start(struct device *dev)
++ fail:
++ 	if (ret < 0) {
++ 		brcmf_err("failed: %d\n", ret);
++-		brcmf_cfg80211_detach(drvr->config);
+++		if (drvr->config) {
+++			brcmf_cfg80211_detach(drvr->config);
+++			drvr->config = NULL;
+++		}
++ 		if (drvr->fws) {
++ 			brcmf_fws_del_interface(ifp);
++ 			brcmf_fws_deinit(drvr);
+diff --git a/package/kernel/mac80211/patches/323-ath9k-add-multi_read-to-be-compatible-with-ath9k_htc.patch b/package/kernel/mac80211/patches/323-ath9k-add-multi_read-to-be-compatible-with-ath9k_htc.patch
+deleted file mode 100644
+index 246bb9d..0000000
+--- a/package/kernel/mac80211/patches/323-ath9k-add-multi_read-to-be-compatible-with-ath9k_htc.patch
++++ /dev/null
+@@ -1,35 +0,0 @@
+-From: Oleksij Rempel <linux@rempel-privat.de>
+-Date: Sun, 22 Mar 2015 19:29:50 +0100
+-Subject: [PATCH] ath9k: add multi_read to be compatible with ath9k_htc
+-
+-Signed-off-by: Oleksij Rempel <linux@rempel-privat.de>
+-Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
+----
+-
+---- a/drivers/net/wireless/ath/ath9k/init.c
+-+++ b/drivers/net/wireless/ath/ath9k/init.c
+-@@ -141,6 +141,16 @@ static unsigned int ath9k_ioread32(void
+- 	return val;
+- }
+- 
+-+static void ath9k_multi_ioread32(void *hw_priv, u32 *addr,
+-+                                u32 *val, u16 count)
+-+{
+-+	int i;
+-+
+-+	for (i = 0; i < count; i++)
+-+		val[i] = ath9k_ioread32(hw_priv, addr[i]);
+-+}
+-+
+-+
+- static unsigned int __ath9k_reg_rmw(struct ath_softc *sc, u32 reg_offset,
+- 				    u32 set, u32 clr)
+- {
+-@@ -530,6 +540,7 @@ static int ath9k_init_softc(u16 devid, s
+- 	ah->hw = sc->hw;
+- 	ah->hw_version.devid = devid;
+- 	ah->reg_ops.read = ath9k_ioread32;
+-+	ah->reg_ops.multi_read = ath9k_multi_ioread32;
+- 	ah->reg_ops.write = ath9k_iowrite32;
+- 	ah->reg_ops.rmw = ath9k_reg_rmw;
+- 	pCap = &ah->caps;
+diff --git a/package/kernel/mac80211/patches/323-brcmfmac-correct-detection-of-p2pdev-interface-event.patch b/package/kernel/mac80211/patches/323-brcmfmac-correct-detection-of-p2pdev-interface-event.patch
+new file mode 100644
+index 0000000..868b0a8
+--- /dev/null
++++ b/package/kernel/mac80211/patches/323-brcmfmac-correct-detection-of-p2pdev-interface-event.patch
+@@ -0,0 +1,105 @@
++From: Arend van Spriel <arend@broadcom.com>
++Date: Wed, 26 Aug 2015 22:14:57 +0200
++Subject: [PATCH] brcmfmac: correct detection of p2pdev interface event
++
++The p2pdev interface is setup in firmware resulting in a interface
++event. This event has role and no-if flag. When role is p2p client
++and no-if flag is set it indicates that this is the p2pdev interface.
++This info is used in handling the event and adding interface in the
++driver.
++
++Reviewed-by: Hante Meuleman <meuleman@broadcom.com>
++Reviewed-by: Franky (Zhenhui) Lin <frankyl@broadcom.com>
++Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
++Signed-off-by: Arend van Spriel <arend@broadcom.com>
++---
++
++--- a/drivers/net/wireless/brcm80211/brcmfmac/core.c
+++++ b/drivers/net/wireless/brcm80211/brcmfmac/core.c
++@@ -795,7 +795,7 @@ fail:
++ }
++ 
++ struct brcmf_if *brcmf_add_if(struct brcmf_pub *drvr, s32 bssidx, s32 ifidx,
++-			      char *name, u8 *mac_addr)
+++			      bool is_p2pdev, char *name, u8 *mac_addr)
++ {
++ 	struct brcmf_if *ifp;
++ 	struct net_device *ndev;
++@@ -821,7 +821,7 @@ struct brcmf_if *brcmf_add_if(struct brc
++ 		}
++ 	}
++ 
++-	if (!brcmf_p2p_enable && bssidx == 1) {
+++	if (!brcmf_p2p_enable && is_p2pdev) {
++ 		/* this is P2P_DEVICE interface */
++ 		brcmf_dbg(INFO, "allocate non-netdev interface\n");
++ 		ifp = kzalloc(sizeof(*ifp), GFP_KERNEL);
++@@ -999,12 +999,12 @@ int brcmf_bus_start(struct device *dev)
++ 	brcmf_dbg(TRACE, "\n");
++ 
++ 	/* add primary networking interface */
++-	ifp = brcmf_add_if(drvr, 0, 0, "wlan%d", NULL);
+++	ifp = brcmf_add_if(drvr, 0, 0, false, "wlan%d", NULL);
++ 	if (IS_ERR(ifp))
++ 		return PTR_ERR(ifp);
++ 
++ 	if (brcmf_p2p_enable)
++-		p2p_ifp = brcmf_add_if(drvr, 1, 0, "p2p%d", NULL);
+++		p2p_ifp = brcmf_add_if(drvr, 1, 0, false, "p2p%d", NULL);
++ 	else
++ 		p2p_ifp = NULL;
++ 	if (IS_ERR(p2p_ifp))
++--- a/drivers/net/wireless/brcm80211/brcmfmac/core.h
+++++ b/drivers/net/wireless/brcm80211/brcmfmac/core.h
++@@ -205,7 +205,7 @@ char *brcmf_ifname(struct brcmf_pub *drv
++ 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 bssidx, s32 ifidx,
++-			      char *name, u8 *mac_addr);
+++			      bool is_p2pdev, char *name, u8 *mac_addr);
++ void brcmf_remove_interface(struct brcmf_if *ifp);
++ int brcmf_get_next_free_bsscfgidx(struct brcmf_pub *drvr);
++ void brcmf_txflowblock_if(struct brcmf_if *ifp,
++--- a/drivers/net/wireless/brcm80211/brcmfmac/fweh.c
+++++ b/drivers/net/wireless/brcm80211/brcmfmac/fweh.c
++@@ -179,6 +179,7 @@ static void brcmf_fweh_handle_if_event(s
++ {
++ 	struct brcmf_if_event *ifevent = data;
++ 	struct brcmf_if *ifp;
+++	bool is_p2pdev;
++ 	int err = 0;
++ 
++ 	brcmf_dbg(EVENT, "action: %u idx: %u bsscfg: %u flags: %u role: %u\n",
++@@ -186,18 +187,16 @@ static void brcmf_fweh_handle_if_event(s
++ 		  ifevent->flags, ifevent->role);
++ 
++ 	/* The P2P Device interface event must not be ignored
++-	 * contrary to what firmware tells us. The only way to
++-	 * distinguish the P2P Device is by looking at the ifidx
++-	 * and bssidx received.
+++	 * contrary to what firmware tells us.
++ 	 */
++-	if (!(ifevent->ifidx == 0 && ifevent->bssidx == 1) &&
++-	    (ifevent->flags & BRCMF_E_IF_FLAG_NOIF)) {
+++	is_p2pdev = (ifevent->flags & BRCMF_E_IF_FLAG_NOIF) &&
+++		    ifevent->role == BRCMF_E_IF_ROLE_P2P_CLIENT;
+++	if (!is_p2pdev && (ifevent->flags & BRCMF_E_IF_FLAG_NOIF)) {
++ 		brcmf_dbg(EVENT, "event can be ignored\n");
++ 		return;
++ 	}
++ 	if (ifevent->ifidx >= BRCMF_MAX_IFS) {
++-		brcmf_err("invalid interface index: %u\n",
++-			  ifevent->ifidx);
+++		brcmf_err("invalid interface index: %u\n", ifevent->ifidx);
++ 		return;
++ 	}
++ 
++@@ -207,7 +206,7 @@ static void brcmf_fweh_handle_if_event(s
++ 		brcmf_dbg(EVENT, "adding %s (%pM)\n", emsg->ifname,
++ 			  emsg->addr);
++ 		ifp = brcmf_add_if(drvr, ifevent->bssidx, ifevent->ifidx,
++-				   emsg->ifname, emsg->addr);
+++				   is_p2pdev, emsg->ifname, emsg->addr);
++ 		if (IS_ERR(ifp))
++ 			return;
++ 		brcmf_fws_add_interface(ifp);
+diff --git a/package/kernel/mac80211/patches/324-ath9k-add-new-function-ath9k_hw_read_array.patch b/package/kernel/mac80211/patches/324-ath9k-add-new-function-ath9k_hw_read_array.patch
+deleted file mode 100644
+index 2eda1c9..0000000
+--- a/package/kernel/mac80211/patches/324-ath9k-add-new-function-ath9k_hw_read_array.patch
++++ /dev/null
+@@ -1,69 +0,0 @@
+-From: Oleksij Rempel <linux@rempel-privat.de>
+-Date: Sun, 22 Mar 2015 19:29:51 +0100
+-Subject: [PATCH] ath9k: add new function ath9k_hw_read_array
+-
+-REG_READ generate most overhead on usb bus. It send and read micro packages
+-and reduce usb bandwidth. To reduce this overhead we should read in batches.
+-
+-Signed-off-by: Oleksij Rempel <linux@rempel-privat.de>
+-Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
+----
+-
+---- a/drivers/net/wireless/ath/ath9k/hw.c
+-+++ b/drivers/net/wireless/ath/ath9k/hw.c
+-@@ -121,6 +121,36 @@ void ath9k_hw_write_array(struct ath_hw
+- 	REGWRITE_BUFFER_FLUSH(ah);
+- }
+- 
+-+void ath9k_hw_read_array(struct ath_hw *ah, u32 array[][2], int size)
+-+{
+-+	u32 *tmp_reg_list, *tmp_data;
+-+	int i;
+-+
+-+	tmp_reg_list = kmalloc(size * sizeof(u32), GFP_KERNEL);
+-+	if (!tmp_reg_list) {
+-+		dev_err(ah->dev, "%s: tmp_reg_list: alloc filed\n", __func__);
+-+		return;
+-+	}
+-+
+-+	tmp_data = kmalloc(size * sizeof(u32), GFP_KERNEL);
+-+	if (!tmp_data) {
+-+		dev_err(ah->dev, "%s tmp_data: alloc filed\n", __func__);
+-+		goto error_tmp_data;
+-+	}
+-+
+-+	for (i = 0; i < size; i++)
+-+		tmp_reg_list[i] = array[i][0];
+-+
+-+	REG_READ_MULTI(ah, tmp_reg_list, tmp_data, size);
+-+
+-+	for (i = 0; i < size; i++)
+-+		array[i][1] = tmp_data[i];
+-+
+-+	kfree(tmp_data);
+-+error_tmp_data:
+-+	kfree(tmp_reg_list);
+-+}
+-+
+- u32 ath9k_hw_reverse_bits(u32 val, u32 n)
+- {
+- 	u32 retval;
+---- a/drivers/net/wireless/ath/ath9k/hw.h
+-+++ b/drivers/net/wireless/ath/ath9k/hw.h
+-@@ -138,6 +138,8 @@
+- 
+- #define REG_WRITE_ARRAY(iniarray, column, regWr) \
+- 	ath9k_hw_write_array(ah, iniarray, column, &(regWr))
+-+#define REG_READ_ARRAY(ah, array, size) \
+-+	ath9k_hw_read_array(ah, array, size)
+- 
+- #define AR_GPIO_OUTPUT_MUX_AS_OUTPUT             0
+- #define AR_GPIO_OUTPUT_MUX_AS_PCIE_ATTENTION_LED 1
+-@@ -1020,6 +1022,7 @@ void ath9k_hw_synth_delay(struct ath_hw
+- bool ath9k_hw_wait(struct ath_hw *ah, u32 reg, u32 mask, u32 val, u32 timeout);
+- void ath9k_hw_write_array(struct ath_hw *ah, const struct ar5416IniArray *array,
+- 			  int column, unsigned int *writecnt);
+-+void ath9k_hw_read_array(struct ath_hw *ah, u32 array[][2], int size);
+- u32 ath9k_hw_reverse_bits(u32 val, u32 n);
+- u16 ath9k_hw_computetxtime(struct ath_hw *ah,
+- 			   u8 phy, int kbps,
+diff --git a/package/kernel/mac80211/patches/324-brcmfmac-use-brcmf_get_ifp-to-map-ifidx-to-struct-br.patch b/package/kernel/mac80211/patches/324-brcmfmac-use-brcmf_get_ifp-to-map-ifidx-to-struct-br.patch
+new file mode 100644
+index 0000000..abd6681
+--- /dev/null
++++ b/package/kernel/mac80211/patches/324-brcmfmac-use-brcmf_get_ifp-to-map-ifidx-to-struct-br.patch
+@@ -0,0 +1,126 @@
++From: Arend van Spriel <arend@broadcom.com>
++Date: Wed, 26 Aug 2015 22:14:58 +0200
++Subject: [PATCH] brcmfmac: use brcmf_get_ifp() to map ifidx to struct
++ brcmf_if instance
++
++The knowledge on how to map the interface index to a struct brcmf_if
++instance is in brcmf_get_ifp() so use that function when only the
++interface index is known instead of accessing brcmf_pub::iflist
++directly.
++
++Reviewed-by: Hante Meuleman <meuleman@broadcom.com>
++Reviewed-by: Franky (Zhenhui) Lin <frankyl@broadcom.com>
++Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
++Signed-off-by: Arend van Spriel <arend@broadcom.com>
++---
++
++--- a/drivers/net/wireless/brcm80211/brcmfmac/btcoex.c
+++++ b/drivers/net/wireless/brcm80211/brcmfmac/btcoex.c
++@@ -149,7 +149,7 @@ static s32 brcmf_btcoex_params_read(stru
++ static void brcmf_btcoex_boost_wifi(struct brcmf_btcoex_info *btci,
++ 				    bool trump_sco)
++ {
++-	struct brcmf_if *ifp = btci->cfg->pub->iflist[0];
+++	struct brcmf_if *ifp = brcmf_get_ifp(btci->cfg->pub, 0);
++ 
++ 	if (trump_sco && !btci->saved_regs_part2) {
++ 		/* this should reduce eSCO agressive
++@@ -468,7 +468,7 @@ int brcmf_btcoex_set_mode(struct brcmf_c
++ {
++ 	struct brcmf_cfg80211_info *cfg = wiphy_priv(vif->wdev.wiphy);
++ 	struct brcmf_btcoex_info *btci = cfg->btcoex;
++-	struct brcmf_if *ifp = cfg->pub->iflist[0];
+++	struct brcmf_if *ifp = brcmf_get_ifp(cfg->pub, 0);
++ 
++ 	switch (mode) {
++ 	case BRCMF_BTCOEX_DISABLED:
++--- a/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c
+++++ b/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c
++@@ -6213,7 +6213,7 @@ static void brcmf_free_wiphy(struct wiph
++ struct brcmf_cfg80211_info *brcmf_cfg80211_attach(struct brcmf_pub *drvr,
++ 						  struct device *busdev)
++ {
++-	struct net_device *ndev = drvr->iflist[0]->ndev;
+++	struct net_device *ndev = brcmf_get_ifp(drvr, 0)->ndev;
++ 	struct brcmf_cfg80211_info *cfg;
++ 	struct wiphy *wiphy;
++ 	struct brcmf_cfg80211_vif *vif;
++--- a/drivers/net/wireless/brcm80211/brcmfmac/feature.c
+++++ b/drivers/net/wireless/brcm80211/brcmfmac/feature.c
++@@ -121,7 +121,7 @@ static void brcmf_feat_iovar_int_set(str
++ 
++ void brcmf_feat_attach(struct brcmf_pub *drvr)
++ {
++-	struct brcmf_if *ifp = drvr->iflist[0];
+++	struct brcmf_if *ifp = brcmf_get_ifp(drvr, 0);
++ 
++ 	brcmf_feat_iovar_int_get(ifp, BRCMF_FEAT_MCHAN, "mchan");
++ 	brcmf_feat_iovar_int_get(ifp, BRCMF_FEAT_PNO, "pfn");
++--- a/drivers/net/wireless/brcm80211/brcmfmac/flowring.c
+++++ b/drivers/net/wireless/brcm80211/brcmfmac/flowring.c
++@@ -221,7 +221,7 @@ static void brcmf_flowring_block(struct
++ 
++ 	bus_if = dev_get_drvdata(flow->dev);
++ 	drvr = bus_if->drvr;
++-	ifp = drvr->iflist[ifidx];
+++	ifp = brcmf_get_ifp(drvr, ifidx);
++ 	brcmf_txflowblock_if(ifp, BRCMF_NETIF_STOP_REASON_FLOW, blocked);
++ 
++ 	spin_unlock_irqrestore(&flow->block_lock, flags);
++--- a/drivers/net/wireless/brcm80211/brcmfmac/fweh.c
+++++ b/drivers/net/wireless/brcm80211/brcmfmac/fweh.c
++@@ -334,7 +334,7 @@ void brcmf_fweh_attach(struct brcmf_pub
++ void brcmf_fweh_detach(struct brcmf_pub *drvr)
++ {
++ 	struct brcmf_fweh_info *fweh = &drvr->fweh;
++-	struct brcmf_if *ifp = drvr->iflist[0];
+++	struct brcmf_if *ifp = brcmf_get_ifp(drvr, 0);
++ 	s8 eventmask[BRCMF_EVENTING_MASK_LEN];
++ 
++ 	if (ifp) {
++--- a/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c
+++++ b/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c
++@@ -972,7 +972,7 @@ static void
++ brcmf_fws_flow_control_check(struct brcmf_fws_info *fws, struct pktq *pq,
++ 			     u8 if_id)
++ {
++-	struct brcmf_if *ifp = fws->drvr->iflist[!if_id ? 0 : if_id + 1];
+++	struct brcmf_if *ifp = brcmf_get_ifp(fws->drvr, if_id);
++ 
++ 	if (WARN_ON(!ifp))
++ 		return;
++@@ -2118,6 +2118,7 @@ static int brcmf_debugfs_fws_stats_read(
++ int brcmf_fws_init(struct brcmf_pub *drvr)
++ {
++ 	struct brcmf_fws_info *fws;
+++	struct brcmf_if *ifp;
++ 	u32 tlv = BRCMF_FWS_FLAGS_RSSI_SIGNALS;
++ 	int rc;
++ 	u32 mode;
++@@ -2177,21 +2178,22 @@ int brcmf_fws_init(struct brcmf_pub *drv
++ 	 * continue. Set mode back to none indicating not enabled.
++ 	 */
++ 	fws->fw_signals = true;
++-	if (brcmf_fil_iovar_int_set(drvr->iflist[0], "tlv", tlv)) {
+++	ifp = brcmf_get_ifp(drvr, 0);
+++	if (brcmf_fil_iovar_int_set(ifp, "tlv", tlv)) {
++ 		brcmf_err("failed to set bdcv2 tlv signaling\n");
++ 		fws->fcmode = BRCMF_FWS_FCMODE_NONE;
++ 		fws->fw_signals = false;
++ 	}
++ 
++-	if (brcmf_fil_iovar_int_set(drvr->iflist[0], "ampdu_hostreorder", 1))
+++	if (brcmf_fil_iovar_int_set(ifp, "ampdu_hostreorder", 1))
++ 		brcmf_dbg(INFO, "enabling AMPDU host-reorder failed\n");
++ 
++ 	/* Enable seq number reuse, if supported */
++-	if (brcmf_fil_iovar_int_get(drvr->iflist[0], "wlfc_mode", &mode) == 0) {
+++	if (brcmf_fil_iovar_int_get(ifp, "wlfc_mode", &mode) == 0) {
++ 		if (BRCMF_FWS_MODE_GET_REUSESEQ(mode)) {
++ 			mode = 0;
++ 			BRCMF_FWS_MODE_SET_REUSESEQ(mode, 1);
++-			if (brcmf_fil_iovar_int_set(drvr->iflist[0],
+++			if (brcmf_fil_iovar_int_set(ifp,
++ 						    "wlfc_mode", mode) == 0) {
++ 				BRCMF_FWS_MODE_SET_REUSESEQ(fws->mode, 1);
++ 			}
+diff --git a/package/kernel/mac80211/patches/325-ath9k-ar9271_hw_pa_cal-use-REG_READ_ARRAY.patch b/package/kernel/mac80211/patches/325-ath9k-ar9271_hw_pa_cal-use-REG_READ_ARRAY.patch
+deleted file mode 100644
+index 4e4888f..0000000
+--- a/package/kernel/mac80211/patches/325-ath9k-ar9271_hw_pa_cal-use-REG_READ_ARRAY.patch
++++ /dev/null
+@@ -1,24 +0,0 @@
+-From: Oleksij Rempel <linux@rempel-privat.de>
+-Date: Sun, 22 Mar 2015 19:29:52 +0100
+-Subject: [PATCH] ath9k: ar9271_hw_pa_cal: use REG_READ_ARRAY
+-
+-insted of reading each register separatly
+-and waste 4ms on each operation, we can
+-use one shot read.
+-
+-Signed-off-by: Oleksij Rempel <linux@rempel-privat.de>
+-Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
+----
+-
+---- a/drivers/net/wireless/ath/ath9k/ar9002_calib.c
+-+++ b/drivers/net/wireless/ath/ath9k/ar9002_calib.c
+-@@ -440,8 +440,7 @@ static void ar9271_hw_pa_cal(struct ath_
+- 		{ AR9285_AN_RF2G3, 0 },
+- 	};
+- 
+--	for (i = 0; i < ARRAY_SIZE(regList); i++)
+--		regList[i][1] = REG_READ(ah, regList[i][0]);
+-+	REG_READ_ARRAY(ah, regList, ARRAY_SIZE(regList));
+- 
+- 	ENABLE_REG_RMW_BUFFER(ah);
+- 	/* 7834, b1=0 */
+diff --git a/package/kernel/mac80211/patches/325-brcmfmac-pass-struct-brcmf_if-instance-in-brcmf_txfi.patch b/package/kernel/mac80211/patches/325-brcmfmac-pass-struct-brcmf_if-instance-in-brcmf_txfi.patch
+new file mode 100644
+index 0000000..23a7b6f
+--- /dev/null
++++ b/package/kernel/mac80211/patches/325-brcmfmac-pass-struct-brcmf_if-instance-in-brcmf_txfi.patch
+@@ -0,0 +1,122 @@
++From: Arend van Spriel <arend@broadcom.com>
++Date: Wed, 26 Aug 2015 22:14:59 +0200
++Subject: [PATCH] brcmfmac: pass struct brcmf_if instance in
++ brcmf_txfinalize()
++
++Most call sites of brcmf_txfinalize already have struct brcmf_if
++instance so pass that to brcmf_txfinalize() as the function
++needs it anyway.
++
++Reviewed-by: Hante Meuleman <meuleman@broadcom.com>
++Reviewed-by: Franky (Zhenhui) Lin <frankyl@broadcom.com>
++Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
++Signed-off-by: Arend van Spriel <arend@broadcom.com>
++---
++
++--- a/drivers/net/wireless/brcm80211/brcmfmac/core.c
+++++ b/drivers/net/wireless/brcm80211/brcmfmac/core.c
++@@ -560,17 +560,11 @@ void brcmf_rx_frame(struct device *dev,
++ 		brcmf_netif_rx(ifp, skb);
++ }
++ 
++-void brcmf_txfinalize(struct brcmf_pub *drvr, struct sk_buff *txp, u8 ifidx,
++-		      bool success)
+++void brcmf_txfinalize(struct brcmf_if *ifp, struct sk_buff *txp, bool success)
++ {
++-	struct brcmf_if *ifp;
++ 	struct ethhdr *eh;
++ 	u16 type;
++ 
++-	ifp = drvr->iflist[ifidx];
++-	if (!ifp)
++-		goto done;
++-
++ 	eh = (struct ethhdr *)(txp->data);
++ 	type = ntohs(eh->h_proto);
++ 
++@@ -582,7 +576,7 @@ void brcmf_txfinalize(struct brcmf_pub *
++ 
++ 	if (!success)
++ 		ifp->stats.tx_errors++;
++-done:
+++
++ 	brcmu_pkt_buf_free_skb(txp);
++ }
++ 
++@@ -600,7 +594,7 @@ void brcmf_txcomplete(struct device *dev
++ 		if (brcmf_proto_hdrpull(drvr, false, txp, &ifp))
++ 			brcmu_pkt_buf_free_skb(txp);
++ 		else
++-			brcmf_txfinalize(drvr, txp, ifp->ifidx, success);
+++			brcmf_txfinalize(ifp, txp, success);
++ 	}
++ }
++ 
++--- a/drivers/net/wireless/brcm80211/brcmfmac/core.h
+++++ b/drivers/net/wireless/brcm80211/brcmfmac/core.h
++@@ -210,8 +210,7 @@ void brcmf_remove_interface(struct brcmf
++ int brcmf_get_next_free_bsscfgidx(struct brcmf_pub *drvr);
++ void brcmf_txflowblock_if(struct brcmf_if *ifp,
++ 			  enum brcmf_netif_stop_reason reason, bool state);
++-void brcmf_txfinalize(struct brcmf_pub *drvr, struct sk_buff *txp, u8 ifidx,
++-		      bool success);
+++void brcmf_txfinalize(struct brcmf_if *ifp, struct sk_buff *txp, bool success);
++ void brcmf_netif_rx(struct brcmf_if *ifp, struct sk_buff *skb);
++ 
++ /* Sets dongle media info (drv_version, mac address). */
++--- a/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c
+++++ b/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c
++@@ -1506,7 +1506,7 @@ brcmf_fws_txs_process(struct brcmf_fws_i
++ 		ret = brcmf_fws_txstatus_suppressed(fws, fifo, skb, ifp->ifidx,
++ 						    genbit, seq);
++ 	if (remove_from_hanger || ret)
++-		brcmf_txfinalize(fws->drvr, skb, ifp->ifidx, true);
+++		brcmf_txfinalize(ifp, skb, true);
++ 
++ 	return 0;
++ }
++@@ -1905,7 +1905,7 @@ int brcmf_fws_process_skb(struct brcmf_i
++ 	if (fws->avoid_queueing) {
++ 		rc = brcmf_proto_txdata(drvr, ifp->ifidx, 0, skb);
++ 		if (rc < 0)
++-			brcmf_txfinalize(drvr, skb, ifp->ifidx, false);
+++			brcmf_txfinalize(ifp, skb, false);
++ 		return rc;
++ 	}
++ 
++@@ -1929,7 +1929,7 @@ int brcmf_fws_process_skb(struct brcmf_i
++ 		brcmf_fws_schedule_deq(fws);
++ 	} else {
++ 		brcmf_err("drop skb: no hanger slot\n");
++-		brcmf_txfinalize(drvr, skb, ifp->ifidx, false);
+++		brcmf_txfinalize(ifp, skb, false);
++ 		rc = -ENOMEM;
++ 	}
++ 	brcmf_fws_unlock(fws);
++@@ -2009,8 +2009,9 @@ static void brcmf_fws_dequeue_worker(str
++ 				ret = brcmf_proto_txdata(drvr, ifidx, 0, skb);
++ 				brcmf_fws_lock(fws);
++ 				if (ret < 0)
++-					brcmf_txfinalize(drvr, skb, ifidx,
++-							 false);
+++					brcmf_txfinalize(brcmf_get_ifp(drvr,
+++								       ifidx),
+++							 skb, false);
++ 				if (fws->bus_flow_blocked)
++ 					break;
++ 			}
++--- a/drivers/net/wireless/brcm80211/brcmfmac/msgbuf.c
+++++ b/drivers/net/wireless/brcm80211/brcmfmac/msgbuf.c
++@@ -873,7 +873,11 @@ brcmf_msgbuf_process_txstatus(struct brc
++ 	commonring = msgbuf->flowrings[flowid];
++ 	atomic_dec(&commonring->outstanding_tx);
++ 
++-	brcmf_txfinalize(msgbuf->drvr, skb, tx_status->msg.ifidx, true);
+++	/* Hante: i believe this was a bug as tx_status->msg.ifidx was used
+++	 * in brcmf_txfinalize as index in drvr->iflist. Can you confirm/deny?
+++	 */
+++	brcmf_txfinalize(brcmf_get_ifp(msgbuf->drvr, tx_status->msg.ifidx),
+++			 skb, true);
++ }
++ 
++ 
+diff --git a/package/kernel/mac80211/patches/326-ath9k-use-one-shot-read-in-ath9k_hw_update_mibstats.patch b/package/kernel/mac80211/patches/326-ath9k-use-one-shot-read-in-ath9k_hw_update_mibstats.patch
+deleted file mode 100644
+index a22cd1d..0000000
+--- a/package/kernel/mac80211/patches/326-ath9k-use-one-shot-read-in-ath9k_hw_update_mibstats.patch
++++ /dev/null
+@@ -1,39 +0,0 @@
+-From: Oleksij Rempel <linux@rempel-privat.de>
+-Date: Sun, 22 Mar 2015 19:29:53 +0100
+-Subject: [PATCH] ath9k: use one shot read in ath9k_hw_update_mibstats
+-
+-this will reduce some overhead on usb bus.
+-
+-Signed-off-by: Oleksij Rempel <linux@rempel-privat.de>
+-Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
+----
+-
+---- a/drivers/net/wireless/ath/ath9k/ani.c
+-+++ b/drivers/net/wireless/ath/ath9k/ani.c
+-@@ -107,11 +107,21 @@ static const struct ani_cck_level_entry
+- static void ath9k_hw_update_mibstats(struct ath_hw *ah,
+- 				     struct ath9k_mib_stats *stats)
+- {
+--	stats->ackrcv_bad += REG_READ(ah, AR_ACK_FAIL);
+--	stats->rts_bad += REG_READ(ah, AR_RTS_FAIL);
+--	stats->fcs_bad += REG_READ(ah, AR_FCS_FAIL);
+--	stats->rts_good += REG_READ(ah, AR_RTS_OK);
+--	stats->beacons += REG_READ(ah, AR_BEACON_CNT);
+-+	u32 addr[5] = {AR_RTS_OK, AR_RTS_FAIL, AR_ACK_FAIL,
+-+		       AR_FCS_FAIL, AR_BEACON_CNT};
+-+	u32 data[5];
+-+
+-+	REG_READ_MULTI(ah, &addr[0], &data[0], 5);
+-+	/* AR_RTS_OK */
+-+	stats->rts_good += data[0];
+-+	/* AR_RTS_FAIL */
+-+	stats->rts_bad += data[1];
+-+	/* AR_ACK_FAIL */
+-+	stats->ackrcv_bad += data[2];
+-+	/* AR_FCS_FAIL */
+-+	stats->fcs_bad += data[3];
+-+	/* AR_BEACON_CNT */
+-+	stats->beacons += data[4];
+- }
+- 
+- static void ath9k_ani_restart(struct ath_hw *ah)
+diff --git a/package/kernel/mac80211/patches/326-brcmfmac-add-mapping-for-interface-index-to-bsscfg-i.patch b/package/kernel/mac80211/patches/326-brcmfmac-add-mapping-for-interface-index-to-bsscfg-i.patch
+new file mode 100644
+index 0000000..8ddc0a6
+--- /dev/null
++++ b/package/kernel/mac80211/patches/326-brcmfmac-add-mapping-for-interface-index-to-bsscfg-i.patch
+@@ -0,0 +1,92 @@
++From: Arend van Spriel <arend@broadcom.com>
++Date: Wed, 26 Aug 2015 22:15:00 +0200
++Subject: [PATCH] brcmfmac: add mapping for interface index to bsscfg
++ index
++
++Because the P2P Device interface in firmware uses the same interface
++index as the primary interface we use the bsscfg index as index in the
++struct brcmf_pub::iflist. However, in the data path we get the interface
++index and not the bsscfg index. So we need a mapping of interface index
++to bsscfg index, which can be determined upon handle adding the interface.
++
++Reviewed-by: Hante Meuleman <meuleman@broadcom.com>
++Reviewed-by: Franky (Zhenhui) Lin <frankyl@broadcom.com>
++Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
++Signed-off-by: Arend van Spriel <arend@broadcom.com>
++---
++
++--- a/drivers/net/wireless/brcm80211/brcmfmac/core.c
+++++ b/drivers/net/wireless/brcm80211/brcmfmac/core.c
++@@ -85,21 +85,20 @@ char *brcmf_ifname(struct brcmf_pub *drv
++ 
++ struct brcmf_if *brcmf_get_ifp(struct brcmf_pub *drvr, int ifidx)
++ {
+++	struct brcmf_if *ifp;
+++	s32 bssidx;
+++
++ 	if (ifidx < 0 || ifidx >= BRCMF_MAX_IFS) {
++ 		brcmf_err("ifidx %d out of range\n", ifidx);
++ 		return NULL;
++ 	}
++ 
++-	/* The ifidx is the idx to map to matching netdev/ifp. When receiving
++-	 * events this is easy because it contains the bssidx which maps
++-	 * 1-on-1 to the netdev/ifp. But for data frames the ifidx is rcvd.
++-	 * bssidx 1 is used for p2p0 and no data can be received or
++-	 * transmitted on it. Therefor bssidx is ifidx + 1 if ifidx > 0
++-	 */
++-	if (ifidx)
++-		ifidx++;
+++	ifp = NULL;
+++	bssidx = drvr->if2bss[ifidx];
+++	if (bssidx >= 0)
+++		ifp = drvr->iflist[bssidx];
++ 
++-	return drvr->iflist[ifidx];
+++	return ifp;
++ }
++ 
++ static void _brcmf_set_multicast_list(struct work_struct *work)
++@@ -831,6 +830,8 @@ struct brcmf_if *brcmf_add_if(struct brc
++ 
++ 		ifp = netdev_priv(ndev);
++ 		ifp->ndev = ndev;
+++		/* store mapping ifidx to bssidx */
+++		drvr->if2bss[ifidx] = bssidx;
++ 	}
++ 
++ 	ifp->drvr = drvr;
++@@ -855,6 +856,7 @@ static void brcmf_del_if(struct brcmf_pu
++ 	struct brcmf_if *ifp;
++ 
++ 	ifp = drvr->iflist[bssidx];
+++	drvr->if2bss[ifp->ifidx] = -1;
++ 	drvr->iflist[bssidx] = NULL;
++ 	if (!ifp) {
++ 		brcmf_err("Null interface, idx=%d\n", bssidx);
++@@ -862,6 +864,7 @@ static void brcmf_del_if(struct brcmf_pu
++ 	}
++ 	brcmf_dbg(TRACE, "Enter, idx=%d, ifidx=%d\n", bssidx, ifp->ifidx);
++ 	if (ifp->ndev) {
+++		drvr->if2bss[ifp->ifidx] = -1;
++ 		if (bssidx == 0) {
++ 			if (ifp->ndev->netdev_ops == &brcmf_netdev_ops_pri) {
++ 				rtnl_lock();
++@@ -926,6 +929,7 @@ int brcmf_attach(struct device *dev)
++ 	if (!drvr)
++ 		return -ENOMEM;
++ 
+++	memset(drvr->if2bss, 0xFF, sizeof(drvr->if2bss));
++ 	mutex_init(&drvr->proto_block);
++ 
++ 	/* Link to bus module */
++--- a/drivers/net/wireless/brcm80211/brcmfmac/core.h
+++++ b/drivers/net/wireless/brcm80211/brcmfmac/core.h
++@@ -122,6 +122,7 @@ struct brcmf_pub {
++ 	struct mac_address addresses[BRCMF_MAX_IFS];
++ 
++ 	struct brcmf_if *iflist[BRCMF_MAX_IFS];
+++	s32 if2bss[BRCMF_MAX_IFS];
++ 
++ 	struct mutex proto_block;
++ 	unsigned char proto_buf[BRCMF_DCMD_MAXLEN];
+diff --git a/package/kernel/mac80211/patches/327-ath9k-ath9k_hw_loadnf-use-REG_RMW.patch b/package/kernel/mac80211/patches/327-ath9k-ath9k_hw_loadnf-use-REG_RMW.patch
+deleted file mode 100644
+index e5a362f..0000000
+--- a/package/kernel/mac80211/patches/327-ath9k-ath9k_hw_loadnf-use-REG_RMW.patch
++++ /dev/null
+@@ -1,71 +0,0 @@
+-From: Oleksij Rempel <linux@rempel-privat.de>
+-Date: Sun, 22 Mar 2015 19:29:54 +0100
+-Subject: [PATCH] ath9k: ath9k_hw_loadnf: use REG_RMW
+-
+-Signed-off-by: Oleksij Rempel <linux@rempel-privat.de>
+-Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
+----
+-
+---- a/drivers/net/wireless/ath/ath9k/calib.c
+-+++ b/drivers/net/wireless/ath/ath9k/calib.c
+-@@ -238,7 +238,6 @@ int ath9k_hw_loadnf(struct ath_hw *ah, s
+- {
+- 	struct ath9k_nfcal_hist *h = NULL;
+- 	unsigned i, j;
+--	int32_t val;
+- 	u8 chainmask = (ah->rxchainmask << 3) | ah->rxchainmask;
+- 	struct ath_common *common = ath9k_hw_common(ah);
+- 	s16 default_nf = ath9k_hw_get_default_nf(ah, chan);
+-@@ -246,6 +245,7 @@ int ath9k_hw_loadnf(struct ath_hw *ah, s
+- 	if (ah->caldata)
+- 		h = ah->caldata->nfCalHist;
+- 
+-+	ENABLE_REG_RMW_BUFFER(ah);
+- 	for (i = 0; i < NUM_NF_READINGS; i++) {
+- 		if (chainmask & (1 << i)) {
+- 			s16 nfval;
+-@@ -258,10 +258,8 @@ int ath9k_hw_loadnf(struct ath_hw *ah, s
+- 			else
+- 				nfval = default_nf;
+- 
+--			val = REG_READ(ah, ah->nf_regs[i]);
+--			val &= 0xFFFFFE00;
+--			val |= (((u32) nfval << 1) & 0x1ff);
+--			REG_WRITE(ah, ah->nf_regs[i], val);
+-+			REG_RMW(ah, ah->nf_regs[i],
+-+				(((u32) nfval << 1) & 0x1ff), 0x1ff);
+- 		}
+- 	}
+- 
+-@@ -274,6 +272,7 @@ int ath9k_hw_loadnf(struct ath_hw *ah, s
+- 	REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL,
+- 		    AR_PHY_AGC_CONTROL_NO_UPDATE_NF);
+- 	REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_NF);
+-+	REG_RMW_BUFFER_FLUSH(ah);
+- 
+- 	/*
+- 	 * Wait for load to complete, should be fast, a few 10s of us.
+-@@ -309,19 +308,17 @@ int ath9k_hw_loadnf(struct ath_hw *ah, s
+- 	 * by the median we just loaded.  This will be initial (and max) value
+- 	 * of next noise floor calibration the baseband does.
+- 	 */
+--	ENABLE_REGWRITE_BUFFER(ah);
+-+	ENABLE_REG_RMW_BUFFER(ah);
+- 	for (i = 0; i < NUM_NF_READINGS; i++) {
+- 		if (chainmask & (1 << i)) {
+- 			if ((i >= AR5416_MAX_CHAINS) && !IS_CHAN_HT40(chan))
+- 				continue;
+- 
+--			val = REG_READ(ah, ah->nf_regs[i]);
+--			val &= 0xFFFFFE00;
+--			val |= (((u32) (-50) << 1) & 0x1ff);
+--			REG_WRITE(ah, ah->nf_regs[i], val);
+-+			REG_RMW(ah, ah->nf_regs[i],
+-+					(((u32) (-50) << 1) & 0x1ff), 0x1ff);
+- 		}
+- 	}
+--	REGWRITE_BUFFER_FLUSH(ah);
+-+	REG_RMW_BUFFER_FLUSH(ah);
+- 
+- 	return 0;
+- }
+diff --git a/package/kernel/mac80211/patches/327-brcmfmac-add-dedicated-debug-level-for-firmware-cons.patch b/package/kernel/mac80211/patches/327-brcmfmac-add-dedicated-debug-level-for-firmware-cons.patch
+new file mode 100644
+index 0000000..a0a798b
+--- /dev/null
++++ b/package/kernel/mac80211/patches/327-brcmfmac-add-dedicated-debug-level-for-firmware-cons.patch
+@@ -0,0 +1,103 @@
++From: Arend van Spriel <arend@broadcom.com>
++Date: Wed, 26 Aug 2015 22:15:01 +0200
++Subject: [PATCH] brcmfmac: add dedicated debug level for firmware
++ console logging
++
++Both PCIe and SDIO devices have the possibility to log the firmware
++console output in kernel log. For PCIe it is logged when PCIE debug
++level is enabled. For SDIO it is logged when user specifies a non-zero
++console interval through debugfs. This patch tries to make it a
++bit more consistent. The firmware console output is only logged when
++FWCON debug level is enabled.
++
++Reviewed-by: Hante Meuleman <meuleman@broadcom.com>
++Reviewed-by: Franky (Zhenhui) Lin <frankyl@broadcom.com>
++Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
++Reviewed-by: Pontus Fuchs <pontusf@broadcom.com>
++Signed-off-by: Arend van Spriel <arend@broadcom.com>
++---
++
++--- a/drivers/net/wireless/brcm80211/brcmfmac/debug.h
+++++ b/drivers/net/wireless/brcm80211/brcmfmac/debug.h
++@@ -37,6 +37,7 @@
++ #define BRCMF_SDIO_VAL		0x00020000
++ #define BRCMF_MSGBUF_VAL	0x00040000
++ #define BRCMF_PCIE_VAL		0x00080000
+++#define BRCMF_FWCON_VAL		0x00100000
++ 
++ /* set default print format */
++ #undef pr_fmt
++@@ -78,6 +79,7 @@ do {								\
++ #define BRCMF_GLOM_ON()		(brcmf_msg_level & BRCMF_GLOM_VAL)
++ #define BRCMF_EVENT_ON()	(brcmf_msg_level & BRCMF_EVENT_VAL)
++ #define BRCMF_FIL_ON()		(brcmf_msg_level & BRCMF_FIL_VAL)
+++#define BRCMF_FWCON_ON()	(brcmf_msg_level & BRCMF_FWCON_VAL)
++ 
++ #else /* defined(DEBUG) || defined(CPTCFG_BRCM_TRACING) */
++ 
++@@ -90,6 +92,7 @@ do {								\
++ #define BRCMF_GLOM_ON()		0
++ #define BRCMF_EVENT_ON()	0
++ #define BRCMF_FIL_ON()		0
+++#define BRCMF_FWCON_ON()	0
++ 
++ #endif /* defined(DEBUG) || defined(CPTCFG_BRCM_TRACING) */
++ 
++--- a/drivers/net/wireless/brcm80211/brcmfmac/pcie.c
+++++ b/drivers/net/wireless/brcm80211/brcmfmac/pcie.c
++@@ -644,7 +644,7 @@ static void brcmf_pcie_bus_console_init(
++ 	addr = console->base_addr + BRCMF_CONSOLE_BUFSIZE_OFFSET;
++ 	console->bufsize = brcmf_pcie_read_tcm32(devinfo, addr);
++ 
++-	brcmf_dbg(PCIE, "Console: base %x, buf %x, size %d\n",
+++	brcmf_dbg(FWCON, "Console: base %x, buf %x, size %d\n",
++ 		  console->base_addr, console->buf_addr, console->bufsize);
++ }
++ 
++@@ -656,6 +656,9 @@ static void brcmf_pcie_bus_console_read(
++ 	u8 ch;
++ 	u32 newidx;
++ 
+++	if (!BRCMF_FWCON_ON())
+++		return;
+++
++ 	console = &devinfo->shared.console;
++ 	addr = console->base_addr + BRCMF_CONSOLE_WRITEIDX_OFFSET;
++ 	newidx = brcmf_pcie_read_tcm32(devinfo, addr);
++@@ -677,7 +680,7 @@ static void brcmf_pcie_bus_console_read(
++ 		}
++ 		if (ch == '\n') {
++ 			console->log_str[console->log_idx] = 0;
++-			brcmf_dbg(PCIE, "CONSOLE: %s", console->log_str);
+++			pr_debug("CONSOLE: %s", console->log_str);
++ 			console->log_idx = 0;
++ 		}
++ 	}
++--- a/drivers/net/wireless/brcm80211/brcmfmac/sdio.c
+++++ b/drivers/net/wireless/brcm80211/brcmfmac/sdio.c
++@@ -123,6 +123,7 @@ struct rte_console {
++ 
++ #define BRCMF_FIRSTREAD	(1 << 6)
++ 
+++#define BRCMF_CONSOLE	10	/* watchdog interval to poll console */
++ 
++ /* SBSDIO_DEVICE_CTL */
++ 
++@@ -3204,6 +3205,8 @@ static void brcmf_sdio_debugfs_create(st
++ 	if (IS_ERR_OR_NULL(dentry))
++ 		return;
++ 
+++	bus->console_interval = BRCMF_CONSOLE;
+++
++ 	brcmf_debugfs_add_entry(drvr, "forensics", brcmf_sdio_forensic_read);
++ 	brcmf_debugfs_add_entry(drvr, "counters",
++ 				brcmf_debugfs_sdio_count_read);
++@@ -3613,7 +3616,7 @@ static void brcmf_sdio_bus_watchdog(stru
++ 	}
++ #ifdef DEBUG
++ 	/* Poll for console output periodically */
++-	if (bus->sdiodev->state == BRCMF_SDIOD_DATA &&
+++	if (bus->sdiodev->state == BRCMF_SDIOD_DATA && BRCMF_FWCON_ON() &&
++ 	    bus->console_interval != 0) {
++ 		bus->console.count += BRCMF_WD_POLL_MS;
++ 		if (bus->console.count >= bus->console_interval) {
+diff --git a/package/kernel/mac80211/patches/328-ath9k-write-buffer-related-optimisation-in-ar5008_hw.patch b/package/kernel/mac80211/patches/328-ath9k-write-buffer-related-optimisation-in-ar5008_hw.patch
+deleted file mode 100644
+index 01c8011..0000000
+--- a/package/kernel/mac80211/patches/328-ath9k-write-buffer-related-optimisation-in-ar5008_hw.patch
++++ /dev/null
+@@ -1,27 +0,0 @@
+-From: Oleksij Rempel <linux@rempel-privat.de>
+-Date: Sun, 22 Mar 2015 19:29:55 +0100
+-Subject: [PATCH] ath9k: write buffer related optimisation in
+- ar5008_hw_set_channel_regs
+-
+-Signed-off-by: Oleksij Rempel <linux@rempel-privat.de>
+-Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
+----
+-
+---- a/drivers/net/wireless/ath/ath9k/ar5008_phy.c
+-+++ b/drivers/net/wireless/ath/ath9k/ar5008_phy.c
+-@@ -681,12 +681,13 @@ static void ar5008_hw_set_channel_regs(s
+- 			phymode |= AR_PHY_FC_DYN2040_PRI_CH;
+- 
+- 	}
+-+	ENABLE_REGWRITE_BUFFER(ah);
+- 	REG_WRITE(ah, AR_PHY_TURBO, phymode);
+- 
+-+	/* This function do only REG_WRITE, so
+-+	 * we can include it to REGWRITE_BUFFER. */
+- 	ath9k_hw_set11nmac2040(ah, chan);
+- 
+--	ENABLE_REGWRITE_BUFFER(ah);
+--
+- 	REG_WRITE(ah, AR_GTXTO, 25 << AR_GTXTO_TIMEOUT_LIMIT_S);
+- 	REG_WRITE(ah, AR_CST, 0xF << AR_CST_TIMEOUT_LIMIT_S);
+- 
+diff --git a/package/kernel/mac80211/patches/328-brcmfmac-remove-ifidx-parameter-from-brcmf_fws_txsta.patch b/package/kernel/mac80211/patches/328-brcmfmac-remove-ifidx-parameter-from-brcmf_fws_txsta.patch
+new file mode 100644
+index 0000000..53e7ede
+--- /dev/null
++++ b/package/kernel/mac80211/patches/328-brcmfmac-remove-ifidx-parameter-from-brcmf_fws_txsta.patch
+@@ -0,0 +1,34 @@
++From: Arend van Spriel <arend@broadcom.com>
++Date: Wed, 26 Aug 2015 22:15:02 +0200
++Subject: [PATCH] brcmfmac: remove ifidx parameter from
++ brcmf_fws_txstatus_suppressed()
++
++The brcmf_fws_txstatus_suppressed() function prototype specifies an
++ifidx parameter which is not used within the function implementation.
++
++Reviewed-by: Hante Meuleman <meuleman@broadcom.com>
++Reviewed-by: Franky (Zhenhui) Lin <frankyl@broadcom.com>
++Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
++Signed-off-by: Arend van Spriel <arend@broadcom.com>
++---
++
++--- a/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c
+++++ b/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c
++@@ -1398,7 +1398,7 @@ done:
++ }
++ 
++ static int brcmf_fws_txstatus_suppressed(struct brcmf_fws_info *fws, int fifo,
++-					 struct sk_buff *skb, u8 ifidx,
+++					 struct sk_buff *skb,
++ 					 u32 genbit, u16 seq)
++ {
++ 	struct brcmf_fws_mac_descriptor *entry = brcmf_skbcb(skb)->mac;
++@@ -1503,7 +1503,7 @@ brcmf_fws_txs_process(struct brcmf_fws_i
++ 		return -EINVAL;
++ 	}
++ 	if (!remove_from_hanger)
++-		ret = brcmf_fws_txstatus_suppressed(fws, fifo, skb, ifp->ifidx,
+++		ret = brcmf_fws_txstatus_suppressed(fws, fifo, skb,
++ 						    genbit, seq);
++ 	if (remove_from_hanger || ret)
++ 		brcmf_txfinalize(ifp, skb, true);
+diff --git a/package/kernel/mac80211/patches/329-ath9k-ath9k_hw_set_4k_power_cal_tabl-use-rmw-buffer.patch b/package/kernel/mac80211/patches/329-ath9k-ath9k_hw_set_4k_power_cal_tabl-use-rmw-buffer.patch
+deleted file mode 100644
+index e5219f2..0000000
+--- a/package/kernel/mac80211/patches/329-ath9k-ath9k_hw_set_4k_power_cal_tabl-use-rmw-buffer.patch
++++ /dev/null
+@@ -1,26 +0,0 @@
+-From: Oleksij Rempel <linux@rempel-privat.de>
+-Date: Sun, 22 Mar 2015 19:29:56 +0100
+-Subject: [PATCH] ath9k: ath9k_hw_set_4k_power_cal_tabl: use rmw buffer
+-
+-Signed-off-by: Oleksij Rempel <linux@rempel-privat.de>
+-Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
+----
+-
+---- a/drivers/net/wireless/ath/ath9k/eeprom_4k.c
+-+++ b/drivers/net/wireless/ath/ath9k/eeprom_4k.c
+-@@ -389,6 +389,7 @@ static void ath9k_hw_set_4k_power_cal_ta
+- 		}
+- 	}
+- 
+-+	ENABLE_REG_RMW_BUFFER(ah);
+- 	REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_NUM_PD_GAIN,
+- 		      (numXpdGain - 1) & 0x3);
+- 	REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_GAIN_1,
+-@@ -396,6 +397,7 @@ static void ath9k_hw_set_4k_power_cal_ta
+- 	REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_GAIN_2,
+- 		      xpdGainValues[1]);
+- 	REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_GAIN_3, 0);
+-+	REG_RMW_BUFFER_FLUSH(ah);
+- 
+- 	for (i = 0; i < AR5416_EEP4K_MAX_CHAINS; i++) {
+- 		regChainOffset = i * 0x1000;
+diff --git a/package/kernel/mac80211/patches/329-brcmfmac-change-prototype-for-brcmf_fws_hdrpull.patch b/package/kernel/mac80211/patches/329-brcmfmac-change-prototype-for-brcmf_fws_hdrpull.patch
+new file mode 100644
+index 0000000..bb05235
+--- /dev/null
++++ b/package/kernel/mac80211/patches/329-brcmfmac-change-prototype-for-brcmf_fws_hdrpull.patch
+@@ -0,0 +1,97 @@
++From: Arend van Spriel <arend@broadcom.com>
++Date: Wed, 26 Aug 2015 22:15:03 +0200
++Subject: [PATCH] brcmfmac: change prototype for brcmf_fws_hdrpull()
++
++Instead of passing ifidx and drvr just pass struct brcmf_if pointer
++which holds both parameters.
++
++Reviewed-by: Hante Meuleman <meuleman@broadcom.com>
++Reviewed-by: Franky (Zhenhui) Lin <frankyl@broadcom.com>
++Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
++Signed-off-by: Arend van Spriel <arend@broadcom.com>
++---
++
++--- a/drivers/net/wireless/brcm80211/brcmfmac/bcdc.c
+++++ b/drivers/net/wireless/brcm80211/brcmfmac/bcdc.c
++@@ -312,8 +312,7 @@ brcmf_proto_bcdc_hdrpull(struct brcmf_pu
++ 
++ 	skb_pull(pktbuf, BCDC_HEADER_LEN);
++ 	if (do_fws)
++-		brcmf_fws_hdrpull(drvr, tmp_if->ifidx, h->data_offset << 2,
++-				  pktbuf);
+++		brcmf_fws_hdrpull(tmp_if, h->data_offset << 2, pktbuf);
++ 	else
++ 		skb_pull(pktbuf, h->data_offset << 2);
++ 
++--- a/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c
+++++ b/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c
++@@ -1616,11 +1616,10 @@ static int brcmf_fws_notify_bcmc_credit_
++ 	return 0;
++ }
++ 
++-int brcmf_fws_hdrpull(struct brcmf_pub *drvr, int ifidx, s16 signal_len,
++-		      struct sk_buff *skb)
+++void brcmf_fws_hdrpull(struct brcmf_if *ifp, s16 siglen, struct sk_buff *skb)
++ {
++ 	struct brcmf_skb_reorder_data *rd;
++-	struct brcmf_fws_info *fws = drvr->fws;
+++	struct brcmf_fws_info *fws = ifp->drvr->fws;
++ 	u8 *signal_data;
++ 	s16 data_len;
++ 	u8 type;
++@@ -1630,20 +1629,20 @@ int brcmf_fws_hdrpull(struct brcmf_pub *
++ 	s32 err;
++ 
++ 	brcmf_dbg(HDRS, "enter: ifidx %d, skblen %u, sig %d\n",
++-		  ifidx, skb->len, signal_len);
+++		  ifp->ifidx, skb->len, siglen);
++ 
++-	WARN_ON(signal_len > skb->len);
+++	WARN_ON(siglen > skb->len);
++ 
++-	if (!signal_len)
++-		return 0;
+++	if (!siglen)
+++		return;
++ 	/* if flow control disabled, skip to packet data and leave */
++ 	if ((!fws) || (!fws->fw_signals)) {
++-		skb_pull(skb, signal_len);
++-		return 0;
+++		skb_pull(skb, siglen);
+++		return;
++ 	}
++ 
++ 	fws->stats.header_pulls++;
++-	data_len = signal_len;
+++	data_len = siglen;
++ 	signal_data = skb->data;
++ 
++ 	status = BRCMF_FWS_RET_OK_NOSCHEDULE;
++@@ -1731,14 +1730,12 @@ int brcmf_fws_hdrpull(struct brcmf_pub *
++ 	/* signalling processing result does
++ 	 * not affect the actual ethernet packet.
++ 	 */
++-	skb_pull(skb, signal_len);
+++	skb_pull(skb, siglen);
++ 
++ 	/* this may be a signal-only packet
++ 	 */
++ 	if (skb->len == 0)
++ 		fws->stats.header_only_pkt++;
++-
++-	return 0;
++ }
++ 
++ static u8 brcmf_fws_precommit_skb(struct brcmf_fws_info *fws, int fifo,
++--- a/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.h
+++++ b/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.h
++@@ -21,8 +21,7 @@
++ int brcmf_fws_init(struct brcmf_pub *drvr);
++ void brcmf_fws_deinit(struct brcmf_pub *drvr);
++ bool brcmf_fws_fc_active(struct brcmf_fws_info *fws);
++-int brcmf_fws_hdrpull(struct brcmf_pub *drvr, int ifidx, s16 signal_len,
++-		      struct sk_buff *skb);
+++void brcmf_fws_hdrpull(struct brcmf_if *ifp, s16 siglen, struct sk_buff *skb);
++ int brcmf_fws_process_skb(struct brcmf_if *ifp, struct sk_buff *skb);
++ 
++ void brcmf_fws_reset_interface(struct brcmf_if *ifp);
+diff --git a/package/kernel/mac80211/patches/330-ath9k-use-rmw-buffer-in-ath9k_hw_set_operating_mode-.patch b/package/kernel/mac80211/patches/330-ath9k-use-rmw-buffer-in-ath9k_hw_set_operating_mode-.patch
+deleted file mode 100644
+index 6ce3f40..0000000
+--- a/package/kernel/mac80211/patches/330-ath9k-use-rmw-buffer-in-ath9k_hw_set_operating_mode-.patch
++++ /dev/null
+@@ -1,43 +0,0 @@
+-From: Oleksij Rempel <linux@rempel-privat.de>
+-Date: Sun, 22 Mar 2015 19:29:57 +0100
+-Subject: [PATCH] ath9k: use rmw buffer in ath9k_hw_set_operating_mode
+- and ath9k_hw_reset
+-
+-Signed-off-by: Oleksij Rempel <linux@rempel-privat.de>
+-Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
+----
+-
+---- a/drivers/net/wireless/ath/ath9k/hw.c
+-+++ b/drivers/net/wireless/ath/ath9k/hw.c
+-@@ -1227,6 +1227,7 @@ static void ath9k_hw_set_operating_mode(
+- 	u32 mask = AR_STA_ID1_STA_AP | AR_STA_ID1_ADHOC;
+- 	u32 set = AR_STA_ID1_KSRCH_MODE;
+- 
+-+	ENABLE_REG_RMW_BUFFER(ah);
+- 	switch (opmode) {
+- 	case NL80211_IFTYPE_ADHOC:
+- 		if (!AR_SREV_9340_13(ah)) {
+-@@ -1248,6 +1249,7 @@ static void ath9k_hw_set_operating_mode(
+- 		break;
+- 	}
+- 	REG_RMW(ah, AR_STA_ID1, set, mask);
+-+	REG_RMW_BUFFER_FLUSH(ah);
+- }
+- 
+- void ath9k_hw_get_delta_slope_vals(struct ath_hw *ah, u32 coef_scaled,
+-@@ -1960,6 +1962,7 @@ int ath9k_hw_reset(struct ath_hw *ah, st
+- 	if (!ath9k_hw_mci_is_enabled(ah))
+- 		REG_WRITE(ah, AR_OBS, 8);
+- 
+-+	ENABLE_REG_RMW_BUFFER(ah);
+- 	if (ah->config.rx_intr_mitigation) {
+- 		REG_RMW_FIELD(ah, AR_RIMT, AR_RIMT_LAST, ah->config.rimt_last);
+- 		REG_RMW_FIELD(ah, AR_RIMT, AR_RIMT_FIRST, ah->config.rimt_first);
+-@@ -1969,6 +1972,7 @@ int ath9k_hw_reset(struct ath_hw *ah, st
+- 		REG_RMW_FIELD(ah, AR_TIMT, AR_TIMT_LAST, 300);
+- 		REG_RMW_FIELD(ah, AR_TIMT, AR_TIMT_FIRST, 750);
+- 	}
+-+	REG_RMW_BUFFER_FLUSH(ah);
+- 
+- 	ath9k_hw_init_bb(ah, chan);
+- 
+diff --git a/package/kernel/mac80211/patches/330-brcmfmac-introduce-brcmf_net_detach-function.patch b/package/kernel/mac80211/patches/330-brcmfmac-introduce-brcmf_net_detach-function.patch
+new file mode 100644
+index 0000000..0651a2f
+--- /dev/null
++++ b/package/kernel/mac80211/patches/330-brcmfmac-introduce-brcmf_net_detach-function.patch
+@@ -0,0 +1,99 @@
++From: Arend van Spriel <arend@broadcom.com>
++Date: Wed, 26 Aug 2015 22:15:04 +0200
++Subject: [PATCH] brcmfmac: introduce brcmf_net_detach() function
++
++In case of error during brcmf_bus_start() the network interfaces were
++freed using free_netdev(). However, the interfaces may have additional
++memory allocated which is not freed. The netdev has destructor set to
++brcmf_cfg80211_free_netdev() which frees the additional memory if
++allocated and call free_netdev(). The brcmf_net_detach() either calls
++brcmf_cfg80211_free_netdev() directly or uses unregister_netdev() when
++struct net_device::reg_state indicates the netdev was registered.
++
++Reported-by: Daniel (Deognyoun) Kim <dekim@broadcom.com>
++Reviewed-by: Hante Meuleman <meuleman@broadcom.com>
++Reviewed-by: Franky (Zhenhui) Lin <frankyl@broadcom.com>
++Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
++Signed-off-by: Arend van Spriel <arend@broadcom.com>
++---
++
++--- a/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c
+++++ b/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c
++@@ -4747,7 +4747,8 @@ void brcmf_cfg80211_free_netdev(struct n
++ 	ifp = netdev_priv(ndev);
++ 	vif = ifp->vif;
++ 
++-	brcmf_free_vif(vif);
+++	if (vif)
+++		brcmf_free_vif(vif);
++ 	free_netdev(ndev);
++ }
++ 
++--- a/drivers/net/wireless/brcm80211/brcmfmac/core.c
+++++ b/drivers/net/wireless/brcm80211/brcmfmac/core.c
++@@ -718,8 +718,6 @@ int brcmf_net_attach(struct brcmf_if *if
++ 	}
++ 
++ 	brcmf_dbg(INFO, "%s: Broadcom Dongle Host Driver\n", ndev->name);
++-
++-	ndev->destructor = brcmf_cfg80211_free_netdev;
++ 	return 0;
++ 
++ fail:
++@@ -729,6 +727,14 @@ fail:
++ 	return -EBADE;
++ }
++ 
+++static void brcmf_net_detach(struct net_device *ndev)
+++{
+++	if (ndev->reg_state == NETREG_REGISTERED)
+++		unregister_netdev(ndev);
+++	else
+++		brcmf_cfg80211_free_netdev(ndev);
+++}
+++
++ static int brcmf_net_p2p_open(struct net_device *ndev)
++ {
++ 	brcmf_dbg(TRACE, "Enter\n");
++@@ -805,8 +811,7 @@ struct brcmf_if *brcmf_add_if(struct brc
++ 			  ifp->ndev->name);
++ 		if (ifidx) {
++ 			netif_stop_queue(ifp->ndev);
++-			unregister_netdev(ifp->ndev);
++-			free_netdev(ifp->ndev);
+++			brcmf_net_detach(ifp->ndev);
++ 			drvr->iflist[bssidx] = NULL;
++ 		} else {
++ 			brcmf_err("ignore IF event\n");
++@@ -828,6 +833,7 @@ struct brcmf_if *brcmf_add_if(struct brc
++ 		if (!ndev)
++ 			return ERR_PTR(-ENOMEM);
++ 
+++		ndev->destructor = brcmf_cfg80211_free_netdev;
++ 		ifp = netdev_priv(ndev);
++ 		ifp->ndev = ndev;
++ 		/* store mapping ifidx to bssidx */
++@@ -879,8 +885,7 @@ static void brcmf_del_if(struct brcmf_pu
++ 			cancel_work_sync(&ifp->setmacaddr_work);
++ 			cancel_work_sync(&ifp->multicast_work);
++ 		}
++-		/* unregister will take care of freeing it */
++-		unregister_netdev(ifp->ndev);
+++		brcmf_net_detach(ifp->ndev);
++ 	}
++ }
++ 
++@@ -1056,11 +1061,11 @@ fail:
++ 			brcmf_fws_deinit(drvr);
++ 		}
++ 		if (drvr->iflist[0]) {
++-			free_netdev(ifp->ndev);
+++			brcmf_net_detach(ifp->ndev);
++ 			drvr->iflist[0] = NULL;
++ 		}
++ 		if (p2p_ifp) {
++-			free_netdev(p2p_ifp->ndev);
+++			brcmf_net_detach(p2p_ifp->ndev);
++ 			drvr->iflist[1] = NULL;
++ 		}
++ 		return ret;
+diff --git a/package/kernel/mac80211/patches/331-ath9k-ath9k_hw_4k_set_board_values-use-rmw-buffer.patch b/package/kernel/mac80211/patches/331-ath9k-ath9k_hw_4k_set_board_values-use-rmw-buffer.patch
+deleted file mode 100644
+index edd6160..0000000
+--- a/package/kernel/mac80211/patches/331-ath9k-ath9k_hw_4k_set_board_values-use-rmw-buffer.patch
++++ /dev/null
+@@ -1,26 +0,0 @@
+-From: Oleksij Rempel <linux@rempel-privat.de>
+-Date: Sun, 22 Mar 2015 19:29:58 +0100
+-Subject: [PATCH] ath9k: ath9k_hw_4k_set_board_values: use rmw buffer
+-
+-Signed-off-by: Oleksij Rempel <linux@rempel-privat.de>
+-Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
+----
+-
+---- a/drivers/net/wireless/ath/ath9k/eeprom_4k.c
+-+++ b/drivers/net/wireless/ath/ath9k/eeprom_4k.c
+-@@ -1082,6 +1082,7 @@ static void ath9k_hw_4k_set_board_values
+- 		mask = BIT(0)|BIT(5)|BIT(10)|BIT(15)|BIT(20)|BIT(25);
+- 		pwrctrl = mask * bb_desired_scale;
+- 		clr = mask * 0x1f;
+-+		ENABLE_REG_RMW_BUFFER(ah);
+- 		REG_RMW(ah, AR_PHY_TX_PWRCTRL8, pwrctrl, clr);
+- 		REG_RMW(ah, AR_PHY_TX_PWRCTRL10, pwrctrl, clr);
+- 		REG_RMW(ah, AR_PHY_CH0_TX_PWRCTRL12, pwrctrl, clr);
+-@@ -1096,6 +1097,7 @@ static void ath9k_hw_4k_set_board_values
+- 		clr = mask * 0x1f;
+- 		REG_RMW(ah, AR_PHY_CH0_TX_PWRCTRL11, pwrctrl, clr);
+- 		REG_RMW(ah, AR_PHY_CH0_TX_PWRCTRL13, pwrctrl, clr);
+-+		REG_RMW_BUFFER_FLUSH(ah);
+- 	}
+- }
+- 
+diff --git a/package/kernel/mac80211/patches/331-brcmfmac-Reset-PCIE-devices-after-recognition.patch b/package/kernel/mac80211/patches/331-brcmfmac-Reset-PCIE-devices-after-recognition.patch
+new file mode 100644
+index 0000000..5a7e447
+--- /dev/null
++++ b/package/kernel/mac80211/patches/331-brcmfmac-Reset-PCIE-devices-after-recognition.patch
+@@ -0,0 +1,193 @@
++From: Hante Meuleman <meuleman@broadcom.com>
++Date: Thu, 27 Aug 2015 16:14:06 +0200
++Subject: [PATCH] brcmfmac: Reset PCIE devices after recognition.
++
++When PCIE type devices are being FW reloaded without being properly
++reset then the device ends up in a locked state, requiring the
++device to be completely powered down. This patch adds a reset
++through watchdog at the moment the device (cores) has been
++recognized. This will solve warm reboot issues.
++
++Cc: Rafal Milecki <zajec5@gmail.com>
++Reviewed-by: Arend Van Spriel <arend@broadcom.com>
++Reviewed-by: Franky (Zhenhui) Lin <frankyl@broadcom.com>
++Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
++Signed-off-by: Hante Meuleman <meuleman@broadcom.com>
++Signed-off-by: Arend van Spriel <arend@broadcom.com>
++---
++
++--- a/drivers/net/wireless/brcm80211/brcmfmac/chip.c
+++++ b/drivers/net/wireless/brcm80211/brcmfmac/chip.c
++@@ -101,6 +101,9 @@
++ /* ARM Cortex M3 core, ID 0x82a */
++ #define BCM4329_CORE_ARM_BASE		0x18002000
++ 
+++/* Max possibly supported memory size (limited by IO mapped memory) */
+++#define BRCMF_CHIP_MAX_MEMSIZE		(4 * 1024 * 1024)
+++
++ #define CORE_SB(base, field) \
++ 		(base + SBCONFIGOFF + offsetof(struct sbconfig, field))
++ #define	SBCOREREV(sbidh) \
++@@ -687,6 +690,12 @@ static int brcmf_chip_get_raminfo(struct
++ 		brcmf_err("RAM size is undetermined\n");
++ 		return -ENOMEM;
++ 	}
+++
+++	if (ci->pub.ramsize > BRCMF_CHIP_MAX_MEMSIZE) {
+++		brcmf_err("RAM size is incorrect\n");
+++		return -ENOMEM;
+++	}
+++
++ 	return 0;
++ }
++ 
++@@ -899,6 +908,15 @@ static int brcmf_chip_recognition(struct
++ 
++ 	/* assure chip is passive for core access */
++ 	brcmf_chip_set_passive(&ci->pub);
+++
+++	/* Call bus specific reset function now. Cores have been determined
+++	 * but further access may require a chip specific reset at this point.
+++	 */
+++	if (ci->ops->reset) {
+++		ci->ops->reset(ci->ctx, &ci->pub);
+++		brcmf_chip_set_passive(&ci->pub);
+++	}
+++
++ 	return brcmf_chip_get_raminfo(ci);
++ }
++ 
++--- a/drivers/net/wireless/brcm80211/brcmfmac/chip.h
+++++ b/drivers/net/wireless/brcm80211/brcmfmac/chip.h
++@@ -73,6 +73,7 @@ struct brcmf_buscore_ops {
++ 	u32 (*read32)(void *ctx, u32 addr);
++ 	void (*write32)(void *ctx, u32 addr, u32 value);
++ 	int (*prepare)(void *ctx);
+++	int (*reset)(void *ctx, struct brcmf_chip *chip);
++ 	int (*setup)(void *ctx, struct brcmf_chip *chip);
++ 	void (*activate)(void *ctx, struct brcmf_chip *chip, u32 rstvec);
++ };
++--- a/drivers/net/wireless/brcm80211/brcmfmac/pcie.c
+++++ b/drivers/net/wireless/brcm80211/brcmfmac/pcie.c
++@@ -74,6 +74,8 @@ enum brcmf_pcie_state {
++ #define BRCMF_PCIE_REG_INTMASK			0x94
++ #define BRCMF_PCIE_REG_SBMBX			0x98
++ 
+++#define BRCMF_PCIE_REG_LINK_STATUS_CTRL		0xBC
+++
++ #define BRCMF_PCIE_PCIE2REG_INTMASK		0x24
++ #define BRCMF_PCIE_PCIE2REG_MAILBOXINT		0x48
++ #define BRCMF_PCIE_PCIE2REG_MAILBOXMASK		0x4C
++@@ -466,6 +468,7 @@ brcmf_pcie_select_core(struct brcmf_pcie
++ 
++ static void brcmf_pcie_reset_device(struct brcmf_pciedev_info *devinfo)
++ {
+++	struct brcmf_core *core;
++ 	u16 cfg_offset[] = { BRCMF_PCIE_CFGREG_STATUS_CMD,
++ 			     BRCMF_PCIE_CFGREG_PM_CSR,
++ 			     BRCMF_PCIE_CFGREG_MSI_CAP,
++@@ -484,32 +487,38 @@ static void brcmf_pcie_reset_device(stru
++ 	if (!devinfo->ci)
++ 		return;
++ 
+++	/* Disable ASPM */
++ 	brcmf_pcie_select_core(devinfo, BCMA_CORE_PCIE2);
++-	brcmf_pcie_write_reg32(devinfo, BRCMF_PCIE_PCIE2REG_CONFIGADDR,
++-			       BRCMF_PCIE_CFGREG_LINK_STATUS_CTRL);
++-	lsc = brcmf_pcie_read_reg32(devinfo, BRCMF_PCIE_PCIE2REG_CONFIGDATA);
+++	pci_read_config_dword(devinfo->pdev, BRCMF_PCIE_REG_LINK_STATUS_CTRL,
+++			      &lsc);
++ 	val = lsc & (~BRCMF_PCIE_LINK_STATUS_CTRL_ASPM_ENAB);
++-	brcmf_pcie_write_reg32(devinfo, BRCMF_PCIE_PCIE2REG_CONFIGDATA, val);
+++	pci_write_config_dword(devinfo->pdev, BRCMF_PCIE_REG_LINK_STATUS_CTRL,
+++			       val);
++ 
+++	/* Watchdog reset */
++ 	brcmf_pcie_select_core(devinfo, BCMA_CORE_CHIPCOMMON);
++ 	WRITECC32(devinfo, watchdog, 4);
++ 	msleep(100);
++ 
+++	/* Restore ASPM */
++ 	brcmf_pcie_select_core(devinfo, BCMA_CORE_PCIE2);
++-	brcmf_pcie_write_reg32(devinfo, BRCMF_PCIE_PCIE2REG_CONFIGADDR,
++-			       BRCMF_PCIE_CFGREG_LINK_STATUS_CTRL);
++-	brcmf_pcie_write_reg32(devinfo, BRCMF_PCIE_PCIE2REG_CONFIGDATA, lsc);
+++	pci_write_config_dword(devinfo->pdev, BRCMF_PCIE_REG_LINK_STATUS_CTRL,
+++			       lsc);
++ 
++-	brcmf_pcie_select_core(devinfo, BCMA_CORE_PCIE2);
++-	for (i = 0; i < ARRAY_SIZE(cfg_offset); i++) {
++-		brcmf_pcie_write_reg32(devinfo, BRCMF_PCIE_PCIE2REG_CONFIGADDR,
++-				       cfg_offset[i]);
++-		val = brcmf_pcie_read_reg32(devinfo,
++-					    BRCMF_PCIE_PCIE2REG_CONFIGDATA);
++-		brcmf_dbg(PCIE, "config offset 0x%04x, value 0x%04x\n",
++-			  cfg_offset[i], val);
++-		brcmf_pcie_write_reg32(devinfo, BRCMF_PCIE_PCIE2REG_CONFIGDATA,
++-				       val);
+++	core = brcmf_chip_get_core(devinfo->ci, BCMA_CORE_PCIE2);
+++	if (core->rev <= 13) {
+++		for (i = 0; i < ARRAY_SIZE(cfg_offset); i++) {
+++			brcmf_pcie_write_reg32(devinfo,
+++					       BRCMF_PCIE_PCIE2REG_CONFIGADDR,
+++					       cfg_offset[i]);
+++			val = brcmf_pcie_read_reg32(devinfo,
+++				BRCMF_PCIE_PCIE2REG_CONFIGDATA);
+++			brcmf_dbg(PCIE, "config offset 0x%04x, value 0x%04x\n",
+++				  cfg_offset[i], val);
+++			brcmf_pcie_write_reg32(devinfo,
+++					       BRCMF_PCIE_PCIE2REG_CONFIGDATA,
+++					       val);
+++		}
++ 	}
++ }
++ 
++@@ -519,8 +528,6 @@ static void brcmf_pcie_attach(struct brc
++ 	u32 config;
++ 
++ 	brcmf_pcie_select_core(devinfo, BCMA_CORE_PCIE2);
++-	if (brcmf_pcie_read_reg32(devinfo, BRCMF_PCIE_PCIE2REG_INTMASK) != 0)
++-		brcmf_pcie_reset_device(devinfo);
++ 	/* BAR1 window may not be sized properly */
++ 	brcmf_pcie_select_core(devinfo, BCMA_CORE_PCIE2);
++ 	brcmf_pcie_write_reg32(devinfo, BRCMF_PCIE_PCIE2REG_CONFIGADDR, 0x4e0);
++@@ -1636,6 +1643,23 @@ static int brcmf_pcie_buscoreprep(void *
++ }
++ 
++ 
+++static int brcmf_pcie_buscore_reset(void *ctx, struct brcmf_chip *chip)
+++{
+++	struct brcmf_pciedev_info *devinfo = (struct brcmf_pciedev_info *)ctx;
+++	u32 val;
+++
+++	devinfo->ci = chip;
+++	brcmf_pcie_reset_device(devinfo);
+++
+++	val = brcmf_pcie_read_reg32(devinfo, BRCMF_PCIE_PCIE2REG_MAILBOXINT);
+++	if (val != 0xffffffff)
+++		brcmf_pcie_write_reg32(devinfo, BRCMF_PCIE_PCIE2REG_MAILBOXINT,
+++				       val);
+++
+++	return 0;
+++}
+++
+++
++ static void brcmf_pcie_buscore_activate(void *ctx, struct brcmf_chip *chip,
++ 					u32 rstvec)
++ {
++@@ -1647,6 +1671,7 @@ static void brcmf_pcie_buscore_activate(
++ 
++ static const struct brcmf_buscore_ops brcmf_pcie_buscore_ops = {
++ 	.prepare = brcmf_pcie_buscoreprep,
+++	.reset = brcmf_pcie_buscore_reset,
++ 	.activate = brcmf_pcie_buscore_activate,
++ 	.read32 = brcmf_pcie_buscore_read32,
++ 	.write32 = brcmf_pcie_buscore_write32,
++@@ -1814,7 +1839,6 @@ brcmf_pcie_remove(struct pci_dev *pdev)
++ 		brcmf_pcie_intr_disable(devinfo);
++ 
++ 	brcmf_detach(&pdev->dev);
++-	brcmf_pcie_reset_device(devinfo);
++ 
++ 	kfree(bus->bus_priv.pcie);
++ 	kfree(bus->msgbuf->flowrings);
+diff --git a/package/kernel/mac80211/patches/332-ath10k-fix-DMA-related-firmware-crashes-on-multiple-.patch b/package/kernel/mac80211/patches/332-ath10k-fix-DMA-related-firmware-crashes-on-multiple-.patch
+new file mode 100644
+index 0000000..52b7fa9
+--- /dev/null
++++ b/package/kernel/mac80211/patches/332-ath10k-fix-DMA-related-firmware-crashes-on-multiple-.patch
+@@ -0,0 +1,33 @@
++From: Felix Fietkau <nbd@openwrt.org>
++Date: Sun, 13 Sep 2015 22:26:10 +0200
++Subject: [PATCH] ath10k: fix DMA related firmware crashes on multiple devices
++
++Some platforms really don't like DMA bursts of 256 bytes, and this
++causes the firmware to crash when sending beacons.
++Also, changing this based on the firmware version does not seem to make
++much sense, so use 128 bytes for all versions.
++
++Cc: stable@vger.kernel.org
++Signed-off-by: Felix Fietkau <nbd@openwrt.org>
++---
++
++--- a/drivers/net/wireless/ath/ath10k/hw.h
+++++ b/drivers/net/wireless/ath/ath10k/hw.h
++@@ -340,7 +340,7 @@ enum ath10k_hw_rate_cck {
++ #define TARGET_10X_MAX_FRAG_ENTRIES		0
++ 
++ /* 10.2 parameters */
++-#define TARGET_10_2_DMA_BURST_SIZE		1
+++#define TARGET_10_2_DMA_BURST_SIZE		0
++ 
++ /* Target specific defines for WMI-TLV firmware */
++ #define TARGET_TLV_NUM_VDEVS			4
++@@ -397,7 +397,7 @@ enum ath10k_hw_rate_cck {
++ 
++ #define TARGET_10_4_TX_DBG_LOG_SIZE		1024
++ #define TARGET_10_4_NUM_WDS_ENTRIES		32
++-#define TARGET_10_4_DMA_BURST_SIZE		1
+++#define TARGET_10_4_DMA_BURST_SIZE		0
++ #define TARGET_10_4_MAC_AGGR_DELIM		0
++ #define TARGET_10_4_RX_SKIP_DEFRAG_TIMEOUT_DUP_DETECTION_CHECK 1
++ #define TARGET_10_4_VOW_CONFIG			0
+diff --git a/package/kernel/mac80211/patches/332-ath9k-ath9k_hw_analog_shift_rmw-use-REG_RMW.patch b/package/kernel/mac80211/patches/332-ath9k-ath9k_hw_analog_shift_rmw-use-REG_RMW.patch
+deleted file mode 100644
+index 3ce4428..0000000
+--- a/package/kernel/mac80211/patches/332-ath9k-ath9k_hw_analog_shift_rmw-use-REG_RMW.patch
++++ /dev/null
+@@ -1,27 +0,0 @@
+-From: Oleksij Rempel <linux@rempel-privat.de>
+-Date: Sun, 22 Mar 2015 19:29:59 +0100
+-Subject: [PATCH] ath9k: ath9k_hw_analog_shift_rmw: use REG_RMW
+-
+-use REG_RMW in ath9k_hw_analog_shift_rmw.
+-It will double execution speed on usb bus.
+-
+-Signed-off-by: Oleksij Rempel <linux@rempel-privat.de>
+-Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
+----
+-
+---- a/drivers/net/wireless/ath/ath9k/eeprom.c
+-+++ b/drivers/net/wireless/ath/ath9k/eeprom.c
+-@@ -27,12 +27,7 @@ void ath9k_hw_analog_shift_regwrite(stru
+- void ath9k_hw_analog_shift_rmw(struct ath_hw *ah, u32 reg, u32 mask,
+- 			       u32 shift, u32 val)
+- {
+--	u32 regVal;
+--
+--	regVal = REG_READ(ah, reg) & ~mask;
+--	regVal |= (val << shift) & mask;
+--
+--	REG_WRITE(ah, reg, regVal);
+-+	REG_RMW(ah, reg, ((val << shift) & mask), mask);
+- 
+- 	if (ah->config.analog_shiftreg)
+- 		udelay(100);
+diff --git a/package/kernel/mac80211/patches/333-ath9k-enable-hw-manual-peak-calibration-for-QCA9561.patch b/package/kernel/mac80211/patches/333-ath9k-enable-hw-manual-peak-calibration-for-QCA9561.patch
+new file mode 100644
+index 0000000..faf6cdc
+--- /dev/null
++++ b/package/kernel/mac80211/patches/333-ath9k-enable-hw-manual-peak-calibration-for-QCA9561.patch
+@@ -0,0 +1,33 @@
++From: Miaoqing Pan <miaoqing@qca.qualcomm.com>
++Date: Tue, 1 Sep 2015 10:56:09 +0800
++Subject: [PATCH] ath9k: enable hw manual peak calibration for QCA9561
++
++This patch fix https://lists.openwrt.org/pipermail/openwrt-devel/
++2015-August/034979.html. As the peak detect calibration is set
++incorrectly.
++
++Signed-off-by: Miaoqing Pan <miaoqing@qca.qualcomm.com>
++---
++
++--- a/drivers/net/wireless/ath/ath9k/ar9003_calib.c
+++++ b/drivers/net/wireless/ath/ath9k/ar9003_calib.c
++@@ -1249,7 +1249,8 @@ static void ar9003_hw_manual_peak_cal(st
++ 		REG_RMW_FIELD(ah, AR_PHY_65NM_RXRF_AGC(chain),
++ 			      AR_PHY_65NM_RXRF_AGC_AGC2G_CALDAC_OVR, 0x0);
++ 
++-	if (AR_SREV_9003_PCOEM(ah) || AR_SREV_9550(ah) || AR_SREV_9531(ah)) {
+++	if (AR_SREV_9003_PCOEM(ah) || AR_SREV_9550(ah) || AR_SREV_9531(ah) ||
+++	    AR_SREV_9561(ah)) {
++ 		if (is_2g)
++ 			REG_RMW_FIELD(ah, AR_PHY_65NM_RXRF_AGC(chain),
++ 				      AR_PHY_65NM_RXRF_AGC_AGC2G_DBDAC_OVR,
++@@ -1640,7 +1641,8 @@ static bool ar9003_hw_init_cal_soc(struc
++ 
++ skip_tx_iqcal:
++ 	if (run_agc_cal || !(ah->ah_flags & AH_FASTCC)) {
++-		if (AR_SREV_9330_11(ah) || AR_SREV_9531(ah) || AR_SREV_9550(ah)) {
+++		if (AR_SREV_9330_11(ah) || AR_SREV_9531(ah) || AR_SREV_9550(ah) ||
+++		    AR_SREV_9561(ah)) {
++ 			for (i = 0; i < AR9300_MAX_CHAINS; i++) {
++ 				if (!(ah->rxchainmask & (1 << i)))
++ 					continue;
+diff --git a/package/kernel/mac80211/patches/333-ath9k-use-REG_RMW-and-rmw-buffer-in-ath9k_hw_4k_set_.patch b/package/kernel/mac80211/patches/333-ath9k-use-REG_RMW-and-rmw-buffer-in-ath9k_hw_4k_set_.patch
+deleted file mode 100644
+index 8f12b36..0000000
+--- a/package/kernel/mac80211/patches/333-ath9k-use-REG_RMW-and-rmw-buffer-in-ath9k_hw_4k_set_.patch
++++ /dev/null
+@@ -1,47 +0,0 @@
+-From: Oleksij Rempel <linux@rempel-privat.de>
+-Date: Sun, 22 Mar 2015 19:30:01 +0100
+-Subject: [PATCH] ath9k: use REG_RMW and rmw buffer in
+- ath9k_hw_4k_set_gain
+-
+-it is possible to reduce time needed for this function
+-by rplacing REG_WRITE with REG_RMW (plus dummy 0) and putt all commands
+-in same buffer.
+-
+-Signed-off-by: Oleksij Rempel <linux@rempel-privat.de>
+-Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
+----
+-
+---- a/drivers/net/wireless/ath/ath9k/eeprom_4k.c
+-+++ b/drivers/net/wireless/ath/ath9k/eeprom_4k.c
+-@@ -772,15 +772,14 @@ static void ath9k_hw_4k_set_gain(struct
+- 				 struct ar5416_eeprom_4k *eep,
+- 				 u8 txRxAttenLocal)
+- {
+--	REG_WRITE(ah, AR_PHY_SWITCH_CHAIN_0,
+--		  pModal->antCtrlChain[0]);
+--
+--	REG_WRITE(ah, AR_PHY_TIMING_CTRL4(0),
+--		  (REG_READ(ah, AR_PHY_TIMING_CTRL4(0)) &
+--		   ~(AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF |
+--		     AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF)) |
+--		  SM(pModal->iqCalICh[0], AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF) |
+--		  SM(pModal->iqCalQCh[0], AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF));
+-+	ENABLE_REG_RMW_BUFFER(ah);
+-+	REG_RMW(ah, AR_PHY_SWITCH_CHAIN_0,
+-+		pModal->antCtrlChain[0], 0);
+-+
+-+	REG_RMW(ah, AR_PHY_TIMING_CTRL4(0),
+-+		SM(pModal->iqCalICh[0], AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF) |
+-+		SM(pModal->iqCalQCh[0], AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF),
+-+		AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF | AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF);
+- 
+- 	if ((eep->baseEepHeader.version & AR5416_EEP_VER_MINOR_MASK) >=
+- 	    AR5416_EEP_MINOR_VER_3) {
+-@@ -819,6 +818,7 @@ static void ath9k_hw_4k_set_gain(struct
+- 		      AR9280_PHY_RXGAIN_TXRX_ATTEN, txRxAttenLocal);
+- 	REG_RMW_FIELD(ah, AR_PHY_RXGAIN + 0x1000,
+- 		      AR9280_PHY_RXGAIN_TXRX_MARGIN, pModal->rxTxMarginCh[0]);
+-+	REG_RMW_BUFFER_FLUSH(ah);
+- }
+- 
+- /*
+diff --git a/package/kernel/mac80211/patches/334-ath9k-use-REG_RMW-and-rmw-buffer-in-ath9k_hw_def_set.patch b/package/kernel/mac80211/patches/334-ath9k-use-REG_RMW-and-rmw-buffer-in-ath9k_hw_def_set.patch
+deleted file mode 100644
+index f26e059..0000000
+--- a/package/kernel/mac80211/patches/334-ath9k-use-REG_RMW-and-rmw-buffer-in-ath9k_hw_def_set.patch
++++ /dev/null
+@@ -1,67 +0,0 @@
+-From: Oleksij Rempel <linux@rempel-privat.de>
+-Date: Sun, 22 Mar 2015 19:30:03 +0100
+-Subject: [PATCH] ath9k: use REG_RMW and rmw buffer in
+- ath9k_hw_def_set_gain
+-
+-Signed-off-by: Oleksij Rempel <linux@rempel-privat.de>
+-Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
+----
+-
+---- a/drivers/net/wireless/ath/ath9k/eeprom_def.c
+-+++ b/drivers/net/wireless/ath/ath9k/eeprom_def.c
+-@@ -466,6 +466,7 @@ static void ath9k_hw_def_set_gain(struct
+- 				  struct ar5416_eeprom_def *eep,
+- 				  u8 txRxAttenLocal, int regChainOffset, int i)
+- {
+-+	ENABLE_REG_RMW_BUFFER(ah);
+- 	if (AR5416_VER_MASK >= AR5416_EEP_MINOR_VER_3) {
+- 		txRxAttenLocal = pModal->txRxAttenCh[i];
+- 
+-@@ -483,16 +484,12 @@ static void ath9k_hw_def_set_gain(struct
+- 			      AR_PHY_GAIN_2GHZ_XATTEN2_DB,
+- 			      pModal->xatten2Db[i]);
+- 		} else {
+--			REG_WRITE(ah, AR_PHY_GAIN_2GHZ + regChainOffset,
+--			  (REG_READ(ah, AR_PHY_GAIN_2GHZ + regChainOffset) &
+--			   ~AR_PHY_GAIN_2GHZ_BSW_MARGIN)
+--			  | SM(pModal-> bswMargin[i],
+--			       AR_PHY_GAIN_2GHZ_BSW_MARGIN));
+--			REG_WRITE(ah, AR_PHY_GAIN_2GHZ + regChainOffset,
+--			  (REG_READ(ah, AR_PHY_GAIN_2GHZ + regChainOffset) &
+--			   ~AR_PHY_GAIN_2GHZ_BSW_ATTEN)
+--			  | SM(pModal->bswAtten[i],
+--			       AR_PHY_GAIN_2GHZ_BSW_ATTEN));
+-+			REG_RMW(ah, AR_PHY_GAIN_2GHZ + regChainOffset,
+-+				SM(pModal-> bswMargin[i], AR_PHY_GAIN_2GHZ_BSW_MARGIN),
+-+				AR_PHY_GAIN_2GHZ_BSW_MARGIN);
+-+			REG_RMW(ah, AR_PHY_GAIN_2GHZ + regChainOffset,
+-+				SM(pModal->bswAtten[i], AR_PHY_GAIN_2GHZ_BSW_ATTEN),
+-+				AR_PHY_GAIN_2GHZ_BSW_ATTEN);
+- 		}
+- 	}
+- 
+-@@ -504,17 +501,14 @@ static void ath9k_hw_def_set_gain(struct
+- 		      AR_PHY_RXGAIN + regChainOffset,
+- 		      AR9280_PHY_RXGAIN_TXRX_MARGIN, pModal->rxTxMarginCh[i]);
+- 	} else {
+--		REG_WRITE(ah,
+--			  AR_PHY_RXGAIN + regChainOffset,
+--			  (REG_READ(ah, AR_PHY_RXGAIN + regChainOffset) &
+--			   ~AR_PHY_RXGAIN_TXRX_ATTEN)
+--			  | SM(txRxAttenLocal, AR_PHY_RXGAIN_TXRX_ATTEN));
+--		REG_WRITE(ah,
+--			  AR_PHY_GAIN_2GHZ + regChainOffset,
+--			  (REG_READ(ah, AR_PHY_GAIN_2GHZ + regChainOffset) &
+--			   ~AR_PHY_GAIN_2GHZ_RXTX_MARGIN) |
+--			  SM(pModal->rxTxMarginCh[i], AR_PHY_GAIN_2GHZ_RXTX_MARGIN));
+-+		REG_RMW(ah, AR_PHY_RXGAIN + regChainOffset,
+-+			SM(txRxAttenLocal, AR_PHY_RXGAIN_TXRX_ATTEN),
+-+			AR_PHY_RXGAIN_TXRX_ATTEN);
+-+		REG_RMW(ah, AR_PHY_GAIN_2GHZ + regChainOffset,
+-+			SM(pModal->rxTxMarginCh[i], AR_PHY_GAIN_2GHZ_RXTX_MARGIN),
+-+			AR_PHY_GAIN_2GHZ_RXTX_MARGIN);
+- 	}
+-+	REG_RMW_BUFFER_FLUSH(ah);
+- }
+- 
+- static void ath9k_hw_def_set_board_values(struct ath_hw *ah,
+diff --git a/package/kernel/mac80211/patches/334-mac80211-fix-tx-sequence-number-assignment-with-soft.patch b/package/kernel/mac80211/patches/334-mac80211-fix-tx-sequence-number-assignment-with-soft.patch
+new file mode 100644
+index 0000000..b19e7ee
+--- /dev/null
++++ b/package/kernel/mac80211/patches/334-mac80211-fix-tx-sequence-number-assignment-with-soft.patch
+@@ -0,0 +1,23 @@
++From: Felix Fietkau <nbd@openwrt.org>
++Date: Thu, 24 Sep 2015 14:10:07 +0200
++Subject: [PATCH] mac80211: fix tx sequence number assignment with software
++ queue + fast-xmit
++
++When using software queueing, tx sequence number assignment happens at
++ieee80211_tx_dequeue time, so the fast-xmit codepath must not do that.
++
++Signed-off-by: Felix Fietkau <nbd@openwrt.org>
++---
++
++--- a/net/mac80211/tx.c
+++++ b/net/mac80211/tx.c
++@@ -2766,7 +2766,8 @@ static bool ieee80211_xmit_fast(struct i
++ 
++ 	if (hdr->frame_control & cpu_to_le16(IEEE80211_STYPE_QOS_DATA)) {
++ 		*ieee80211_get_qos_ctl(hdr) = tid;
++-		hdr->seq_ctrl = ieee80211_tx_next_seq(sta, tid);
+++		if (!sta->sta.txq[0])
+++			hdr->seq_ctrl = ieee80211_tx_next_seq(sta, tid);
++ 	} else {
++ 		info->flags |= IEEE80211_TX_CTL_ASSIGN_SEQ;
++ 		hdr->seq_ctrl = cpu_to_le16(sdata->sequence_number);
+diff --git a/package/kernel/mac80211/patches/335-brcmfmac-Fix-oops-when-SDIO-device-is-removed.patch b/package/kernel/mac80211/patches/335-brcmfmac-Fix-oops-when-SDIO-device-is-removed.patch
+deleted file mode 100644
+index 5e63a80..0000000
+--- a/package/kernel/mac80211/patches/335-brcmfmac-Fix-oops-when-SDIO-device-is-removed.patch
++++ /dev/null
+@@ -1,44 +0,0 @@
+-From: Hante Meuleman <meuleman@broadcom.com>
+-Date: Fri, 6 Mar 2015 18:40:38 +0100
+-Subject: [PATCH] brcmfmac: Fix oops when SDIO device is removed.
+-
+-On removal of SDIO card both functions of card will be getting
+-a remove call. When the first is hanging in ctrl frame xmit then
+-the second will cause oops. This patch fixes the xmit ctrl
+-handling in case of serious errors and also limits the handling
+-for remove to function 1 only.
+-
+-Reviewed-by: Arend Van Spriel <arend@broadcom.com>
+-Reviewed-by: Franky (Zhenhui) Lin <frankyl@broadcom.com>
+-Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
+-Reviewed-by: Daniel (Deognyoun) Kim <dekim@broadcom.com>
+-Signed-off-by: Hante Meuleman <meuleman@broadcom.com>
+-Signed-off-by: Arend van Spriel <arend@broadcom.com>
+-Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
+----
+-
+---- a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c
+-+++ b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c
+-@@ -1194,7 +1194,7 @@ static void brcmf_ops_sdio_remove(struct
+- 	brcmf_dbg(SDIO, "sdio device ID: 0x%04x\n", func->device);
+- 	brcmf_dbg(SDIO, "Function: %d\n", func->num);
+- 
+--	if (func->num != 1 && func->num != 2)
+-+	if (func->num != 1)
+- 		return;
+- 
+- 	bus_if = dev_get_drvdata(&func->dev);
+---- a/drivers/net/wireless/brcm80211/brcmfmac/sdio.c
+-+++ b/drivers/net/wireless/brcm80211/brcmfmac/sdio.c
+-@@ -2740,6 +2740,11 @@ static void brcmf_sdio_dpc(struct brcmf_
+- 	if ((bus->sdiodev->state != BRCMF_SDIOD_DATA) || (err != 0)) {
+- 		brcmf_err("failed backplane access over SDIO, halting operation\n");
+- 		atomic_set(&bus->intstatus, 0);
+-+		if (bus->ctrl_frame_stat) {
+-+			bus->ctrl_frame_err = -ENODEV;
+-+			bus->ctrl_frame_stat = false;
+-+			brcmf_sdio_wait_event_wakeup(bus);
+-+		}
+- 	} else if (atomic_read(&bus->intstatus) ||
+- 		   atomic_read(&bus->ipend) > 0 ||
+- 		   (!atomic_read(&bus->fcstate) &&
+diff --git a/package/kernel/mac80211/patches/335-mac80211-fix-handling-of-PS-filtering-with-fast-xmit.patch b/package/kernel/mac80211/patches/335-mac80211-fix-handling-of-PS-filtering-with-fast-xmit.patch
+new file mode 100644
+index 0000000..7aef205
+--- /dev/null
++++ b/package/kernel/mac80211/patches/335-mac80211-fix-handling-of-PS-filtering-with-fast-xmit.patch
+@@ -0,0 +1,45 @@
++From: Felix Fietkau <nbd@openwrt.org>
++Date: Thu, 24 Sep 2015 14:11:40 +0200
++Subject: [PATCH] mac80211: fix handling of PS filtering with fast-xmit
++
++Fixes dropped packets in the tx path in case a non-PS station triggers
++the tx filter.
++
++Cc: stable@vger.kernel.org # 4.2
++Signed-off-by: Felix Fietkau <nbd@openwrt.org>
++---
++
++--- a/net/mac80211/status.c
+++++ b/net/mac80211/status.c
++@@ -101,6 +101,7 @@ static void ieee80211_handle_filtered_fr
++ 	 * when it wakes up for the next time.
++ 	 */
++ 	set_sta_flag(sta, WLAN_STA_CLEAR_PS_FILT);
+++	ieee80211_clear_fast_xmit(sta);
++ 
++ 	/*
++ 	 * This code races in the following way:
++--- a/net/mac80211/tx.c
+++++ b/net/mac80211/tx.c
++@@ -1217,8 +1217,10 @@ ieee80211_tx_prepare(struct ieee80211_su
++ 
++ 	if (!tx->sta)
++ 		info->flags |= IEEE80211_TX_CTL_CLEAR_PS_FILT;
++-	else if (test_and_clear_sta_flag(tx->sta, WLAN_STA_CLEAR_PS_FILT))
+++	else if (test_and_clear_sta_flag(tx->sta, WLAN_STA_CLEAR_PS_FILT)) {
++ 		info->flags |= IEEE80211_TX_CTL_CLEAR_PS_FILT;
+++		ieee80211_check_fast_xmit(tx->sta);
+++	}
++ 
++ 	info->flags |= IEEE80211_TX_CTL_FIRST_FRAGMENT;
++ 
++@@ -2450,7 +2452,8 @@ void ieee80211_check_fast_xmit(struct st
++ 
++ 	if (test_sta_flag(sta, WLAN_STA_PS_STA) ||
++ 	    test_sta_flag(sta, WLAN_STA_PS_DRIVER) ||
++-	    test_sta_flag(sta, WLAN_STA_PS_DELIVER))
+++	    test_sta_flag(sta, WLAN_STA_PS_DELIVER) ||
+++	    test_sta_flag(sta, WLAN_STA_CLEAR_PS_FILT))
++ 		goto out;
++ 
++ 	if (sdata->noack_map)
+diff --git a/package/kernel/mac80211/patches/336-ath9k-declare-required-extra-tx-headroom.patch b/package/kernel/mac80211/patches/336-ath9k-declare-required-extra-tx-headroom.patch
+new file mode 100644
+index 0000000..4d88591
+--- /dev/null
++++ b/package/kernel/mac80211/patches/336-ath9k-declare-required-extra-tx-headroom.patch
+@@ -0,0 +1,22 @@
++From: Felix Fietkau <nbd@openwrt.org>
++Date: Thu, 24 Sep 2015 16:57:37 +0200
++Subject: [PATCH] ath9k: declare required extra tx headroom
++
++ath9k inserts padding between the 802.11 header and the data area (to
++align it). Since it didn't declare this extra required headroom, this
++led to some nasty issues like randomly dropped packets in some setups.
++
++Cc: stable@vger.kernel.org
++Signed-off-by: Felix Fietkau <nbd@openwrt.org>
++---
++
++--- a/drivers/net/wireless/ath/ath9k/init.c
+++++ b/drivers/net/wireless/ath/ath9k/init.c
++@@ -875,6 +875,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->extra_tx_headroom = 4;
++ 
++ 	hw->wiphy->available_antennas_rx = BIT(ah->caps.max_rxchains) - 1;
++ 	hw->wiphy->available_antennas_tx = BIT(ah->caps.max_txchains) - 1;
+diff --git a/package/kernel/mac80211/patches/336-brcmfmac-Simplify-watchdog-sleep.patch b/package/kernel/mac80211/patches/336-brcmfmac-Simplify-watchdog-sleep.patch
+deleted file mode 100644
+index 201da75..0000000
+--- a/package/kernel/mac80211/patches/336-brcmfmac-Simplify-watchdog-sleep.patch
++++ /dev/null
+@@ -1,157 +0,0 @@
+-From: Hante Meuleman <meuleman@broadcom.com>
+-Date: Fri, 6 Mar 2015 18:40:39 +0100
+-Subject: [PATCH] brcmfmac: Simplify watchdog sleep.
+-
+-The watchdog thread is used to put the SDIO bus to sleep when the
+-system is idling. This patch simplifies the way it is determined
+-when sleep can be entered.
+-
+-Reviewed-by: Arend Van Spriel <arend@broadcom.com>
+-Reviewed-by: Franky (Zhenhui) Lin <frankyl@broadcom.com>
+-Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
+-Reviewed-by: Daniel (Deognyoun) Kim <dekim@broadcom.com>
+-Signed-off-by: Hante Meuleman <meuleman@broadcom.com>
+-Signed-off-by: Arend van Spriel <arend@broadcom.com>
+-Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
+----
+-
+---- a/drivers/net/wireless/brcm80211/brcmfmac/sdio.c
+-+++ b/drivers/net/wireless/brcm80211/brcmfmac/sdio.c
+-@@ -485,10 +485,9 @@ struct brcmf_sdio {
+- #endif				/* DEBUG */
+- 
+- 	uint clkstate;		/* State of sd and backplane clock(s) */
+--	bool activity;		/* Activity flag for clock down */
+- 	s32 idletime;		/* Control for activity timeout */
+--	s32 idlecount;	/* Activity timeout counter */
+--	s32 idleclock;	/* How to set bus driver when idle */
+-+	s32 idlecount;		/* Activity timeout counter */
+-+	s32 idleclock;		/* How to set bus driver when idle */
+- 	bool rxflow_mode;	/* Rx flow control mode */
+- 	bool rxflow;		/* Is rx flow control on */
+- 	bool alp_only;		/* Don't use HT clock (ALP only) */
+-@@ -511,6 +510,7 @@ struct brcmf_sdio {
+- 	struct workqueue_struct *brcmf_wq;
+- 	struct work_struct datawork;
+- 	atomic_t dpc_tskcnt;
+-+	atomic_t dpc_running;
+- 
+- 	bool txoff;		/* Transmit flow-controlled */
+- 	struct brcmf_sdio_count sdcnt;
+-@@ -959,13 +959,8 @@ static int brcmf_sdio_clkctl(struct brcm
+- 	brcmf_dbg(SDIO, "Enter\n");
+- 
+- 	/* Early exit if we're already there */
+--	if (bus->clkstate == target) {
+--		if (target == CLK_AVAIL) {
+--			brcmf_sdio_wd_timer(bus, BRCMF_WD_POLL_MS);
+--			bus->activity = true;
+--		}
+-+	if (bus->clkstate == target)
+- 		return 0;
+--	}
+- 
+- 	switch (target) {
+- 	case CLK_AVAIL:
+-@@ -975,7 +970,6 @@ static int brcmf_sdio_clkctl(struct brcm
+- 		/* Now request HT Avail on the backplane */
+- 		brcmf_sdio_htclk(bus, true, pendok);
+- 		brcmf_sdio_wd_timer(bus, BRCMF_WD_POLL_MS);
+--		bus->activity = true;
+- 		break;
+- 
+- 	case CLK_SDONLY:
+-@@ -1024,17 +1018,6 @@ brcmf_sdio_bus_sleep(struct brcmf_sdio *
+- 
+- 		/* Going to sleep */
+- 		if (sleep) {
+--			/* Don't sleep if something is pending */
+--			if (atomic_read(&bus->intstatus) ||
+--			    atomic_read(&bus->ipend) > 0 ||
+--			    bus->ctrl_frame_stat ||
+--			    (!atomic_read(&bus->fcstate) &&
+--			    brcmu_pktq_mlen(&bus->txq, ~bus->flowcontrol) &&
+--			    data_ok(bus))) {
+--				 err = -EBUSY;
+--				 goto done;
+--			}
+--
+- 			clkcsr = brcmf_sdiod_regrb(bus->sdiodev,
+- 						   SBSDIO_FUNC1_CHIPCLKCSR,
+- 						   &err);
+-@@ -1045,11 +1028,7 @@ brcmf_sdio_bus_sleep(struct brcmf_sdio *
+- 						  SBSDIO_ALP_AVAIL_REQ, &err);
+- 			}
+- 			err = brcmf_sdio_kso_control(bus, false);
+--			/* disable watchdog */
+--			if (!err)
+--				brcmf_sdio_wd_timer(bus, 0);
+- 		} else {
+--			bus->idlecount = 0;
+- 			err = brcmf_sdio_kso_control(bus, true);
+- 		}
+- 		if (err) {
+-@@ -3566,7 +3545,7 @@ void brcmf_sdio_isr(struct brcmf_sdio *b
+- 	queue_work(bus->brcmf_wq, &bus->datawork);
+- }
+- 
+--static bool brcmf_sdio_bus_watchdog(struct brcmf_sdio *bus)
+-+static void brcmf_sdio_bus_watchdog(struct brcmf_sdio *bus)
+- {
+- 	brcmf_dbg(TIMER, "Enter\n");
+- 
+-@@ -3627,22 +3606,21 @@ static bool brcmf_sdio_bus_watchdog(stru
+- #endif				/* DEBUG */
+- 
+- 	/* On idle timeout clear activity flag and/or turn off clock */
+--	if ((bus->idletime > 0) && (bus->clkstate == CLK_AVAIL)) {
+--		if (++bus->idlecount >= bus->idletime) {
+-+	if ((atomic_read(&bus->dpc_tskcnt) == 0) &&
+-+	    (atomic_read(&bus->dpc_running) == 0) &&
+-+	    (bus->idletime > 0) && (bus->clkstate == CLK_AVAIL)) {
+-+		bus->idlecount++;
+-+		if (bus->idlecount > bus->idletime) {
+-+			brcmf_dbg(SDIO, "idle\n");
+-+			sdio_claim_host(bus->sdiodev->func[1]);
+-+			brcmf_sdio_wd_timer(bus, 0);
+- 			bus->idlecount = 0;
+--			if (bus->activity) {
+--				bus->activity = false;
+--				brcmf_sdio_wd_timer(bus, BRCMF_WD_POLL_MS);
+--			} else {
+--				brcmf_dbg(SDIO, "idle\n");
+--				sdio_claim_host(bus->sdiodev->func[1]);
+--				brcmf_sdio_bus_sleep(bus, true, false);
+--				sdio_release_host(bus->sdiodev->func[1]);
+--			}
+-+			brcmf_sdio_bus_sleep(bus, true, false);
+-+			sdio_release_host(bus->sdiodev->func[1]);
+- 		}
+-+	} else {
+-+		bus->idlecount = 0;
+- 	}
+--
+--	return (atomic_read(&bus->ipend) > 0);
+- }
+- 
+- static void brcmf_sdio_dataworker(struct work_struct *work)
+-@@ -3651,8 +3629,11 @@ static void brcmf_sdio_dataworker(struct
+- 					      datawork);
+- 
+- 	while (atomic_read(&bus->dpc_tskcnt)) {
+-+		atomic_set(&bus->dpc_running, 1);
+- 		atomic_set(&bus->dpc_tskcnt, 0);
+- 		brcmf_sdio_dpc(bus);
+-+		bus->idlecount = 0;
+-+		atomic_set(&bus->dpc_running, 0);
+- 	}
+- 	if (brcmf_sdiod_freezing(bus->sdiodev)) {
+- 		brcmf_sdiod_change_state(bus->sdiodev, BRCMF_SDIOD_DOWN);
+-@@ -4154,6 +4135,7 @@ struct brcmf_sdio *brcmf_sdio_probe(stru
+- 	}
+- 	/* Initialize DPC thread */
+- 	atomic_set(&bus->dpc_tskcnt, 0);
+-+	atomic_set(&bus->dpc_running, 0);
+- 
+- 	/* Assign bus interface call back */
+- 	bus->sdiodev->bus_if->dev = bus->sdiodev->dev;
+diff --git a/package/kernel/mac80211/patches/337-brcmfmac-Fix-possible-race-condition.patch b/package/kernel/mac80211/patches/337-brcmfmac-Fix-possible-race-condition.patch
+deleted file mode 100644
+index 3a2de7a..0000000
+--- a/package/kernel/mac80211/patches/337-brcmfmac-Fix-possible-race-condition.patch
++++ /dev/null
+@@ -1,83 +0,0 @@
+-From: Hante Meuleman <meuleman@broadcom.com>
+-Date: Fri, 6 Mar 2015 18:40:40 +0100
+-Subject: [PATCH] brcmfmac: Fix possible race-condition.
+-
+-SDIO is using a "shared" variable to handoff ctl frames to DPC
+-and to see when they are done. In a timeout situation this can
+-lead to erroneous situation where DPC started to handle the ctl
+-frame while the timeout expired. This patch will fix this by
+-adding locking around the shared variable.
+-
+-Reviewed-by: Arend Van Spriel <arend@broadcom.com>
+-Reviewed-by: Franky (Zhenhui) Lin <frankyl@broadcom.com>
+-Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
+-Reviewed-by: Daniel (Deognyoun) Kim <dekim@broadcom.com>
+-Signed-off-by: Hante Meuleman <meuleman@broadcom.com>
+-Signed-off-by: Arend van Spriel <arend@broadcom.com>
+-Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
+----
+-
+---- a/drivers/net/wireless/brcm80211/brcmfmac/sdio.c
+-+++ b/drivers/net/wireless/brcm80211/brcmfmac/sdio.c
+-@@ -2700,11 +2700,13 @@ static void brcmf_sdio_dpc(struct brcmf_
+- 	if (bus->ctrl_frame_stat && (bus->clkstate == CLK_AVAIL) &&
+- 	    data_ok(bus)) {
+- 		sdio_claim_host(bus->sdiodev->func[1]);
+--		err = brcmf_sdio_tx_ctrlframe(bus,  bus->ctrl_frame_buf,
+--					      bus->ctrl_frame_len);
+-+		if (bus->ctrl_frame_stat) {
+-+			err = brcmf_sdio_tx_ctrlframe(bus,  bus->ctrl_frame_buf,
+-+						      bus->ctrl_frame_len);
+-+			bus->ctrl_frame_err = err;
+-+			bus->ctrl_frame_stat = false;
+-+		}
+- 		sdio_release_host(bus->sdiodev->func[1]);
+--		bus->ctrl_frame_err = err;
+--		bus->ctrl_frame_stat = false;
+- 		brcmf_sdio_wait_event_wakeup(bus);
+- 	}
+- 	/* Send queued frames (limit 1 if rx may still be pending) */
+-@@ -2720,9 +2722,13 @@ static void brcmf_sdio_dpc(struct brcmf_
+- 		brcmf_err("failed backplane access over SDIO, halting operation\n");
+- 		atomic_set(&bus->intstatus, 0);
+- 		if (bus->ctrl_frame_stat) {
+--			bus->ctrl_frame_err = -ENODEV;
+--			bus->ctrl_frame_stat = false;
+--			brcmf_sdio_wait_event_wakeup(bus);
+-+			sdio_claim_host(bus->sdiodev->func[1]);
+-+			if (bus->ctrl_frame_stat) {
+-+				bus->ctrl_frame_err = -ENODEV;
+-+				bus->ctrl_frame_stat = false;
+-+				brcmf_sdio_wait_event_wakeup(bus);
+-+			}
+-+			sdio_release_host(bus->sdiodev->func[1]);
+- 		}
+- 	} else if (atomic_read(&bus->intstatus) ||
+- 		   atomic_read(&bus->ipend) > 0 ||
+-@@ -2930,15 +2936,20 @@ brcmf_sdio_bus_txctl(struct device *dev,
+- 	brcmf_sdio_trigger_dpc(bus);
+- 	wait_event_interruptible_timeout(bus->ctrl_wait, !bus->ctrl_frame_stat,
+- 					 msecs_to_jiffies(CTL_DONE_TIMEOUT));
+--
+--	if (!bus->ctrl_frame_stat) {
+-+	ret = 0;
+-+	if (bus->ctrl_frame_stat) {
+-+		sdio_claim_host(bus->sdiodev->func[1]);
+-+		if (bus->ctrl_frame_stat) {
+-+			brcmf_dbg(SDIO, "ctrl_frame timeout\n");
+-+			bus->ctrl_frame_stat = false;
+-+			ret = -ETIMEDOUT;
+-+		}
+-+		sdio_release_host(bus->sdiodev->func[1]);
+-+	}
+-+	if (!ret) {
+- 		brcmf_dbg(SDIO, "ctrl_frame complete, err=%d\n",
+- 			  bus->ctrl_frame_err);
+- 		ret = bus->ctrl_frame_err;
+--	} else {
+--		brcmf_dbg(SDIO, "ctrl_frame timeout\n");
+--		bus->ctrl_frame_stat = false;
+--		ret = -ETIMEDOUT;
+- 	}
+- 
+- 	if (ret)
+diff --git a/package/kernel/mac80211/patches/337-nl80211-put-current-TX-power-in-interface-info.patch b/package/kernel/mac80211/patches/337-nl80211-put-current-TX-power-in-interface-info.patch
+new file mode 100644
+index 0000000..df2cc4b
+--- /dev/null
++++ b/package/kernel/mac80211/patches/337-nl80211-put-current-TX-power-in-interface-info.patch
+@@ -0,0 +1,37 @@
++From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <zajec5@gmail.com>
++Date: Mon, 31 Aug 2015 22:59:38 +0200
++Subject: [PATCH] nl80211: put current TX power in interface info
++MIME-Version: 1.0
++Content-Type: text/plain; charset=UTF-8
++Content-Transfer-Encoding: 8bit
++
++Many drivers implement reading current TX power (using either cfg80211
++or ieee80211 op) but userspace can't get it using nl80211. Right now the
++only way to access it is to call some wext ioctl.
++Let's put TX power in interface info reply (callback is wdev specific)
++just like we do with current channel.
++To be consistent (e.g. NL80211_CMD_SET_WIPHY) let's use mBm as na unit.
++
++Signed-off-by: Rafał Miłecki <zajec5@gmail.com>
++Signed-off-by: Johannes Berg <johannes.berg@intel.com>
++---
++
++--- a/net/wireless/nl80211.c
+++++ b/net/wireless/nl80211.c
++@@ -2406,6 +2406,16 @@ static int nl80211_send_iface(struct sk_
++ 		}
++ 	}
++ 
+++	if (rdev->ops->get_tx_power) {
+++		int dbm, ret;
+++
+++		ret = rdev_get_tx_power(rdev, wdev, &dbm);
+++		if (ret == 0 &&
+++		    nla_put_u32(msg, NL80211_ATTR_WIPHY_TX_POWER_LEVEL,
+++				DBM_TO_MBM(dbm)))
+++			goto nla_put_failure;
+++	}
+++
++ 	if (wdev->ssid_len) {
++ 		if (nla_put(msg, NL80211_ATTR_SSID, wdev->ssid_len, wdev->ssid))
++ 			goto nla_put_failure;
+diff --git a/package/kernel/mac80211/patches/338-brcmfmac-Add-support-for-BCM4345-SDIO-chipset.patch b/package/kernel/mac80211/patches/338-brcmfmac-Add-support-for-BCM4345-SDIO-chipset.patch
+deleted file mode 100644
+index c9eb900..0000000
+--- a/package/kernel/mac80211/patches/338-brcmfmac-Add-support-for-BCM4345-SDIO-chipset.patch
++++ /dev/null
+@@ -1,86 +0,0 @@
+-From: Syed Asifful Dayyan <syedd@broadcom.com>
+-Date: Fri, 6 Mar 2015 18:40:42 +0100
+-Subject: [PATCH] brcmfmac: Add support for BCM4345 SDIO chipset.
+-
+-These changes add support for BCM4345 SDIO chipset.
+-
+-Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
+-Reviewed-by: Arend Van Spriel <arend@broadcom.com>
+-Reviewed-by: Hante Meuleman <meuleman@broadcom.com>
+-Reviewed-by: Daniel (Deognyoun) Kim <dekim@broadcom.com>
+-Signed-off-by: Syed Asifful Dayyan <syedd@broadcom.com>
+-Signed-off-by: Arend van Spriel <arend@broadcom.com>
+-Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
+----
+-
+---- a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c
+-+++ b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c
+-@@ -1096,6 +1096,7 @@ static const struct sdio_device_id brcmf
+- 	BRCMF_SDIO_DEVICE(SDIO_DEVICE_ID_BROADCOM_43341),
+- 	BRCMF_SDIO_DEVICE(SDIO_DEVICE_ID_BROADCOM_43362),
+- 	BRCMF_SDIO_DEVICE(SDIO_DEVICE_ID_BROADCOM_4335_4339),
+-+	BRCMF_SDIO_DEVICE(SDIO_DEVICE_ID_BROADCOM_4345),
+- 	BRCMF_SDIO_DEVICE(SDIO_DEVICE_ID_BROADCOM_4354),
+- 	{ /* end: all zeroes */ }
+- };
+---- a/drivers/net/wireless/brcm80211/brcmfmac/chip.c
+-+++ b/drivers/net/wireless/brcm80211/brcmfmac/chip.c
+-@@ -491,6 +491,10 @@ static void brcmf_chip_get_raminfo(struc
+- 	case BRCM_CC_43362_CHIP_ID:
+- 		ci->pub.ramsize = 0x3c000;
+- 		break;
+-+	case BRCM_CC_4345_CHIP_ID:
+-+		ci->pub.ramsize = 0xc8000;
+-+		ci->pub.rambase = 0x198000;
+-+		break;
+- 	case BRCM_CC_4339_CHIP_ID:
+- 	case BRCM_CC_4354_CHIP_ID:
+- 	case BRCM_CC_4356_CHIP_ID:
+---- a/drivers/net/wireless/brcm80211/brcmfmac/sdio.c
+-+++ b/drivers/net/wireless/brcm80211/brcmfmac/sdio.c
+-@@ -617,6 +617,8 @@ static const struct sdiod_drive_str sdio
+- #define BCM43362_NVRAM_NAME		"brcm/brcmfmac43362-sdio.txt"
+- #define BCM4339_FIRMWARE_NAME		"brcm/brcmfmac4339-sdio.bin"
+- #define BCM4339_NVRAM_NAME		"brcm/brcmfmac4339-sdio.txt"
+-+#define BCM4345_FIRMWARE_NAME		"brcm/brcmfmac4345-sdio.bin"
+-+#define BCM4345_NVRAM_NAME		"brcm/brcmfmac4345-sdio.txt"
+- #define BCM4354_FIRMWARE_NAME		"brcm/brcmfmac4354-sdio.bin"
+- #define BCM4354_NVRAM_NAME		"brcm/brcmfmac4354-sdio.txt"
+- 
+-@@ -640,6 +642,8 @@ MODULE_FIRMWARE(BCM43362_FIRMWARE_NAME);
+- MODULE_FIRMWARE(BCM43362_NVRAM_NAME);
+- MODULE_FIRMWARE(BCM4339_FIRMWARE_NAME);
+- MODULE_FIRMWARE(BCM4339_NVRAM_NAME);
+-+MODULE_FIRMWARE(BCM4345_FIRMWARE_NAME);
+-+MODULE_FIRMWARE(BCM4345_NVRAM_NAME);
+- MODULE_FIRMWARE(BCM4354_FIRMWARE_NAME);
+- MODULE_FIRMWARE(BCM4354_NVRAM_NAME);
+- 
+-@@ -669,6 +673,7 @@ static const struct brcmf_firmware_names
+- 	{ BRCM_CC_4335_CHIP_ID, 0xFFFFFFFF, BRCMF_FIRMWARE_NVRAM(BCM4335) },
+- 	{ BRCM_CC_43362_CHIP_ID, 0xFFFFFFFE, BRCMF_FIRMWARE_NVRAM(BCM43362) },
+- 	{ BRCM_CC_4339_CHIP_ID, 0xFFFFFFFF, BRCMF_FIRMWARE_NVRAM(BCM4339) },
+-+	{ BRCM_CC_4345_CHIP_ID, 0xFFFFFFFF, BRCMF_FIRMWARE_NVRAM(BCM4345) },
+- 	{ BRCM_CC_4354_CHIP_ID, 0xFFFFFFFF, BRCMF_FIRMWARE_NVRAM(BCM4354) }
+- };
+- 
+---- a/drivers/net/wireless/brcm80211/include/brcm_hw_ids.h
+-+++ b/drivers/net/wireless/brcm80211/include/brcm_hw_ids.h
+-@@ -37,6 +37,7 @@
+- #define BRCM_CC_43362_CHIP_ID		43362
+- #define BRCM_CC_4335_CHIP_ID		0x4335
+- #define BRCM_CC_4339_CHIP_ID		0x4339
+-+#define BRCM_CC_4345_CHIP_ID		0x4345
+- #define BRCM_CC_4354_CHIP_ID		0x4354
+- #define BRCM_CC_4356_CHIP_ID		0x4356
+- #define BRCM_CC_43566_CHIP_ID		43566
+---- a/include/linux/mmc/sdio_ids.h
+-+++ b/include/linux/mmc/sdio_ids.h
+-@@ -33,6 +33,7 @@
+- #define SDIO_DEVICE_ID_BROADCOM_43341		0xa94d
+- #define SDIO_DEVICE_ID_BROADCOM_4335_4339	0x4335
+- #define SDIO_DEVICE_ID_BROADCOM_43362		0xa962
+-+#define SDIO_DEVICE_ID_BROADCOM_4345		0x4345
+- #define SDIO_DEVICE_ID_BROADCOM_4354		0x4354
+- 
+- #define SDIO_VENDOR_ID_INTEL			0x0089
+diff --git a/package/kernel/mac80211/patches/338-mac80211-initialize-tid-field-in-struct-ieee80211_tx.patch b/package/kernel/mac80211/patches/338-mac80211-initialize-tid-field-in-struct-ieee80211_tx.patch
+new file mode 100644
+index 0000000..2f492e0
+--- /dev/null
++++ b/package/kernel/mac80211/patches/338-mac80211-initialize-tid-field-in-struct-ieee80211_tx.patch
+@@ -0,0 +1,21 @@
++From: Felix Fietkau <nbd@openwrt.org>
++Date: Mon, 5 Oct 2015 17:41:25 +0200
++Subject: [PATCH] mac80211: initialize tid field in struct ieee80211_txq
++
++Signed-off-by: Felix Fietkau <nbd@openwrt.org>
++---
++
++--- a/net/mac80211/util.c
+++++ b/net/mac80211/util.c
++@@ -3288,9 +3288,11 @@ void ieee80211_init_tx_queue(struct ieee
++ 	if (sta) {
++ 		txqi->txq.sta = &sta->sta;
++ 		sta->sta.txq[tid] = &txqi->txq;
+++		txqi->txq.tid = tid;
++ 		txqi->txq.ac = ieee802_1d_to_ac[tid & 7];
++ 	} else {
++ 		sdata->vif.txq = &txqi->txq;
+++		txqi->txq.tid = 0;
++ 		txqi->txq.ac = IEEE80211_AC_BE;
++ 	}
++ }
+diff --git a/package/kernel/mac80211/patches/339-brcmfmac-remove-duplication-of-ramsize-info.patch b/package/kernel/mac80211/patches/339-brcmfmac-remove-duplication-of-ramsize-info.patch
+deleted file mode 100644
+index 7a688c4..0000000
+--- a/package/kernel/mac80211/patches/339-brcmfmac-remove-duplication-of-ramsize-info.patch
++++ /dev/null
+@@ -1,48 +0,0 @@
+-From: Arend van Spriel <arend@broadcom.com>
+-Date: Wed, 11 Mar 2015 16:11:27 +0100
+-Subject: [PATCH] brcmfmac: remove duplication of ramsize info
+-
+-Removing the ramsize from the brcmf_sdio structure to avoid
+-duplication. The information is available in brcmf_chip
+-structure.
+-
+-Reviewed-by: Hante Meuleman <meuleman@broadcom.com>
+-Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
+-Signed-off-by: Arend van Spriel <arend@broadcom.com>
+-Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
+----
+-
+---- a/drivers/net/wireless/brcm80211/brcmfmac/sdio.c
+-+++ b/drivers/net/wireless/brcm80211/brcmfmac/sdio.c
+-@@ -432,8 +432,6 @@ struct brcmf_sdio {
+- 	struct brcmf_sdio_dev *sdiodev;	/* sdio device handler */
+- 	struct brcmf_chip *ci;	/* Chip info struct */
+- 
+--	u32 ramsize;		/* Size of RAM in SOCRAM (bytes) */
+--
+- 	u32 hostintmask;	/* Copy of Host Interrupt Mask */
+- 	atomic_t intstatus;	/* Intstatus bits (events) pending */
+- 	atomic_t fcstate;	/* State of dongle flow-control */
+-@@ -1075,7 +1073,7 @@ static int brcmf_sdio_readshared(struct
+- 	struct sdpcm_shared_le sh_le;
+- 	__le32 addr_le;
+- 
+--	shaddr = bus->ci->rambase + bus->ramsize - 4;
+-+	shaddr = bus->ci->rambase + bus->ci->ramsize - 4;
+- 
+- 	/*
+- 	 * Read last word in socram to determine
+-@@ -3871,13 +3869,6 @@ brcmf_sdio_probe_attach(struct brcmf_sdi
+- 		drivestrength = DEFAULT_SDIO_DRIVE_STRENGTH;
+- 	brcmf_sdio_drivestrengthinit(bus->sdiodev, bus->ci, drivestrength);
+- 
+--	/* Get info on the SOCRAM cores... */
+--	bus->ramsize = bus->ci->ramsize;
+--	if (!(bus->ramsize)) {
+--		brcmf_err("failed to find SOCRAM memory!\n");
+--		goto fail;
+--	}
+--
+- 	/* Set card control so an SDIO card reset does a WLAN backplane reset */
+- 	reg_val = brcmf_sdiod_regrb(bus->sdiodev,
+- 				    SDIO_CCCR_BRCM_CARDCTRL, &err);
+diff --git a/package/kernel/mac80211/patches/340-brcmfmac-always-perform-cores-checks.patch b/package/kernel/mac80211/patches/340-brcmfmac-always-perform-cores-checks.patch
+deleted file mode 100644
+index e2a2074..0000000
+--- a/package/kernel/mac80211/patches/340-brcmfmac-always-perform-cores-checks.patch
++++ /dev/null
+@@ -1,74 +0,0 @@
+-From: Arend van Spriel <arend@broadcom.com>
+-Date: Wed, 11 Mar 2015 16:11:28 +0100
+-Subject: [PATCH] brcmfmac: always perform cores checks
+-
+-Instead of checking the cores in the chip only if CONFIG_BRCMDBG
+-is selected perform the check always and extend it with more sanity
+-checking.
+-
+-Reviewed-by: Hante Meuleman <meuleman@broadcom.com>
+-Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
+-Signed-off-by: Arend van Spriel <arend@broadcom.com>
+-Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
+----
+-
+---- a/drivers/net/wireless/brcm80211/brcmfmac/chip.c
+-+++ b/drivers/net/wireless/brcm80211/brcmfmac/chip.c
+-@@ -419,13 +419,13 @@ static struct brcmf_core *brcmf_chip_add
+- 	return &core->pub;
+- }
+- 
+--#ifdef DEBUG
+- /* safety check for chipinfo */
+- static int brcmf_chip_cores_check(struct brcmf_chip_priv *ci)
+- {
+- 	struct brcmf_core_priv *core;
+- 	bool need_socram = false;
+- 	bool has_socram = false;
+-+	bool cpu_found = false;
+- 	int idx = 1;
+- 
+- 	list_for_each_entry(core, &ci->cores, list) {
+-@@ -435,12 +435,14 @@ static int brcmf_chip_cores_check(struct
+- 
+- 		switch (core->pub.id) {
+- 		case BCMA_CORE_ARM_CM3:
+-+			cpu_found = true;
+- 			need_socram = true;
+- 			break;
+- 		case BCMA_CORE_INTERNAL_MEM:
+- 			has_socram = true;
+- 			break;
+- 		case BCMA_CORE_ARM_CR4:
+-+			cpu_found = true;
+- 			if (ci->pub.rambase == 0) {
+- 				brcmf_err("RAM base not provided with ARM CR4 core\n");
+- 				return -ENOMEM;
+-@@ -451,19 +453,21 @@ static int brcmf_chip_cores_check(struct
+- 		}
+- 	}
+- 
+-+	if (!cpu_found) {
+-+		brcmf_err("CPU core not detected\n");
+-+		return -ENXIO;
+-+	}
+- 	/* check RAM core presence for ARM CM3 core */
+- 	if (need_socram && !has_socram) {
+- 		brcmf_err("RAM core not provided with ARM CM3 core\n");
+- 		return -ENODEV;
+- 	}
+-+	if (!ci->pub.ramsize) {
+-+		brcmf_err("RAM size is undetermined\n");
+-+		return -ENOMEM;
+-+	}
+- 	return 0;
+- }
+--#else	/* DEBUG */
+--static inline int brcmf_chip_cores_check(struct brcmf_chip_priv *ci)
+--{
+--	return 0;
+--}
+--#endif
+- 
+- static void brcmf_chip_get_raminfo(struct brcmf_chip_priv *ci)
+- {
+diff --git a/package/kernel/mac80211/patches/341-brcmfmac-rename-chip-download-functions.patch b/package/kernel/mac80211/patches/341-brcmfmac-rename-chip-download-functions.patch
+deleted file mode 100644
+index a272800..0000000
+--- a/package/kernel/mac80211/patches/341-brcmfmac-rename-chip-download-functions.patch
++++ /dev/null
+@@ -1,240 +0,0 @@
+-From: Arend van Spriel <arend@broadcom.com>
+-Date: Wed, 11 Mar 2015 16:11:29 +0100
+-Subject: [PATCH] brcmfmac: rename chip download functions
+-
+-The functions brcmf_chip_[enter/exit]_download() are not exclusively
+-used for firmware download so rename these more appropriate.
+-
+-Reviewed-by: Hante Meuleman <meuleman@broadcom.com>
+-Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
+-Signed-off-by: Arend van Spriel <arend@broadcom.com>
+-Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
+----
+-
+---- a/drivers/net/wireless/brcm80211/brcmfmac/chip.c
+-+++ b/drivers/net/wireless/brcm80211/brcmfmac/chip.c
+-@@ -807,7 +807,7 @@ struct brcmf_chip *brcmf_chip_attach(voi
+- 		err = -EINVAL;
+- 	if (WARN_ON(!ops->prepare))
+- 		err = -EINVAL;
+--	if (WARN_ON(!ops->exit_dl))
+-+	if (WARN_ON(!ops->activate))
+- 		err = -EINVAL;
+- 	if (err < 0)
+- 		return ERR_PTR(-EINVAL);
+-@@ -905,7 +905,7 @@ void brcmf_chip_resetcore(struct brcmf_c
+- }
+- 
+- static void
+--brcmf_chip_cm3_enterdl(struct brcmf_chip_priv *chip)
+-+brcmf_chip_cm3_set_passive(struct brcmf_chip_priv *chip)
+- {
+- 	struct brcmf_core *core;
+- 
+-@@ -919,7 +919,7 @@ brcmf_chip_cm3_enterdl(struct brcmf_chip
+- 	brcmf_chip_resetcore(core, 0, 0, 0);
+- }
+- 
+--static bool brcmf_chip_cm3_exitdl(struct brcmf_chip_priv *chip)
+-+static bool brcmf_chip_cm3_set_active(struct brcmf_chip_priv *chip)
+- {
+- 	struct brcmf_core *core;
+- 
+-@@ -929,7 +929,7 @@ static bool brcmf_chip_cm3_exitdl(struct
+- 		return false;
+- 	}
+- 
+--	chip->ops->exit_dl(chip->ctx, &chip->pub, 0);
+-+	chip->ops->activate(chip->ctx, &chip->pub, 0);
+- 
+- 	core = brcmf_chip_get_core(&chip->pub, BCMA_CORE_ARM_CM3);
+- 	brcmf_chip_resetcore(core, 0, 0, 0);
+-@@ -938,7 +938,7 @@ static bool brcmf_chip_cm3_exitdl(struct
+- }
+- 
+- static inline void
+--brcmf_chip_cr4_enterdl(struct brcmf_chip_priv *chip)
+-+brcmf_chip_cr4_set_passive(struct brcmf_chip_priv *chip)
+- {
+- 	struct brcmf_core *core;
+- 
+-@@ -951,11 +951,11 @@ brcmf_chip_cr4_enterdl(struct brcmf_chip
+- 			     D11_BCMA_IOCTL_PHYCLOCKEN);
+- }
+- 
+--static bool brcmf_chip_cr4_exitdl(struct brcmf_chip_priv *chip, u32 rstvec)
+-+static bool brcmf_chip_cr4_set_active(struct brcmf_chip_priv *chip, u32 rstvec)
+- {
+- 	struct brcmf_core *core;
+- 
+--	chip->ops->exit_dl(chip->ctx, &chip->pub, rstvec);
+-+	chip->ops->activate(chip->ctx, &chip->pub, rstvec);
+- 
+- 	/* restore ARM */
+- 	core = brcmf_chip_get_core(&chip->pub, BCMA_CORE_ARM_CR4);
+-@@ -964,7 +964,7 @@ static bool brcmf_chip_cr4_exitdl(struct
+- 	return true;
+- }
+- 
+--void brcmf_chip_enter_download(struct brcmf_chip *pub)
+-+void brcmf_chip_set_passive(struct brcmf_chip *pub)
+- {
+- 	struct brcmf_chip_priv *chip;
+- 	struct brcmf_core *arm;
+-@@ -974,14 +974,14 @@ void brcmf_chip_enter_download(struct br
+- 	chip = container_of(pub, struct brcmf_chip_priv, pub);
+- 	arm = brcmf_chip_get_core(pub, BCMA_CORE_ARM_CR4);
+- 	if (arm) {
+--		brcmf_chip_cr4_enterdl(chip);
+-+		brcmf_chip_cr4_set_passive(chip);
+- 		return;
+- 	}
+- 
+--	brcmf_chip_cm3_enterdl(chip);
+-+	brcmf_chip_cm3_set_passive(chip);
+- }
+- 
+--bool brcmf_chip_exit_download(struct brcmf_chip *pub, u32 rstvec)
+-+bool brcmf_chip_set_active(struct brcmf_chip *pub, u32 rstvec)
+- {
+- 	struct brcmf_chip_priv *chip;
+- 	struct brcmf_core *arm;
+-@@ -991,9 +991,9 @@ bool brcmf_chip_exit_download(struct brc
+- 	chip = container_of(pub, struct brcmf_chip_priv, pub);
+- 	arm = brcmf_chip_get_core(pub, BCMA_CORE_ARM_CR4);
+- 	if (arm)
+--		return brcmf_chip_cr4_exitdl(chip, rstvec);
+-+		return brcmf_chip_cr4_set_active(chip, rstvec);
+- 
+--	return brcmf_chip_cm3_exitdl(chip);
+-+	return brcmf_chip_cm3_set_active(chip);
+- }
+- 
+- bool brcmf_chip_sr_capable(struct brcmf_chip *pub)
+---- a/drivers/net/wireless/brcm80211/brcmfmac/chip.h
+-+++ b/drivers/net/wireless/brcm80211/brcmfmac/chip.h
+-@@ -64,7 +64,7 @@ struct brcmf_core {
+-  * @write32: write 32-bit value over bus.
+-  * @prepare: prepare bus for core configuration.
+-  * @setup: bus-specific core setup.
+-- * @exit_dl: exit download state.
+-+ * @active: chip becomes active.
+-  *	The callback should use the provided @rstvec when non-zero.
+-  */
+- struct brcmf_buscore_ops {
+-@@ -72,7 +72,7 @@ struct brcmf_buscore_ops {
+- 	void (*write32)(void *ctx, u32 addr, u32 value);
+- 	int (*prepare)(void *ctx);
+- 	int (*setup)(void *ctx, struct brcmf_chip *chip);
+--	void (*exit_dl)(void *ctx, struct brcmf_chip *chip, u32 rstvec);
+-+	void (*activate)(void *ctx, struct brcmf_chip *chip, u32 rstvec);
+- };
+- 
+- struct brcmf_chip *brcmf_chip_attach(void *ctx,
+-@@ -84,8 +84,8 @@ bool brcmf_chip_iscoreup(struct brcmf_co
+- void brcmf_chip_coredisable(struct brcmf_core *core, u32 prereset, u32 reset);
+- void brcmf_chip_resetcore(struct brcmf_core *core, u32 prereset, u32 reset,
+- 			  u32 postreset);
+--void brcmf_chip_enter_download(struct brcmf_chip *ci);
+--bool brcmf_chip_exit_download(struct brcmf_chip *ci, u32 rstvec);
+-+void brcmf_chip_set_passive(struct brcmf_chip *ci);
+-+bool brcmf_chip_set_active(struct brcmf_chip *ci, u32 rstvec);
+- bool brcmf_chip_sr_capable(struct brcmf_chip *pub);
+- 
+- #endif /* BRCMF_AXIDMP_H */
+---- a/drivers/net/wireless/brcm80211/brcmfmac/pcie.c
+-+++ b/drivers/net/wireless/brcm80211/brcmfmac/pcie.c
+-@@ -509,7 +509,7 @@ static void brcmf_pcie_attach(struct brc
+- 
+- static int brcmf_pcie_enter_download_state(struct brcmf_pciedev_info *devinfo)
+- {
+--	brcmf_chip_enter_download(devinfo->ci);
+-+	brcmf_chip_set_passive(devinfo->ci);
+- 
+- 	if (devinfo->ci->chip == BRCM_CC_43602_CHIP_ID) {
+- 		brcmf_pcie_select_core(devinfo, BCMA_CORE_ARM_CR4);
+-@@ -536,7 +536,7 @@ static int brcmf_pcie_exit_download_stat
+- 		brcmf_chip_resetcore(core, 0, 0, 0);
+- 	}
+- 
+--	return !brcmf_chip_exit_download(devinfo->ci, resetintr);
+-+	return !brcmf_chip_set_active(devinfo->ci, resetintr);
+- }
+- 
+- 
+-@@ -1566,8 +1566,8 @@ static int brcmf_pcie_buscoreprep(void *
+- }
+- 
+- 
+--static void brcmf_pcie_buscore_exitdl(void *ctx, struct brcmf_chip *chip,
+--				      u32 rstvec)
+-+static void brcmf_pcie_buscore_activate(void *ctx, struct brcmf_chip *chip,
+-+					u32 rstvec)
+- {
+- 	struct brcmf_pciedev_info *devinfo = (struct brcmf_pciedev_info *)ctx;
+- 
+-@@ -1577,7 +1577,7 @@ static void brcmf_pcie_buscore_exitdl(vo
+- 
+- static const struct brcmf_buscore_ops brcmf_pcie_buscore_ops = {
+- 	.prepare = brcmf_pcie_buscoreprep,
+--	.exit_dl = brcmf_pcie_buscore_exitdl,
+-+	.activate = brcmf_pcie_buscore_activate,
+- 	.read32 = brcmf_pcie_buscore_read32,
+- 	.write32 = brcmf_pcie_buscore_write32,
+- };
+---- a/drivers/net/wireless/brcm80211/brcmfmac/sdio.c
+-+++ b/drivers/net/wireless/brcm80211/brcmfmac/sdio.c
+-@@ -3357,7 +3357,7 @@ static int brcmf_sdio_download_firmware(
+- 	brcmf_sdio_clkctl(bus, CLK_AVAIL, false);
+- 
+- 	/* Keep arm in reset */
+--	brcmf_chip_enter_download(bus->ci);
+-+	brcmf_chip_set_passive(bus->ci);
+- 
+- 	rstvec = get_unaligned_le32(fw->data);
+- 	brcmf_dbg(SDIO, "firmware rstvec: %x\n", rstvec);
+-@@ -3378,7 +3378,7 @@ static int brcmf_sdio_download_firmware(
+- 	}
+- 
+- 	/* Take arm out of reset */
+--	if (!brcmf_chip_exit_download(bus->ci, rstvec)) {
+-+	if (!brcmf_chip_set_active(bus->ci, rstvec)) {
+- 		brcmf_err("error getting out of ARM core reset\n");
+- 		goto err;
+- 	}
+-@@ -3771,8 +3771,8 @@ static int brcmf_sdio_buscoreprep(void *
+- 	return 0;
+- }
+- 
+--static void brcmf_sdio_buscore_exitdl(void *ctx, struct brcmf_chip *chip,
+--				      u32 rstvec)
+-+static void brcmf_sdio_buscore_activate(void *ctx, struct brcmf_chip *chip,
+-+					u32 rstvec)
+- {
+- 	struct brcmf_sdio_dev *sdiodev = ctx;
+- 	struct brcmf_core *core;
+-@@ -3815,7 +3815,7 @@ static void brcmf_sdio_buscore_write32(v
+- 
+- static const struct brcmf_buscore_ops brcmf_sdio_buscore_ops = {
+- 	.prepare = brcmf_sdio_buscoreprep,
+--	.exit_dl = brcmf_sdio_buscore_exitdl,
+-+	.activate = brcmf_sdio_buscore_activate,
+- 	.read32 = brcmf_sdio_buscore_read32,
+- 	.write32 = brcmf_sdio_buscore_write32,
+- };
+-@@ -4239,12 +4239,11 @@ void brcmf_sdio_remove(struct brcmf_sdio
+- 				sdio_claim_host(bus->sdiodev->func[1]);
+- 				brcmf_sdio_clkctl(bus, CLK_AVAIL, false);
+- 				/* Leave the device in state where it is
+--				 * 'quiet'. This is done by putting it in
+--				 * download_state which essentially resets
+--				 * all necessary cores.
+-+				 * 'passive'. This is done by resetting all
+-+				 * necessary cores.
+- 				 */
+- 				msleep(20);
+--				brcmf_chip_enter_download(bus->ci);
+-+				brcmf_chip_set_passive(bus->ci);
+- 				brcmf_sdio_clkctl(bus, CLK_NONE, false);
+- 				sdio_release_host(bus->sdiodev->func[1]);
+- 			}
+diff --git a/package/kernel/mac80211/patches/342-brcmfmac-assure-device-is-ready-for-download-after-b.patch b/package/kernel/mac80211/patches/342-brcmfmac-assure-device-is-ready-for-download-after-b.patch
+deleted file mode 100644
+index 6b1dd81..0000000
+--- a/package/kernel/mac80211/patches/342-brcmfmac-assure-device-is-ready-for-download-after-b.patch
++++ /dev/null
+@@ -1,61 +0,0 @@
+-From: Arend van Spriel <arend@broadcom.com>
+-Date: Wed, 11 Mar 2015 16:11:30 +0100
+-Subject: [PATCH] brcmfmac: assure device is ready for download after
+- brcmf_chip_attach()
+-
+-Make the brcmf_chip_attach() function responsible for putting the
+-device in a state where it is accessible for firmware download.
+-
+-Reviewed-by: Hante Meuleman <meuleman@broadcom.com>
+-Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
+-Signed-off-by: Arend van Spriel <arend@broadcom.com>
+-Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
+----
+-
+---- a/drivers/net/wireless/brcm80211/brcmfmac/chip.c
+-+++ b/drivers/net/wireless/brcm80211/brcmfmac/chip.c
+-@@ -786,12 +786,6 @@ static int brcmf_chip_setup(struct brcmf
+- 	if (chip->ops->setup)
+- 		ret = chip->ops->setup(chip->ctx, pub);
+- 
+--	/*
+--	 * Make sure any on-chip ARM is off (in case strapping is wrong),
+--	 * or downloaded code was already running.
+--	 */
+--	brcmf_chip_disable_arm(chip, BCMA_CORE_ARM_CM3);
+--	brcmf_chip_disable_arm(chip, BCMA_CORE_ARM_CR4);
+- 	return ret;
+- }
+- 
+-@@ -833,6 +827,8 @@ struct brcmf_chip *brcmf_chip_attach(voi
+- 	if (err < 0)
+- 		goto fail;
+- 
+-+	/* assure chip is passive for download */
+-+	brcmf_chip_set_passive(&chip->pub);
+- 	return &chip->pub;
+- 
+- fail:
+---- a/drivers/net/wireless/brcm80211/brcmfmac/pcie.c
+-+++ b/drivers/net/wireless/brcm80211/brcmfmac/pcie.c
+-@@ -509,8 +509,6 @@ static void brcmf_pcie_attach(struct brc
+- 
+- static int brcmf_pcie_enter_download_state(struct brcmf_pciedev_info *devinfo)
+- {
+--	brcmf_chip_set_passive(devinfo->ci);
+--
+- 	if (devinfo->ci->chip == BRCM_CC_43602_CHIP_ID) {
+- 		brcmf_pcie_select_core(devinfo, BCMA_CORE_ARM_CR4);
+- 		brcmf_pcie_write_reg32(devinfo, BRCMF_PCIE_ARMCR4REG_BANKIDX,
+---- a/drivers/net/wireless/brcm80211/brcmfmac/sdio.c
+-+++ b/drivers/net/wireless/brcm80211/brcmfmac/sdio.c
+-@@ -3356,9 +3356,6 @@ static int brcmf_sdio_download_firmware(
+- 	sdio_claim_host(bus->sdiodev->func[1]);
+- 	brcmf_sdio_clkctl(bus, CLK_AVAIL, false);
+- 
+--	/* Keep arm in reset */
+--	brcmf_chip_set_passive(bus->ci);
+--
+- 	rstvec = get_unaligned_le32(fw->data);
+- 	brcmf_dbg(SDIO, "firmware rstvec: %x\n", rstvec);
+- 
+diff --git a/package/kernel/mac80211/patches/343-brcmfmac-extract-ram-size-info-from-internal-memory-.patch b/package/kernel/mac80211/patches/343-brcmfmac-extract-ram-size-info-from-internal-memory-.patch
+deleted file mode 100644
+index bcc2ed4..0000000
+--- a/package/kernel/mac80211/patches/343-brcmfmac-extract-ram-size-info-from-internal-memory-.patch
++++ /dev/null
+@@ -1,367 +0,0 @@
+-From: Arend van Spriel <arend@broadcom.com>
+-Date: Wed, 11 Mar 2015 16:11:31 +0100
+-Subject: [PATCH] brcmfmac: extract ram size info from internal memory
+- registers
+-
+-Instead of hard-coded memory sizes it is possible to obtain that
+-information from the internal memory registers.
+-
+-Reviewed-by: Hante Meuleman <meuleman@broadcom.com>
+-Reviewed-by: Franky (Zhenhui) Lin <frankyl@broadcom.com>
+-Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
+-Signed-off-by: Arend van Spriel <arend@broadcom.com>
+-Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
+----
+-
+---- a/drivers/net/wireless/brcm80211/brcmfmac/chip.c
+-+++ b/drivers/net/wireless/brcm80211/brcmfmac/chip.c
+-@@ -100,9 +100,6 @@
+- #define BCM4329_CORE_SOCRAM_BASE	0x18003000
+- /* ARM Cortex M3 core, ID 0x82a */
+- #define BCM4329_CORE_ARM_BASE		0x18002000
+--#define BCM4329_RAMSIZE			0x48000
+--/* bcm43143 */
+--#define BCM43143_RAMSIZE		0x70000
+- 
+- #define CORE_SB(base, field) \
+- 		(base + SBCONFIGOFF + offsetof(struct sbconfig, field))
+-@@ -150,6 +147,78 @@ struct sbconfig {
+- 	u32 sbidhigh;	/* identification */
+- };
+- 
+-+/* bankidx and bankinfo reg defines corerev >= 8 */
+-+#define SOCRAM_BANKINFO_RETNTRAM_MASK	0x00010000
+-+#define SOCRAM_BANKINFO_SZMASK		0x0000007f
+-+#define SOCRAM_BANKIDX_ROM_MASK		0x00000100
+-+
+-+#define SOCRAM_BANKIDX_MEMTYPE_SHIFT	8
+-+/* socram bankinfo memtype */
+-+#define SOCRAM_MEMTYPE_RAM		0
+-+#define SOCRAM_MEMTYPE_R0M		1
+-+#define SOCRAM_MEMTYPE_DEVRAM		2
+-+
+-+#define SOCRAM_BANKINFO_SZBASE		8192
+-+#define SRCI_LSS_MASK		0x00f00000
+-+#define SRCI_LSS_SHIFT		20
+-+#define	SRCI_SRNB_MASK		0xf0
+-+#define	SRCI_SRNB_SHIFT		4
+-+#define	SRCI_SRBSZ_MASK		0xf
+-+#define	SRCI_SRBSZ_SHIFT	0
+-+#define SR_BSZ_BASE		14
+-+
+-+struct sbsocramregs {
+-+	u32 coreinfo;
+-+	u32 bwalloc;
+-+	u32 extracoreinfo;
+-+	u32 biststat;
+-+	u32 bankidx;
+-+	u32 standbyctrl;
+-+
+-+	u32 errlogstatus;	/* rev 6 */
+-+	u32 errlogaddr;	/* rev 6 */
+-+	/* used for patching rev 3 & 5 */
+-+	u32 cambankidx;
+-+	u32 cambankstandbyctrl;
+-+	u32 cambankpatchctrl;
+-+	u32 cambankpatchtblbaseaddr;
+-+	u32 cambankcmdreg;
+-+	u32 cambankdatareg;
+-+	u32 cambankmaskreg;
+-+	u32 PAD[1];
+-+	u32 bankinfo;	/* corev 8 */
+-+	u32 bankpda;
+-+	u32 PAD[14];
+-+	u32 extmemconfig;
+-+	u32 extmemparitycsr;
+-+	u32 extmemparityerrdata;
+-+	u32 extmemparityerrcnt;
+-+	u32 extmemwrctrlandsize;
+-+	u32 PAD[84];
+-+	u32 workaround;
+-+	u32 pwrctl;		/* corerev >= 2 */
+-+	u32 PAD[133];
+-+	u32 sr_control;     /* corerev >= 15 */
+-+	u32 sr_status;      /* corerev >= 15 */
+-+	u32 sr_address;     /* corerev >= 15 */
+-+	u32 sr_data;        /* corerev >= 15 */
+-+};
+-+
+-+#define SOCRAMREGOFFS(_f)	offsetof(struct sbsocramregs, _f)
+-+
+-+#define ARMCR4_CAP		(0x04)
+-+#define ARMCR4_BANKIDX		(0x40)
+-+#define ARMCR4_BANKINFO		(0x44)
+-+#define ARMCR4_BANKPDA		(0x4C)
+-+
+-+#define	ARMCR4_TCBBNB_MASK	0xf0
+-+#define	ARMCR4_TCBBNB_SHIFT	4
+-+#define	ARMCR4_TCBANB_MASK	0xf
+-+#define	ARMCR4_TCBANB_SHIFT	0
+-+
+-+#define	ARMCR4_BSZ_MASK		0x3f
+-+#define	ARMCR4_BSZ_MULT		8192
+-+
+- struct brcmf_core_priv {
+- 	struct brcmf_core pub;
+- 	u32 wrapbase;
+-@@ -443,10 +512,6 @@ static int brcmf_chip_cores_check(struct
+- 			break;
+- 		case BCMA_CORE_ARM_CR4:
+- 			cpu_found = true;
+--			if (ci->pub.rambase == 0) {
+--				brcmf_err("RAM base not provided with ARM CR4 core\n");
+--				return -ENOMEM;
+--			}
+- 			break;
+- 		default:
+- 			break;
+-@@ -462,60 +527,160 @@ static int brcmf_chip_cores_check(struct
+- 		brcmf_err("RAM core not provided with ARM CM3 core\n");
+- 		return -ENODEV;
+- 	}
+--	if (!ci->pub.ramsize) {
+--		brcmf_err("RAM size is undetermined\n");
+--		return -ENOMEM;
+--	}
+- 	return 0;
+- }
+- 
+--static void brcmf_chip_get_raminfo(struct brcmf_chip_priv *ci)
+-+static u32 brcmf_chip_core_read32(struct brcmf_core_priv *core, u16 reg)
+- {
+--	switch (ci->pub.chip) {
+--	case BRCM_CC_4329_CHIP_ID:
+--		ci->pub.ramsize = BCM4329_RAMSIZE;
+--		break;
+--	case BRCM_CC_43143_CHIP_ID:
+--		ci->pub.ramsize = BCM43143_RAMSIZE;
+--		break;
+--	case BRCM_CC_43241_CHIP_ID:
+--		ci->pub.ramsize = 0x90000;
+--		break;
+--	case BRCM_CC_4330_CHIP_ID:
+--		ci->pub.ramsize = 0x48000;
+--		break;
+-+	return core->chip->ops->read32(core->chip->ctx, core->pub.base + reg);
+-+}
+-+
+-+static void brcmf_chip_core_write32(struct brcmf_core_priv *core,
+-+				    u16 reg, u32 val)
+-+{
+-+	core->chip->ops->write32(core->chip->ctx, core->pub.base + reg, val);
+-+}
+-+
+-+static bool brcmf_chip_socram_banksize(struct brcmf_core_priv *core, u8 idx,
+-+				       u32 *banksize)
+-+{
+-+	u32 bankinfo;
+-+	u32 bankidx = (SOCRAM_MEMTYPE_RAM << SOCRAM_BANKIDX_MEMTYPE_SHIFT);
+-+
+-+	bankidx |= idx;
+-+	brcmf_chip_core_write32(core, SOCRAMREGOFFS(bankidx), bankidx);
+-+	bankinfo = brcmf_chip_core_read32(core, SOCRAMREGOFFS(bankinfo));
+-+	*banksize = (bankinfo & SOCRAM_BANKINFO_SZMASK) + 1;
+-+	*banksize *= SOCRAM_BANKINFO_SZBASE;
+-+	return !!(bankinfo & SOCRAM_BANKINFO_RETNTRAM_MASK);
+-+}
+-+
+-+static void brcmf_chip_socram_ramsize(struct brcmf_core_priv *sr, u32 *ramsize,
+-+				      u32 *srsize)
+-+{
+-+	u32 coreinfo;
+-+	uint nb, banksize, lss;
+-+	bool retent;
+-+	int i;
+-+
+-+	*ramsize = 0;
+-+	*srsize = 0;
+-+
+-+	if (WARN_ON(sr->pub.rev < 4))
+-+		return;
+-+
+-+	if (!brcmf_chip_iscoreup(&sr->pub))
+-+		brcmf_chip_resetcore(&sr->pub, 0, 0, 0);
+-+
+-+	/* Get info for determining size */
+-+	coreinfo = brcmf_chip_core_read32(sr, SOCRAMREGOFFS(coreinfo));
+-+	nb = (coreinfo & SRCI_SRNB_MASK) >> SRCI_SRNB_SHIFT;
+-+
+-+	if ((sr->pub.rev <= 7) || (sr->pub.rev == 12)) {
+-+		banksize = (coreinfo & SRCI_SRBSZ_MASK);
+-+		lss = (coreinfo & SRCI_LSS_MASK) >> SRCI_LSS_SHIFT;
+-+		if (lss != 0)
+-+			nb--;
+-+		*ramsize = nb * (1 << (banksize + SR_BSZ_BASE));
+-+		if (lss != 0)
+-+			*ramsize += (1 << ((lss - 1) + SR_BSZ_BASE));
+-+	} else {
+-+		nb = (coreinfo & SRCI_SRNB_MASK) >> SRCI_SRNB_SHIFT;
+-+		for (i = 0; i < nb; i++) {
+-+			retent = brcmf_chip_socram_banksize(sr, i, &banksize);
+-+			*ramsize += banksize;
+-+			if (retent)
+-+				*srsize += banksize;
+-+		}
+-+	}
+-+
+-+	/* hardcoded save&restore memory sizes */
+-+	switch (sr->chip->pub.chip) {
+- 	case BRCM_CC_4334_CHIP_ID:
+--	case BRCM_CC_43340_CHIP_ID:
+--		ci->pub.ramsize = 0x80000;
+-+		if (sr->chip->pub.chiprev < 2)
+-+			*srsize = (32 * 1024);
+- 		break;
+--	case BRCM_CC_4335_CHIP_ID:
+--		ci->pub.ramsize = 0xc0000;
+--		ci->pub.rambase = 0x180000;
+--		break;
+--	case BRCM_CC_43362_CHIP_ID:
+--		ci->pub.ramsize = 0x3c000;
+-+	default:
+- 		break;
+-+	}
+-+}
+-+
+-+/** Return the TCM-RAM size of the ARMCR4 core. */
+-+static u32 brcmf_chip_tcm_ramsize(struct brcmf_core_priv *cr4)
+-+{
+-+	u32 corecap;
+-+	u32 memsize = 0;
+-+	u32 nab;
+-+	u32 nbb;
+-+	u32 totb;
+-+	u32 bxinfo;
+-+	u32 idx;
+-+
+-+	corecap = brcmf_chip_core_read32(cr4, ARMCR4_CAP);
+-+
+-+	nab = (corecap & ARMCR4_TCBANB_MASK) >> ARMCR4_TCBANB_SHIFT;
+-+	nbb = (corecap & ARMCR4_TCBBNB_MASK) >> ARMCR4_TCBBNB_SHIFT;
+-+	totb = nab + nbb;
+-+
+-+	for (idx = 0; idx < totb; idx++) {
+-+		brcmf_chip_core_write32(cr4, ARMCR4_BANKIDX, idx);
+-+		bxinfo = brcmf_chip_core_read32(cr4, ARMCR4_BANKINFO);
+-+		memsize += ((bxinfo & ARMCR4_BSZ_MASK) + 1) * ARMCR4_BSZ_MULT;
+-+	}
+-+
+-+	return memsize;
+-+}
+-+
+-+static u32 brcmf_chip_tcm_rambase(struct brcmf_chip_priv *ci)
+-+{
+-+	switch (ci->pub.chip) {
+- 	case BRCM_CC_4345_CHIP_ID:
+--		ci->pub.ramsize = 0xc8000;
+--		ci->pub.rambase = 0x198000;
+--		break;
+-+		return 0x198000;
+-+	case BRCM_CC_4335_CHIP_ID:
+- 	case BRCM_CC_4339_CHIP_ID:
+- 	case BRCM_CC_4354_CHIP_ID:
+- 	case BRCM_CC_4356_CHIP_ID:
+- 	case BRCM_CC_43567_CHIP_ID:
+- 	case BRCM_CC_43569_CHIP_ID:
+- 	case BRCM_CC_43570_CHIP_ID:
+--		ci->pub.ramsize = 0xc0000;
+--		ci->pub.rambase = 0x180000;
+--		break;
+- 	case BRCM_CC_43602_CHIP_ID:
+--		ci->pub.ramsize = 0xf0000;
+--		ci->pub.rambase = 0x180000;
+--		break;
+-+		return 0x180000;
+- 	default:
+- 		brcmf_err("unknown chip: %s\n", ci->pub.name);
+- 		break;
+- 	}
+-+	return 0;
+-+}
+-+
+-+static int brcmf_chip_get_raminfo(struct brcmf_chip_priv *ci)
+-+{
+-+	struct brcmf_core_priv *mem_core;
+-+	struct brcmf_core *mem;
+-+
+-+	mem = brcmf_chip_get_core(&ci->pub, BCMA_CORE_ARM_CR4);
+-+	if (mem) {
+-+		mem_core = container_of(mem, struct brcmf_core_priv, pub);
+-+		ci->pub.ramsize = brcmf_chip_tcm_ramsize(mem_core);
+-+		ci->pub.rambase = brcmf_chip_tcm_rambase(ci);
+-+		if (!ci->pub.rambase) {
+-+			brcmf_err("RAM base not provided with ARM CR4 core\n");
+-+			return -EINVAL;
+-+		}
+-+	} else {
+-+		mem = brcmf_chip_get_core(&ci->pub, BCMA_CORE_INTERNAL_MEM);
+-+		mem_core = container_of(mem, struct brcmf_core_priv, pub);
+-+		brcmf_chip_socram_ramsize(mem_core, &ci->pub.ramsize,
+-+					  &ci->pub.srsize);
+-+	}
+-+	brcmf_dbg(INFO, "RAM: base=0x%x size=%d (0x%x) sr=%d (0x%x)\n",
+-+		  ci->pub.rambase, ci->pub.ramsize, ci->pub.ramsize,
+-+		  ci->pub.srsize, ci->pub.srsize);
+-+
+-+	if (!ci->pub.ramsize) {
+-+		brcmf_err("RAM size is undetermined\n");
+-+		return -ENOMEM;
+-+	}
+-+	return 0;
+- }
+- 
+- static u32 brcmf_chip_dmp_get_desc(struct brcmf_chip_priv *ci, u32 *eromaddr,
+-@@ -668,6 +833,7 @@ static int brcmf_chip_recognition(struct
+- 	struct brcmf_core *core;
+- 	u32 regdata;
+- 	u32 socitype;
+-+	int ret;
+- 
+- 	/* Get CC core rev
+- 	 * Chipid is assume to be at offset 0 from SI_ENUM_BASE
+-@@ -720,9 +886,13 @@ static int brcmf_chip_recognition(struct
+- 		return -ENODEV;
+- 	}
+- 
+--	brcmf_chip_get_raminfo(ci);
+--
+--	return brcmf_chip_cores_check(ci);
+-+	ret = brcmf_chip_cores_check(ci);
+-+	if (ret)
+-+		return ret;
+-+
+-+	/* assure chip is passive for core access */
+-+	brcmf_chip_set_passive(&ci->pub);
+-+	return brcmf_chip_get_raminfo(ci);
+- }
+- 
+- static void brcmf_chip_disable_arm(struct brcmf_chip_priv *chip, u16 id)
+-@@ -827,8 +997,6 @@ struct brcmf_chip *brcmf_chip_attach(voi
+- 	if (err < 0)
+- 		goto fail;
+- 
+--	/* assure chip is passive for download */
+--	brcmf_chip_set_passive(&chip->pub);
+- 	return &chip->pub;
+- 
+- fail:
+---- a/drivers/net/wireless/brcm80211/brcmfmac/chip.h
+-+++ b/drivers/net/wireless/brcm80211/brcmfmac/chip.h
+-@@ -30,7 +30,8 @@
+-  * @pmucaps: PMU capabilities.
+-  * @pmurev: PMU revision.
+-  * @rambase: RAM base address (only applicable for ARM CR4 chips).
+-- * @ramsize: amount of RAM on chip.
+-+ * @ramsize: amount of RAM on chip including retention.
+-+ * @srsize: amount of retention RAM on chip.
+-  * @name: string representation of the chip identifier.
+-  */
+- struct brcmf_chip {
+-@@ -41,6 +42,7 @@ struct brcmf_chip {
+- 	u32 pmurev;
+- 	u32 rambase;
+- 	u32 ramsize;
+-+	u32 srsize;
+- 	char name[8];
+- };
+- 
+diff --git a/package/kernel/mac80211/patches/344-brcmfmac-take-save-restore-memory-into-account-for-S.patch b/package/kernel/mac80211/patches/344-brcmfmac-take-save-restore-memory-into-account-for-S.patch
+deleted file mode 100644
+index 69618a7..0000000
+--- a/package/kernel/mac80211/patches/344-brcmfmac-take-save-restore-memory-into-account-for-S.patch
++++ /dev/null
+@@ -1,96 +0,0 @@
+-From: Arend van Spriel <arend@broadcom.com>
+-Date: Wed, 11 Mar 2015 16:11:32 +0100
+-Subject: [PATCH] brcmfmac: take save&restore memory into account for SDIO
+- shared info
+-
+-The firmware provides pointer to SDIO shared information at end of
+-RAM during firmware initialization. End of RAM is obviously determined
+-by the actual ram size, but part of that may be used for save&restore
+-memory. In that case another location in RAM will hold the pointer.
+-
+-Reviewed-by: Hante Meuleman <meuleman@broadcom.com>
+-Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
+-Signed-off-by: Arend van Spriel <arend@broadcom.com>
+-Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
+----
+-
+---- a/drivers/net/wireless/brcm80211/brcmfmac/sdio.c
+-+++ b/drivers/net/wireless/brcm80211/brcmfmac/sdio.c
+-@@ -1067,44 +1067,47 @@ static inline bool brcmf_sdio_valid_shar
+- static int brcmf_sdio_readshared(struct brcmf_sdio *bus,
+- 				 struct sdpcm_shared *sh)
+- {
+--	u32 addr;
+-+	u32 addr = 0;
+- 	int rv;
+- 	u32 shaddr = 0;
+- 	struct sdpcm_shared_le sh_le;
+- 	__le32 addr_le;
+- 
+--	shaddr = bus->ci->rambase + bus->ci->ramsize - 4;
+-+	sdio_claim_host(bus->sdiodev->func[1]);
+-+	brcmf_sdio_bus_sleep(bus, false, false);
+- 
+- 	/*
+- 	 * Read last word in socram to determine
+- 	 * address of sdpcm_shared structure
+- 	 */
+--	sdio_claim_host(bus->sdiodev->func[1]);
+--	brcmf_sdio_bus_sleep(bus, false, false);
+--	rv = brcmf_sdiod_ramrw(bus->sdiodev, false, shaddr, (u8 *)&addr_le, 4);
+--	sdio_release_host(bus->sdiodev->func[1]);
+-+	shaddr = bus->ci->rambase + bus->ci->ramsize - 4;
+-+	if (!bus->ci->rambase && brcmf_chip_sr_capable(bus->ci))
+-+		shaddr -= bus->ci->srsize;
+-+	rv = brcmf_sdiod_ramrw(bus->sdiodev, false, shaddr,
+-+			       (u8 *)&addr_le, 4);
+- 	if (rv < 0)
+--		return rv;
+--
+--	addr = le32_to_cpu(addr_le);
+--
+--	brcmf_dbg(SDIO, "sdpcm_shared address 0x%08X\n", addr);
+-+		goto fail;
+- 
+- 	/*
+- 	 * Check if addr is valid.
+- 	 * NVRAM length at the end of memory should have been overwritten.
+- 	 */
+-+	addr = le32_to_cpu(addr_le);
+- 	if (!brcmf_sdio_valid_shared_address(addr)) {
+--			brcmf_err("invalid sdpcm_shared address 0x%08X\n",
+--				  addr);
+--			return -EINVAL;
+-+		brcmf_err("invalid sdpcm_shared address 0x%08X\n", addr);
+-+		rv = -EINVAL;
+-+		goto fail;
+- 	}
+- 
+-+	brcmf_dbg(INFO, "sdpcm_shared address 0x%08X\n", addr);
+-+
+- 	/* Read hndrte_shared structure */
+- 	rv = brcmf_sdiod_ramrw(bus->sdiodev, false, addr, (u8 *)&sh_le,
+- 			       sizeof(struct sdpcm_shared_le));
+- 	if (rv < 0)
+--		return rv;
+-+		goto fail;
+-+
+-+	sdio_release_host(bus->sdiodev->func[1]);
+- 
+- 	/* Endianness */
+- 	sh->flags = le32_to_cpu(sh_le.flags);
+-@@ -1121,8 +1124,13 @@ static int brcmf_sdio_readshared(struct
+- 			  sh->flags & SDPCM_SHARED_VERSION_MASK);
+- 		return -EPROTO;
+- 	}
+--
+- 	return 0;
+-+
+-+fail:
+-+	brcmf_err("unable to obtain sdpcm_shared info: rv=%d (addr=0x%x)\n",
+-+		  rv, addr);
+-+	sdio_release_host(bus->sdiodev->func[1]);
+-+	return rv;
+- }
+- 
+- static void brcmf_sdio_get_console_addr(struct brcmf_sdio *bus)
+diff --git a/package/kernel/mac80211/patches/345-brcmfmac-fix-watchdog-timer-regression.patch b/package/kernel/mac80211/patches/345-brcmfmac-fix-watchdog-timer-regression.patch
+deleted file mode 100644
+index 1b10dbb..0000000
+--- a/package/kernel/mac80211/patches/345-brcmfmac-fix-watchdog-timer-regression.patch
++++ /dev/null
+@@ -1,59 +0,0 @@
+-From: Arend van Spriel <arend@broadcom.com>
+-Date: Wed, 11 Mar 2015 16:11:33 +0100
+-Subject: [PATCH] brcmfmac: fix watchdog timer regression
+-
+-The watchdog timer is used to put the device in a low-power mode when
+-it is idle for some time. This timer is stopped during that mode and
+-should be restarted upon activity. This has been broken by commit
+-d4150fced0365 ("brcmfmac: Simplify watchdog sleep."). This patch
+-restores the behaviour as it was before that commit.
+-
+-Reported-by: Pontus Fuchs <pontusf@broadcom.com>
+-Reviewed-by: Hante Meuleman <meuleman@broadcom.com>
+-Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
+-Signed-off-by: Arend van Spriel <arend@broadcom.com>
+-Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
+----
+-
+---- a/drivers/net/wireless/brcm80211/brcmfmac/sdio.c
+-+++ b/drivers/net/wireless/brcm80211/brcmfmac/sdio.c
+-@@ -972,7 +972,6 @@ static int brcmf_sdio_clkctl(struct brcm
+- 			brcmf_sdio_sdclk(bus, true);
+- 		/* Now request HT Avail on the backplane */
+- 		brcmf_sdio_htclk(bus, true, pendok);
+--		brcmf_sdio_wd_timer(bus, BRCMF_WD_POLL_MS);
+- 		break;
+- 
+- 	case CLK_SDONLY:
+-@@ -984,7 +983,6 @@ static int brcmf_sdio_clkctl(struct brcm
+- 		else
+- 			brcmf_err("request for %d -> %d\n",
+- 				  bus->clkstate, target);
+--		brcmf_sdio_wd_timer(bus, BRCMF_WD_POLL_MS);
+- 		break;
+- 
+- 	case CLK_NONE:
+-@@ -993,7 +991,6 @@ static int brcmf_sdio_clkctl(struct brcm
+- 			brcmf_sdio_htclk(bus, false, false);
+- 		/* Now remove the SD clock */
+- 		brcmf_sdio_sdclk(bus, false);
+--		brcmf_sdio_wd_timer(bus, 0);
+- 		break;
+- 	}
+- #ifdef DEBUG
+-@@ -1048,6 +1045,7 @@ end:
+- 			brcmf_sdio_clkctl(bus, CLK_NONE, pendok);
+- 	} else {
+- 		brcmf_sdio_clkctl(bus, CLK_AVAIL, pendok);
+-+		brcmf_sdio_wd_timer(bus, BRCMF_WD_POLL_MS);
+- 	}
+- 	bus->sleeping = sleep;
+- 	brcmf_dbg(SDIO, "new state %s\n",
+-@@ -4242,6 +4240,7 @@ void brcmf_sdio_remove(struct brcmf_sdio
+- 		if (bus->ci) {
+- 			if (bus->sdiodev->state != BRCMF_SDIOD_NOMEDIUM) {
+- 				sdio_claim_host(bus->sdiodev->func[1]);
+-+				brcmf_sdio_wd_timer(bus, 0);
+- 				brcmf_sdio_clkctl(bus, CLK_AVAIL, false);
+- 				/* Leave the device in state where it is
+- 				 * 'passive'. This is done by resetting all
+diff --git a/package/kernel/mac80211/patches/346-brcmfmac-avoid-runtime-pm-for-sdio-host-controller.patch b/package/kernel/mac80211/patches/346-brcmfmac-avoid-runtime-pm-for-sdio-host-controller.patch
+deleted file mode 100644
+index af76f13..0000000
+--- a/package/kernel/mac80211/patches/346-brcmfmac-avoid-runtime-pm-for-sdio-host-controller.patch
++++ /dev/null
+@@ -1,44 +0,0 @@
+-From: Arend van Spriel <arend@broadcom.com>
+-Date: Wed, 18 Mar 2015 13:25:21 +0100
+-Subject: [PATCH] brcmfmac: avoid runtime-pm for sdio host controller
+-
+-Several host controllers supporting runtime-pm are causing issues
+-with our sdio wireless cards because they disable the sdio interrupt
+-upon going into runtime suspend. This patch avoids that by doing
+-a pm_runtime_forbid() call during the probe. Tested with Sony Vaio
+-Duo 13 which uses sdhci-acpi host controller.
+-
+-Reviewed-by: Hante Meuleman <meuleman@broadcom.com>
+-Reviewed-by: Franky (Zhenhui) Lin <frankyl@broadcom.com>
+-Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
+-Signed-off-by: Arend van Spriel <arend@broadcom.com>
+-Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
+----
+-
+---- a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c
+-+++ b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c
+-@@ -29,6 +29,7 @@
+- #include <linux/mmc/host.h>
+- #include <linux/platform_device.h>
+- #include <linux/platform_data/brcmfmac-sdio.h>
+-+#include <linux/pm_runtime.h>
+- #include <linux/suspend.h>
+- #include <linux/errno.h>
+- #include <linux/module.h>
+-@@ -1006,6 +1007,7 @@ static int brcmf_sdiod_remove(struct brc
+- 	sg_free_table(&sdiodev->sgtable);
+- 	sdiodev->sbwad = 0;
+- 
+-+	pm_runtime_allow(sdiodev->func[1]->card->host->parent);
+- 	return 0;
+- }
+- 
+-@@ -1074,7 +1076,7 @@ static int brcmf_sdiod_probe(struct brcm
+- 		ret = -ENODEV;
+- 		goto out;
+- 	}
+--
+-+	pm_runtime_forbid(host->parent);
+- out:
+- 	if (ret)
+- 		brcmf_sdiod_remove(sdiodev);
+diff --git a/package/kernel/mac80211/patches/347-brcmfmac-Add-necessary-memory-barriers-for-SDIO.patch b/package/kernel/mac80211/patches/347-brcmfmac-Add-necessary-memory-barriers-for-SDIO.patch
+deleted file mode 100644
+index c419cc6..0000000
+--- a/package/kernel/mac80211/patches/347-brcmfmac-Add-necessary-memory-barriers-for-SDIO.patch
++++ /dev/null
+@@ -1,171 +0,0 @@
+-From: Hante Meuleman <meuleman@broadcom.com>
+-Date: Wed, 18 Mar 2015 13:25:22 +0100
+-Subject: [PATCH] brcmfmac: Add necessary memory barriers for SDIO.
+-
+-SDIO uses a thread to handle all communication with the device,
+-for this data is exchanged between threads. This data needs proper
+-memory barriers to make sure that data "exchange" is going correct.
+-
+-Reviewed-by: Arend Van Spriel <arend@broadcom.com>
+-Reviewed-by: Franky (Zhenhui) Lin <frankyl@broadcom.com>
+-Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
+-Reviewed-by: Daniel (Deognyoun) Kim <dekim@broadcom.com>
+-Signed-off-by: Hante Meuleman <meuleman@broadcom.com>
+-Signed-off-by: Arend van Spriel <arend@broadcom.com>
+-Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
+----
+-
+---- a/drivers/net/wireless/brcm80211/brcmfmac/sdio.c
+-+++ b/drivers/net/wireless/brcm80211/brcmfmac/sdio.c
+-@@ -507,8 +507,8 @@ struct brcmf_sdio {
+- 
+- 	struct workqueue_struct *brcmf_wq;
+- 	struct work_struct datawork;
+--	atomic_t dpc_tskcnt;
+--	atomic_t dpc_running;
+-+	bool dpc_triggered;
+-+	bool dpc_running;
+- 
+- 	bool txoff;		/* Transmit flow-controlled */
+- 	struct brcmf_sdio_count sdcnt;
+-@@ -2713,6 +2713,7 @@ static void brcmf_sdio_dpc(struct brcmf_
+- 			err = brcmf_sdio_tx_ctrlframe(bus,  bus->ctrl_frame_buf,
+- 						      bus->ctrl_frame_len);
+- 			bus->ctrl_frame_err = err;
+-+			wmb();
+- 			bus->ctrl_frame_stat = false;
+- 		}
+- 		sdio_release_host(bus->sdiodev->func[1]);
+-@@ -2734,6 +2735,7 @@ static void brcmf_sdio_dpc(struct brcmf_
+- 			sdio_claim_host(bus->sdiodev->func[1]);
+- 			if (bus->ctrl_frame_stat) {
+- 				bus->ctrl_frame_err = -ENODEV;
+-+				wmb();
+- 				bus->ctrl_frame_stat = false;
+- 				brcmf_sdio_wait_event_wakeup(bus);
+- 			}
+-@@ -2744,7 +2746,7 @@ static void brcmf_sdio_dpc(struct brcmf_
+- 		   (!atomic_read(&bus->fcstate) &&
+- 		    brcmu_pktq_mlen(&bus->txq, ~bus->flowcontrol) &&
+- 		    data_ok(bus))) {
+--		atomic_inc(&bus->dpc_tskcnt);
+-+		bus->dpc_triggered = true;
+- 	}
+- }
+- 
+-@@ -2940,6 +2942,7 @@ brcmf_sdio_bus_txctl(struct device *dev,
+- 	/* Send from dpc */
+- 	bus->ctrl_frame_buf = msg;
+- 	bus->ctrl_frame_len = msglen;
+-+	wmb();
+- 	bus->ctrl_frame_stat = true;
+- 
+- 	brcmf_sdio_trigger_dpc(bus);
+-@@ -2958,6 +2961,7 @@ brcmf_sdio_bus_txctl(struct device *dev,
+- 	if (!ret) {
+- 		brcmf_dbg(SDIO, "ctrl_frame complete, err=%d\n",
+- 			  bus->ctrl_frame_err);
+-+		rmb();
+- 		ret = bus->ctrl_frame_err;
+- 	}
+- 
+-@@ -3526,8 +3530,8 @@ done:
+- 
+- void brcmf_sdio_trigger_dpc(struct brcmf_sdio *bus)
+- {
+--	if (atomic_read(&bus->dpc_tskcnt) == 0) {
+--		atomic_inc(&bus->dpc_tskcnt);
+-+	if (!bus->dpc_triggered) {
+-+		bus->dpc_triggered = true;
+- 		queue_work(bus->brcmf_wq, &bus->datawork);
+- 	}
+- }
+-@@ -3558,7 +3562,7 @@ void brcmf_sdio_isr(struct brcmf_sdio *b
+- 	if (!bus->intr)
+- 		brcmf_err("isr w/o interrupt configured!\n");
+- 
+--	atomic_inc(&bus->dpc_tskcnt);
+-+	bus->dpc_triggered = true;
+- 	queue_work(bus->brcmf_wq, &bus->datawork);
+- }
+- 
+-@@ -3578,7 +3582,7 @@ static void brcmf_sdio_bus_watchdog(stru
+- 		if (!bus->intr ||
+- 		    (bus->sdcnt.intrcount == bus->sdcnt.lastintrs)) {
+- 
+--			if (atomic_read(&bus->dpc_tskcnt) == 0) {
+-+			if (!bus->dpc_triggered) {
+- 				u8 devpend;
+- 
+- 				sdio_claim_host(bus->sdiodev->func[1]);
+-@@ -3596,7 +3600,7 @@ static void brcmf_sdio_bus_watchdog(stru
+- 				bus->sdcnt.pollcnt++;
+- 				atomic_set(&bus->ipend, 1);
+- 
+--				atomic_inc(&bus->dpc_tskcnt);
+-+				bus->dpc_triggered = true;
+- 				queue_work(bus->brcmf_wq, &bus->datawork);
+- 			}
+- 		}
+-@@ -3623,17 +3627,21 @@ static void brcmf_sdio_bus_watchdog(stru
+- #endif				/* DEBUG */
+- 
+- 	/* On idle timeout clear activity flag and/or turn off clock */
+--	if ((atomic_read(&bus->dpc_tskcnt) == 0) &&
+--	    (atomic_read(&bus->dpc_running) == 0) &&
+--	    (bus->idletime > 0) && (bus->clkstate == CLK_AVAIL)) {
+--		bus->idlecount++;
+--		if (bus->idlecount > bus->idletime) {
+--			brcmf_dbg(SDIO, "idle\n");
+--			sdio_claim_host(bus->sdiodev->func[1]);
+--			brcmf_sdio_wd_timer(bus, 0);
+-+	if (!bus->dpc_triggered) {
+-+		rmb();
+-+		if ((!bus->dpc_running) && (bus->idletime > 0) &&
+-+		    (bus->clkstate == CLK_AVAIL)) {
+-+			bus->idlecount++;
+-+			if (bus->idlecount > bus->idletime) {
+-+				brcmf_dbg(SDIO, "idle\n");
+-+				sdio_claim_host(bus->sdiodev->func[1]);
+-+				brcmf_sdio_wd_timer(bus, 0);
+-+				bus->idlecount = 0;
+-+				brcmf_sdio_bus_sleep(bus, true, false);
+-+				sdio_release_host(bus->sdiodev->func[1]);
+-+			}
+-+		} else {
+- 			bus->idlecount = 0;
+--			brcmf_sdio_bus_sleep(bus, true, false);
+--			sdio_release_host(bus->sdiodev->func[1]);
+- 		}
+- 	} else {
+- 		bus->idlecount = 0;
+-@@ -3645,13 +3653,14 @@ static void brcmf_sdio_dataworker(struct
+- 	struct brcmf_sdio *bus = container_of(work, struct brcmf_sdio,
+- 					      datawork);
+- 
+--	while (atomic_read(&bus->dpc_tskcnt)) {
+--		atomic_set(&bus->dpc_running, 1);
+--		atomic_set(&bus->dpc_tskcnt, 0);
+-+	bus->dpc_running = true;
+-+	wmb();
+-+	while (ACCESS_ONCE(bus->dpc_triggered)) {
+-+		bus->dpc_triggered = false;
+- 		brcmf_sdio_dpc(bus);
+- 		bus->idlecount = 0;
+--		atomic_set(&bus->dpc_running, 0);
+- 	}
+-+	bus->dpc_running = false;
+- 	if (brcmf_sdiod_freezing(bus->sdiodev)) {
+- 		brcmf_sdiod_change_state(bus->sdiodev, BRCMF_SDIOD_DOWN);
+- 		brcmf_sdiod_try_freeze(bus->sdiodev);
+-@@ -4144,8 +4153,8 @@ struct brcmf_sdio *brcmf_sdio_probe(stru
+- 		bus->watchdog_tsk = NULL;
+- 	}
+- 	/* Initialize DPC thread */
+--	atomic_set(&bus->dpc_tskcnt, 0);
+--	atomic_set(&bus->dpc_running, 0);
+-+	bus->dpc_triggered = false;
+-+	bus->dpc_running = false;
+- 
+- 	/* Assign bus interface call back */
+- 	bus->sdiodev->bus_if->dev = bus->sdiodev->dev;
+diff --git a/package/kernel/mac80211/patches/348-brcmfmac-Remove-unnecessary-new-line-in-pcie-console.patch b/package/kernel/mac80211/patches/348-brcmfmac-Remove-unnecessary-new-line-in-pcie-console.patch
+deleted file mode 100644
+index 1bc98a0..0000000
+--- a/package/kernel/mac80211/patches/348-brcmfmac-Remove-unnecessary-new-line-in-pcie-console.patch
++++ /dev/null
+@@ -1,26 +0,0 @@
+-From: Hante Meuleman <meuleman@broadcom.com>
+-Date: Wed, 18 Mar 2015 13:25:24 +0100
+-Subject: [PATCH] brcmfmac: Remove unnecessary new-line in pcie console
+- logging.
+-
+-Reviewed-by: Arend Van Spriel <arend@broadcom.com>
+-Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
+-Signed-off-by: Hante Meuleman <meuleman@broadcom.com>
+-Signed-off-by: Arend van Spriel <arend@broadcom.com>
+-Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
+----
+-
+---- a/drivers/net/wireless/brcm80211/brcmfmac/pcie.c
+-+++ b/drivers/net/wireless/brcm80211/brcmfmac/pcie.c
+-@@ -651,10 +651,9 @@ static void brcmf_pcie_bus_console_read(
+- 			console->log_str[console->log_idx] = ch;
+- 			console->log_idx++;
+- 		}
+--
+- 		if (ch == '\n') {
+- 			console->log_str[console->log_idx] = 0;
+--			brcmf_dbg(PCIE, "CONSOLE: %s\n", console->log_str);
+-+			brcmf_dbg(PCIE, "CONSOLE: %s", console->log_str);
+- 			console->log_idx = 0;
+- 		}
+- 	}
+diff --git a/package/kernel/mac80211/patches/349-brcmfmac-add-MODULE_FIRMWARE-macros-for-bcm4356-PCIe.patch b/package/kernel/mac80211/patches/349-brcmfmac-add-MODULE_FIRMWARE-macros-for-bcm4356-PCIe.patch
+deleted file mode 100644
+index fcf0bf3..0000000
+--- a/package/kernel/mac80211/patches/349-brcmfmac-add-MODULE_FIRMWARE-macros-for-bcm4356-PCIe.patch
++++ /dev/null
+@@ -1,26 +0,0 @@
+-From: Arend van Spriel <arend@broadcom.com>
+-Date: Wed, 18 Mar 2015 13:25:25 +0100
+-Subject: [PATCH] brcmfmac: add MODULE_FIRMWARE() macros for bcm4356 PCIe
+- device
+-
+-The BCM4356 PCIe wireless device was added recently but overlooked
+-the fact that the MODULE_FIRMWARE() macros were missing for the
+-firmwares needed by this device.
+-
+-Reviewed-by: Hante Meuleman <meuleman@broadcom.com>
+-Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
+-Signed-off-by: Arend van Spriel <arend@broadcom.com>
+-Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
+----
+-
+---- a/drivers/net/wireless/brcm80211/brcmfmac/pcie.c
+-+++ b/drivers/net/wireless/brcm80211/brcmfmac/pcie.c
+-@@ -189,6 +189,8 @@ MODULE_FIRMWARE(BRCMF_PCIE_43602_FW_NAME
+- MODULE_FIRMWARE(BRCMF_PCIE_43602_NVRAM_NAME);
+- MODULE_FIRMWARE(BRCMF_PCIE_4354_FW_NAME);
+- MODULE_FIRMWARE(BRCMF_PCIE_4354_NVRAM_NAME);
+-+MODULE_FIRMWARE(BRCMF_PCIE_4356_FW_NAME);
+-+MODULE_FIRMWARE(BRCMF_PCIE_4356_NVRAM_NAME);
+- MODULE_FIRMWARE(BRCMF_PCIE_43570_FW_NAME);
+- MODULE_FIRMWARE(BRCMF_PCIE_43570_NVRAM_NAME);
+- 
+diff --git a/package/kernel/mac80211/patches/350-brcmfmac-add-support-for-BCM43430-SDIO-chipset.patch b/package/kernel/mac80211/patches/350-brcmfmac-add-support-for-BCM43430-SDIO-chipset.patch
+deleted file mode 100644
+index b3e9bc9..0000000
+--- a/package/kernel/mac80211/patches/350-brcmfmac-add-support-for-BCM43430-SDIO-chipset.patch
++++ /dev/null
+@@ -1,138 +0,0 @@
+-From: Arend van Spriel <arend@broadcom.com>
+-Date: Wed, 18 Mar 2015 13:25:26 +0100
+-Subject: [PATCH] brcmfmac: add support for BCM43430 SDIO chipset
+-
+-This patch added support for the BCM43430 802.11n SDIO chipset.
+-
+-Reviewed-by: Hante Meuleman <meuleman@broadcom.com>
+-Reviewed-by: Daniel (Deognyoun) Kim <dekim@broadcom.com>
+-Reviewed-by: Franky (Zhenhui) Lin <frankyl@broadcom.com>
+-Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
+-Signed-off-by: Arend van Spriel <arend@broadcom.com>
+-Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
+----
+-
+---- a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c
+-+++ b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c
+-@@ -1098,6 +1098,7 @@ static const struct sdio_device_id brcmf
+- 	BRCMF_SDIO_DEVICE(SDIO_DEVICE_ID_BROADCOM_43341),
+- 	BRCMF_SDIO_DEVICE(SDIO_DEVICE_ID_BROADCOM_43362),
+- 	BRCMF_SDIO_DEVICE(SDIO_DEVICE_ID_BROADCOM_4335_4339),
+-+	BRCMF_SDIO_DEVICE(SDIO_DEVICE_ID_BROADCOM_43430),
+- 	BRCMF_SDIO_DEVICE(SDIO_DEVICE_ID_BROADCOM_4345),
+- 	BRCMF_SDIO_DEVICE(SDIO_DEVICE_ID_BROADCOM_4354),
+- 	{ /* end: all zeroes */ }
+---- a/drivers/net/wireless/brcm80211/brcmfmac/chip.c
+-+++ b/drivers/net/wireless/brcm80211/brcmfmac/chip.c
+-@@ -600,6 +600,12 @@ static void brcmf_chip_socram_ramsize(st
+- 		if (sr->chip->pub.chiprev < 2)
+- 			*srsize = (32 * 1024);
+- 		break;
+-+	case BRCM_CC_43430_CHIP_ID:
+-+		/* assume sr for now as we can not check
+-+		 * firmware sr capability at this point.
+-+		 */
+-+		*srsize = (64 * 1024);
+-+		break;
+- 	default:
+- 		break;
+- 	}
+-@@ -1072,6 +1078,7 @@ static void
+- brcmf_chip_cm3_set_passive(struct brcmf_chip_priv *chip)
+- {
+- 	struct brcmf_core *core;
+-+	struct brcmf_core_priv *sr;
+- 
+- 	brcmf_chip_disable_arm(chip, BCMA_CORE_ARM_CM3);
+- 	core = brcmf_chip_get_core(&chip->pub, BCMA_CORE_80211);
+-@@ -1081,6 +1088,13 @@ brcmf_chip_cm3_set_passive(struct brcmf_
+- 			     D11_BCMA_IOCTL_PHYCLOCKEN);
+- 	core = brcmf_chip_get_core(&chip->pub, BCMA_CORE_INTERNAL_MEM);
+- 	brcmf_chip_resetcore(core, 0, 0, 0);
+-+
+-+	/* disable bank #3 remap for this device */
+-+	if (chip->pub.chip == BRCM_CC_43430_CHIP_ID) {
+-+		sr = container_of(core, struct brcmf_core_priv, pub);
+-+		brcmf_chip_core_write32(sr, SOCRAMREGOFFS(bankidx), 3);
+-+		brcmf_chip_core_write32(sr, SOCRAMREGOFFS(bankpda), 0);
+-+	}
+- }
+- 
+- static bool brcmf_chip_cm3_set_active(struct brcmf_chip_priv *chip)
+-@@ -1188,6 +1202,10 @@ bool brcmf_chip_sr_capable(struct brcmf_
+- 		addr = CORE_CC_REG(base, chipcontrol_data);
+- 		reg = chip->ops->read32(chip->ctx, addr);
+- 		return (reg & pmu_cc3_mask) != 0;
+-+	case BRCM_CC_43430_CHIP_ID:
+-+		addr = CORE_CC_REG(base, sr_control1);
+-+		reg = chip->ops->read32(chip->ctx, addr);
+-+		return reg != 0;
+- 	default:
+- 		addr = CORE_CC_REG(base, pmucapabilities_ext);
+- 		reg = chip->ops->read32(chip->ctx, addr);
+---- a/drivers/net/wireless/brcm80211/brcmfmac/sdio.c
+-+++ b/drivers/net/wireless/brcm80211/brcmfmac/sdio.c
+-@@ -615,6 +615,8 @@ static const struct sdiod_drive_str sdio
+- #define BCM43362_NVRAM_NAME		"brcm/brcmfmac43362-sdio.txt"
+- #define BCM4339_FIRMWARE_NAME		"brcm/brcmfmac4339-sdio.bin"
+- #define BCM4339_NVRAM_NAME		"brcm/brcmfmac4339-sdio.txt"
+-+#define BCM43430_FIRMWARE_NAME		"brcm/brcmfmac43430-sdio.bin"
+-+#define BCM43430_NVRAM_NAME		"brcm/brcmfmac43430-sdio.txt"
+- #define BCM4345_FIRMWARE_NAME		"brcm/brcmfmac4345-sdio.bin"
+- #define BCM4345_NVRAM_NAME		"brcm/brcmfmac4345-sdio.txt"
+- #define BCM4354_FIRMWARE_NAME		"brcm/brcmfmac4354-sdio.bin"
+-@@ -640,6 +642,8 @@ MODULE_FIRMWARE(BCM43362_FIRMWARE_NAME);
+- MODULE_FIRMWARE(BCM43362_NVRAM_NAME);
+- MODULE_FIRMWARE(BCM4339_FIRMWARE_NAME);
+- MODULE_FIRMWARE(BCM4339_NVRAM_NAME);
+-+MODULE_FIRMWARE(BCM43430_FIRMWARE_NAME);
+-+MODULE_FIRMWARE(BCM43430_NVRAM_NAME);
+- MODULE_FIRMWARE(BCM4345_FIRMWARE_NAME);
+- MODULE_FIRMWARE(BCM4345_NVRAM_NAME);
+- MODULE_FIRMWARE(BCM4354_FIRMWARE_NAME);
+-@@ -671,6 +675,7 @@ static const struct brcmf_firmware_names
+- 	{ BRCM_CC_4335_CHIP_ID, 0xFFFFFFFF, BRCMF_FIRMWARE_NVRAM(BCM4335) },
+- 	{ BRCM_CC_43362_CHIP_ID, 0xFFFFFFFE, BRCMF_FIRMWARE_NVRAM(BCM43362) },
+- 	{ BRCM_CC_4339_CHIP_ID, 0xFFFFFFFF, BRCMF_FIRMWARE_NVRAM(BCM4339) },
+-+	{ BRCM_CC_43430_CHIP_ID, 0xFFFFFFFF, BRCMF_FIRMWARE_NVRAM(BCM43430) },
+- 	{ BRCM_CC_4345_CHIP_ID, 0xFFFFFFFF, BRCMF_FIRMWARE_NVRAM(BCM4345) },
+- 	{ BRCM_CC_4354_CHIP_ID, 0xFFFFFFFF, BRCMF_FIRMWARE_NVRAM(BCM4354) }
+- };
+---- a/drivers/net/wireless/brcm80211/include/brcm_hw_ids.h
+-+++ b/drivers/net/wireless/brcm80211/include/brcm_hw_ids.h
+-@@ -37,6 +37,7 @@
+- #define BRCM_CC_43362_CHIP_ID		43362
+- #define BRCM_CC_4335_CHIP_ID		0x4335
+- #define BRCM_CC_4339_CHIP_ID		0x4339
+-+#define BRCM_CC_43430_CHIP_ID		43430
+- #define BRCM_CC_4345_CHIP_ID		0x4345
+- #define BRCM_CC_4354_CHIP_ID		0x4354
+- #define BRCM_CC_4356_CHIP_ID		0x4356
+---- a/drivers/net/wireless/brcm80211/include/chipcommon.h
+-+++ b/drivers/net/wireless/brcm80211/include/chipcommon.h
+-@@ -183,7 +183,14 @@ struct chipcregs {
+- 	u8 uart1lsr;
+- 	u8 uart1msr;
+- 	u8 uart1scratch;
+--	u32 PAD[126];
+-+	u32 PAD[62];
+-+
+-+	/* save/restore, corerev >= 48 */
+-+	u32 sr_capability;          /* 0x500 */
+-+	u32 sr_control0;            /* 0x504 */
+-+	u32 sr_control1;            /* 0x508 */
+-+	u32 gpio_control;           /* 0x50C */
+-+	u32 PAD[60];
+- 
+- 	/* PMU registers (corerev >= 20) */
+- 	u32 pmucontrol;	/* 0x600 */
+---- a/include/linux/mmc/sdio_ids.h
+-+++ b/include/linux/mmc/sdio_ids.h
+-@@ -33,6 +33,7 @@
+- #define SDIO_DEVICE_ID_BROADCOM_43341		0xa94d
+- #define SDIO_DEVICE_ID_BROADCOM_4335_4339	0x4335
+- #define SDIO_DEVICE_ID_BROADCOM_43362		0xa962
+-+#define SDIO_DEVICE_ID_BROADCOM_43430		0xa9a6
+- #define SDIO_DEVICE_ID_BROADCOM_4345		0x4345
+- #define SDIO_DEVICE_ID_BROADCOM_4354		0x4354
+- 
+diff --git a/package/kernel/mac80211/patches/351-brcmfmac-only-support-the-BCM43455-7-device.patch b/package/kernel/mac80211/patches/351-brcmfmac-only-support-the-BCM43455-7-device.patch
+deleted file mode 100644
+index c3d7bc2..0000000
+--- a/package/kernel/mac80211/patches/351-brcmfmac-only-support-the-BCM43455-7-device.patch
++++ /dev/null
+@@ -1,50 +0,0 @@
+-From: Arend van Spriel <arend@broadcom.com>
+-Date: Wed, 18 Mar 2015 13:25:27 +0100
+-Subject: [PATCH] brcmfmac: only support the BCM43455/7 device
+-
+-Recently support was added for the BCM4345 SDIO chipset by
+-commit 9c51026509d7 ("brcmfmac: Add support for BCM4345 SDIO chipset")
+-however this was verified using a BCM43455 device, which is
+-a more recent revision of the chip. This patch assure that
+-older revisions are not probed as they would fail.
+-
+-Reviewed-by: Hante Meuleman <meuleman@broadcom.com>
+-Reviewed-by: Syed Asifful Dayyan <syedd@broadcom.com>
+-Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
+-Signed-off-by: Arend van Spriel <arend@broadcom.com>
+-Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
+----
+-
+---- a/drivers/net/wireless/brcm80211/brcmfmac/sdio.c
+-+++ b/drivers/net/wireless/brcm80211/brcmfmac/sdio.c
+-@@ -617,8 +617,8 @@ static const struct sdiod_drive_str sdio
+- #define BCM4339_NVRAM_NAME		"brcm/brcmfmac4339-sdio.txt"
+- #define BCM43430_FIRMWARE_NAME		"brcm/brcmfmac43430-sdio.bin"
+- #define BCM43430_NVRAM_NAME		"brcm/brcmfmac43430-sdio.txt"
+--#define BCM4345_FIRMWARE_NAME		"brcm/brcmfmac4345-sdio.bin"
+--#define BCM4345_NVRAM_NAME		"brcm/brcmfmac4345-sdio.txt"
+-+#define BCM43455_FIRMWARE_NAME		"brcm/brcmfmac43455-sdio.bin"
+-+#define BCM43455_NVRAM_NAME		"brcm/brcmfmac43455-sdio.txt"
+- #define BCM4354_FIRMWARE_NAME		"brcm/brcmfmac4354-sdio.bin"
+- #define BCM4354_NVRAM_NAME		"brcm/brcmfmac4354-sdio.txt"
+- 
+-@@ -644,8 +644,8 @@ MODULE_FIRMWARE(BCM4339_FIRMWARE_NAME);
+- MODULE_FIRMWARE(BCM4339_NVRAM_NAME);
+- MODULE_FIRMWARE(BCM43430_FIRMWARE_NAME);
+- MODULE_FIRMWARE(BCM43430_NVRAM_NAME);
+--MODULE_FIRMWARE(BCM4345_FIRMWARE_NAME);
+--MODULE_FIRMWARE(BCM4345_NVRAM_NAME);
+-+MODULE_FIRMWARE(BCM43455_FIRMWARE_NAME);
+-+MODULE_FIRMWARE(BCM43455_NVRAM_NAME);
+- MODULE_FIRMWARE(BCM4354_FIRMWARE_NAME);
+- MODULE_FIRMWARE(BCM4354_NVRAM_NAME);
+- 
+-@@ -676,7 +676,7 @@ static const struct brcmf_firmware_names
+- 	{ BRCM_CC_43362_CHIP_ID, 0xFFFFFFFE, BRCMF_FIRMWARE_NVRAM(BCM43362) },
+- 	{ BRCM_CC_4339_CHIP_ID, 0xFFFFFFFF, BRCMF_FIRMWARE_NVRAM(BCM4339) },
+- 	{ BRCM_CC_43430_CHIP_ID, 0xFFFFFFFF, BRCMF_FIRMWARE_NVRAM(BCM43430) },
+--	{ BRCM_CC_4345_CHIP_ID, 0xFFFFFFFF, BRCMF_FIRMWARE_NVRAM(BCM4345) },
+-+	{ BRCM_CC_4345_CHIP_ID, 0xFFFFFFC0, BRCMF_FIRMWARE_NVRAM(BCM43455) },
+- 	{ BRCM_CC_4354_CHIP_ID, 0xFFFFFFFF, BRCMF_FIRMWARE_NVRAM(BCM4354) }
+- };
+- 
+diff --git a/package/kernel/mac80211/patches/352-brcmfmac-remove-support-for-unreleased-BCM4354-PCIe.patch b/package/kernel/mac80211/patches/352-brcmfmac-remove-support-for-unreleased-BCM4354-PCIe.patch
+deleted file mode 100644
+index a62cfdf..0000000
+--- a/package/kernel/mac80211/patches/352-brcmfmac-remove-support-for-unreleased-BCM4354-PCIe.patch
++++ /dev/null
+@@ -1,52 +0,0 @@
+-From: Arend van Spriel <arend@broadcom.com>
+-Date: Wed, 18 Mar 2015 13:25:28 +0100
+-Subject: [PATCH] brcmfmac: remove support for unreleased BCM4354 PCIe
+-
+-There are no known BCM4354 PCIe devices released so removing
+-support from the driver until proven otherwise.
+-
+-Reviewed-by: Hante Meuleman <meuleman@broadcom.com>
+-Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
+-Signed-off-by: Arend van Spriel <arend@broadcom.com>
+-Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
+----
+-
+---- a/drivers/net/wireless/brcm80211/brcmfmac/pcie.c
+-+++ b/drivers/net/wireless/brcm80211/brcmfmac/pcie.c
+-@@ -47,8 +47,6 @@ enum brcmf_pcie_state {
+- 
+- #define BRCMF_PCIE_43602_FW_NAME		"brcm/brcmfmac43602-pcie.bin"
+- #define BRCMF_PCIE_43602_NVRAM_NAME		"brcm/brcmfmac43602-pcie.txt"
+--#define BRCMF_PCIE_4354_FW_NAME			"brcm/brcmfmac4354-pcie.bin"
+--#define BRCMF_PCIE_4354_NVRAM_NAME		"brcm/brcmfmac4354-pcie.txt"
+- #define BRCMF_PCIE_4356_FW_NAME			"brcm/brcmfmac4356-pcie.bin"
+- #define BRCMF_PCIE_4356_NVRAM_NAME		"brcm/brcmfmac4356-pcie.txt"
+- #define BRCMF_PCIE_43570_FW_NAME		"brcm/brcmfmac43570-pcie.bin"
+-@@ -187,8 +185,6 @@ enum brcmf_pcie_state {
+- 
+- MODULE_FIRMWARE(BRCMF_PCIE_43602_FW_NAME);
+- MODULE_FIRMWARE(BRCMF_PCIE_43602_NVRAM_NAME);
+--MODULE_FIRMWARE(BRCMF_PCIE_4354_FW_NAME);
+--MODULE_FIRMWARE(BRCMF_PCIE_4354_NVRAM_NAME);
+- MODULE_FIRMWARE(BRCMF_PCIE_4356_FW_NAME);
+- MODULE_FIRMWARE(BRCMF_PCIE_4356_NVRAM_NAME);
+- MODULE_FIRMWARE(BRCMF_PCIE_43570_FW_NAME);
+-@@ -1327,10 +1323,6 @@ static int brcmf_pcie_get_fwnames(struct
+- 		fw_name = BRCMF_PCIE_43602_FW_NAME;
+- 		nvram_name = BRCMF_PCIE_43602_NVRAM_NAME;
+- 		break;
+--	case BRCM_CC_4354_CHIP_ID:
+--		fw_name = BRCMF_PCIE_4354_FW_NAME;
+--		nvram_name = BRCMF_PCIE_4354_NVRAM_NAME;
+--		break;
+- 	case BRCM_CC_4356_CHIP_ID:
+- 		fw_name = BRCMF_PCIE_4356_FW_NAME;
+- 		nvram_name = BRCMF_PCIE_4356_NVRAM_NAME;
+-@@ -1855,7 +1847,6 @@ cleanup:
+- 	PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_NETWORK_OTHER << 8, 0xffff00, 0 }
+- 
+- static struct pci_device_id brcmf_pcie_devid_table[] = {
+--	BRCMF_PCIE_DEVICE(BRCM_PCIE_4354_DEVICE_ID),
+- 	BRCMF_PCIE_DEVICE(BRCM_PCIE_4356_DEVICE_ID),
+- 	BRCMF_PCIE_DEVICE(BRCM_PCIE_43567_DEVICE_ID),
+- 	BRCMF_PCIE_DEVICE(BRCM_PCIE_43570_DEVICE_ID),
+diff --git a/package/kernel/mac80211/patches/353-brcmfmac-disable-MBSS-feature-for-BCM43362.patch b/package/kernel/mac80211/patches/353-brcmfmac-disable-MBSS-feature-for-BCM43362.patch
+deleted file mode 100644
+index 366ff85..0000000
+--- a/package/kernel/mac80211/patches/353-brcmfmac-disable-MBSS-feature-for-BCM43362.patch
++++ /dev/null
+@@ -1,28 +0,0 @@
+-From: Arend van Spriel <arend@broadcom.com>
+-Date: Fri, 20 Mar 2015 22:18:17 +0100
+-Subject: [PATCH] brcmfmac: disable MBSS feature for BCM43362
+-
+-The BCM43362 firmware falsely reports it is capable of providing
+-MBSS. As a result AP mode no longer works for this device. Therefor
+-disable MBSS in the driver for this chipset.
+-
+-Cc: stable@vger.kernel.org # 3.19.y
+-Reported-by: Jorg Krause <jkrause@posteo.de>
+-Reviewed-by: Hante Meuleman <meuleman@broadcom.com>
+-Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
+-Signed-off-by: Arend van Spriel <arend@broadcom.com>
+-Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
+----
+-
+---- a/drivers/net/wireless/brcm80211/brcmfmac/feature.c
+-+++ b/drivers/net/wireless/brcm80211/brcmfmac/feature.c
+-@@ -126,7 +126,8 @@ void brcmf_feat_attach(struct brcmf_pub
+- 	brcmf_feat_iovar_int_get(ifp, BRCMF_FEAT_MCHAN, "mchan");
+- 	if (drvr->bus_if->wowl_supported)
+- 		brcmf_feat_iovar_int_get(ifp, BRCMF_FEAT_WOWL, "wowl");
+--	brcmf_feat_iovar_int_set(ifp, BRCMF_FEAT_MBSS, "mbss", 0);
+-+	if (drvr->bus_if->chip != BRCM_CC_43362_CHIP_ID)
+-+		brcmf_feat_iovar_int_set(ifp, BRCMF_FEAT_MBSS, "mbss", 0);
+- 
+- 	/* set chip related quirks */
+- 	switch (drvr->bus_if->chip) {
+diff --git a/package/kernel/mac80211/patches/354-brcmfmac-use-static-superset-of-channels-for-wiphy-b.patch b/package/kernel/mac80211/patches/354-brcmfmac-use-static-superset-of-channels-for-wiphy-b.patch
+deleted file mode 100644
+index 6e461f6..0000000
+--- a/package/kernel/mac80211/patches/354-brcmfmac-use-static-superset-of-channels-for-wiphy-b.patch
++++ /dev/null
+@@ -1,300 +0,0 @@
+-From: Arend van Spriel <arend@broadcom.com>
+-Date: Tue, 14 Apr 2015 20:10:24 +0200
+-Subject: [PATCH] brcmfmac: use static superset of channels for wiphy
+- bands
+-
+-The driver was constructing a list of channels per wiphy band
+-by querying the device. This list is not what the hardware is
+-able to do as it is already filtered by the country setting in
+-the device. As user-space may change the country this would
+-require updating the channel list which is not recommended [1].
+-This patch introduces a superset of channels. The individual
+-channels are disabled appropriately by querying the device.
+-
+-[1] http://mid.gmane.org/1426706320.3001.21.camel@sipsolutions.net
+-
+-Reviewed-by: Hante Meuleman <meuleman@broadcom.com>
+-Reviewed-by: Daniel (Deognyoun) Kim <dekim@broadcom.com>
+-Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
+-Signed-off-by: Arend van Spriel <arend@broadcom.com>
+----
+-
+---- a/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c
+-+++ b/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c
+-@@ -129,13 +129,47 @@ static struct ieee80211_rate __wl_rates[
+- 	RATETAB_ENT(BRCM_RATE_54M, 0),
+- };
+- 
+--#define wl_a_rates		(__wl_rates + 4)
+--#define wl_a_rates_size	8
+- #define wl_g_rates		(__wl_rates + 0)
+--#define wl_g_rates_size	12
+-+#define wl_g_rates_size		ARRAY_SIZE(__wl_rates)
+-+#define wl_a_rates		(__wl_rates + 4)
+-+#define wl_a_rates_size		(wl_g_rates_size - 4)
+-+
+-+#define CHAN2G(_channel, _freq) {				\
+-+	.band			= IEEE80211_BAND_2GHZ,		\
+-+	.center_freq		= (_freq),			\
+-+	.hw_value		= (_channel),			\
+-+	.flags			= IEEE80211_CHAN_DISABLED,	\
+-+	.max_antenna_gain	= 0,				\
+-+	.max_power		= 30,				\
+-+}
+-+
+-+#define CHAN5G(_channel) {					\
+-+	.band			= IEEE80211_BAND_5GHZ,		\
+-+	.center_freq		= 5000 + (5 * (_channel)),	\
+-+	.hw_value		= (_channel),			\
+-+	.flags			= IEEE80211_CHAN_DISABLED,	\
+-+	.max_antenna_gain	= 0,				\
+-+	.max_power		= 30,				\
+-+}
+-+
+-+static struct ieee80211_channel __wl_2ghz_channels[] = {
+-+	CHAN2G(1, 2412), CHAN2G(2, 2417), CHAN2G(3, 2422), CHAN2G(4, 2427),
+-+	CHAN2G(5, 2432), CHAN2G(6, 2437), CHAN2G(7, 2442), CHAN2G(8, 2447),
+-+	CHAN2G(9, 2452), CHAN2G(10, 2457), CHAN2G(11, 2462), CHAN2G(12, 2467),
+-+	CHAN2G(13, 2472), CHAN2G(14, 2484)
+-+};
+-+
+-+static struct ieee80211_channel __wl_5ghz_channels[] = {
+-+	CHAN5G(34), CHAN5G(36), CHAN5G(38), CHAN5G(40), CHAN5G(42),
+-+	CHAN5G(44), CHAN5G(46), CHAN5G(48), CHAN5G(52), CHAN5G(56),
+-+	CHAN5G(60), CHAN5G(64), CHAN5G(100), CHAN5G(104), CHAN5G(108),
+-+	CHAN5G(112), CHAN5G(116), CHAN5G(120), CHAN5G(124), CHAN5G(128),
+-+	CHAN5G(132), CHAN5G(136), CHAN5G(140), CHAN5G(144), CHAN5G(149),
+-+	CHAN5G(153), CHAN5G(157), CHAN5G(161), CHAN5G(165)
+-+};
+- 
+- /* Band templates duplicated per wiphy. The channel info
+-- * is filled in after querying the device.
+-+ * above is added to the band during setup.
+-  */
+- static const struct ieee80211_supported_band __wl_band_2ghz = {
+- 	.band = IEEE80211_BAND_2GHZ,
+-@@ -143,7 +177,7 @@ static const struct ieee80211_supported_
+- 	.n_bitrates = wl_g_rates_size,
+- };
+- 
+--static const struct ieee80211_supported_band __wl_band_5ghz_a = {
+-+static const struct ieee80211_supported_band __wl_band_5ghz = {
+- 	.band = IEEE80211_BAND_5GHZ,
+- 	.bitrates = wl_a_rates,
+- 	.n_bitrates = wl_a_rates_size,
+-@@ -5252,40 +5286,6 @@ dongle_scantime_out:
+- 	return err;
+- }
+- 
+--/* Filter the list of channels received from firmware counting only
+-- * the 20MHz channels. The wiphy band data only needs those which get
+-- * flagged to indicate if they can take part in higher bandwidth.
+-- */
+--static void brcmf_count_20mhz_channels(struct brcmf_cfg80211_info *cfg,
+--				       struct brcmf_chanspec_list *chlist,
+--				       u32 chcnt[])
+--{
+--	u32 total = le32_to_cpu(chlist->count);
+--	struct brcmu_chan ch;
+--	int i;
+--
+--	for (i = 0; i < total; i++) {
+--		ch.chspec = (u16)le32_to_cpu(chlist->element[i]);
+--		cfg->d11inf.decchspec(&ch);
+--
+--		/* Firmware gives a ordered list. We skip non-20MHz
+--		 * channels is 2G. For 5G we can abort upon reaching
+--		 * a non-20MHz channel in the list.
+--		 */
+--		if (ch.bw != BRCMU_CHAN_BW_20) {
+--			if (ch.band == BRCMU_CHAN_BAND_5G)
+--				break;
+--			else
+--				continue;
+--		}
+--
+--		if (ch.band == BRCMU_CHAN_BAND_2G)
+--			chcnt[0] += 1;
+--		else if (ch.band == BRCMU_CHAN_BAND_5G)
+--			chcnt[1] += 1;
+--	}
+--}
+--
+- static void brcmf_update_bw40_channel_flag(struct ieee80211_channel *channel,
+- 					   struct brcmu_chan *ch)
+- {
+-@@ -5321,7 +5321,6 @@ static int brcmf_construct_chaninfo(stru
+- 	u32 i, j;
+- 	u32 total;
+- 	u32 chaninfo;
+--	u32 chcnt[2] = { 0, 0 };
+- 	u32 index;
+- 
+- 	pbuf = kzalloc(BRCMF_DCMD_MEDLEN, GFP_KERNEL);
+-@@ -5338,42 +5337,15 @@ static int brcmf_construct_chaninfo(stru
+- 		goto fail_pbuf;
+- 	}
+- 
+--	brcmf_count_20mhz_channels(cfg, list, chcnt);
+- 	wiphy = cfg_to_wiphy(cfg);
+--	if (chcnt[0]) {
+--		band = kmemdup(&__wl_band_2ghz, sizeof(__wl_band_2ghz),
+--			       GFP_KERNEL);
+--		if (band == NULL) {
+--			err = -ENOMEM;
+--			goto fail_pbuf;
+--		}
+--		band->channels = kcalloc(chcnt[0], sizeof(*channel),
+--					 GFP_KERNEL);
+--		if (band->channels == NULL) {
+--			kfree(band);
+--			err = -ENOMEM;
+--			goto fail_pbuf;
+--		}
+--		band->n_channels = 0;
+--		wiphy->bands[IEEE80211_BAND_2GHZ] = band;
+--	}
+--	if (chcnt[1]) {
+--		band = kmemdup(&__wl_band_5ghz_a, sizeof(__wl_band_5ghz_a),
+--			       GFP_KERNEL);
+--		if (band == NULL) {
+--			err = -ENOMEM;
+--			goto fail_band2g;
+--		}
+--		band->channels = kcalloc(chcnt[1], sizeof(*channel),
+--					 GFP_KERNEL);
+--		if (band->channels == NULL) {
+--			kfree(band);
+--			err = -ENOMEM;
+--			goto fail_band2g;
+--		}
+--		band->n_channels = 0;
+--		wiphy->bands[IEEE80211_BAND_5GHZ] = band;
+--	}
+-+	band = wiphy->bands[IEEE80211_BAND_2GHZ];
+-+	if (band)
+-+		for (i = 0; i < band->n_channels; i++)
+-+			band->channels[i].flags = IEEE80211_CHAN_DISABLED;
+-+	band = wiphy->bands[IEEE80211_BAND_5GHZ];
+-+	if (band)
+-+		for (i = 0; i < band->n_channels; i++)
+-+			band->channels[i].flags = IEEE80211_CHAN_DISABLED;
+- 
+- 	total = le32_to_cpu(list->count);
+- 	for (i = 0; i < total; i++) {
+-@@ -5388,6 +5360,8 @@ static int brcmf_construct_chaninfo(stru
+- 			brcmf_err("Invalid channel Spec. 0x%x.\n", ch.chspec);
+- 			continue;
+- 		}
+-+		if (!band)
+-+			continue;
+- 		if (!(bw_cap[band->band] & WLC_BW_40MHZ_BIT) &&
+- 		    ch.bw == BRCMU_CHAN_BW_40)
+- 			continue;
+-@@ -5415,9 +5389,9 @@ static int brcmf_construct_chaninfo(stru
+- 		} else if (ch.bw == BRCMU_CHAN_BW_40) {
+- 			brcmf_update_bw40_channel_flag(&channel[index], &ch);
+- 		} else {
+--			/* disable other bandwidths for now as mentioned
+--			 * order assure they are enabled for subsequent
+--			 * chanspecs.
+-+			/* enable the channel and disable other bandwidths
+-+			 * for now as mentioned order assure they are enabled
+-+			 * for subsequent chanspecs.
+- 			 */
+- 			channel[index].flags = IEEE80211_CHAN_NO_HT40 |
+- 					       IEEE80211_CHAN_NO_80MHZ;
+-@@ -5436,16 +5410,8 @@ static int brcmf_construct_chaninfo(stru
+- 						IEEE80211_CHAN_NO_IR;
+- 			}
+- 		}
+--		if (index == band->n_channels)
+--			band->n_channels++;
+- 	}
+--	kfree(pbuf);
+--	return 0;
+- 
+--fail_band2g:
+--	kfree(wiphy->bands[IEEE80211_BAND_2GHZ]->channels);
+--	kfree(wiphy->bands[IEEE80211_BAND_2GHZ]);
+--	wiphy->bands[IEEE80211_BAND_2GHZ] = NULL;
+- fail_pbuf:
+- 	kfree(pbuf);
+- 	return err;
+-@@ -5778,7 +5744,12 @@ static void brcmf_wiphy_wowl_params(stru
+- 
+- static int brcmf_setup_wiphy(struct wiphy *wiphy, struct brcmf_if *ifp)
+- {
+-+	struct ieee80211_supported_band *band;
+- 	struct ieee80211_iface_combination ifc_combo;
+-+	__le32 bandlist[3];
+-+	u32 n_bands;
+-+	int err, i;
+-+
+- 	wiphy->max_scan_ssids = WL_NUM_SCAN_MAX;
+- 	wiphy->max_scan_ie_len = BRCMF_SCAN_IE_LEN_MAX;
+- 	wiphy->max_num_pmkids = WL_NUM_PMKIDS_MAX;
+-@@ -5820,7 +5791,52 @@ static int brcmf_setup_wiphy(struct wiph
+- 	if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_WOWL))
+- 		brcmf_wiphy_wowl_params(wiphy);
+- 
+--	return brcmf_setup_wiphybands(wiphy);
+-+	err = brcmf_fil_cmd_data_get(ifp, BRCMF_C_GET_BANDLIST, &bandlist,
+-+				     sizeof(bandlist));
+-+	if (err) {
+-+		brcmf_err("could not obtain band info: err=%d\n", err);
+-+		return err;
+-+	}
+-+	/* first entry in bandlist is number of bands */
+-+	n_bands = le32_to_cpu(bandlist[0]);
+-+	for (i = 1; i <= n_bands && i < ARRAY_SIZE(bandlist); i++) {
+-+		if (bandlist[i] == cpu_to_le32(WLC_BAND_2G)) {
+-+			band = kmemdup(&__wl_band_2ghz, sizeof(__wl_band_2ghz),
+-+				       GFP_KERNEL);
+-+			if (!band)
+-+				return -ENOMEM;
+-+
+-+			band->channels = kmemdup(&__wl_2ghz_channels,
+-+						 sizeof(__wl_2ghz_channels),
+-+						 GFP_KERNEL);
+-+			if (!band->channels) {
+-+				kfree(band);
+-+				return -ENOMEM;
+-+			}
+-+
+-+			band->n_channels = ARRAY_SIZE(__wl_2ghz_channels);
+-+			wiphy->bands[IEEE80211_BAND_2GHZ] = band;
+-+		}
+-+		if (bandlist[i] == cpu_to_le32(WLC_BAND_5G)) {
+-+			band = kmemdup(&__wl_band_5ghz, sizeof(__wl_band_5ghz),
+-+				       GFP_KERNEL);
+-+			if (!band)
+-+				return -ENOMEM;
+-+
+-+			band->channels = kmemdup(&__wl_5ghz_channels,
+-+						 sizeof(__wl_5ghz_channels),
+-+						 GFP_KERNEL);
+-+			if (!band->channels) {
+-+				kfree(band);
+-+				return -ENOMEM;
+-+			}
+-+
+-+			band->n_channels = ARRAY_SIZE(__wl_5ghz_channels);
+-+			wiphy->bands[IEEE80211_BAND_5GHZ] = band;
+-+		}
+-+	}
+-+	err = brcmf_setup_wiphybands(wiphy);
+-+	return err;
+- }
+- 
+- static s32 brcmf_config_dongle(struct brcmf_cfg80211_info *cfg)
+-@@ -6011,6 +6027,9 @@ static void brcmf_cfg80211_reg_notifier(
+- 
+- static void brcmf_free_wiphy(struct wiphy *wiphy)
+- {
+-+	if (!wiphy)
+-+		return;
+-+
+- 	kfree(wiphy->iface_combinations);
+- 	if (wiphy->bands[IEEE80211_BAND_2GHZ]) {
+- 		kfree(wiphy->bands[IEEE80211_BAND_2GHZ]->channels);
+diff --git a/package/kernel/mac80211/patches/355-brcmfmac-update-wiphy-band-information-upon-updating.patch b/package/kernel/mac80211/patches/355-brcmfmac-update-wiphy-band-information-upon-updating.patch
+deleted file mode 100644
+index a0c22eb..0000000
+--- a/package/kernel/mac80211/patches/355-brcmfmac-update-wiphy-band-information-upon-updating.patch
++++ /dev/null
+@@ -1,29 +0,0 @@
+-From: Arend van Spriel <arend@broadcom.com>
+-Date: Tue, 14 Apr 2015 20:10:25 +0200
+-Subject: [PATCH] brcmfmac: update wiphy band information upon updating
+- regulatory domain
+-
+-When change the country code the available channels may change. So
+-the wiphy bands should be updated accordingly.
+-
+-Reviewed-by: Daniel (Deognyoun) Kim <dekim@broadcom.com>
+-Reviewed-by: Hante Meuleman <meuleman@broadcom.com>
+-Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
+-Signed-off-by: Arend van Spriel <arend@broadcom.com>
+----
+-
+---- a/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c
+-+++ b/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c
+-@@ -6022,7 +6022,11 @@ static void brcmf_cfg80211_reg_notifier(
+- 	memset(&ccreq, 0, sizeof(ccreq));
+- 	ccreq.rev = cpu_to_le32(-1);
+- 	memcpy(ccreq.ccode, req->alpha2, sizeof(req->alpha2));
+--	brcmf_fil_iovar_data_set(ifp, "country", &ccreq, sizeof(ccreq));
+-+	if (brcmf_fil_iovar_data_set(ifp, "country", &ccreq, sizeof(ccreq))) {
+-+		brcmf_err("firmware rejected country setting\n");
+-+		return;
+-+	}
+-+	brcmf_setup_wiphybands(wiphy);
+- }
+- 
+- static void brcmf_free_wiphy(struct wiphy *wiphy)
+diff --git a/package/kernel/mac80211/patches/356-brcmfmac-add-description-for-feature-flags.patch b/package/kernel/mac80211/patches/356-brcmfmac-add-description-for-feature-flags.patch
+deleted file mode 100644
+index 193f507..0000000
+--- a/package/kernel/mac80211/patches/356-brcmfmac-add-description-for-feature-flags.patch
++++ /dev/null
+@@ -1,24 +0,0 @@
+-From: Arend van Spriel <arend@broadcom.com>
+-Date: Tue, 14 Apr 2015 20:10:26 +0200
+-Subject: [PATCH] brcmfmac: add description for feature flags
+-
+-Some feature flags were not described in the header file. Adding
+-the description.
+-
+-Reviewed-by: Hante Meuleman <meuleman@broadcom.com>
+-Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
+-Signed-off-by: Arend van Spriel <arend@broadcom.com>
+----
+-
+---- a/drivers/net/wireless/brcm80211/brcmfmac/feature.h
+-+++ b/drivers/net/wireless/brcm80211/brcmfmac/feature.h
+-@@ -19,7 +19,9 @@
+- /*
+-  * Features:
+-  *
+-+ * MBSS: multiple BSSID support (eg. guest network in AP mode).
+-  * MCHAN: multi-channel for concurrent P2P.
+-+ * WOWL: Wake-On-WLAN.
+-  */
+- #define BRCMF_FEAT_LIST \
+- 	BRCMF_FEAT_DEF(MBSS) \
+diff --git a/package/kernel/mac80211/patches/357-brcmfmac-make-scheduled-scan-support-conditional.patch b/package/kernel/mac80211/patches/357-brcmfmac-make-scheduled-scan-support-conditional.patch
+deleted file mode 100644
+index 42330b4..0000000
+--- a/package/kernel/mac80211/patches/357-brcmfmac-make-scheduled-scan-support-conditional.patch
++++ /dev/null
+@@ -1,51 +0,0 @@
+-From: Arend van Spriel <arend@broadcom.com>
+-Date: Tue, 14 Apr 2015 20:10:27 +0200
+-Subject: [PATCH] brcmfmac: make scheduled scan support conditional
+-
+-The scheduled scan support depends on firmware supporting the PNO
+-feature. This feature is optional so add a feature flag for this
+-in the driver and announce scheduled scan support accordingly.
+-
+-Reviewed-by: Hante Meuleman <meuleman@broadcom.com>
+-Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
+-Signed-off-by: Arend van Spriel <arend@broadcom.com>
+----
+-
+---- a/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c
+-+++ b/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c
+-@@ -5782,7 +5782,8 @@ static int brcmf_setup_wiphy(struct wiph
+- 		wiphy->flags |= WIPHY_FLAG_SUPPORTS_FW_ROAM;
+- 	wiphy->mgmt_stypes = brcmf_txrx_stypes;
+- 	wiphy->max_remain_on_channel_duration = 5000;
+--	brcmf_wiphy_pno_params(wiphy);
+-+	if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_PNO))
+-+		brcmf_wiphy_pno_params(wiphy);
+- 
+- 	/* vendor commands/events support */
+- 	wiphy->vendor_commands = brcmf_vendor_cmds;
+---- a/drivers/net/wireless/brcm80211/brcmfmac/feature.c
+-+++ b/drivers/net/wireless/brcm80211/brcmfmac/feature.c
+-@@ -124,6 +124,7 @@ void brcmf_feat_attach(struct brcmf_pub
+- 	struct brcmf_if *ifp = drvr->iflist[0];
+- 
+- 	brcmf_feat_iovar_int_get(ifp, BRCMF_FEAT_MCHAN, "mchan");
+-+	brcmf_feat_iovar_int_get(ifp, BRCMF_FEAT_PNO, "pfn");
+- 	if (drvr->bus_if->wowl_supported)
+- 		brcmf_feat_iovar_int_get(ifp, BRCMF_FEAT_WOWL, "wowl");
+- 	if (drvr->bus_if->chip != BRCM_CC_43362_CHIP_ID)
+---- a/drivers/net/wireless/brcm80211/brcmfmac/feature.h
+-+++ b/drivers/net/wireless/brcm80211/brcmfmac/feature.h
+-@@ -21,11 +21,13 @@
+-  *
+-  * MBSS: multiple BSSID support (eg. guest network in AP mode).
+-  * MCHAN: multi-channel for concurrent P2P.
+-+ * PNO: preferred network offload.
+-  * WOWL: Wake-On-WLAN.
+-  */
+- #define BRCMF_FEAT_LIST \
+- 	BRCMF_FEAT_DEF(MBSS) \
+- 	BRCMF_FEAT_DEF(MCHAN) \
+-+	BRCMF_FEAT_DEF(PNO) \
+- 	BRCMF_FEAT_DEF(WOWL)
+- /*
+-  * Quirks:
+diff --git a/package/kernel/mac80211/patches/358-brcmfmac-add-support-for-BCM4324-rev-B5-chipset.patch b/package/kernel/mac80211/patches/358-brcmfmac-add-support-for-BCM4324-rev-B5-chipset.patch
+deleted file mode 100644
+index b859d46..0000000
+--- a/package/kernel/mac80211/patches/358-brcmfmac-add-support-for-BCM4324-rev-B5-chipset.patch
++++ /dev/null
+@@ -1,43 +0,0 @@
+-From: Arend van Spriel <arend@broadcom.com>
+-Date: Tue, 14 Apr 2015 20:10:28 +0200
+-Subject: [PATCH] brcmfmac: add support for BCM4324 rev B5 chipset
+-
+-This patch adds support for the BCM4324 B5 revision. This device
+-is similar to BCM43241 from driver and firmware perspective. It
+-is known to be used in Lenovo Thinkpad Tablet devices.
+-
+-Reviewed-by: Hante Meuleman <meuleman@broadcom.com>
+-Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
+-Signed-off-by: Arend van Spriel <arend@broadcom.com>
+----
+-
+---- a/drivers/net/wireless/brcm80211/brcmfmac/sdio.c
+-+++ b/drivers/net/wireless/brcm80211/brcmfmac/sdio.c
+-@@ -601,6 +601,8 @@ static const struct sdiod_drive_str sdio
+- #define BCM43241B0_NVRAM_NAME		"brcm/brcmfmac43241b0-sdio.txt"
+- #define BCM43241B4_FIRMWARE_NAME	"brcm/brcmfmac43241b4-sdio.bin"
+- #define BCM43241B4_NVRAM_NAME		"brcm/brcmfmac43241b4-sdio.txt"
+-+#define BCM43241B5_FIRMWARE_NAME	"brcm/brcmfmac43241b5-sdio.bin"
+-+#define BCM43241B5_NVRAM_NAME		"brcm/brcmfmac43241b5-sdio.txt"
+- #define BCM4329_FIRMWARE_NAME		"brcm/brcmfmac4329-sdio.bin"
+- #define BCM4329_NVRAM_NAME		"brcm/brcmfmac4329-sdio.txt"
+- #define BCM4330_FIRMWARE_NAME		"brcm/brcmfmac4330-sdio.bin"
+-@@ -628,6 +630,8 @@ MODULE_FIRMWARE(BCM43241B0_FIRMWARE_NAME
+- MODULE_FIRMWARE(BCM43241B0_NVRAM_NAME);
+- MODULE_FIRMWARE(BCM43241B4_FIRMWARE_NAME);
+- MODULE_FIRMWARE(BCM43241B4_NVRAM_NAME);
+-+MODULE_FIRMWARE(BCM43241B5_FIRMWARE_NAME);
+-+MODULE_FIRMWARE(BCM43241B5_NVRAM_NAME);
+- MODULE_FIRMWARE(BCM4329_FIRMWARE_NAME);
+- MODULE_FIRMWARE(BCM4329_NVRAM_NAME);
+- MODULE_FIRMWARE(BCM4330_FIRMWARE_NAME);
+-@@ -667,7 +671,8 @@ enum brcmf_firmware_type {
+- static const struct brcmf_firmware_names brcmf_fwname_data[] = {
+- 	{ BRCM_CC_43143_CHIP_ID, 0xFFFFFFFF, BRCMF_FIRMWARE_NVRAM(BCM43143) },
+- 	{ BRCM_CC_43241_CHIP_ID, 0x0000001F, BRCMF_FIRMWARE_NVRAM(BCM43241B0) },
+--	{ BRCM_CC_43241_CHIP_ID, 0xFFFFFFE0, BRCMF_FIRMWARE_NVRAM(BCM43241B4) },
+-+	{ BRCM_CC_43241_CHIP_ID, 0x00000020, BRCMF_FIRMWARE_NVRAM(BCM43241B4) },
+-+	{ BRCM_CC_43241_CHIP_ID, 0xFFFFFFC0, BRCMF_FIRMWARE_NVRAM(BCM43241B5) },
+- 	{ BRCM_CC_4329_CHIP_ID, 0xFFFFFFFF, BRCMF_FIRMWARE_NVRAM(BCM4329) },
+- 	{ BRCM_CC_4330_CHIP_ID, 0xFFFFFFFF, BRCMF_FIRMWARE_NVRAM(BCM4330) },
+- 	{ BRCM_CC_4334_CHIP_ID, 0xFFFFFFFF, BRCMF_FIRMWARE_NVRAM(BCM4334) },
+diff --git a/package/kernel/mac80211/patches/359-brcmfmac-process-interrupt-regardless-sdiod-state.patch b/package/kernel/mac80211/patches/359-brcmfmac-process-interrupt-regardless-sdiod-state.patch
+deleted file mode 100644
+index d420308..0000000
+--- a/package/kernel/mac80211/patches/359-brcmfmac-process-interrupt-regardless-sdiod-state.patch
++++ /dev/null
+@@ -1,27 +0,0 @@
+-From: Arend van Spriel <arend@broadcom.com>
+-Date: Tue, 14 Apr 2015 20:10:29 +0200
+-Subject: [PATCH] brcmfmac: process interrupt regardless sdiod state
+-
+-When the sdio bus state is not ready to process we abort the
+-interrupt service routine. This is not wanted as it keeps the
+-interrupt source active. Better clear the interrupt source.
+-
+-Reviewed-by: Hante Meuleman <meuleman@broadcom.com>
+-Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
+-Reviewed-by: Franky (Zhenhui) Lin <frankyl@broadcom.com>
+-Signed-off-by: Arend van Spriel <arend@broadcom.com>
+----
+-
+---- a/drivers/net/wireless/brcm80211/brcmfmac/sdio.c
+-+++ b/drivers/net/wireless/brcm80211/brcmfmac/sdio.c
+-@@ -3555,10 +3555,6 @@ void brcmf_sdio_isr(struct brcmf_sdio *b
+- 		return;
+- 	}
+- 
+--	if (bus->sdiodev->state != BRCMF_SDIOD_DATA) {
+--		brcmf_err("bus is down. we have nothing to do\n");
+--		return;
+--	}
+- 	/* Count the interrupt call */
+- 	bus->sdcnt.intrcount++;
+- 	if (in_interrupt())
+diff --git a/package/kernel/mac80211/patches/360-brcmfmac-fix-sdio-suspend-and-resume.patch b/package/kernel/mac80211/patches/360-brcmfmac-fix-sdio-suspend-and-resume.patch
+deleted file mode 100644
+index ac5584e..0000000
+--- a/package/kernel/mac80211/patches/360-brcmfmac-fix-sdio-suspend-and-resume.patch
++++ /dev/null
+@@ -1,68 +0,0 @@
+-From: Arend van Spriel <arend@broadcom.com>
+-Date: Tue, 14 Apr 2015 20:10:30 +0200
+-Subject: [PATCH] brcmfmac: fix sdio suspend and resume
+-
+-commit 330b4e4be937 ("brcmfmac: Add wowl support for SDIO devices.")
+-changed the behaviour by removing the MMC_PM_KEEP_POWER flag for
+-non-wowl scenario, which needs to be restored. Another necessary
+-change is to mark the card as being non-removable. With this in place
+-the suspend resume test passes successfully doing:
+-
+- # echo devices > /sys/power/pm_test
+- # echo mem > /sys/power/state
+-
+-Note that power may still be switched off when system is going
+-in S3 state.
+-
+-Reported-by: Fu, Zhonghui <<zhonghui.fu@linux.intel.com>
+-Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
+-Reviewed-by: Franky (Zhenhui) Lin <frankyl@broadcom.com>
+-Signed-off-by: Arend van Spriel <arend@broadcom.com>
+----
+-
+---- a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c
+-+++ b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c
+-@@ -1011,6 +1011,14 @@ static int brcmf_sdiod_remove(struct brc
+- 	return 0;
+- }
+- 
+-+static void brcmf_sdiod_host_fixup(struct mmc_host *host)
+-+{
+-+	/* runtime-pm powers off the device */
+-+	pm_runtime_forbid(host->parent);
+-+	/* avoid removal detection upon resume */
+-+	host->caps |= MMC_CAP_NONREMOVABLE;
+-+}
+-+
+- static int brcmf_sdiod_probe(struct brcmf_sdio_dev *sdiodev)
+- {
+- 	struct sdio_func *func;
+-@@ -1076,7 +1084,7 @@ static int brcmf_sdiod_probe(struct brcm
+- 		ret = -ENODEV;
+- 		goto out;
+- 	}
+--	pm_runtime_forbid(host->parent);
+-+	brcmf_sdiod_host_fixup(host);
+- out:
+- 	if (ret)
+- 		brcmf_sdiod_remove(sdiodev);
+-@@ -1246,15 +1254,15 @@ static int brcmf_ops_sdio_suspend(struct
+- 	brcmf_sdiod_freezer_on(sdiodev);
+- 	brcmf_sdio_wd_timer(sdiodev->bus, 0);
+- 
+-+	sdio_flags = MMC_PM_KEEP_POWER;
+- 	if (sdiodev->wowl_enabled) {
+--		sdio_flags = MMC_PM_KEEP_POWER;
+- 		if (sdiodev->pdata->oob_irq_supported)
+- 			enable_irq_wake(sdiodev->pdata->oob_irq_nr);
+- 		else
+--			sdio_flags = MMC_PM_WAKE_SDIO_IRQ;
+--		if (sdio_set_host_pm_flags(sdiodev->func[1], sdio_flags))
+--			brcmf_err("Failed to set pm_flags %x\n", sdio_flags);
+-+			sdio_flags |= MMC_PM_WAKE_SDIO_IRQ;
+- 	}
+-+	if (sdio_set_host_pm_flags(sdiodev->func[1], sdio_flags))
+-+		brcmf_err("Failed to set pm_flags %x\n", sdio_flags);
+- 	return 0;
+- }
+- 
+diff --git a/package/kernel/mac80211/patches/361-brcmfmac-add-support-for-BCM4358-PCIe-device.patch b/package/kernel/mac80211/patches/361-brcmfmac-add-support-for-BCM4358-PCIe-device.patch
+deleted file mode 100644
+index a521b65..0000000
+--- a/package/kernel/mac80211/patches/361-brcmfmac-add-support-for-BCM4358-PCIe-device.patch
++++ /dev/null
+@@ -1,77 +0,0 @@
+-From: Arend van Spriel <arend@broadcom.com>
+-Date: Tue, 14 Apr 2015 20:10:31 +0200
+-Subject: [PATCH] brcmfmac: add support for BCM4358 PCIe device
+-
+-This patch adds support for the BCM4358 2x2 11ac device.
+-
+-Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
+-Signed-off-by: Arend van Spriel <arend@broadcom.com>
+----
+-
+---- a/drivers/net/wireless/brcm80211/brcmfmac/chip.c
+-+++ b/drivers/net/wireless/brcm80211/brcmfmac/chip.c
+-@@ -649,6 +649,7 @@ static u32 brcmf_chip_tcm_rambase(struct
+- 	case BRCM_CC_43567_CHIP_ID:
+- 	case BRCM_CC_43569_CHIP_ID:
+- 	case BRCM_CC_43570_CHIP_ID:
+-+	case BRCM_CC_4358_CHIP_ID:
+- 	case BRCM_CC_43602_CHIP_ID:
+- 		return 0x180000;
+- 	default:
+---- a/drivers/net/wireless/brcm80211/brcmfmac/pcie.c
+-+++ b/drivers/net/wireless/brcm80211/brcmfmac/pcie.c
+-@@ -51,6 +51,8 @@ enum brcmf_pcie_state {
+- #define BRCMF_PCIE_4356_NVRAM_NAME		"brcm/brcmfmac4356-pcie.txt"
+- #define BRCMF_PCIE_43570_FW_NAME		"brcm/brcmfmac43570-pcie.bin"
+- #define BRCMF_PCIE_43570_NVRAM_NAME		"brcm/brcmfmac43570-pcie.txt"
+-+#define BRCMF_PCIE_4358_FW_NAME			"brcm/brcmfmac4358-pcie.bin"
+-+#define BRCMF_PCIE_4358_NVRAM_NAME		"brcm/brcmfmac4358-pcie.txt"
+- 
+- #define BRCMF_PCIE_FW_UP_TIMEOUT		2000 /* msec */
+- 
+-@@ -189,6 +191,8 @@ MODULE_FIRMWARE(BRCMF_PCIE_4356_FW_NAME)
+- MODULE_FIRMWARE(BRCMF_PCIE_4356_NVRAM_NAME);
+- MODULE_FIRMWARE(BRCMF_PCIE_43570_FW_NAME);
+- MODULE_FIRMWARE(BRCMF_PCIE_43570_NVRAM_NAME);
+-+MODULE_FIRMWARE(BRCMF_PCIE_4358_FW_NAME);
+-+MODULE_FIRMWARE(BRCMF_PCIE_4358_NVRAM_NAME);
+- 
+- 
+- struct brcmf_pcie_console {
+-@@ -1333,6 +1337,10 @@ static int brcmf_pcie_get_fwnames(struct
+- 		fw_name = BRCMF_PCIE_43570_FW_NAME;
+- 		nvram_name = BRCMF_PCIE_43570_NVRAM_NAME;
+- 		break;
+-+	case BRCM_CC_4358_CHIP_ID:
+-+		fw_name = BRCMF_PCIE_4358_FW_NAME;
+-+		nvram_name = BRCMF_PCIE_4358_NVRAM_NAME;
+-+		break;
+- 	default:
+- 		brcmf_err("Unsupported chip 0x%04x\n", devinfo->ci->chip);
+- 		return -ENODEV;
+-@@ -1850,6 +1858,7 @@ static struct pci_device_id brcmf_pcie_d
+- 	BRCMF_PCIE_DEVICE(BRCM_PCIE_4356_DEVICE_ID),
+- 	BRCMF_PCIE_DEVICE(BRCM_PCIE_43567_DEVICE_ID),
+- 	BRCMF_PCIE_DEVICE(BRCM_PCIE_43570_DEVICE_ID),
+-+	BRCMF_PCIE_DEVICE(BRCM_PCIE_4358_DEVICE_ID),
+- 	BRCMF_PCIE_DEVICE(BRCM_PCIE_43602_DEVICE_ID),
+- 	BRCMF_PCIE_DEVICE(BRCM_PCIE_43602_2G_DEVICE_ID),
+- 	BRCMF_PCIE_DEVICE(BRCM_PCIE_43602_5G_DEVICE_ID),
+---- a/drivers/net/wireless/brcm80211/include/brcm_hw_ids.h
+-+++ b/drivers/net/wireless/brcm80211/include/brcm_hw_ids.h
+-@@ -45,6 +45,7 @@
+- #define BRCM_CC_43567_CHIP_ID		43567
+- #define BRCM_CC_43569_CHIP_ID		43569
+- #define BRCM_CC_43570_CHIP_ID		43570
+-+#define BRCM_CC_4358_CHIP_ID		0x4358
+- #define BRCM_CC_43602_CHIP_ID		43602
+- 
+- /* USB Device IDs */
+-@@ -59,6 +60,7 @@
+- #define BRCM_PCIE_4356_DEVICE_ID	0x43ec
+- #define BRCM_PCIE_43567_DEVICE_ID	0x43d3
+- #define BRCM_PCIE_43570_DEVICE_ID	0x43d9
+-+#define BRCM_PCIE_4358_DEVICE_ID	0x43e9
+- #define BRCM_PCIE_43602_DEVICE_ID	0x43ba
+- #define BRCM_PCIE_43602_2G_DEVICE_ID	0x43bb
+- #define BRCM_PCIE_43602_5G_DEVICE_ID	0x43bc
+diff --git a/package/kernel/mac80211/patches/362-brcmfmac-add-additional-43602-pcie-device-id.patch b/package/kernel/mac80211/patches/362-brcmfmac-add-additional-43602-pcie-device-id.patch
+deleted file mode 100644
+index bcbb984..0000000
+--- a/package/kernel/mac80211/patches/362-brcmfmac-add-additional-43602-pcie-device-id.patch
++++ /dev/null
+@@ -1,30 +0,0 @@
+-From: Hante Meuleman <meuleman@broadcom.com>
+-Date: Tue, 14 Apr 2015 20:10:32 +0200
+-Subject: [PATCH] brcmfmac: add additional 43602 pcie device id.
+-
+-Reviewed-by: Arend Van Spriel <arend@broadcom.com>
+-Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
+-Signed-off-by: Hante Meuleman <meuleman@broadcom.com>
+-Signed-off-by: Arend van Spriel <arend@broadcom.com>
+----
+-
+---- a/drivers/net/wireless/brcm80211/brcmfmac/pcie.c
+-+++ b/drivers/net/wireless/brcm80211/brcmfmac/pcie.c
+-@@ -1862,6 +1862,7 @@ static struct pci_device_id brcmf_pcie_d
+- 	BRCMF_PCIE_DEVICE(BRCM_PCIE_43602_DEVICE_ID),
+- 	BRCMF_PCIE_DEVICE(BRCM_PCIE_43602_2G_DEVICE_ID),
+- 	BRCMF_PCIE_DEVICE(BRCM_PCIE_43602_5G_DEVICE_ID),
+-+	BRCMF_PCIE_DEVICE(BRCM_PCIE_43602_RAW_DEVICE_ID),
+- 	{ /* end: all zeroes */ }
+- };
+- 
+---- a/drivers/net/wireless/brcm80211/include/brcm_hw_ids.h
+-+++ b/drivers/net/wireless/brcm80211/include/brcm_hw_ids.h
+-@@ -64,6 +64,7 @@
+- #define BRCM_PCIE_43602_DEVICE_ID	0x43ba
+- #define BRCM_PCIE_43602_2G_DEVICE_ID	0x43bb
+- #define BRCM_PCIE_43602_5G_DEVICE_ID	0x43bc
+-+#define BRCM_PCIE_43602_RAW_DEVICE_ID	43602
+- 
+- /* brcmsmac IDs */
+- #define BCM4313_D11N2G_ID	0x4727	/* 4313 802.11n 2.4G device */
+diff --git a/package/kernel/mac80211/patches/363-brcmfmac-Add-support-for-multiple-PCIE-devices-in-nv.patch b/package/kernel/mac80211/patches/363-brcmfmac-Add-support-for-multiple-PCIE-devices-in-nv.patch
+deleted file mode 100644
+index 5f9bbea..0000000
+--- a/package/kernel/mac80211/patches/363-brcmfmac-Add-support-for-multiple-PCIE-devices-in-nv.patch
++++ /dev/null
+@@ -1,351 +0,0 @@
+-From: Hante Meuleman <meuleman@broadcom.com>
+-Date: Tue, 14 Apr 2015 20:10:33 +0200
+-Subject: [PATCH] brcmfmac: Add support for multiple PCIE devices in
+- nvram.
+-
+-With PCIE it is possible to support multiple devices with the
+-same device type. They all load the same nvram file. In order to
+-support this the nvram can specify which part of the nvram is
+-for which pcie device. This patch adds support for these new
+-types of nvram files.
+-
+-Reviewed-by: Arend Van Spriel <arend@broadcom.com>
+-Reviewed-by: Franky (Zhenhui) Lin <frankyl@broadcom.com>
+-Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
+-Reviewed-by: Daniel (Deognyoun) Kim <dekim@broadcom.com>
+-Signed-off-by: Hante Meuleman <meuleman@broadcom.com>
+-Signed-off-by: Arend van Spriel <arend@broadcom.com>
+----
+-
+---- a/drivers/net/wireless/brcm80211/brcmfmac/firmware.c
+-+++ b/drivers/net/wireless/brcm80211/brcmfmac/firmware.c
+-@@ -23,6 +23,10 @@
+- #include "debug.h"
+- #include "firmware.h"
+- 
+-+#define BRCMF_FW_MAX_NVRAM_SIZE			64000
+-+#define BRCMF_FW_NVRAM_DEVPATH_LEN		19	/* devpath0=pcie/1/4/ */
+-+#define BRCMF_FW_NVRAM_PCIEDEV_LEN		9	/* pcie/1/4/ */
+-+
+- char brcmf_firmware_path[BRCMF_FW_PATH_LEN];
+- module_param_string(firmware_path, brcmf_firmware_path,
+- 		    BRCMF_FW_PATH_LEN, 0440);
+-@@ -46,6 +50,8 @@ enum nvram_parser_state {
+-  * @column: current column in line.
+-  * @pos: byte offset in input buffer.
+-  * @entry: start position of key,value entry.
+-+ * @multi_dev_v1: detect pcie multi device v1 (compressed).
+-+ * @multi_dev_v2: detect pcie multi device v2.
+-  */
+- struct nvram_parser {
+- 	enum nvram_parser_state state;
+-@@ -56,6 +62,8 @@ struct nvram_parser {
+- 	u32 column;
+- 	u32 pos;
+- 	u32 entry;
+-+	bool multi_dev_v1;
+-+	bool multi_dev_v2;
+- };
+- 
+- static bool is_nvram_char(char c)
+-@@ -108,6 +116,10 @@ static enum nvram_parser_state brcmf_nvr
+- 			st = COMMENT;
+- 		else
+- 			st = VALUE;
+-+		if (strncmp(&nvp->fwnv->data[nvp->entry], "devpath", 7) == 0)
+-+			nvp->multi_dev_v1 = true;
+-+		if (strncmp(&nvp->fwnv->data[nvp->entry], "pcie/", 5) == 0)
+-+			nvp->multi_dev_v2 = true;
+- 	} else if (!is_nvram_char(c)) {
+- 		brcmf_dbg(INFO, "warning: ln=%d:col=%d: '=' expected, skip invalid key entry\n",
+- 			  nvp->line, nvp->column);
+-@@ -133,6 +145,8 @@ brcmf_nvram_handle_value(struct nvram_pa
+- 		ekv = (u8 *)&nvp->fwnv->data[nvp->pos];
+- 		skv = (u8 *)&nvp->fwnv->data[nvp->entry];
+- 		cplen = ekv - skv;
+-+		if (nvp->nvram_len + cplen + 1 >= BRCMF_FW_MAX_NVRAM_SIZE)
+-+			return END;
+- 		/* copy to output buffer */
+- 		memcpy(&nvp->nvram[nvp->nvram_len], skv, cplen);
+- 		nvp->nvram_len += cplen;
+-@@ -180,10 +194,18 @@ static enum nvram_parser_state
+- static int brcmf_init_nvram_parser(struct nvram_parser *nvp,
+- 				   const struct firmware *nv)
+- {
+-+	size_t size;
+-+
+- 	memset(nvp, 0, sizeof(*nvp));
+- 	nvp->fwnv = nv;
+-+	/* Limit size to MAX_NVRAM_SIZE, some files contain lot of comment */
+-+	if (nv->size > BRCMF_FW_MAX_NVRAM_SIZE)
+-+		size = BRCMF_FW_MAX_NVRAM_SIZE;
+-+	else
+-+		size = nv->size;
+- 	/* Alloc for extra 0 byte + roundup by 4 + length field */
+--	nvp->nvram = kzalloc(nv->size + 1 + 3 + sizeof(u32), GFP_KERNEL);
+-+	size += 1 + 3 + sizeof(u32);
+-+	nvp->nvram = kzalloc(size, GFP_KERNEL);
+- 	if (!nvp->nvram)
+- 		return -ENOMEM;
+- 
+-@@ -192,12 +214,136 @@ static int brcmf_init_nvram_parser(struc
+- 	return 0;
+- }
+- 
+-+/* brcmf_fw_strip_multi_v1 :Some nvram files contain settings for multiple
+-+ * devices. Strip it down for one device, use domain_nr/bus_nr to determine
+-+ * which data is to be returned. v1 is the version where nvram is stored
+-+ * compressed and "devpath" maps to index for valid entries.
+-+ */
+-+static void brcmf_fw_strip_multi_v1(struct nvram_parser *nvp, u16 domain_nr,
+-+				    u16 bus_nr)
+-+{
+-+	u32 i, j;
+-+	bool found;
+-+	u8 *nvram;
+-+	u8 id;
+-+
+-+	nvram = kzalloc(nvp->nvram_len + 1 + 3 + sizeof(u32), GFP_KERNEL);
+-+	if (!nvram)
+-+		goto fail;
+-+
+-+	/* min length: devpath0=pcie/1/4/ + 0:x=y */
+-+	if (nvp->nvram_len < BRCMF_FW_NVRAM_DEVPATH_LEN + 6)
+-+		goto fail;
+-+
+-+	/* First search for the devpathX and see if it is the configuration
+-+	 * for domain_nr/bus_nr. Search complete nvp
+-+	 */
+-+	found = false;
+-+	i = 0;
+-+	while (i < nvp->nvram_len - BRCMF_FW_NVRAM_DEVPATH_LEN) {
+-+		/* Format: devpathX=pcie/Y/Z/
+-+		 * Y = domain_nr, Z = bus_nr, X = virtual ID
+-+		 */
+-+		if ((strncmp(&nvp->nvram[i], "devpath", 7) == 0) &&
+-+		    (strncmp(&nvp->nvram[i + 8], "=pcie/", 6) == 0)) {
+-+			if (((nvp->nvram[i + 14] - '0') == domain_nr) &&
+-+			    ((nvp->nvram[i + 16] - '0') == bus_nr)) {
+-+				id = nvp->nvram[i + 7] - '0';
+-+				found = true;
+-+				break;
+-+			}
+-+		}
+-+		while (nvp->nvram[i] != 0)
+-+			i++;
+-+		i++;
+-+	}
+-+	if (!found)
+-+		goto fail;
+-+
+-+	/* Now copy all valid entries, release old nvram and assign new one */
+-+	i = 0;
+-+	j = 0;
+-+	while (i < nvp->nvram_len) {
+-+		if ((nvp->nvram[i] - '0' == id) && (nvp->nvram[i + 1] == ':')) {
+-+			i += 2;
+-+			while (nvp->nvram[i] != 0) {
+-+				nvram[j] = nvp->nvram[i];
+-+				i++;
+-+				j++;
+-+			}
+-+			nvram[j] = 0;
+-+			j++;
+-+		}
+-+		while (nvp->nvram[i] != 0)
+-+			i++;
+-+		i++;
+-+	}
+-+	kfree(nvp->nvram);
+-+	nvp->nvram = nvram;
+-+	nvp->nvram_len = j;
+-+	return;
+-+
+-+fail:
+-+	kfree(nvram);
+-+	nvp->nvram_len = 0;
+-+}
+-+
+-+/* brcmf_fw_strip_multi_v2 :Some nvram files contain settings for multiple
+-+ * devices. Strip it down for one device, use domain_nr/bus_nr to determine
+-+ * which data is to be returned. v2 is the version where nvram is stored
+-+ * uncompressed, all relevant valid entries are identified by
+-+ * pcie/domain_nr/bus_nr:
+-+ */
+-+static void brcmf_fw_strip_multi_v2(struct nvram_parser *nvp, u16 domain_nr,
+-+				    u16 bus_nr)
+-+{
+-+	u32 i, j;
+-+	u8 *nvram;
+-+
+-+	nvram = kzalloc(nvp->nvram_len + 1 + 3 + sizeof(u32), GFP_KERNEL);
+-+	if (!nvram)
+-+		goto fail;
+-+
+-+	/* Copy all valid entries, release old nvram and assign new one.
+-+	 * Valid entries are of type pcie/X/Y/ where X = domain_nr and
+-+	 * Y = bus_nr.
+-+	 */
+-+	i = 0;
+-+	j = 0;
+-+	while (i < nvp->nvram_len - BRCMF_FW_NVRAM_PCIEDEV_LEN) {
+-+		if ((strncmp(&nvp->nvram[i], "pcie/", 5) == 0) &&
+-+		    (nvp->nvram[i + 6] == '/') && (nvp->nvram[i + 8] == '/') &&
+-+		    ((nvp->nvram[i + 5] - '0') == domain_nr) &&
+-+		    ((nvp->nvram[i + 7] - '0') == bus_nr)) {
+-+			i += BRCMF_FW_NVRAM_PCIEDEV_LEN;
+-+			while (nvp->nvram[i] != 0) {
+-+				nvram[j] = nvp->nvram[i];
+-+				i++;
+-+				j++;
+-+			}
+-+			nvram[j] = 0;
+-+			j++;
+-+		}
+-+		while (nvp->nvram[i] != 0)
+-+			i++;
+-+		i++;
+-+	}
+-+	kfree(nvp->nvram);
+-+	nvp->nvram = nvram;
+-+	nvp->nvram_len = j;
+-+	return;
+-+fail:
+-+	kfree(nvram);
+-+	nvp->nvram_len = 0;
+-+}
+-+
+- /* brcmf_nvram_strip :Takes a buffer of "<var>=<value>\n" lines read from a fil
+-  * and ending in a NUL. Removes carriage returns, empty lines, comment lines,
+-  * and converts newlines to NULs. Shortens buffer as needed and pads with NULs.
+-  * End of buffer is completed with token identifying length of buffer.
+-  */
+--static void *brcmf_fw_nvram_strip(const struct firmware *nv, u32 *new_length)
+-+static void *brcmf_fw_nvram_strip(const struct firmware *nv, u32 *new_length,
+-+				  u16 domain_nr, u16 bus_nr)
+- {
+- 	struct nvram_parser nvp;
+- 	u32 pad;
+-@@ -212,6 +358,16 @@ static void *brcmf_fw_nvram_strip(const
+- 		if (nvp.state == END)
+- 			break;
+- 	}
+-+	if (nvp.multi_dev_v1)
+-+		brcmf_fw_strip_multi_v1(&nvp, domain_nr, bus_nr);
+-+	else if (nvp.multi_dev_v2)
+-+		brcmf_fw_strip_multi_v2(&nvp, domain_nr, bus_nr);
+-+
+-+	if (nvp.nvram_len == 0) {
+-+		kfree(nvp.nvram);
+-+		return NULL;
+-+	}
+-+
+- 	pad = nvp.nvram_len;
+- 	*new_length = roundup(nvp.nvram_len + 1, 4);
+- 	while (pad != *new_length) {
+-@@ -239,6 +395,8 @@ struct brcmf_fw {
+- 	u16 flags;
+- 	const struct firmware *code;
+- 	const char *nvram_name;
+-+	u16 domain_nr;
+-+	u16 bus_nr;
+- 	void (*done)(struct device *dev, const struct firmware *fw,
+- 		     void *nvram_image, u32 nvram_len);
+- };
+-@@ -254,7 +412,8 @@ static void brcmf_fw_request_nvram_done(
+- 		goto fail;
+- 
+- 	if (fw) {
+--		nvram = brcmf_fw_nvram_strip(fw, &nvram_length);
+-+		nvram = brcmf_fw_nvram_strip(fw, &nvram_length,
+-+					     fwctx->domain_nr, fwctx->bus_nr);
+- 		release_firmware(fw);
+- 		if (!nvram && !(fwctx->flags & BRCMF_FW_REQ_NV_OPTIONAL))
+- 			goto fail;
+-@@ -309,11 +468,12 @@ fail:
+- 	kfree(fwctx);
+- }
+- 
+--int brcmf_fw_get_firmwares(struct device *dev, u16 flags,
+--			   const char *code, const char *nvram,
+--			   void (*fw_cb)(struct device *dev,
+--					 const struct firmware *fw,
+--					 void *nvram_image, u32 nvram_len))
+-+int brcmf_fw_get_firmwares_pcie(struct device *dev, u16 flags,
+-+				const char *code, const char *nvram,
+-+				void (*fw_cb)(struct device *dev,
+-+					      const struct firmware *fw,
+-+					      void *nvram_image, u32 nvram_len),
+-+				u16 domain_nr, u16 bus_nr)
+- {
+- 	struct brcmf_fw *fwctx;
+- 
+-@@ -333,8 +493,21 @@ int brcmf_fw_get_firmwares(struct device
+- 	fwctx->done = fw_cb;
+- 	if (flags & BRCMF_FW_REQUEST_NVRAM)
+- 		fwctx->nvram_name = nvram;
+-+	fwctx->domain_nr = domain_nr;
+-+	fwctx->bus_nr = bus_nr;
+- 
+- 	return request_firmware_nowait(THIS_MODULE, true, code, dev,
+- 				       GFP_KERNEL, fwctx,
+- 				       brcmf_fw_request_code_done);
+- }
+-+
+-+int brcmf_fw_get_firmwares(struct device *dev, u16 flags,
+-+			   const char *code, const char *nvram,
+-+			   void (*fw_cb)(struct device *dev,
+-+					 const struct firmware *fw,
+-+					 void *nvram_image, u32 nvram_len))
+-+{
+-+	return brcmf_fw_get_firmwares_pcie(dev, flags, code, nvram, fw_cb, 0,
+-+					   0);
+-+}
+-+
+---- a/drivers/net/wireless/brcm80211/brcmfmac/firmware.h
+-+++ b/drivers/net/wireless/brcm80211/brcmfmac/firmware.h
+-@@ -32,6 +32,12 @@ void brcmf_fw_nvram_free(void *nvram);
+-  * fails it will not use the callback, but call device_release_driver()
+-  * instead which will call the driver .remove() callback.
+-  */
+-+int brcmf_fw_get_firmwares_pcie(struct device *dev, u16 flags,
+-+				const char *code, const char *nvram,
+-+				void (*fw_cb)(struct device *dev,
+-+					      const struct firmware *fw,
+-+					      void *nvram_image, u32 nvram_len),
+-+				u16 domain_nr, u16 bus_nr);
+- int brcmf_fw_get_firmwares(struct device *dev, u16 flags,
+- 			   const char *code, const char *nvram,
+- 			   void (*fw_cb)(struct device *dev,
+---- a/drivers/net/wireless/brcm80211/brcmfmac/pcie.c
+-+++ b/drivers/net/wireless/brcm80211/brcmfmac/pcie.c
+-@@ -1649,8 +1649,13 @@ brcmf_pcie_probe(struct pci_dev *pdev, c
+- 	struct brcmf_pciedev_info *devinfo;
+- 	struct brcmf_pciedev *pcie_bus_dev;
+- 	struct brcmf_bus *bus;
+-+	u16 domain_nr;
+-+	u16 bus_nr;
+- 
+--	brcmf_dbg(PCIE, "Enter %x:%x\n", pdev->vendor, pdev->device);
+-+	domain_nr = pci_domain_nr(pdev->bus) + 1;
+-+	bus_nr = pdev->bus->number;
+-+	brcmf_dbg(PCIE, "Enter %x:%x (%d/%d)\n", pdev->vendor, pdev->device,
+-+		  domain_nr, bus_nr);
+- 
+- 	ret = -ENOMEM;
+- 	devinfo = kzalloc(sizeof(*devinfo), GFP_KERNEL);
+-@@ -1699,10 +1704,10 @@ brcmf_pcie_probe(struct pci_dev *pdev, c
+- 	if (ret)
+- 		goto fail_bus;
+- 
+--	ret = brcmf_fw_get_firmwares(bus->dev, BRCMF_FW_REQUEST_NVRAM |
+--					       BRCMF_FW_REQ_NV_OPTIONAL,
+--				     devinfo->fw_name, devinfo->nvram_name,
+--				     brcmf_pcie_setup);
+-+	ret = brcmf_fw_get_firmwares_pcie(bus->dev, BRCMF_FW_REQUEST_NVRAM |
+-+						    BRCMF_FW_REQ_NV_OPTIONAL,
+-+					  devinfo->fw_name, devinfo->nvram_name,
+-+					  brcmf_pcie_setup, domain_nr, bus_nr);
+- 	if (ret == 0)
+- 		return 0;
+- fail_bus:
+diff --git a/package/kernel/mac80211/patches/364-brcmfmac-cleanup-a-sizeof.patch b/package/kernel/mac80211/patches/364-brcmfmac-cleanup-a-sizeof.patch
+deleted file mode 100644
+index d26e118..0000000
+--- a/package/kernel/mac80211/patches/364-brcmfmac-cleanup-a-sizeof.patch
++++ /dev/null
+@@ -1,23 +0,0 @@
+-From: Dan Carpenter <dan.carpenter@oracle.com>
+-Date: Thu, 7 May 2015 12:59:19 +0300
+-Subject: [PATCH] brcmfmac: cleanup a sizeof()
+-
+-"flowrings" and "*flowrings" are both pointers so this always returns
+-sizeof(void *) and the current code works fine.  But "*flowrings" is
+-intended here and static checkers complain, so lets change it.
+-
+-Signed-off-by: Dan Carpenter <dan.carpenter@oracle.com>
+-Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
+----
+-
+---- a/drivers/net/wireless/brcm80211/brcmfmac/pcie.c
+-+++ b/drivers/net/wireless/brcm80211/brcmfmac/pcie.c
+-@@ -1617,7 +1617,7 @@ static void brcmf_pcie_setup(struct devi
+- 		bus->msgbuf->commonrings[i] =
+- 				&devinfo->shared.commonrings[i]->commonring;
+- 
+--	flowrings = kcalloc(devinfo->shared.nrof_flowrings, sizeof(flowrings),
+-+	flowrings = kcalloc(devinfo->shared.nrof_flowrings, sizeof(*flowrings),
+- 			    GFP_KERNEL);
+- 	if (!flowrings)
+- 		goto fail;
+diff --git a/package/kernel/mac80211/patches/365-brcmfmac-check-result-of-USB-firmware-request.patch b/package/kernel/mac80211/patches/365-brcmfmac-check-result-of-USB-firmware-request.patch
+deleted file mode 100644
+index 9b2880d..0000000
+--- a/package/kernel/mac80211/patches/365-brcmfmac-check-result-of-USB-firmware-request.patch
++++ /dev/null
+@@ -1,33 +0,0 @@
+-From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <zajec5@gmail.com>
+-Date: Thu, 7 May 2015 14:13:03 +0200
+-Subject: [PATCH] brcmfmac: check result of USB firmware request
+-MIME-Version: 1.0
+-Content-Type: text/plain; charset=UTF-8
+-Content-Transfer-Encoding: 8bit
+-
+-This prevents silence failures with driver waiting (infinitely) for a
+-callback.
+-
+-Signed-off-by: Rafał Miłecki <zajec5@gmail.com>
+-Acked-by: Arend van Spriel <arend@broadcom.com>
+-Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
+----
+-
+---- a/drivers/net/wireless/brcm80211/brcmfmac/usb.c
+-+++ b/drivers/net/wireless/brcm80211/brcmfmac/usb.c
+-@@ -1270,8 +1270,13 @@ static int brcmf_usb_probe_cb(struct brc
+- 	bus->chiprev = bus_pub->chiprev;
+- 
+- 	/* request firmware here */
+--	brcmf_fw_get_firmwares(dev, 0, brcmf_usb_get_fwname(devinfo), NULL,
+--			       brcmf_usb_probe_phase2);
+-+	ret = brcmf_fw_get_firmwares(dev, 0, brcmf_usb_get_fwname(devinfo),
+-+				     NULL, brcmf_usb_probe_phase2);
+-+	if (ret) {
+-+		brcmf_err("firmware request failed: %d\n", ret);
+-+		goto fail;
+-+	}
+-+
+- 	return 0;
+- 
+- fail:
+diff --git a/package/kernel/mac80211/patches/366-brcmfmac-prohibit-ACPI-power-management-for-brcmfmac.patch b/package/kernel/mac80211/patches/366-brcmfmac-prohibit-ACPI-power-management-for-brcmfmac.patch
+deleted file mode 100644
+index d46b300..0000000
+--- a/package/kernel/mac80211/patches/366-brcmfmac-prohibit-ACPI-power-management-for-brcmfmac.patch
++++ /dev/null
+@@ -1,47 +0,0 @@
+-From: "Fu, Zhonghui" <zhonghui.fu@linux.intel.com>
+-Date: Mon, 11 May 2015 10:41:32 +0800
+-Subject: [PATCH] brcmfmac: prohibit ACPI power management for brcmfmac driver
+-
+-ACPI will manage WiFi chip's power state during suspend/resume
+-process on some tablet platforms(such as ASUS T100TA). This is
+-not supported by brcmfmac driver now, and the context of WiFi
+-chip will be damaged after resume. This patch informs ACPI not
+-to manage WiFi chip's power state.
+-
+-Signed-off-by: Zhonghui Fu <zhonghui.fu@linux.intel.com>
+-Acked-by: Arend van Spriel <arend@broadcom.com>
+-Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
+----
+-
+---- a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c
+-+++ b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c
+-@@ -33,6 +33,7 @@
+- #include <linux/suspend.h>
+- #include <linux/errno.h>
+- #include <linux/module.h>
+-+#include <linux/acpi.h>
+- #include <net/cfg80211.h>
+- 
+- #include <defs.h>
+-@@ -1122,6 +1123,8 @@ static int brcmf_ops_sdio_probe(struct s
+- 	int err;
+- 	struct brcmf_sdio_dev *sdiodev;
+- 	struct brcmf_bus *bus_if;
+-+	struct device *dev;
+-+	struct acpi_device *adev;
+- 
+- 	brcmf_dbg(SDIO, "Enter\n");
+- 	brcmf_dbg(SDIO, "Class=%x\n", func->class);
+-@@ -1129,6 +1132,12 @@ static int brcmf_ops_sdio_probe(struct s
+- 	brcmf_dbg(SDIO, "sdio device ID: 0x%04x\n", func->device);
+- 	brcmf_dbg(SDIO, "Function#: %d\n", func->num);
+- 
+-+	/* prohibit ACPI power management for this device */
+-+	dev = &func->dev;
+-+	adev = ACPI_COMPANION(dev);
+-+	if (adev)
+-+		adev->flags.power_manageable = 0;
+-+
+- 	/* Consume func num 1 but dont do anything with it. */
+- 	if (func->num == 1)
+- 		return 0;
+diff --git a/package/kernel/mac80211/patches/367-brcmfmac-avoid-gcc-5.1-warning.patch b/package/kernel/mac80211/patches/367-brcmfmac-avoid-gcc-5.1-warning.patch
+deleted file mode 100644
+index 9b4609f..0000000
+--- a/package/kernel/mac80211/patches/367-brcmfmac-avoid-gcc-5.1-warning.patch
++++ /dev/null
+@@ -1,30 +0,0 @@
+-From: Arnd Bergmann <arnd@arndb.de>
+-Date: Tue, 12 May 2015 23:54:25 +0200
+-Subject: [PATCH] brcmfmac: avoid gcc-5.1 warning
+-
+-gcc-5.0 gained a new warning in the fwsignal portion of the brcmfmac
+-driver:
+-
+-drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c: In function 'brcmf_fws_txs_process':
+-drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c:1478:8: warning: 'skb' may be used uninitialized in this function [-Wmaybe-uninitialized]
+-
+-This is a false positive, and marking the brcmf_fws_hanger_poppkt function
+-as 'static inline' makes the warning go away. I have checked the object
+-file output and while a little code gets moved around, the size of
+-the binary remains identical.
+-
+-Signed-off-by: Arnd Bergmann <arnd@arndb.de>
+-Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
+----
+-
+---- a/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c
+-+++ b/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c
+-@@ -635,7 +635,7 @@ static int brcmf_fws_hanger_pushpkt(stru
+- 	return 0;
+- }
+- 
+--static int brcmf_fws_hanger_poppkt(struct brcmf_fws_hanger *h,
+-+static inline int brcmf_fws_hanger_poppkt(struct brcmf_fws_hanger *h,
+- 					  u32 slot_id, struct sk_buff **pktout,
+- 					  bool remove_item)
+- {
+diff --git a/package/kernel/mac80211/patches/368-brcmfmac-allow-device-tree-node-without-interrupts-p.patch b/package/kernel/mac80211/patches/368-brcmfmac-allow-device-tree-node-without-interrupts-p.patch
+deleted file mode 100644
+index b16782d..0000000
+--- a/package/kernel/mac80211/patches/368-brcmfmac-allow-device-tree-node-without-interrupts-p.patch
++++ /dev/null
+@@ -1,45 +0,0 @@
+-From: Arend van Spriel <arend@broadcom.com>
+-Date: Wed, 20 May 2015 14:09:47 +0200
+-Subject: [PATCH] brcmfmac: allow device tree node without 'interrupts'
+- property
+-
+-As described in the device tree bindings for 'brcm,bcm4329-fmac'
+-nodes, the interrupts property is optional. So adding a check
+-for the presence of this property before attempting to parse
+-and map the interrupt. If not present or parsing fails return
+-and fallback to in-band sdio interrupt.
+-
+-Reviewed-by: Hante Meuleman <meuleman@broadcom.com>
+-Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
+-Signed-off-by: Arend van Spriel <arend@broadcom.com>
+-Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
+----
+-
+---- a/drivers/net/wireless/brcm80211/brcmfmac/of.c
+-+++ b/drivers/net/wireless/brcm80211/brcmfmac/of.c
+-@@ -39,10 +39,16 @@ void brcmf_of_probe(struct brcmf_sdio_de
+- 	if (!sdiodev->pdata)
+- 		return;
+- 
+-+	if (of_property_read_u32(np, "brcm,drive-strength", &val) == 0)
+-+		sdiodev->pdata->drive_strength = val;
+-+
+-+	/* make sure there are interrupts defined in the node */
+-+	if (!of_find_property(np, "interrupts", NULL))
+-+		return;
+-+
+- 	irq = irq_of_parse_and_map(np, 0);
+- 	if (!irq) {
+- 		brcmf_err("interrupt could not be mapped\n");
+--		devm_kfree(dev, sdiodev->pdata);
+- 		return;
+- 	}
+- 	irqf = irqd_get_trigger_type(irq_get_irq_data(irq));
+-@@ -50,7 +56,4 @@ void brcmf_of_probe(struct brcmf_sdio_de
+- 	sdiodev->pdata->oob_irq_supported = true;
+- 	sdiodev->pdata->oob_irq_nr = irq;
+- 	sdiodev->pdata->oob_irq_flags = irqf;
+--
+--	if (of_property_read_u32(np, "brcm,drive-strength", &val) == 0)
+--		sdiodev->pdata->drive_strength = val;
+- }
+diff --git a/package/kernel/mac80211/patches/369-brcmfmac-Improve-throughput-by-scheduling-msbug-flow.patch b/package/kernel/mac80211/patches/369-brcmfmac-Improve-throughput-by-scheduling-msbug-flow.patch
+deleted file mode 100644
+index f81250e..0000000
+--- a/package/kernel/mac80211/patches/369-brcmfmac-Improve-throughput-by-scheduling-msbug-flow.patch
++++ /dev/null
+@@ -1,87 +0,0 @@
+-From: Hante Meuleman <meuleman@broadcom.com>
+-Date: Wed, 20 May 2015 14:09:48 +0200
+-Subject: [PATCH] brcmfmac: Improve throughput by scheduling msbug flow worker.
+-
+-The tx flow worker in msgbuf gets scheduled at tx till a certain
+-threshold has been reached. Then the tx completes will take over
+-the scheduling. When amsdu and ampdu is used the frames are
+-transferred wireless in a very bulky fashion, in combination
+-with this scheduling algorithm and buffer limiters in the stack
+-this can result in limited throughput. This change causes the
+-flow worker to be scheduled more frequently from tx.
+-
+-Reviewed-by: Arend Van Spriel <arend@broadcom.com>
+-Reviewed-by: Franky (Zhenhui) Lin <frankyl@broadcom.com>
+-Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
+-Reviewed-by: Daniel (Deognyoun) Kim <dekim@broadcom.com>
+-Signed-off-by: Hante Meuleman <meuleman@broadcom.com>
+-Signed-off-by: Arend van Spriel <arend@broadcom.com>
+-Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
+----
+-
+---- a/drivers/net/wireless/brcm80211/brcmfmac/flowring.c
+-+++ b/drivers/net/wireless/brcm80211/brcmfmac/flowring.c
+-@@ -249,8 +249,8 @@ void brcmf_flowring_delete(struct brcmf_
+- }
+- 
+- 
+--void brcmf_flowring_enqueue(struct brcmf_flowring *flow, u8 flowid,
+--			    struct sk_buff *skb)
+-+u32 brcmf_flowring_enqueue(struct brcmf_flowring *flow, u8 flowid,
+-+			   struct sk_buff *skb)
+- {
+- 	struct brcmf_flowring_ring *ring;
+- 
+-@@ -271,6 +271,7 @@ void brcmf_flowring_enqueue(struct brcmf
+- 		if (skb_queue_len(&ring->skblist) < BRCMF_FLOWRING_LOW)
+- 			brcmf_flowring_block(flow, flowid, false);
+- 	}
+-+	return skb_queue_len(&ring->skblist);
+- }
+- 
+- 
+---- a/drivers/net/wireless/brcm80211/brcmfmac/flowring.h
+-+++ b/drivers/net/wireless/brcm80211/brcmfmac/flowring.h
+-@@ -64,8 +64,8 @@ u32 brcmf_flowring_create(struct brcmf_f
+- void brcmf_flowring_delete(struct brcmf_flowring *flow, u8 flowid);
+- void brcmf_flowring_open(struct brcmf_flowring *flow, u8 flowid);
+- u8 brcmf_flowring_tid(struct brcmf_flowring *flow, u8 flowid);
+--void brcmf_flowring_enqueue(struct brcmf_flowring *flow, u8 flowid,
+--			    struct sk_buff *skb);
+-+u32 brcmf_flowring_enqueue(struct brcmf_flowring *flow, u8 flowid,
+-+			   struct sk_buff *skb);
+- struct sk_buff *brcmf_flowring_dequeue(struct brcmf_flowring *flow, u8 flowid);
+- void brcmf_flowring_reinsert(struct brcmf_flowring *flow, u8 flowid,
+- 			     struct sk_buff *skb);
+---- a/drivers/net/wireless/brcm80211/brcmfmac/msgbuf.c
+-+++ b/drivers/net/wireless/brcm80211/brcmfmac/msgbuf.c
+-@@ -73,7 +73,7 @@
+- #define BRCMF_MSGBUF_TX_FLUSH_CNT1		32
+- #define BRCMF_MSGBUF_TX_FLUSH_CNT2		96
+- 
+--#define BRCMF_MSGBUF_DELAY_TXWORKER_THRS	64
+-+#define BRCMF_MSGBUF_DELAY_TXWORKER_THRS	96
+- #define BRCMF_MSGBUF_TRICKLE_TXWORKER_THRS	32
+- 
+- struct msgbuf_common_hdr {
+-@@ -797,6 +797,8 @@ static int brcmf_msgbuf_txdata(struct br
+- 	struct brcmf_flowring *flow = msgbuf->flow;
+- 	struct ethhdr *eh = (struct ethhdr *)(skb->data);
+- 	u32 flowid;
+-+	u32 queue_count;
+-+	bool force;
+- 
+- 	flowid = brcmf_flowring_lookup(flow, eh->h_dest, skb->priority, ifidx);
+- 	if (flowid == BRCMF_FLOWRING_INVALID_ID) {
+-@@ -804,8 +806,9 @@ static int brcmf_msgbuf_txdata(struct br
+- 		if (flowid == BRCMF_FLOWRING_INVALID_ID)
+- 			return -ENOMEM;
+- 	}
+--	brcmf_flowring_enqueue(flow, flowid, skb);
+--	brcmf_msgbuf_schedule_txdata(msgbuf, flowid, false);
+-+	queue_count = brcmf_flowring_enqueue(flow, flowid, skb);
+-+	force = ((queue_count % BRCMF_MSGBUF_TRICKLE_TXWORKER_THRS) == 0);
+-+	brcmf_msgbuf_schedule_txdata(msgbuf, flowid, force);
+- 
+- 	return 0;
+- }
+diff --git a/package/kernel/mac80211/patches/370-brcmfmac-remove-pci-shared-structure-rev4-support.patch b/package/kernel/mac80211/patches/370-brcmfmac-remove-pci-shared-structure-rev4-support.patch
+deleted file mode 100644
+index 61153c4..0000000
+--- a/package/kernel/mac80211/patches/370-brcmfmac-remove-pci-shared-structure-rev4-support.patch
++++ /dev/null
+@@ -1,41 +0,0 @@
+-From: Franky Lin <frankyl@broadcom.com>
+-Date: Wed, 20 May 2015 14:09:49 +0200
+-Subject: [PATCH] brcmfmac: remove pci shared structure rev4 support
+-
+-All pcie full dongle chips supported by fmac are using rev 5+ shared
+-structure. This patch removes the rev4 related code.
+-
+-Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
+-Reviewed-by: Hante Meuleman <meuleman@broadcom.com>
+-Reviewed-by: Arend Van Spriel <arend@broadcom.com>
+-Signed-off-by: Franky Lin <frankyl@broadcom.com>
+-Signed-off-by: Arend van Spriel <arend@broadcom.com>
+-Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
+----
+-
+---- a/drivers/net/wireless/brcm80211/brcmfmac/pcie.c
+-+++ b/drivers/net/wireless/brcm80211/brcmfmac/pcie.c
+-@@ -112,10 +112,9 @@ enum brcmf_pcie_state {
+- 						 BRCMF_PCIE_MB_INT_D2H3_DB0 | \
+- 						 BRCMF_PCIE_MB_INT_D2H3_DB1)
+- 
+--#define BRCMF_PCIE_MIN_SHARED_VERSION		4
+-+#define BRCMF_PCIE_MIN_SHARED_VERSION		5
+- #define BRCMF_PCIE_MAX_SHARED_VERSION		5
+- #define BRCMF_PCIE_SHARED_VERSION_MASK		0x00FF
+--#define BRCMF_PCIE_SHARED_TXPUSH_SUPPORT	0x4000
+- 
+- #define BRCMF_PCIE_FLAGS_HTOD_SPLIT		0x4000
+- #define BRCMF_PCIE_FLAGS_DTOH_SPLIT		0x8000
+-@@ -1280,11 +1279,6 @@ brcmf_pcie_init_share_ram_info(struct br
+- 		brcmf_err("Unsupported PCIE version %d\n", version);
+- 		return -EINVAL;
+- 	}
+--	if (shared->flags & BRCMF_PCIE_SHARED_TXPUSH_SUPPORT) {
+--		brcmf_err("Unsupported legacy TX mode 0x%x\n",
+--			  shared->flags & BRCMF_PCIE_SHARED_TXPUSH_SUPPORT);
+--		return -EINVAL;
+--	}
+- 
+- 	addr = sharedram_addr + BRCMF_SHARED_MAX_RXBUFPOST_OFFSET;
+- 	shared->max_rxbufpost = brcmf_pcie_read_tcm16(devinfo, addr);
+diff --git a/package/kernel/mac80211/patches/371-brcmfmac-remove-dummy-cache-flush-invalidate-functio.patch b/package/kernel/mac80211/patches/371-brcmfmac-remove-dummy-cache-flush-invalidate-functio.patch
+deleted file mode 100644
+index 8c8eebe..0000000
+--- a/package/kernel/mac80211/patches/371-brcmfmac-remove-dummy-cache-flush-invalidate-functio.patch
++++ /dev/null
+@@ -1,120 +0,0 @@
+-From: Franky Lin <frankyl@broadcom.com>
+-Date: Wed, 20 May 2015 14:09:50 +0200
+-Subject: [PATCH] brcmfmac: remove dummy cache flush/invalidate function
+-
+-brcmf_dma_flush and brcmf_dma_invalidate_cache are not necessary and
+-have never been implemented.
+-
+-Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
+-Reviewed-by: Hante Meuleman <meuleman@broadcom.com>
+-Reviewed-by: Arend Van Spriel <arend@broadcom.com>
+-Signed-off-by: Franky Lin <frankyl@broadcom.com>
+-Signed-off-by: Arend van Spriel <arend@broadcom.com>
+-Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
+----
+-
+---- a/drivers/net/wireless/brcm80211/brcmfmac/commonring.c
+-+++ b/drivers/net/wireless/brcm80211/brcmfmac/commonring.c
+-@@ -22,17 +22,6 @@
+- #include "core.h"
+- #include "commonring.h"
+- 
+--
+--/* dma flushing needs implementation for mips and arm platforms. Should
+-- * be put in util. Note, this is not real flushing. It is virtual non
+-- * cached memory. Only write buffers should have to be drained. Though
+-- * this may be different depending on platform......
+-- * SEE ALSO msgbuf.c
+-- */
+--#define brcmf_dma_flush(addr, len)
+--#define brcmf_dma_invalidate_cache(addr, len)
+--
+--
+- void brcmf_commonring_register_cb(struct brcmf_commonring *commonring,
+- 				  int (*cr_ring_bell)(void *ctx),
+- 				  int (*cr_update_rptr)(void *ctx),
+-@@ -206,14 +195,9 @@ int brcmf_commonring_write_complete(stru
+- 	address = commonring->buf_addr;
+- 	address += (commonring->f_ptr * commonring->item_len);
+- 	if (commonring->f_ptr > commonring->w_ptr) {
+--		brcmf_dma_flush(address,
+--				(commonring->depth - commonring->f_ptr) *
+--				commonring->item_len);
+- 		address = commonring->buf_addr;
+- 		commonring->f_ptr = 0;
+- 	}
+--	brcmf_dma_flush(address, (commonring->w_ptr - commonring->f_ptr) *
+--			commonring->item_len);
+- 
+- 	commonring->f_ptr = commonring->w_ptr;
+- 
+-@@ -258,8 +242,6 @@ void *brcmf_commonring_get_read_ptr(stru
+- 	if (commonring->r_ptr == commonring->depth)
+- 		commonring->r_ptr = 0;
+- 
+--	brcmf_dma_invalidate_cache(ret_addr, *n_ items * commonring->item_len);
+--
+- 	return ret_addr;
+- }
+- 
+---- a/drivers/net/wireless/brcm80211/brcmfmac/msgbuf.c
+-+++ b/drivers/net/wireless/brcm80211/brcmfmac/msgbuf.c
+-@@ -278,16 +278,6 @@ struct brcmf_msgbuf_pktids {
+- 	struct brcmf_msgbuf_pktid *array;
+- };
+- 
+--
+--/* dma flushing needs implementation for mips and arm platforms. Should
+-- * be put in util. Note, this is not real flushing. It is virtual non
+-- * cached memory. Only write buffers should have to be drained. Though
+-- * this may be different depending on platform......
+-- */
+--#define brcmf_dma_flush(addr, len)
+--#define brcmf_dma_invalidate_cache(addr, len)
+--
+--
+- static void brcmf_msgbuf_rxbuf_ioctlresp_post(struct brcmf_msgbuf *msgbuf);
+- 
+- 
+-@@ -462,7 +452,6 @@ static int brcmf_msgbuf_tx_ioctl(struct
+- 		memcpy(msgbuf->ioctbuf, buf, buf_len);
+- 	else
+- 		memset(msgbuf->ioctbuf, 0, buf_len);
+--	brcmf_dma_flush(ioctl_buf, buf_len);
+- 
+- 	err = brcmf_commonring_write_complete(commonring);
+- 	brcmf_commonring_unlock(commonring);
+---- a/drivers/net/wireless/brcm80211/brcmfmac/pcie.c
+-+++ b/drivers/net/wireless/brcm80211/brcmfmac/pcie.c
+-@@ -276,15 +276,6 @@ static const u32 brcmf_ring_itemsize[BRC
+- };
+- 
+- 
+--/* dma flushing needs implementation for mips and arm platforms. Should
+-- * be put in util. Note, this is not real flushing. It is virtual non
+-- * cached memory. Only write buffers should have to be drained. Though
+-- * this may be different depending on platform......
+-- */
+--#define brcmf_dma_flush(addr, len)
+--#define brcmf_dma_invalidate_cache(addr, len)
+--
+--
+- static u32
+- brcmf_pcie_read_reg32(struct brcmf_pciedev_info *devinfo, u32 reg_offset)
+- {
+-@@ -1174,7 +1165,6 @@ static int brcmf_pcie_init_scratchbuffer
+- 		goto fail;
+- 
+- 	memset(devinfo->shared.scratch, 0, BRCMF_DMA_D2H_SCRATCH_BUF_LEN);
+--	brcmf_dma_flush(devinfo->shared.scratch, BRCMF_DMA_D2H_SCRATCH_BUF_LEN);
+- 
+- 	addr = devinfo->shared.tcm_base_address +
+- 	       BRCMF_SHARED_DMA_SCRATCH_ADDR_OFFSET;
+-@@ -1192,7 +1182,6 @@ static int brcmf_pcie_init_scratchbuffer
+- 		goto fail;
+- 
+- 	memset(devinfo->shared.ringupd, 0, BRCMF_DMA_D2H_RINGUPD_BUF_LEN);
+--	brcmf_dma_flush(devinfo->shared.ringupd, BRCMF_DMA_D2H_RINGUPD_BUF_LEN);
+- 
+- 	addr = devinfo->shared.tcm_base_address +
+- 	       BRCMF_SHARED_DMA_RINGUPD_ADDR_OFFSET;
+diff --git a/package/kernel/mac80211/patches/372-brcmfmac-add-support-for-dma-indices-feature.patch b/package/kernel/mac80211/patches/372-brcmfmac-add-support-for-dma-indices-feature.patch
+deleted file mode 100644
+index 2f50abd..0000000
+--- a/package/kernel/mac80211/patches/372-brcmfmac-add-support-for-dma-indices-feature.patch
++++ /dev/null
+@@ -1,270 +0,0 @@
+-From: Franky Lin <frankyl@broadcom.com>
+-Date: Wed, 20 May 2015 14:09:51 +0200
+-Subject: [PATCH] brcmfmac: add support for dma indices feature
+-
+-PCIe full dongle firmware can support a dma indices feature with which
+-firmware can update/fetch the read/write indices of message buffer
+-rings on both host to dongle and dongle to host directions. The support is
+-announced by firmware through shared flags.
+-
+-Reviewed-by: Arend Van Spriel <arend@broadcom.com>
+-Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
+-Signed-off-by: Franky Lin <frankyl@broadcom.com>
+-Signed-off-by: Arend van Spriel <arend@broadcom.com>
+-Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
+----
+-
+---- a/drivers/net/wireless/brcm80211/brcmfmac/pcie.c
+-+++ b/drivers/net/wireless/brcm80211/brcmfmac/pcie.c
+-@@ -115,6 +115,8 @@ enum brcmf_pcie_state {
+- #define BRCMF_PCIE_MIN_SHARED_VERSION		5
+- #define BRCMF_PCIE_MAX_SHARED_VERSION		5
+- #define BRCMF_PCIE_SHARED_VERSION_MASK		0x00FF
+-+#define BRCMF_PCIE_SHARED_DMA_INDEX		0x10000
+-+#define BRCMF_PCIE_SHARED_DMA_2B_IDX		0x100000
+- 
+- #define BRCMF_PCIE_FLAGS_HTOD_SPLIT		0x4000
+- #define BRCMF_PCIE_FLAGS_DTOH_SPLIT		0x8000
+-@@ -146,6 +148,10 @@ enum brcmf_pcie_state {
+- #define BRCMF_SHARED_RING_H2D_R_IDX_PTR_OFFSET	8
+- #define BRCMF_SHARED_RING_D2H_W_IDX_PTR_OFFSET	12
+- #define BRCMF_SHARED_RING_D2H_R_IDX_PTR_OFFSET	16
+-+#define BRCMF_SHARED_RING_H2D_WP_HADDR_OFFSET	20
+-+#define BRCMF_SHARED_RING_H2D_RP_HADDR_OFFSET	28
+-+#define BRCMF_SHARED_RING_D2H_WP_HADDR_OFFSET	36
+-+#define BRCMF_SHARED_RING_D2H_RP_HADDR_OFFSET	44
+- #define BRCMF_SHARED_RING_TCM_MEMLOC_OFFSET	0
+- #define BRCMF_SHARED_RING_MAX_SUB_QUEUES	52
+- 
+-@@ -247,6 +253,13 @@ struct brcmf_pciedev_info {
+- 	bool mbdata_completed;
+- 	bool irq_allocated;
+- 	bool wowl_enabled;
+-+	u8 dma_idx_sz;
+-+	void *idxbuf;
+-+	u32 idxbuf_sz;
+-+	dma_addr_t idxbuf_dmahandle;
+-+	u16 (*read_ptr)(struct brcmf_pciedev_info *devinfo, u32 mem_offset);
+-+	void (*write_ptr)(struct brcmf_pciedev_info *devinfo, u32 mem_offset,
+-+			  u16 value);
+- };
+- 
+- struct brcmf_pcie_ringbuf {
+-@@ -323,6 +336,25 @@ brcmf_pcie_write_tcm16(struct brcmf_pcie
+- }
+- 
+- 
+-+static u16
+-+brcmf_pcie_read_idx(struct brcmf_pciedev_info *devinfo, u32 mem_offset)
+-+{
+-+	u16 *address = devinfo->idxbuf + mem_offset;
+-+
+-+	return (*(address));
+-+}
+-+
+-+
+-+static void
+-+brcmf_pcie_write_idx(struct brcmf_pciedev_info *devinfo, u32 mem_offset,
+-+		     u16 value)
+-+{
+-+	u16 *address = devinfo->idxbuf + mem_offset;
+-+
+-+	*(address) = value;
+-+}
+-+
+-+
+- static u32
+- brcmf_pcie_read_tcm32(struct brcmf_pciedev_info *devinfo, u32 mem_offset)
+- {
+-@@ -868,7 +900,7 @@ static int brcmf_pcie_ring_mb_write_rptr
+- 	brcmf_dbg(PCIE, "W r_ptr %d (%d), ring %d\n", commonring->r_ptr,
+- 		  commonring->w_ptr, ring->id);
+- 
+--	brcmf_pcie_write_tcm16(devinfo, ring->r_idx_addr, commonring->r_ptr);
+-+	devinfo->write_ptr(devinfo, ring->r_idx_addr, commonring->r_ptr);
+- 
+- 	return 0;
+- }
+-@@ -886,7 +918,7 @@ static int brcmf_pcie_ring_mb_write_wptr
+- 	brcmf_dbg(PCIE, "W w_ptr %d (%d), ring %d\n", commonring->w_ptr,
+- 		  commonring->r_ptr, ring->id);
+- 
+--	brcmf_pcie_write_tcm16(devinfo, ring->w_idx_addr, commonring->w_ptr);
+-+	devinfo->write_ptr(devinfo, ring->w_idx_addr, commonring->w_ptr);
+- 
+- 	return 0;
+- }
+-@@ -915,7 +947,7 @@ static int brcmf_pcie_ring_mb_update_rpt
+- 	if (devinfo->state != BRCMFMAC_PCIE_STATE_UP)
+- 		return -EIO;
+- 
+--	commonring->r_ptr = brcmf_pcie_read_tcm16(devinfo, ring->r_idx_addr);
+-+	commonring->r_ptr = devinfo->read_ptr(devinfo, ring->r_idx_addr);
+- 
+- 	brcmf_dbg(PCIE, "R r_ptr %d (%d), ring %d\n", commonring->r_ptr,
+- 		  commonring->w_ptr, ring->id);
+-@@ -933,7 +965,7 @@ static int brcmf_pcie_ring_mb_update_wpt
+- 	if (devinfo->state != BRCMFMAC_PCIE_STATE_UP)
+- 		return -EIO;
+- 
+--	commonring->w_ptr = brcmf_pcie_read_tcm16(devinfo, ring->w_idx_addr);
+-+	commonring->w_ptr = devinfo->read_ptr(devinfo, ring->w_idx_addr);
+- 
+- 	brcmf_dbg(PCIE, "R w_ptr %d (%d), ring %d\n", commonring->w_ptr,
+- 		  commonring->r_ptr, ring->id);
+-@@ -1038,6 +1070,13 @@ static void brcmf_pcie_release_ringbuffe
+- 	}
+- 	kfree(devinfo->shared.flowrings);
+- 	devinfo->shared.flowrings = NULL;
+-+	if (devinfo->idxbuf) {
+-+		dma_free_coherent(&devinfo->pdev->dev,
+-+				  devinfo->idxbuf_sz,
+-+				  devinfo->idxbuf,
+-+				  devinfo->idxbuf_dmahandle);
+-+		devinfo->idxbuf = NULL;
+-+	}
+- }
+- 
+- 
+-@@ -1053,19 +1092,72 @@ static int brcmf_pcie_init_ringbuffers(s
+- 	u32 addr;
+- 	u32 ring_mem_ptr;
+- 	u32 i;
+-+	u64 address;
+-+	u32 bufsz;
+- 	u16 max_sub_queues;
+-+	u8 idx_offset;
+- 
+- 	ring_addr = devinfo->shared.ring_info_addr;
+- 	brcmf_dbg(PCIE, "Base ring addr = 0x%08x\n", ring_addr);
+-+	addr = ring_addr + BRCMF_SHARED_RING_MAX_SUB_QUEUES;
+-+	max_sub_queues = brcmf_pcie_read_tcm16(devinfo, addr);
+- 
+--	addr = ring_addr + BRCMF_SHARED_RING_D2H_W_IDX_PTR_OFFSET;
+--	d2h_w_idx_ptr = brcmf_pcie_read_tcm32(devinfo, addr);
+--	addr = ring_addr + BRCMF_SHARED_RING_D2H_R_IDX_PTR_OFFSET;
+--	d2h_r_idx_ptr = brcmf_pcie_read_tcm32(devinfo, addr);
+--	addr = ring_addr + BRCMF_SHARED_RING_H2D_W_IDX_PTR_OFFSET;
+--	h2d_w_idx_ptr = brcmf_pcie_read_tcm32(devinfo, addr);
+--	addr = ring_addr + BRCMF_SHARED_RING_H2D_R_IDX_PTR_OFFSET;
+--	h2d_r_idx_ptr = brcmf_pcie_read_tcm32(devinfo, addr);
+-+	if (devinfo->dma_idx_sz != 0) {
+-+		bufsz = (BRCMF_NROF_D2H_COMMON_MSGRINGS + max_sub_queues) *
+-+			devinfo->dma_idx_sz * 2;
+-+		devinfo->idxbuf = dma_alloc_coherent(&devinfo->pdev->dev, bufsz,
+-+						     &devinfo->idxbuf_dmahandle,
+-+						     GFP_KERNEL);
+-+		if (!devinfo->idxbuf)
+-+			devinfo->dma_idx_sz = 0;
+-+	}
+-+
+-+	if (devinfo->dma_idx_sz == 0) {
+-+		addr = ring_addr + BRCMF_SHARED_RING_D2H_W_IDX_PTR_OFFSET;
+-+		d2h_w_idx_ptr = brcmf_pcie_read_tcm32(devinfo, addr);
+-+		addr = ring_addr + BRCMF_SHARED_RING_D2H_R_IDX_PTR_OFFSET;
+-+		d2h_r_idx_ptr = brcmf_pcie_read_tcm32(devinfo, addr);
+-+		addr = ring_addr + BRCMF_SHARED_RING_H2D_W_IDX_PTR_OFFSET;
+-+		h2d_w_idx_ptr = brcmf_pcie_read_tcm32(devinfo, addr);
+-+		addr = ring_addr + BRCMF_SHARED_RING_H2D_R_IDX_PTR_OFFSET;
+-+		h2d_r_idx_ptr = brcmf_pcie_read_tcm32(devinfo, addr);
+-+		idx_offset = sizeof(u32);
+-+		devinfo->write_ptr = brcmf_pcie_write_tcm16;
+-+		devinfo->read_ptr = brcmf_pcie_read_tcm16;
+-+		brcmf_dbg(PCIE, "Using TCM indices\n");
+-+	} else {
+-+		memset(devinfo->idxbuf, 0, bufsz);
+-+		devinfo->idxbuf_sz = bufsz;
+-+		idx_offset = devinfo->dma_idx_sz;
+-+		devinfo->write_ptr = brcmf_pcie_write_idx;
+-+		devinfo->read_ptr = brcmf_pcie_read_idx;
+-+
+-+		h2d_w_idx_ptr = 0;
+-+		addr = ring_addr + BRCMF_SHARED_RING_H2D_WP_HADDR_OFFSET;
+-+		address = (u64)devinfo->idxbuf_dmahandle;
+-+		brcmf_pcie_write_tcm32(devinfo, addr, address & 0xffffffff);
+-+		brcmf_pcie_write_tcm32(devinfo, addr + 4, address >> 32);
+-+
+-+		h2d_r_idx_ptr = h2d_w_idx_ptr + max_sub_queues * idx_offset;
+-+		addr = ring_addr + BRCMF_SHARED_RING_H2D_RP_HADDR_OFFSET;
+-+		address += max_sub_queues * idx_offset;
+-+		brcmf_pcie_write_tcm32(devinfo, addr, address & 0xffffffff);
+-+		brcmf_pcie_write_tcm32(devinfo, addr + 4, address >> 32);
+-+
+-+		d2h_w_idx_ptr = h2d_r_idx_ptr + max_sub_queues * idx_offset;
+-+		addr = ring_addr + BRCMF_SHARED_RING_D2H_WP_HADDR_OFFSET;
+-+		address += max_sub_queues * idx_offset;
+-+		brcmf_pcie_write_tcm32(devinfo, addr, address & 0xffffffff);
+-+		brcmf_pcie_write_tcm32(devinfo, addr + 4, address >> 32);
+-+
+-+		d2h_r_idx_ptr = d2h_w_idx_ptr +
+-+				BRCMF_NROF_D2H_COMMON_MSGRINGS * idx_offset;
+-+		addr = ring_addr + BRCMF_SHARED_RING_D2H_RP_HADDR_OFFSET;
+-+		address += BRCMF_NROF_D2H_COMMON_MSGRINGS * idx_offset;
+-+		brcmf_pcie_write_tcm32(devinfo, addr, address & 0xffffffff);
+-+		brcmf_pcie_write_tcm32(devinfo, addr + 4, address >> 32);
+-+		brcmf_dbg(PCIE, "Using host memory indices\n");
+-+	}
+- 
+- 	addr = ring_addr + BRCMF_SHARED_RING_TCM_MEMLOC_OFFSET;
+- 	ring_mem_ptr = brcmf_pcie_read_tcm32(devinfo, addr);
+-@@ -1079,8 +1171,8 @@ static int brcmf_pcie_init_ringbuffers(s
+- 		ring->id = i;
+- 		devinfo->shared.commonrings[i] = ring;
+- 
+--		h2d_w_idx_ptr += sizeof(u32);
+--		h2d_r_idx_ptr += sizeof(u32);
+-+		h2d_w_idx_ptr += idx_offset;
+-+		h2d_r_idx_ptr += idx_offset;
+- 		ring_mem_ptr += BRCMF_RING_MEM_SZ;
+- 	}
+- 
+-@@ -1094,13 +1186,11 @@ static int brcmf_pcie_init_ringbuffers(s
+- 		ring->id = i;
+- 		devinfo->shared.commonrings[i] = ring;
+- 
+--		d2h_w_idx_ptr += sizeof(u32);
+--		d2h_r_idx_ptr += sizeof(u32);
+-+		d2h_w_idx_ptr += idx_offset;
+-+		d2h_r_idx_ptr += idx_offset;
+- 		ring_mem_ptr += BRCMF_RING_MEM_SZ;
+- 	}
+- 
+--	addr = ring_addr + BRCMF_SHARED_RING_MAX_SUB_QUEUES;
+--	max_sub_queues = brcmf_pcie_read_tcm16(devinfo, addr);
+- 	devinfo->shared.nrof_flowrings =
+- 			max_sub_queues - BRCMF_NROF_H2D_COMMON_MSGRINGS;
+- 	rings = kcalloc(devinfo->shared.nrof_flowrings, sizeof(*ring),
+-@@ -1124,15 +1214,15 @@ static int brcmf_pcie_init_ringbuffers(s
+- 					     ring);
+- 		ring->w_idx_addr = h2d_w_idx_ptr;
+- 		ring->r_idx_addr = h2d_r_idx_ptr;
+--		h2d_w_idx_ptr += sizeof(u32);
+--		h2d_r_idx_ptr += sizeof(u32);
+-+		h2d_w_idx_ptr += idx_offset;
+-+		h2d_r_idx_ptr += idx_offset;
+- 	}
+- 	devinfo->shared.flowrings = rings;
+- 
+- 	return 0;
+- 
+- fail:
+--	brcmf_err("Allocating commonring buffers failed\n");
+-+	brcmf_err("Allocating ring buffers failed\n");
+- 	brcmf_pcie_release_ringbuffers(devinfo);
+- 	return -ENOMEM;
+- }
+-@@ -1269,6 +1359,14 @@ brcmf_pcie_init_share_ram_info(struct br
+- 		return -EINVAL;
+- 	}
+- 
+-+	/* check firmware support dma indicies */
+-+	if (shared->flags & BRCMF_PCIE_SHARED_DMA_INDEX) {
+-+		if (shared->flags & BRCMF_PCIE_SHARED_DMA_2B_IDX)
+-+			devinfo->dma_idx_sz = sizeof(u16);
+-+		else
+-+			devinfo->dma_idx_sz = sizeof(u32);
+-+	}
+-+
+- 	addr = sharedram_addr + BRCMF_SHARED_MAX_RXBUFPOST_OFFSET;
+- 	shared->max_rxbufpost = brcmf_pcie_read_tcm16(devinfo, addr);
+- 	if (shared->max_rxbufpost == 0)
+diff --git a/package/kernel/mac80211/patches/373-brcmfmac-avoid-null-pointer-access-when-brcmf_msgbuf.patch b/package/kernel/mac80211/patches/373-brcmfmac-avoid-null-pointer-access-when-brcmf_msgbuf.patch
+deleted file mode 100644
+index 28408d2..0000000
+--- a/package/kernel/mac80211/patches/373-brcmfmac-avoid-null-pointer-access-when-brcmf_msgbuf.patch
++++ /dev/null
+@@ -1,102 +0,0 @@
+-From: Arend van Spriel <arend@broadcom.com>
+-Date: Tue, 26 May 2015 13:19:46 +0200
+-Subject: [PATCH] brcmfmac: avoid null pointer access when
+- brcmf_msgbuf_get_pktid() fails
+-
+-The function brcmf_msgbuf_get_pktid() may return a NULL pointer so
+-the callers should check the return pointer before accessing it to
+-avoid the crash below (see [1]):
+-
+-brcmfmac: brcmf_msgbuf_get_pktid: Invalid packet id 273 (not in use)
+-BUG: unable to handle kernel NULL pointer dereference at 0000000000000080
+-IP: [<ffffffff8145b225>] skb_pull+0x5/0x50
+-PGD 0
+-Oops: 0000 [#1] PREEMPT SMP
+-Modules linked in: pci_stub vboxpci(O) vboxnetflt(O) vboxnetadp(O) vboxdrv(O)
+- snd_hda_codec_hdmi bnep mousedev hid_generic ushwmon msr ext4 crc16 mbcache
+- jbd2 sd_mod uas usb_storage ahci libahci libata scsi_mod xhci_pci xhci_hcd
+- usbcore usb_common
+-CPU: 0 PID: 1661 Comm: irq/61-brcmf_pc Tainted: G O    4.0.1-MacbookPro-ARCH #1
+-Hardware name: Apple Inc. MacBookPro12,1/Mac-E43C1C25D4880AD6,
+- BIOS MBP121.88Z.0167.B02.1503241251 03/24/2015
+-task: ffff880264203cc0 ti: ffff88025ffe4000 task.ti: ffff88025ffe4000
+-RIP: 0010:[<ffffffff8145b225>]  [<ffffffff8145b225>] skb_pull+0x5/0x50
+-RSP: 0018:ffff88025ffe7d40  EFLAGS: 00010202
+-RAX: 0000000000000000 RBX: ffff88008a33c000 RCX: 0000000000000044
+-RDX: 0000000000000000 RSI: 000000000000004a RDI: 0000000000000000
+-RBP: ffff88025ffe7da8 R08: 0000000000000096 R09: 000000000000004a
+-R10: 0000000000000000 R11: 000000000000048e R12: ffff88025ff14f00
+-R13: 0000000000000000 R14: ffff880263b48200 R15: ffff88008a33c000
+-FS:  0000000000000000(0000) GS:ffff88026ec00000(0000) knlGS:0000000000000000
+-CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
+-CR2: 0000000000000080 CR3: 000000000180b000 CR4: 00000000003407f0
+-Stack:
+- ffffffffa06aed74 ffff88025ffe7dc8 ffff880263b48270 ffff880263b48278
+- 05ea88020000004a 0002ffff81014635 000000001720b2f6 ffff88026ec116c0
+- ffff880263b48200 0000000000010000 ffff880263b4ae00 ffff880264203cc0
+-Call Trace:
+- [<ffffffffa06aed74>] ? brcmf_msgbuf_process_rx+0x404/0x480 [brcmfmac]
+- [<ffffffff810cea60>] ? irq_finalize_oneshot.part.30+0xf0/0xf0
+- [<ffffffffa06afb55>] brcmf_proto_msgbuf_rx_trigger+0x35/0xf0 [brcmfmac]
+- [<ffffffffa06baf2a>] brcmf_pcie_isr_thread_v2+0x8a/0x130 [brcmfmac]
+- [<ffffffff810cea80>] irq_thread_fn+0x20/0x50
+- [<ffffffff810ceddf>] irq_thread+0x13f/0x170
+- [<ffffffff810cebf0>] ? wake_threads_waitq+0x30/0x30
+- [<ffffffff810ceca0>] ? irq_thread_dtor+0xb0/0xb0
+- [<ffffffff81092a08>] kthread+0xd8/0xf0
+- [<ffffffff81092930>] ? kthread_create_on_node+0x1c0/0x1c0
+- [<ffffffff8156d898>] ret_from_fork+0x58/0x90
+- [<ffffffff81092930>] ? kthread_create_on_node+0x1c0/0x1c0
+-Code: 01 83 e2 f7 88 50 01 48 83 c4 08 5b 5d f3 c3 0f 1f 80 00 00 00 00 83 e2
+- f7 88 50 01 c3 66 0f 1f 84 00 00 00 00 00 0f 1f
+-RIP  [<ffffffff8145b225>] skb_pull+0x5/0x50
+- RSP <ffff88025ffe7d40>
+-CR2: 0000000000000080
+----[ end trace b074c0f90e7c997d ]---
+-
+-[1] http://mid.gmane.org/20150430193259.GA5630@googlemail.com
+-
+-Cc: <stable@vger.kernel.org> # v3.18, v3.19, v4.0, v4.1
+-Reported-by: Michael Hornung <mhornung.linux@gmail.com>
+-Reviewed-by: Hante Meuleman <meuleman@broadcom.com>
+-Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
+-Signed-off-by: Arend van Spriel <arend@broadcom.com>
+----
+-
+---- a/drivers/net/wireless/brcm80211/brcmfmac/msgbuf.c
+-+++ b/drivers/net/wireless/brcm80211/brcmfmac/msgbuf.c
+-@@ -500,11 +500,9 @@ static int brcmf_msgbuf_query_dcmd(struc
+- 				     msgbuf->rx_pktids,
+- 				     msgbuf->ioctl_resp_pktid);
+- 	if (msgbuf->ioctl_resp_ret_len != 0) {
+--		if (!skb) {
+--			brcmf_err("Invalid packet id idx recv'd %d\n",
+--				  msgbuf->ioctl_resp_pktid);
+-+		if (!skb)
+- 			return -EBADF;
+--		}
+-+
+- 		memcpy(buf, skb->data, (len < msgbuf->ioctl_resp_ret_len) ?
+- 				       len : msgbuf->ioctl_resp_ret_len);
+- 	}
+-@@ -866,10 +864,8 @@ brcmf_msgbuf_process_txstatus(struct brc
+- 	flowid -= BRCMF_NROF_H2D_COMMON_MSGRINGS;
+- 	skb = brcmf_msgbuf_get_pktid(msgbuf->drvr->bus_if->dev,
+- 				     msgbuf->tx_pktids, idx);
+--	if (!skb) {
+--		brcmf_err("Invalid packet id idx recv'd %d\n", idx);
+-+	if (!skb)
+- 		return;
+--	}
+- 
+- 	set_bit(flowid, msgbuf->txstatus_done_map);
+- 	commonring = msgbuf->flowrings[flowid];
+-@@ -1148,6 +1144,8 @@ brcmf_msgbuf_process_rx_complete(struct
+- 
+- 	skb = brcmf_msgbuf_get_pktid(msgbuf->drvr->bus_if->dev,
+- 				     msgbuf->rx_pktids, idx);
+-+	if (!skb)
+-+		return;
+- 
+- 	if (data_offset)
+- 		skb_pull(skb, data_offset);
+diff --git a/package/kernel/mac80211/patches/374-brcmfmac-fix-invalid-access-to-struct-acpi_device-fi.patch b/package/kernel/mac80211/patches/374-brcmfmac-fix-invalid-access-to-struct-acpi_device-fi.patch
+deleted file mode 100644
+index f023034..0000000
+--- a/package/kernel/mac80211/patches/374-brcmfmac-fix-invalid-access-to-struct-acpi_device-fi.patch
++++ /dev/null
+@@ -1,63 +0,0 @@
+-From: Arend van Spriel <arend@broadcom.com>
+-Date: Wed, 27 May 2015 19:31:41 +0200
+-Subject: [PATCH] brcmfmac: fix invalid access to struct acpi_device fields
+-
+-The fields of struct acpi_device are only known when CONFIG_ACPI is
+-defined. Fix this by using a helper function. This will resolve the
+-issue found in linux-next:
+-
+- ../brcmfmac/bcmsdh.c: In function 'brcmf_ops_sdio_probe':
+- ../brcmfmac/bcmsdh.c:1139:7: error: dereferencing pointer to incomplete type
+-   adev->flags.power_manageable = 0;
+-       ^
+-
+-Fixes: f0992ace680c ("brcmfmac: prohibit ACPI power management ...")
+-Cc: Fu, Zhonghui <zhonghui.fu@linux.intel.com>
+-Reported-by: Stephen Rothwell <sfr@canb.auug.org.au>
+-Signed-off-by: Arend van Spriel <arend@broadcom.com>
+-Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
+----
+-
+---- a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c
+-+++ b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c
+-@@ -1117,6 +1117,18 @@ MODULE_DEVICE_TABLE(sdio, brcmf_sdmmc_id
+- static struct brcmfmac_sdio_platform_data *brcmfmac_sdio_pdata;
+- 
+- 
+-+static void brcmf_sdiod_acpi_set_power_manageable(struct device *dev,
+-+						  int val)
+-+{
+-+#if IS_ENABLED(CONFIG_ACPI)
+-+	struct acpi_device *adev;
+-+
+-+	adev = ACPI_COMPANION(dev);
+-+	if (adev)
+-+		adev->flags.power_manageable = 0;
+-+#endif
+-+}
+-+
+- static int brcmf_ops_sdio_probe(struct sdio_func *func,
+- 				const struct sdio_device_id *id)
+- {
+-@@ -1124,7 +1136,6 @@ static int brcmf_ops_sdio_probe(struct s
+- 	struct brcmf_sdio_dev *sdiodev;
+- 	struct brcmf_bus *bus_if;
+- 	struct device *dev;
+--	struct acpi_device *adev;
+- 
+- 	brcmf_dbg(SDIO, "Enter\n");
+- 	brcmf_dbg(SDIO, "Class=%x\n", func->class);
+-@@ -1132,11 +1143,9 @@ static int brcmf_ops_sdio_probe(struct s
+- 	brcmf_dbg(SDIO, "sdio device ID: 0x%04x\n", func->device);
+- 	brcmf_dbg(SDIO, "Function#: %d\n", func->num);
+- 
+--	/* prohibit ACPI power management for this device */
+- 	dev = &func->dev;
+--	adev = ACPI_COMPANION(dev);
+--	if (adev)
+--		adev->flags.power_manageable = 0;
+-+	/* prohibit ACPI power management for this device */
+-+	brcmf_sdiod_acpi_set_power_manageable(dev, 0);
+- 
+- 	/* Consume func num 1 but dont do anything with it. */
+- 	if (func->num == 1)
+diff --git a/package/kernel/mac80211/patches/375-brcmfmac-simplify-check-stripping-v2-NVRAM.patch b/package/kernel/mac80211/patches/375-brcmfmac-simplify-check-stripping-v2-NVRAM.patch
+deleted file mode 100644
+index 2bfd44f..0000000
+--- a/package/kernel/mac80211/patches/375-brcmfmac-simplify-check-stripping-v2-NVRAM.patch
++++ /dev/null
+@@ -1,56 +0,0 @@
+-From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <zajec5@gmail.com>
+-Date: Wed, 20 May 2015 09:34:21 +0200
+-Subject: [PATCH] brcmfmac: simplify check stripping v2 NVRAM
+-MIME-Version: 1.0
+-Content-Type: text/plain; charset=UTF-8
+-Content-Transfer-Encoding: 8bit
+-
+-Comparing NVRAM entry with a full filtering string is simpler than
+-comparing it with a short prefix and then checking random chars at magic
+-offsets. The cost of snprintf relatively low, we execute it just once.
+-Tested on BCM43602 with NVRAM hacked to use V2 format.
+-
+-Signed-off-by: Rafał Miłecki <zajec5@gmail.com>
+-Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
+----
+-
+---- a/drivers/net/wireless/brcm80211/brcmfmac/firmware.c
+-+++ b/drivers/net/wireless/brcm80211/brcmfmac/firmware.c
+-@@ -25,7 +25,7 @@
+- 
+- #define BRCMF_FW_MAX_NVRAM_SIZE			64000
+- #define BRCMF_FW_NVRAM_DEVPATH_LEN		19	/* devpath0=pcie/1/4/ */
+--#define BRCMF_FW_NVRAM_PCIEDEV_LEN		9	/* pcie/1/4/ */
+-+#define BRCMF_FW_NVRAM_PCIEDEV_LEN		10	/* pcie/1/4/ + \0 */
+- 
+- char brcmf_firmware_path[BRCMF_FW_PATH_LEN];
+- module_param_string(firmware_path, brcmf_firmware_path,
+-@@ -297,6 +297,8 @@ fail:
+- static void brcmf_fw_strip_multi_v2(struct nvram_parser *nvp, u16 domain_nr,
+- 				    u16 bus_nr)
+- {
+-+	char prefix[BRCMF_FW_NVRAM_PCIEDEV_LEN];
+-+	size_t len;
+- 	u32 i, j;
+- 	u8 *nvram;
+- 
+-@@ -308,14 +310,13 @@ static void brcmf_fw_strip_multi_v2(stru
+- 	 * Valid entries are of type pcie/X/Y/ where X = domain_nr and
+- 	 * Y = bus_nr.
+- 	 */
+-+	snprintf(prefix, sizeof(prefix), "pcie/%d/%d/", domain_nr, bus_nr);
+-+	len = strlen(prefix);
+- 	i = 0;
+- 	j = 0;
+--	while (i < nvp->nvram_len - BRCMF_FW_NVRAM_PCIEDEV_LEN) {
+--		if ((strncmp(&nvp->nvram[i], "pcie/", 5) == 0) &&
+--		    (nvp->nvram[i + 6] == '/') && (nvp->nvram[i + 8] == '/') &&
+--		    ((nvp->nvram[i + 5] - '0') == domain_nr) &&
+--		    ((nvp->nvram[i + 7] - '0') == bus_nr)) {
+--			i += BRCMF_FW_NVRAM_PCIEDEV_LEN;
+-+	while (i < nvp->nvram_len - len) {
+-+		if (strncmp(&nvp->nvram[i], prefix, len) == 0) {
+-+			i += len;
+- 			while (nvp->nvram[i] != 0) {
+- 				nvram[j] = nvp->nvram[i];
+- 				i++;
+diff --git a/package/kernel/mac80211/patches/376-brcmfmac-simplify-check-finding-NVRAM-v1-device-path.patch b/package/kernel/mac80211/patches/376-brcmfmac-simplify-check-finding-NVRAM-v1-device-path.patch
+deleted file mode 100644
+index 0e65114..0000000
+--- a/package/kernel/mac80211/patches/376-brcmfmac-simplify-check-finding-NVRAM-v1-device-path.patch
++++ /dev/null
+@@ -1,57 +0,0 @@
+-From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <zajec5@gmail.com>
+-Date: Wed, 20 May 2015 11:01:08 +0200
+-Subject: [PATCH] brcmfmac: simplify check finding NVRAM v1 device path
+-MIME-Version: 1.0
+-Content-Type: text/plain; charset=UTF-8
+-Content-Transfer-Encoding: 8bit
+-
+-With a simple use of snprintf and small buffer we can compare NVRAM
+-entry value with a full string. This way we avoid checking random chars
+-at magic offsets.
+-Tested on BCM43602 with NVRAM hacked to use v1 format.
+-
+-Signed-off-by: Rafał Miłecki <zajec5@gmail.com>
+-Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
+----
+-
+---- a/drivers/net/wireless/brcm80211/brcmfmac/firmware.c
+-+++ b/drivers/net/wireless/brcm80211/brcmfmac/firmware.c
+-@@ -222,6 +222,10 @@ static int brcmf_init_nvram_parser(struc
+- static void brcmf_fw_strip_multi_v1(struct nvram_parser *nvp, u16 domain_nr,
+- 				    u16 bus_nr)
+- {
+-+	/* Device path with a leading '=' key-value separator */
+-+	char pcie_path[] = "=pcie/?/?";
+-+	size_t pcie_len;
+-+
+- 	u32 i, j;
+- 	bool found;
+- 	u8 *nvram;
+-@@ -238,6 +242,9 @@ static void brcmf_fw_strip_multi_v1(stru
+- 	/* First search for the devpathX and see if it is the configuration
+- 	 * for domain_nr/bus_nr. Search complete nvp
+- 	 */
+-+	snprintf(pcie_path, sizeof(pcie_path), "=pcie/%d/%d", domain_nr,
+-+		 bus_nr);
+-+	pcie_len = strlen(pcie_path);
+- 	found = false;
+- 	i = 0;
+- 	while (i < nvp->nvram_len - BRCMF_FW_NVRAM_DEVPATH_LEN) {
+-@@ -245,13 +252,10 @@ static void brcmf_fw_strip_multi_v1(stru
+- 		 * Y = domain_nr, Z = bus_nr, X = virtual ID
+- 		 */
+- 		if ((strncmp(&nvp->nvram[i], "devpath", 7) == 0) &&
+--		    (strncmp(&nvp->nvram[i + 8], "=pcie/", 6) == 0)) {
+--			if (((nvp->nvram[i + 14] - '0') == domain_nr) &&
+--			    ((nvp->nvram[i + 16] - '0') == bus_nr)) {
+--				id = nvp->nvram[i + 7] - '0';
+--				found = true;
+--				break;
+--			}
+-+		    (strncmp(&nvp->nvram[i + 8], pcie_path, pcie_len) == 0)) {
+-+			id = nvp->nvram[i + 7] - '0';
+-+			found = true;
+-+			break;
+- 		}
+- 		while (nvp->nvram[i] != 0)
+- 			i++;
+diff --git a/package/kernel/mac80211/patches/377-brcmfmac-treat-0-as-end-of-comment-when-parsing-NVRA.patch b/package/kernel/mac80211/patches/377-brcmfmac-treat-0-as-end-of-comment-when-parsing-NVRA.patch
+deleted file mode 100644
+index dc174e5..0000000
+--- a/package/kernel/mac80211/patches/377-brcmfmac-treat-0-as-end-of-comment-when-parsing-NVRA.patch
++++ /dev/null
+@@ -1,45 +0,0 @@
+-From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <zajec5@gmail.com>
+-Date: Wed, 20 May 2015 13:59:54 +0200
+-Subject: [PATCH] brcmfmac: treat \0 as end of comment when parsing NVRAM
+-MIME-Version: 1.0
+-Content-Type: text/plain; charset=UTF-8
+-Content-Transfer-Encoding: 8bit
+-
+-This fixes brcmfmac dealing with NVRAM coming from platform e.g. from a
+-flash MTD partition. In such cases entries are separated by \0 instead
+-of \n which caused ignoring whole content after the first "comment".
+-While platform NVRAM doesn't usually contain comments, we switch to
+-COMMENT state after e.g. finding an unexpected char in key name.
+-
+-Signed-off-by: Rafał Miłecki <zajec5@gmail.com>
+-Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
+----
+-
+---- a/drivers/net/wireless/brcm80211/brcmfmac/firmware.c
+-+++ b/drivers/net/wireless/brcm80211/brcmfmac/firmware.c
+-@@ -162,17 +162,20 @@ brcmf_nvram_handle_value(struct nvram_pa
+- static enum nvram_parser_state
+- brcmf_nvram_handle_comment(struct nvram_parser *nvp)
+- {
+--	char *eol, *sol;
+-+	char *eoc, *sol;
+- 
+- 	sol = (char *)&nvp->fwnv->data[nvp->pos];
+--	eol = strchr(sol, '\n');
+--	if (eol == NULL)
+--		return END;
+-+	eoc = strchr(sol, '\n');
+-+	if (!eoc) {
+-+		eoc = strchr(sol, '\0');
+-+		if (!eoc)
+-+			return END;
+-+	}
+- 
+- 	/* eat all moving to next line */
+- 	nvp->line++;
+- 	nvp->column = 1;
+--	nvp->pos += (eol - sol) + 1;
+-+	nvp->pos += (eoc - sol) + 1;
+- 	return IDLE;
+- }
+- 
+diff --git a/package/kernel/mac80211/patches/378-brcmfmac-allow-NVRAM-values-to-contain-spaces.patch b/package/kernel/mac80211/patches/378-brcmfmac-allow-NVRAM-values-to-contain-spaces.patch
+deleted file mode 100644
+index 5700142..0000000
+--- a/package/kernel/mac80211/patches/378-brcmfmac-allow-NVRAM-values-to-contain-spaces.patch
++++ /dev/null
+@@ -1,50 +0,0 @@
+-From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <zajec5@gmail.com>
+-Date: Sat, 23 May 2015 09:15:33 +0200
+-Subject: [PATCH] brcmfmac: allow NVRAM values to contain spaces
+-MIME-Version: 1.0
+-Content-Type: text/plain; charset=UTF-8
+-Content-Transfer-Encoding: 8bit
+-
+-Platform NVRAMs often contain values with spaces. Even if right now most
+-firmware-supported entries are simple values, we shouldn't reject these
+-with spaces. It was semi-confirmed by Broadcom in the early patch adding
+-support for platform NVRAMs.
+-
+-Signed-off-by: Rafał Miłecki <zajec5@gmail.com>
+-Acked-by: Arend van Spriel <arend@broadcom.com>
+-Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
+----
+-
+---- a/drivers/net/wireless/brcm80211/brcmfmac/firmware.c
+-+++ b/drivers/net/wireless/brcm80211/brcmfmac/firmware.c
+-@@ -66,6 +66,12 @@ struct nvram_parser {
+- 	bool multi_dev_v2;
+- };
+- 
+-+/**
+-+ * is_nvram_char() - check if char is a valid one for NVRAM entry
+-+ *
+-+ * It accepts all printable ASCII chars except for '#' which opens a comment.
+-+ * Please note that ' ' (space) while accepted is not a valid key name char.
+-+ */
+- static bool is_nvram_char(char c)
+- {
+- 	/* comment marker excluded */
+-@@ -73,7 +79,7 @@ static bool is_nvram_char(char c)
+- 		return false;
+- 
+- 	/* key and value may have any other readable character */
+--	return (c > 0x20 && c < 0x7f);
+-+	return (c >= 0x20 && c < 0x7f);
+- }
+- 
+- static bool is_whitespace(char c)
+-@@ -120,7 +126,7 @@ static enum nvram_parser_state brcmf_nvr
+- 			nvp->multi_dev_v1 = true;
+- 		if (strncmp(&nvp->fwnv->data[nvp->entry], "pcie/", 5) == 0)
+- 			nvp->multi_dev_v2 = true;
+--	} else if (!is_nvram_char(c)) {
+-+	} else if (!is_nvram_char(c) || c == ' ') {
+- 		brcmf_dbg(INFO, "warning: ln=%d:col=%d: '=' expected, skip invalid key entry\n",
+- 			  nvp->line, nvp->column);
+- 		return COMMENT;
+diff --git a/package/kernel/mac80211/patches/379-ath9k-fix-DMA-stop-sequence-for-AR9003.patch b/package/kernel/mac80211/patches/379-ath9k-fix-DMA-stop-sequence-for-AR9003.patch
+deleted file mode 100644
+index 814b0d7..0000000
+--- a/package/kernel/mac80211/patches/379-ath9k-fix-DMA-stop-sequence-for-AR9003.patch
++++ /dev/null
+@@ -1,33 +0,0 @@
+-From: Felix Fietkau <nbd@openwrt.org>
+-Date: Tue, 2 Jun 2015 10:35:46 +0200
+-Subject: [PATCH] ath9k: fix DMA stop sequence for AR9003+
+-
+-AR93xx and newer needs to stop rx before tx to avoid getting the DMA
+-engine or MAC into a stuck state.
+-This should reduce/fix the occurence of "Failed to stop Tx DMA" logspam.
+-
+-Cc: stable@vger.kernel.org
+-Signed-off-by: Felix Fietkau <nbd@openwrt.org>
+----
+-
+---- a/drivers/net/wireless/ath/ath9k/main.c
+-+++ b/drivers/net/wireless/ath/ath9k/main.c
+-@@ -216,11 +216,13 @@ static bool ath_prepare_reset(struct ath
+- 	ath_stop_ani(sc);
+- 	ath9k_hw_disable_interrupts(ah);
+- 
+--	if (!ath_drain_all_txq(sc))
+--		ret = false;
+--
+--	if (!ath_stoprecv(sc))
+--		ret = false;
+-+	if (AR_SREV_9300_20_OR_LATER(ah)) {
+-+		ret &= ath_stoprecv(sc);
+-+		ret &= ath_drain_all_txq(sc);
+-+	} else {
+-+		ret &= ath_drain_all_txq(sc);
+-+		ret &= ath_stoprecv(sc);
+-+	}
+- 
+- 	return ret;
+- }
+diff --git a/package/kernel/mac80211/patches/380-brcmfmac-support-NVRAMs-containing-pci-devpaths-inst.patch b/package/kernel/mac80211/patches/380-brcmfmac-support-NVRAMs-containing-pci-devpaths-inst.patch
+deleted file mode 100644
+index 7bbd57e..0000000
+--- a/package/kernel/mac80211/patches/380-brcmfmac-support-NVRAMs-containing-pci-devpaths-inst.patch
++++ /dev/null
+@@ -1,56 +0,0 @@
+-From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <zajec5@gmail.com>
+-Date: Thu, 28 May 2015 14:19:21 +0200
+-Subject: [PATCH] brcmfmac: support NVRAMs containing pci devpaths (instead of
+- pcie)
+-MIME-Version: 1.0
+-Content-Type: text/plain; charset=UTF-8
+-Content-Transfer-Encoding: 8bit
+-
+-Recently Broadcom added support for NVRAMs with entries for multiple
+-PCIe devices. One of the supported formats is based on prefixes defined
+-like: devpath0=pcie/1/4/ and entries like 0:foo=bar 0:baz=qux etc.
+-
+-Unfortunately there are also a bit older devices using different way of
+-defining prefixes, e.g. SmartRG SR400ac (2 x BCM43602) with entries:
+-devpath0=pci/1/1/
+-devpath1=pci/2/1
+-Broadcom stated this old format will never be used/supported by brcmfmac
+-but given the simplicity of this patch I'll insist on supporting it.
+-
+-Signed-off-by: Rafał Miłecki <zajec5@gmail.com>
+-Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
+----
+-
+---- a/drivers/net/wireless/brcm80211/brcmfmac/firmware.c
+-+++ b/drivers/net/wireless/brcm80211/brcmfmac/firmware.c
+-@@ -232,6 +232,8 @@ static void brcmf_fw_strip_multi_v1(stru
+- 				    u16 bus_nr)
+- {
+- 	/* Device path with a leading '=' key-value separator */
+-+	char pci_path[] = "=pci/?/?";
+-+	size_t pci_len;
+- 	char pcie_path[] = "=pcie/?/?";
+- 	size_t pcie_len;
+- 
+-@@ -251,6 +253,9 @@ static void brcmf_fw_strip_multi_v1(stru
+- 	/* First search for the devpathX and see if it is the configuration
+- 	 * for domain_nr/bus_nr. Search complete nvp
+- 	 */
+-+	snprintf(pci_path, sizeof(pci_path), "=pci/%d/%d", domain_nr,
+-+		 bus_nr);
+-+	pci_len = strlen(pci_path);
+- 	snprintf(pcie_path, sizeof(pcie_path), "=pcie/%d/%d", domain_nr,
+- 		 bus_nr);
+- 	pcie_len = strlen(pcie_path);
+-@@ -260,8 +265,9 @@ static void brcmf_fw_strip_multi_v1(stru
+- 		/* Format: devpathX=pcie/Y/Z/
+- 		 * Y = domain_nr, Z = bus_nr, X = virtual ID
+- 		 */
+--		if ((strncmp(&nvp->nvram[i], "devpath", 7) == 0) &&
+--		    (strncmp(&nvp->nvram[i + 8], pcie_path, pcie_len) == 0)) {
+-+		if (strncmp(&nvp->nvram[i], "devpath", 7) == 0 &&
+-+		    (!strncmp(&nvp->nvram[i + 8], pci_path, pci_len) ||
+-+		     !strncmp(&nvp->nvram[i + 8], pcie_path, pcie_len))) {
+- 			id = nvp->nvram[i + 7] - '0';
+- 			found = true;
+- 			break;
+diff --git a/package/kernel/mac80211/patches/381-brcmfmac-set-wiphy-perm_addr-to-hardware-MAC-address.patch b/package/kernel/mac80211/patches/381-brcmfmac-set-wiphy-perm_addr-to-hardware-MAC-address.patch
+deleted file mode 100644
+index 1eff6ed..0000000
+--- a/package/kernel/mac80211/patches/381-brcmfmac-set-wiphy-perm_addr-to-hardware-MAC-address.patch
++++ /dev/null
+@@ -1,23 +0,0 @@
+-From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <zajec5@gmail.com>
+-Date: Sun, 31 May 2015 02:52:26 +0200
+-Subject: [PATCH] brcmfmac: set wiphy perm_addr to hardware MAC address
+-MIME-Version: 1.0
+-Content-Type: text/plain; charset=UTF-8
+-Content-Transfer-Encoding: 8bit
+-
+-This allows e.g. user space to use /sys/class/ieee80211/*/macaddress
+-
+-Signed-off-by: Rafał Miłecki <zajec5@gmail.com>
+-Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
+----
+-
+---- a/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c
+-+++ b/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c
+-@@ -6070,6 +6070,7 @@ struct brcmf_cfg80211_info *brcmf_cfg802
+- 		brcmf_err("Could not allocate wiphy device\n");
+- 		return NULL;
+- 	}
+-+	memcpy(wiphy->perm_addr, drvr->mac, ETH_ALEN);
+- 	set_wiphy_dev(wiphy, busdev);
+- 
+- 	cfg = wiphy_priv(wiphy);
+diff --git a/package/kernel/mac80211/patches/382-brcmfmac-use-direct-data-pointer-in-NVRAM-parser-str.patch b/package/kernel/mac80211/patches/382-brcmfmac-use-direct-data-pointer-in-NVRAM-parser-str.patch
+deleted file mode 100644
+index c6e83dd..0000000
+--- a/package/kernel/mac80211/patches/382-brcmfmac-use-direct-data-pointer-in-NVRAM-parser-str.patch
++++ /dev/null
+@@ -1,144 +0,0 @@
+-From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <zajec5@gmail.com>
+-Date: Thu, 4 Jun 2015 22:11:07 +0200
+-Subject: [PATCH] brcmfmac: use direct data pointer in NVRAM parser struct
+-MIME-Version: 1.0
+-Content-Type: text/plain; charset=UTF-8
+-Content-Transfer-Encoding: 8bit
+-
+-As we plan to add support for platform NVRAM we should store direct
+-data pointer without the extra struct firmware layer. This will allow
+-us to support other sources with the only requirement being u8 buffer.
+-
+-Signed-off-by: Rafał Miłecki <zajec5@gmail.com>
+-Acked-by: Arend van Spriel <arend@broadcom.com>
+-Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
+----
+-
+---- a/drivers/net/wireless/brcm80211/brcmfmac/firmware.c
+-+++ b/drivers/net/wireless/brcm80211/brcmfmac/firmware.c
+-@@ -43,7 +43,7 @@ enum nvram_parser_state {
+-  * struct nvram_parser - internal info for parser.
+-  *
+-  * @state: current parser state.
+-- * @fwnv: input buffer being parsed.
+-+ * @data: input buffer being parsed.
+-  * @nvram: output buffer with parse result.
+-  * @nvram_len: lenght of parse result.
+-  * @line: current line.
+-@@ -55,7 +55,7 @@ enum nvram_parser_state {
+-  */
+- struct nvram_parser {
+- 	enum nvram_parser_state state;
+--	const struct firmware *fwnv;
+-+	const u8 *data;
+- 	u8 *nvram;
+- 	u32 nvram_len;
+- 	u32 line;
+-@@ -91,7 +91,7 @@ static enum nvram_parser_state brcmf_nvr
+- {
+- 	char c;
+- 
+--	c = nvp->fwnv->data[nvp->pos];
+-+	c = nvp->data[nvp->pos];
+- 	if (c == '\n')
+- 		return COMMENT;
+- 	if (is_whitespace(c))
+-@@ -115,16 +115,16 @@ static enum nvram_parser_state brcmf_nvr
+- 	enum nvram_parser_state st = nvp->state;
+- 	char c;
+- 
+--	c = nvp->fwnv->data[nvp->pos];
+-+	c = nvp->data[nvp->pos];
+- 	if (c == '=') {
+- 		/* ignore RAW1 by treating as comment */
+--		if (strncmp(&nvp->fwnv->data[nvp->entry], "RAW1", 4) == 0)
+-+		if (strncmp(&nvp->data[nvp->entry], "RAW1", 4) == 0)
+- 			st = COMMENT;
+- 		else
+- 			st = VALUE;
+--		if (strncmp(&nvp->fwnv->data[nvp->entry], "devpath", 7) == 0)
+-+		if (strncmp(&nvp->data[nvp->entry], "devpath", 7) == 0)
+- 			nvp->multi_dev_v1 = true;
+--		if (strncmp(&nvp->fwnv->data[nvp->entry], "pcie/", 5) == 0)
+-+		if (strncmp(&nvp->data[nvp->entry], "pcie/", 5) == 0)
+- 			nvp->multi_dev_v2 = true;
+- 	} else if (!is_nvram_char(c) || c == ' ') {
+- 		brcmf_dbg(INFO, "warning: ln=%d:col=%d: '=' expected, skip invalid key entry\n",
+-@@ -145,11 +145,11 @@ brcmf_nvram_handle_value(struct nvram_pa
+- 	char *ekv;
+- 	u32 cplen;
+- 
+--	c = nvp->fwnv->data[nvp->pos];
+-+	c = nvp->data[nvp->pos];
+- 	if (!is_nvram_char(c)) {
+- 		/* key,value pair complete */
+--		ekv = (u8 *)&nvp->fwnv->data[nvp->pos];
+--		skv = (u8 *)&nvp->fwnv->data[nvp->entry];
+-+		ekv = (u8 *)&nvp->data[nvp->pos];
+-+		skv = (u8 *)&nvp->data[nvp->entry];
+- 		cplen = ekv - skv;
+- 		if (nvp->nvram_len + cplen + 1 >= BRCMF_FW_MAX_NVRAM_SIZE)
+- 			return END;
+-@@ -170,7 +170,7 @@ brcmf_nvram_handle_comment(struct nvram_
+- {
+- 	char *eoc, *sol;
+- 
+--	sol = (char *)&nvp->fwnv->data[nvp->pos];
+-+	sol = (char *)&nvp->data[nvp->pos];
+- 	eoc = strchr(sol, '\n');
+- 	if (!eoc) {
+- 		eoc = strchr(sol, '\0');
+-@@ -201,17 +201,17 @@ static enum nvram_parser_state
+- };
+- 
+- static int brcmf_init_nvram_parser(struct nvram_parser *nvp,
+--				   const struct firmware *nv)
+-+				   const u8 *data, size_t data_len)
+- {
+- 	size_t size;
+- 
+- 	memset(nvp, 0, sizeof(*nvp));
+--	nvp->fwnv = nv;
+-+	nvp->data = data;
+- 	/* Limit size to MAX_NVRAM_SIZE, some files contain lot of comment */
+--	if (nv->size > BRCMF_FW_MAX_NVRAM_SIZE)
+-+	if (data_len > BRCMF_FW_MAX_NVRAM_SIZE)
+- 		size = BRCMF_FW_MAX_NVRAM_SIZE;
+- 	else
+--		size = nv->size;
+-+		size = data_len;
+- 	/* Alloc for extra 0 byte + roundup by 4 + length field */
+- 	size += 1 + 3 + sizeof(u32);
+- 	nvp->nvram = kzalloc(size, GFP_KERNEL);
+-@@ -362,18 +362,18 @@ fail:
+-  * and converts newlines to NULs. Shortens buffer as needed and pads with NULs.
+-  * End of buffer is completed with token identifying length of buffer.
+-  */
+--static void *brcmf_fw_nvram_strip(const struct firmware *nv, u32 *new_length,
+--				  u16 domain_nr, u16 bus_nr)
+-+static void *brcmf_fw_nvram_strip(const u8 *data, size_t data_len,
+-+				  u32 *new_length, u16 domain_nr, u16 bus_nr)
+- {
+- 	struct nvram_parser nvp;
+- 	u32 pad;
+- 	u32 token;
+- 	__le32 token_le;
+- 
+--	if (brcmf_init_nvram_parser(&nvp, nv) < 0)
+-+	if (brcmf_init_nvram_parser(&nvp, data, data_len) < 0)
+- 		return NULL;
+- 
+--	while (nvp.pos < nv->size) {
+-+	while (nvp.pos < data_len) {
+- 		nvp.state = nv_parser_states[nvp.state](&nvp);
+- 		if (nvp.state == END)
+- 			break;
+-@@ -432,7 +432,7 @@ static void brcmf_fw_request_nvram_done(
+- 		goto fail;
+- 
+- 	if (fw) {
+--		nvram = brcmf_fw_nvram_strip(fw, &nvram_length,
+-+		nvram = brcmf_fw_nvram_strip(fw->data, fw->size, &nvram_length,
+- 					     fwctx->domain_nr, fwctx->bus_nr);
+- 		release_firmware(fw);
+- 		if (!nvram && !(fwctx->flags & BRCMF_FW_REQ_NV_OPTIONAL))
+diff --git a/package/kernel/mac80211/patches/383-b43-fix-support-for-14e4-4321-PCI-dev-with-BCM4321-c.patch b/package/kernel/mac80211/patches/383-b43-fix-support-for-14e4-4321-PCI-dev-with-BCM4321-c.patch
+deleted file mode 100644
+index 4ecef3b..0000000
+--- a/package/kernel/mac80211/patches/383-b43-fix-support-for-14e4-4321-PCI-dev-with-BCM4321-c.patch
++++ /dev/null
+@@ -1,32 +0,0 @@
+-From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <zajec5@gmail.com>
+-Date: Sat, 6 Jun 2015 22:45:59 +0200
+-Subject: [PATCH] b43: fix support for 14e4:4321 PCI dev with BCM4321 chipset
+-MIME-Version: 1.0
+-Content-Type: text/plain; charset=UTF-8
+-Content-Transfer-Encoding: 8bit
+-
+-It seems Broadcom released two devices with conflicting device id. There
+-are for sure 14e4:4321 PCI devices with BCM4321 (N-PHY) chipset, they
+-can be found in routers, e.g. Netgear WNR834Bv2. However, according to
+-Broadcom public sources 0x4321 is also used for 5 GHz BCM4306 (G-PHY).
+-It's unsure if they meant PCI device id, or "virtual" id (from SPROM).
+-To distinguish these devices lets check PHY type (G vs. N).
+-
+-Signed-off-by: Rafał Miłecki <zajec5@gmail.com>
+-Cc: <stable@vger.kernel.org> # 3.16+
+-Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
+----
+-
+---- a/drivers/net/wireless/b43/main.c
+-+++ b/drivers/net/wireless/b43/main.c
+-@@ -5365,6 +5365,10 @@ static void b43_supported_bands(struct b
+- 		*have_5ghz_phy = true;
+- 		return;
+- 	case 0x4321: /* BCM4306 */
+-+		/* There are 14e4:4321 PCI devs with 2.4 GHz BCM4321 (N-PHY) */
+-+		if (dev->phy.type != B43_PHYTYPE_G)
+-+			break;
+-+		/* fall through */
+- 	case 0x4313: /* BCM4311 */
+- 	case 0x431a: /* BCM4318 */
+- 	case 0x432a: /* BCM4321 */
+diff --git a/package/kernel/mac80211/patches/384-ath9k-force-rx_clear-when-disabling-rx.patch b/package/kernel/mac80211/patches/384-ath9k-force-rx_clear-when-disabling-rx.patch
+deleted file mode 100644
+index bddb15a..0000000
+--- a/package/kernel/mac80211/patches/384-ath9k-force-rx_clear-when-disabling-rx.patch
++++ /dev/null
+@@ -1,31 +0,0 @@
+-From: Felix Fietkau <nbd@openwrt.org>
+-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
+-Rx related DMA stop warnings
+-
+-Cc: stable@vger.kernel.org
+-Signed-off-by: Felix Fietkau <nbd@openwrt.org>
+----
+-
+---- a/drivers/net/wireless/ath/ath9k/mac.c
+-+++ b/drivers/net/wireless/ath/ath9k/mac.c
+-@@ -677,13 +677,15 @@ void ath9k_hw_startpcureceive(struct ath
+- 
+- 	ath9k_ani_reset(ah, is_scanning);
+- 
+--	REG_CLR_BIT(ah, AR_DIAG_SW, (AR_DIAG_RX_DIS | AR_DIAG_RX_ABORT));
+-+	REG_CLR_BIT(ah, AR_DIAG_SW,
+-+		    AR_DIAG_RX_DIS | AR_DIAG_RX_ABORT | AR_DIAG_FORCE_RX_CLEAR);
+- }
+- EXPORT_SYMBOL(ath9k_hw_startpcureceive);
+- 
+- void ath9k_hw_abortpcurecv(struct ath_hw *ah)
+- {
+--	REG_SET_BIT(ah, AR_DIAG_SW, AR_DIAG_RX_ABORT | AR_DIAG_RX_DIS);
+-+	REG_SET_BIT(ah, AR_DIAG_SW,
+-+		    AR_DIAG_RX_DIS | AR_DIAG_RX_ABORT | AR_DIAG_FORCE_RX_CLEAR);
+- 
+- 	ath9k_hw_disable_mib_counters(ah);
+- }
+diff --git a/package/kernel/mac80211/patches/385-ath9k_hw-fix-device-ID-check-for-AR956x.patch b/package/kernel/mac80211/patches/385-ath9k_hw-fix-device-ID-check-for-AR956x.patch
+deleted file mode 100644
+index 2674efb..0000000
+--- a/package/kernel/mac80211/patches/385-ath9k_hw-fix-device-ID-check-for-AR956x.patch
++++ /dev/null
+@@ -1,20 +0,0 @@
+-From: Felix Fietkau <nbd@openwrt.org>
+-Date: Sun, 21 Jun 2015 19:45:59 +0200
+-Subject: [PATCH] ath9k_hw: fix device ID check for AR956x
+-
+-Because of the missing return, the macVersion value was being
+-overwritten with an invalid register read
+-
+-Signed-off-by: Felix Fietkau <nbd@openwrt.org>
+----
+-
+---- a/drivers/net/wireless/ath/ath9k/hw.c
+-+++ b/drivers/net/wireless/ath/ath9k/hw.c
+-@@ -278,6 +278,7 @@ static void ath9k_hw_read_revisions(stru
+- 		return;
+- 	case AR9300_DEVID_QCA956X:
+- 		ah->hw_version.macVersion = AR_SREV_VERSION_9561;
+-+		return;
+- 	}
+- 
+- 	val = REG_READ(ah, AR_SREV) & AR_SREV_ID;
+diff --git a/package/kernel/mac80211/patches/385-brcmfmac-Update-msgbuf-read-pointer-quicker.patch b/package/kernel/mac80211/patches/385-brcmfmac-Update-msgbuf-read-pointer-quicker.patch
+deleted file mode 100644
+index 74df9f9..0000000
+--- a/package/kernel/mac80211/patches/385-brcmfmac-Update-msgbuf-read-pointer-quicker.patch
++++ /dev/null
+@@ -1,109 +0,0 @@
+-From: Hante Meuleman <meuleman@broadcom.com>
+-Date: Mon, 8 Jun 2015 14:38:32 +0200
+-Subject: [PATCH] brcmfmac: Update msgbuf read pointer quicker.
+-
+-On device to host data using msgbuf the read pointer gets updated
+-once all data is processed. Updating this pointer more frequently
+-allows the firmware to add more data quicker. This will result in
+-slightly higher and more stable throughput on CPU bounded host
+-processors.
+-
+-Reviewed-by: Arend Van Spriel <arend@broadcom.com>
+-Reviewed-by: Franky (Zhenhui) Lin <frankyl@broadcom.com>
+-Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
+-Signed-off-by: Hante Meuleman <meuleman@broadcom.com>
+-Signed-off-by: Arend van Spriel <arend@broadcom.com>
+-Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
+----
+-
+---- a/drivers/net/wireless/brcm80211/brcmfmac/commonring.c
+-+++ b/drivers/net/wireless/brcm80211/brcmfmac/commonring.c
+-@@ -223,8 +223,6 @@ void brcmf_commonring_write_cancel(struc
+- void *brcmf_commonring_get_read_ptr(struct brcmf_commonring *commonring,
+- 				    u16 *n_items)
+- {
+--	void *ret_addr;
+--
+- 	if (commonring->cr_update_wptr)
+- 		commonring->cr_update_wptr(commonring->cr_ctx);
+- 
+-@@ -235,19 +233,18 @@ void *brcmf_commonring_get_read_ptr(stru
+- 	if (*n_items == 0)
+- 		return NULL;
+- 
+--	ret_addr = commonring->buf_addr +
+--		   (commonring->r_ptr * commonring->item_len);
+--
+--	commonring->r_ptr += *n_items;
+--	if (commonring->r_ptr == commonring->depth)
+--		commonring->r_ptr = 0;
+--
+--	return ret_addr;
+-+	return commonring->buf_addr +
+-+	       (commonring->r_ptr * commonring->item_len);
+- }
+- 
+- 
+--int brcmf_commonring_read_complete(struct brcmf_commonring *commonring)
+-+int brcmf_commonring_read_complete(struct brcmf_commonring *commonring,
+-+				   u16 n_items)
+- {
+-+	commonring->r_ptr += n_items;
+-+	if (commonring->r_ptr == commonring->depth)
+-+		commonring->r_ptr = 0;
+-+
+- 	if (commonring->cr_write_rptr)
+- 		return commonring->cr_write_rptr(commonring->cr_ctx);
+- 
+---- a/drivers/net/wireless/brcm80211/brcmfmac/commonring.h
+-+++ b/drivers/net/wireless/brcm80211/brcmfmac/commonring.h
+-@@ -62,7 +62,8 @@ void brcmf_commonring_write_cancel(struc
+- 				   u16 n_items);
+- void *brcmf_commonring_get_read_ptr(struct brcmf_commonring *commonring,
+- 				    u16 *n_items);
+--int brcmf_commonring_read_complete(struct brcmf_commonring *commonring);
+-+int brcmf_commonring_read_complete(struct brcmf_commonring *commonring,
+-+				   u16 n_items);
+- 
+- #define brcmf_commonring_n_items(commonring) (commonring->depth)
+- #define brcmf_commonring_len_item(commonring) (commonring->item_len)
+---- a/drivers/net/wireless/brcm80211/brcmfmac/msgbuf.c
+-+++ b/drivers/net/wireless/brcm80211/brcmfmac/msgbuf.c
+-@@ -75,6 +75,8 @@
+- 
+- #define BRCMF_MSGBUF_DELAY_TXWORKER_THRS	96
+- #define BRCMF_MSGBUF_TRICKLE_TXWORKER_THRS	32
+-+#define BRCMF_MSGBUF_UPDATE_RX_PTR_THRS		48
+-+
+- 
+- struct msgbuf_common_hdr {
+- 	u8				msgtype;
+-@@ -1257,19 +1259,27 @@ static void brcmf_msgbuf_process_rx(stru
+- {
+- 	void *buf;
+- 	u16 count;
+-+	u16 processed;
+- 
+- again:
+- 	buf = brcmf_commonring_get_read_ptr(commonring, &count);
+- 	if (buf == NULL)
+- 		return;
+- 
+-+	processed = 0;
+- 	while (count) {
+- 		brcmf_msgbuf_process_msgtype(msgbuf,
+- 					     buf + msgbuf->rx_dataoffset);
+- 		buf += brcmf_commonring_len_item(commonring);
+-+		processed++;
+-+		if (processed == BRCMF_MSGBUF_UPDATE_RX_PTR_THRS) {
+-+			brcmf_commonring_read_complete(commonring, processed);
+-+			processed = 0;
+-+		}
+- 		count--;
+- 	}
+--	brcmf_commonring_read_complete(commonring);
+-+	if (processed)
+-+		brcmf_commonring_read_complete(commonring, processed);
+- 
+- 	if (commonring->r_ptr == 0)
+- 		goto again;
+diff --git a/package/kernel/mac80211/patches/386-brcmfmac-remove-chipinfo-debugfs-entry.patch b/package/kernel/mac80211/patches/386-brcmfmac-remove-chipinfo-debugfs-entry.patch
+deleted file mode 100644
+index 9e5b486..0000000
+--- a/package/kernel/mac80211/patches/386-brcmfmac-remove-chipinfo-debugfs-entry.patch
++++ /dev/null
+@@ -1,39 +0,0 @@
+-From: Arend van Spriel <arend@broadcom.com>
+-Date: Mon, 8 Jun 2015 14:38:33 +0200
+-Subject: [PATCH] brcmfmac: remove chipinfo debugfs entry
+-
+-The information provided by chipinfo is also provided by the
+-revinfo debugfs entry. Removing it from debugfs.
+-
+-Reviewed-by: Hante Meuleman <meuleman@broadcom.com>
+-Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
+-Signed-off-by: Arend van Spriel <arend@broadcom.com>
+-Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
+----
+-
+---- a/drivers/net/wireless/brcm80211/brcmfmac/debug.c
+-+++ b/drivers/net/wireless/brcm80211/brcmfmac/debug.c
+-@@ -41,15 +41,6 @@ void brcmf_debugfs_exit(void)
+- 	root_folder = NULL;
+- }
+- 
+--static int brcmf_debugfs_chipinfo_read(struct seq_file *seq, void *data)
+--{
+--	struct brcmf_bus *bus = dev_get_drvdata(seq->private);
+--
+--	seq_printf(seq, "chip: %x(%u) rev %u\n",
+--		   bus->chip, bus->chip, bus->chiprev);
+--	return 0;
+--}
+--
+- int brcmf_debugfs_attach(struct brcmf_pub *drvr)
+- {
+- 	struct device *dev = drvr->bus_if->dev;
+-@@ -58,7 +49,6 @@ int brcmf_debugfs_attach(struct brcmf_pu
+- 		return -ENODEV;
+- 
+- 	drvr->dbgfs_dir = debugfs_create_dir(dev_name(dev), root_folder);
+--	brcmf_debugfs_add_entry(drvr, "chipinfo", brcmf_debugfs_chipinfo_read);
+- 
+- 	return PTR_ERR_OR_ZERO(drvr->dbgfs_dir);
+- }
+diff --git a/package/kernel/mac80211/patches/387-brcmfmac-remove-watchdog-reset-from-brcmf_pcie_busco.patch b/package/kernel/mac80211/patches/387-brcmfmac-remove-watchdog-reset-from-brcmf_pcie_busco.patch
+deleted file mode 100644
+index c38b2cd..0000000
+--- a/package/kernel/mac80211/patches/387-brcmfmac-remove-watchdog-reset-from-brcmf_pcie_busco.patch
++++ /dev/null
+@@ -1,53 +0,0 @@
+-From: Arend van Spriel <arend@broadcom.com>
+-Date: Mon, 8 Jun 2015 14:38:34 +0200
+-Subject: [PATCH] brcmfmac: remove watchdog reset from
+- brcmf_pcie_buscoreprep()
+-
+-The watchdog reset as done in brcmf_pcie_buscoreprep() is not
+-sufficient. It needs to modify PCIe core registers as well
+-which is properly done by brcmf_pcie_reset_device() after the
+-chip recognition is done. So the faulty watchdog reset can be
+-removed as it was causing driver reload to fail and hang the
+-system requiring a power-cycle. Instead the call to to the
+-brcmf_pcie_reset_device() function is done twice in the unload.
+-
+-Reviewed-by: Hante Meuleman <meuleman@broadcom.com>
+-Reviewed-by: Daniel (Deognyoun) Kim <dekim@broadcom.com>
+-Reviewed-by: Franky (Zhenhui) Lin <frankyl@broadcom.com>
+-Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
+-Signed-off-by: Arend van Spriel <arend@broadcom.com>
+-Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
+----
+-
+---- a/drivers/net/wireless/brcm80211/brcmfmac/pcie.c
+-+++ b/drivers/net/wireless/brcm80211/brcmfmac/pcie.c
+-@@ -1629,20 +1629,7 @@ static void brcmf_pcie_buscore_write32(v
+- 
+- static int brcmf_pcie_buscoreprep(void *ctx)
+- {
+--	struct brcmf_pciedev_info *devinfo = (struct brcmf_pciedev_info *)ctx;
+--	int err;
+--
+--	err = brcmf_pcie_get_resource(devinfo);
+--	if (err == 0) {
+--		/* Set CC watchdog to reset all the cores on the chip to bring
+--		 * back dongle to a sane state.
+--		 */
+--		brcmf_pcie_buscore_write32(ctx, CORE_CC_REG(SI_ENUM_BASE,
+--							    watchdog), 4);
+--		msleep(100);
+--	}
+--
+--	return err;
+-+	return brcmf_pcie_get_resource(ctx);
+- }
+- 
+- 
+-@@ -1824,6 +1811,7 @@ brcmf_pcie_remove(struct pci_dev *pdev)
+- 		brcmf_pcie_intr_disable(devinfo);
+- 
+- 	brcmf_detach(&pdev->dev);
+-+	brcmf_pcie_reset_device(devinfo);
+- 
+- 	kfree(bus->bus_priv.pcie);
+- 	kfree(bus->msgbuf->flowrings);
+diff --git a/package/kernel/mac80211/patches/388-brcmfmac-use-debugfs_create_devm_seqfile-helper-func.patch b/package/kernel/mac80211/patches/388-brcmfmac-use-debugfs_create_devm_seqfile-helper-func.patch
+deleted file mode 100644
+index 756fbb2..0000000
+--- a/package/kernel/mac80211/patches/388-brcmfmac-use-debugfs_create_devm_seqfile-helper-func.patch
++++ /dev/null
+@@ -1,69 +0,0 @@
+-From: Arend van Spriel <arend@broadcom.com>
+-Date: Mon, 8 Jun 2015 14:38:35 +0200
+-Subject: [PATCH] brcmfmac: use debugfs_create_devm_seqfile() helper
+- function
+-
+-Some time ago the function debugfs_create_devm_seqfile() was
+-introduced in debugfs. The caller simply needs to provide a
+-device pointer and read function. The function brcmf_debugfs_add_entry()
+-is now simply a wrapper only doing the work for CONFIG_BRCMDBG.
+-
+-Reviewed-by: Hante Meuleman <meuleman@broadcom.com>
+-Reviewed-by: Franky (Zhenhui) Lin <frankyl@broadcom.com>
+-Reviewed-by: Daniel (Deognyoun) Kim <dekim@broadcom.com>
+-Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
+-Signed-off-by: Arend van Spriel <arend@broadcom.com>
+-Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
+----
+-
+---- a/drivers/net/wireless/brcm80211/brcmfmac/debug.c
+-+++ b/drivers/net/wireless/brcm80211/brcmfmac/debug.c
+-@@ -64,44 +64,12 @@ struct dentry *brcmf_debugfs_get_devdir(
+- 	return drvr->dbgfs_dir;
+- }
+- 
+--struct brcmf_debugfs_entry {
+--	int (*read)(struct seq_file *seq, void *data);
+--	struct brcmf_pub *drvr;
+--};
+--
+--static int brcmf_debugfs_entry_open(struct inode *inode, struct file *f)
+--{
+--	struct brcmf_debugfs_entry *entry = inode->i_private;
+--
+--	return single_open(f, entry->read, entry->drvr->bus_if->dev);
+--}
+--
+--static const struct file_operations brcmf_debugfs_def_ops = {
+--	.owner = THIS_MODULE,
+--	.open = brcmf_debugfs_entry_open,
+--	.release = single_release,
+--	.read = seq_read,
+--	.llseek = seq_lseek
+--};
+--
+- int brcmf_debugfs_add_entry(struct brcmf_pub *drvr, const char *fn,
+- 			    int (*read_fn)(struct seq_file *seq, void *data))
+- {
+--	struct dentry *dentry =  drvr->dbgfs_dir;
+--	struct brcmf_debugfs_entry *entry;
+--
+--	if (IS_ERR_OR_NULL(dentry))
+--		return -ENOENT;
+--
+--	entry = devm_kzalloc(drvr->bus_if->dev, sizeof(*entry), GFP_KERNEL);
+--	if (!entry)
+--		return -ENOMEM;
+--
+--	entry->read = read_fn;
+--	entry->drvr = drvr;
+--
+--	dentry = debugfs_create_file(fn, S_IRUGO, dentry, entry,
+--				     &brcmf_debugfs_def_ops);
+-+	struct dentry *e;
+- 
+--	return PTR_ERR_OR_ZERO(dentry);
+-+	e = debugfs_create_devm_seqfile(drvr->bus_if->dev, fn,
+-+					drvr->dbgfs_dir, read_fn);
+-+	return PTR_ERR_OR_ZERO(e);
+- }
+diff --git a/package/kernel/mac80211/patches/389-0001-brcmfmac-Check-if-firmware-supports-p2p.patch b/package/kernel/mac80211/patches/389-0001-brcmfmac-Check-if-firmware-supports-p2p.patch
+deleted file mode 100644
+index ff24a4a..0000000
+--- a/package/kernel/mac80211/patches/389-0001-brcmfmac-Check-if-firmware-supports-p2p.patch
++++ /dev/null
+@@ -1,42 +0,0 @@
+-From: Pontus Fuchs <pontusf@broadcom.com>
+-Date: Thu, 11 Jun 2015 00:12:17 +0200
+-Subject: [PATCH] brcmfmac: Check if firmware supports p2p
+-
+-Add a feature flag to reflect the firmware's p2p capability.
+-
+-Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
+-Reviewed-by: Hante Meuleman <meuleman@broadcom.com>
+-Reviewed-by: Arend Van Spriel <arend@broadcom.com>
+-Signed-off-by: Pontus Fuchs <pontusf@broadcom.com>
+-Signed-off-by: Arend van Spriel <arend@broadcom.com>
+-Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
+----
+-
+---- a/drivers/net/wireless/brcm80211/brcmfmac/feature.c
+-+++ b/drivers/net/wireless/brcm80211/brcmfmac/feature.c
+-@@ -129,6 +129,7 @@ void brcmf_feat_attach(struct brcmf_pub
+- 		brcmf_feat_iovar_int_get(ifp, BRCMF_FEAT_WOWL, "wowl");
+- 	if (drvr->bus_if->chip != BRCM_CC_43362_CHIP_ID)
+- 		brcmf_feat_iovar_int_set(ifp, BRCMF_FEAT_MBSS, "mbss", 0);
+-+	brcmf_feat_iovar_int_get(ifp, BRCMF_FEAT_P2P, "p2p");
+- 
+- 	/* set chip related quirks */
+- 	switch (drvr->bus_if->chip) {
+---- a/drivers/net/wireless/brcm80211/brcmfmac/feature.h
+-+++ b/drivers/net/wireless/brcm80211/brcmfmac/feature.h
+-@@ -23,12 +23,14 @@
+-  * MCHAN: multi-channel for concurrent P2P.
+-  * PNO: preferred network offload.
+-  * WOWL: Wake-On-WLAN.
+-+ * P2P: peer-to-peer
+-  */
+- #define BRCMF_FEAT_LIST \
+- 	BRCMF_FEAT_DEF(MBSS) \
+- 	BRCMF_FEAT_DEF(MCHAN) \
+- 	BRCMF_FEAT_DEF(PNO) \
+--	BRCMF_FEAT_DEF(WOWL)
+-+	BRCMF_FEAT_DEF(WOWL) \
+-+	BRCMF_FEAT_DEF(P2P)
+- /*
+-  * Quirks:
+-  *
+diff --git a/package/kernel/mac80211/patches/389-0002-brcmfmac-Build-wiphy-mode-and-interface-combinations.patch b/package/kernel/mac80211/patches/389-0002-brcmfmac-Build-wiphy-mode-and-interface-combinations.patch
+deleted file mode 100644
+index 3876ba0..0000000
+--- a/package/kernel/mac80211/patches/389-0002-brcmfmac-Build-wiphy-mode-and-interface-combinations.patch
++++ /dev/null
+@@ -1,198 +0,0 @@
+-From: Pontus Fuchs <pontusf@broadcom.com>
+-Date: Thu, 11 Jun 2015 00:12:18 +0200
+-Subject: [PATCH] brcmfmac: Build wiphy mode and interface combinations
+- dynamically
+-
+-Switch from using semi hard coded interface combinations. This makes
+-it easier to announce what the firmware actually supports. This fixes
+-the case where brcmfmac announces p2p but the firmware doesn't
+-support it.
+-
+-Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
+-Reviewed-by: Hante Meuleman <meuleman@broadcom.com>
+-Reviewed-by: Arend Van Spriel <arend@broadcom.com>
+-Signed-off-by: Pontus Fuchs <pontusf@broadcom.com>
+-Signed-off-by: Arend van Spriel <arend@broadcom.com>
+-Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
+----
+-
+---- a/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c
+-+++ b/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c
+-@@ -52,8 +52,6 @@
+- #define BRCMF_PNO_SCAN_COMPLETE		1
+- #define BRCMF_PNO_SCAN_INCOMPLETE	0
+- 
+--#define BRCMF_IFACE_MAX_CNT		3
+--
+- #define WPA_OUI				"\x00\x50\xF2"	/* WPA OUI */
+- #define WPA_OUI_TYPE			1
+- #define RSN_OUI				"\x00\x0F\xAC"	/* RSN OUI */
+-@@ -5639,53 +5637,6 @@ static int brcmf_setup_wiphybands(struct
+- 	return 0;
+- }
+- 
+--static const struct ieee80211_iface_limit brcmf_iface_limits_mbss[] = {
+--	{
+--		.max = 1,
+--		.types = BIT(NL80211_IFTYPE_STATION) |
+--			 BIT(NL80211_IFTYPE_ADHOC)
+--	},
+--	{
+--		.max = 4,
+--		.types = BIT(NL80211_IFTYPE_AP)
+--	},
+--	{
+--		.max = 1,
+--		.types = BIT(NL80211_IFTYPE_P2P_CLIENT) |
+--			 BIT(NL80211_IFTYPE_P2P_GO)
+--	},
+--	{
+--		.max = 1,
+--		.types = BIT(NL80211_IFTYPE_P2P_DEVICE)
+--	}
+--};
+--
+--static const struct ieee80211_iface_limit brcmf_iface_limits_sbss[] = {
+--	{
+--		.max = 2,
+--		.types = BIT(NL80211_IFTYPE_STATION) |
+--			 BIT(NL80211_IFTYPE_ADHOC) |
+--			 BIT(NL80211_IFTYPE_AP)
+--	},
+--	{
+--		.max = 1,
+--		.types = BIT(NL80211_IFTYPE_P2P_CLIENT) |
+--			 BIT(NL80211_IFTYPE_P2P_GO)
+--	},
+--	{
+--		.max = 1,
+--		.types = BIT(NL80211_IFTYPE_P2P_DEVICE)
+--	}
+--};
+--static struct ieee80211_iface_combination brcmf_iface_combos[] = {
+--	{
+--		 .max_interfaces = BRCMF_IFACE_MAX_CNT,
+--		 .num_different_channels = 1,
+--		 .n_limits = ARRAY_SIZE(brcmf_iface_limits_sbss),
+--		 .limits = brcmf_iface_limits_sbss,
+--	}
+--};
+--
+- static const struct ieee80211_txrx_stypes
+- brcmf_txrx_stypes[NUM_NL80211_IFTYPES] = {
+- 	[NL80211_IFTYPE_STATION] = {
+-@@ -5715,6 +5666,67 @@ brcmf_txrx_stypes[NUM_NL80211_IFTYPES] =
+- 	}
+- };
+- 
+-+static int brcmf_setup_ifmodes(struct wiphy *wiphy, struct brcmf_if *ifp)
+-+{
+-+	struct ieee80211_iface_combination *combo = NULL;
+-+	struct ieee80211_iface_limit *limits = NULL;
+-+	int i = 0, max_iface_cnt;
+-+
+-+	combo = kzalloc(sizeof(*combo), GFP_KERNEL);
+-+	if (!combo)
+-+		goto err;
+-+
+-+	limits = kzalloc(sizeof(*limits) * 4, GFP_KERNEL);
+-+	if (!limits)
+-+		goto err;
+-+
+-+	wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) |
+-+				 BIT(NL80211_IFTYPE_ADHOC) |
+-+				 BIT(NL80211_IFTYPE_AP);
+-+
+-+	if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_MCHAN))
+-+		combo->num_different_channels = 2;
+-+	else
+-+		combo->num_different_channels = 1;
+-+
+-+	if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_MBSS)) {
+-+		limits[i].max = 1;
+-+		limits[i++].types = BIT(NL80211_IFTYPE_STATION);
+-+		limits[i].max = 4;
+-+		limits[i++].types = BIT(NL80211_IFTYPE_AP);
+-+		max_iface_cnt = 5;
+-+	} else {
+-+		limits[i].max = 2;
+-+		limits[i++].types = BIT(NL80211_IFTYPE_STATION) |
+-+				    BIT(NL80211_IFTYPE_AP);
+-+		max_iface_cnt = 2;
+-+	}
+-+
+-+	if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_P2P)) {
+-+		wiphy->interface_modes |= BIT(NL80211_IFTYPE_P2P_CLIENT) |
+-+					  BIT(NL80211_IFTYPE_P2P_GO) |
+-+					  BIT(NL80211_IFTYPE_P2P_DEVICE);
+-+		limits[i].max = 1;
+-+		limits[i++].types = BIT(NL80211_IFTYPE_P2P_CLIENT) |
+-+				    BIT(NL80211_IFTYPE_P2P_GO);
+-+		limits[i].max = 1;
+-+		limits[i++].types = BIT(NL80211_IFTYPE_P2P_DEVICE);
+-+		max_iface_cnt += 2;
+-+	}
+-+	combo->max_interfaces = max_iface_cnt;
+-+	combo->limits = limits;
+-+	combo->n_limits = i;
+-+
+-+	wiphy->iface_combinations = combo;
+-+	wiphy->n_iface_combinations = 1;
+-+	return 0;
+-+
+-+err:
+-+	kfree(limits);
+-+	kfree(combo);
+-+	return -ENOMEM;
+-+}
+-+
+- static void brcmf_wiphy_pno_params(struct wiphy *wiphy)
+- {
+- 	/* scheduled scan settings */
+-@@ -5745,7 +5757,6 @@ static void brcmf_wiphy_wowl_params(stru
+- static int brcmf_setup_wiphy(struct wiphy *wiphy, struct brcmf_if *ifp)
+- {
+- 	struct ieee80211_supported_band *band;
+--	struct ieee80211_iface_combination ifc_combo;
+- 	__le32 bandlist[3];
+- 	u32 n_bands;
+- 	int err, i;
+-@@ -5753,24 +5764,11 @@ static int brcmf_setup_wiphy(struct wiph
+- 	wiphy->max_scan_ssids = WL_NUM_SCAN_MAX;
+- 	wiphy->max_scan_ie_len = BRCMF_SCAN_IE_LEN_MAX;
+- 	wiphy->max_num_pmkids = WL_NUM_PMKIDS_MAX;
+--	wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) |
+--				 BIT(NL80211_IFTYPE_ADHOC) |
+--				 BIT(NL80211_IFTYPE_AP) |
+--				 BIT(NL80211_IFTYPE_P2P_CLIENT) |
+--				 BIT(NL80211_IFTYPE_P2P_GO) |
+--				 BIT(NL80211_IFTYPE_P2P_DEVICE);
+--	/* need VSDB firmware feature for concurrent channels */
+--	ifc_combo = brcmf_iface_combos[0];
+--	if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_MCHAN))
+--		ifc_combo.num_different_channels = 2;
+--	if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_MBSS)) {
+--		ifc_combo.n_limits = ARRAY_SIZE(brcmf_iface_limits_mbss),
+--		ifc_combo.limits = brcmf_iface_limits_mbss;
+--	}
+--	wiphy->iface_combinations = kmemdup(&ifc_combo,
+--					    sizeof(ifc_combo),
+--					    GFP_KERNEL);
+--	wiphy->n_iface_combinations = ARRAY_SIZE(brcmf_iface_combos);
+-+
+-+	err = brcmf_setup_ifmodes(wiphy, ifp);
+-+	if (err)
+-+		return err;
+-+
+- 	wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
+- 	wiphy->cipher_suites = __wl_cipher_suites;
+- 	wiphy->n_cipher_suites = ARRAY_SIZE(__wl_cipher_suites);
+-@@ -6035,6 +6033,8 @@ static void brcmf_free_wiphy(struct wiph
+- 	if (!wiphy)
+- 		return;
+- 
+-+	if (wiphy->iface_combinations)
+-+		kfree(wiphy->iface_combinations->limits);
+- 	kfree(wiphy->iface_combinations);
+- 	if (wiphy->bands[IEEE80211_BAND_2GHZ]) {
+- 		kfree(wiphy->bands[IEEE80211_BAND_2GHZ]->channels);
+diff --git a/package/kernel/mac80211/patches/389-0003-brcmfmac-rework-.get_station-callback.patch b/package/kernel/mac80211/patches/389-0003-brcmfmac-rework-.get_station-callback.patch
+deleted file mode 100644
+index 7bd0686..0000000
+--- a/package/kernel/mac80211/patches/389-0003-brcmfmac-rework-.get_station-callback.patch
++++ /dev/null
+@@ -1,326 +0,0 @@
+-From: Arend van Spriel <arend@broadcom.com>
+-Date: Thu, 11 Jun 2015 00:12:19 +0200
+-Subject: [PATCH] brcmfmac: rework .get_station() callback
+-
+-The .get_station() cfg80211 callback is used in several scenarios. In
+-managed mode it can obtain information about the access-point and its
+-BSS parameters. In managed mode it can also obtain information about
+-TDLS peers. In AP mode it can obtain information about connected
+-clients.
+-
+-Reviewed-by: Hante Meuleman <meuleman@broadcom.com>
+-Reviewed-by: Daniel (Deognyoun) Kim <dekim@broadcom.com>
+-Reviewed-by: Franky (Zhenhui) Lin <frankyl@broadcom.com>
+-Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
+-Signed-off-by: Arend van Spriel <arend@broadcom.com>
+-Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
+----
+-
+---- a/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c
+-+++ b/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c
+-@@ -2395,27 +2395,80 @@ brcmf_cfg80211_reconfigure_wep(struct br
+- 		brcmf_err("set wsec error (%d)\n", err);
+- }
+- 
+-+static void brcmf_convert_sta_flags(u32 fw_sta_flags, struct station_info *si)
+-+{
+-+	struct nl80211_sta_flag_update *sfu;
+-+
+-+	brcmf_dbg(TRACE, "flags %08x\n", fw_sta_flags);
+-+	si->filled |= BIT(NL80211_STA_INFO_STA_FLAGS);
+-+	sfu = &si->sta_flags;
+-+	sfu->mask = BIT(NL80211_STA_FLAG_WME) |
+-+		    BIT(NL80211_STA_FLAG_AUTHENTICATED) |
+-+		    BIT(NL80211_STA_FLAG_ASSOCIATED) |
+-+		    BIT(NL80211_STA_FLAG_AUTHORIZED);
+-+	if (fw_sta_flags & BRCMF_STA_WME)
+-+		sfu->set |= BIT(NL80211_STA_FLAG_WME);
+-+	if (fw_sta_flags & BRCMF_STA_AUTHE)
+-+		sfu->set |= BIT(NL80211_STA_FLAG_AUTHENTICATED);
+-+	if (fw_sta_flags & BRCMF_STA_ASSOC)
+-+		sfu->set |= BIT(NL80211_STA_FLAG_ASSOCIATED);
+-+	if (fw_sta_flags & BRCMF_STA_AUTHO)
+-+		sfu->set |= BIT(NL80211_STA_FLAG_AUTHORIZED);
+-+}
+-+
+-+static void brcmf_fill_bss_param(struct brcmf_if *ifp, struct station_info *si)
+-+{
+-+	struct {
+-+		__le32 len;
+-+		struct brcmf_bss_info_le bss_le;
+-+	} *buf;
+-+	u16 capability;
+-+	int err;
+-+
+-+	buf = kzalloc(WL_BSS_INFO_MAX, GFP_KERNEL);
+-+	if (!buf)
+-+		return;
+-+
+-+	buf->len = cpu_to_le32(WL_BSS_INFO_MAX);
+-+	err = brcmf_fil_cmd_data_get(ifp, BRCMF_C_GET_BSS_INFO, buf,
+-+				     WL_BSS_INFO_MAX);
+-+	if (err) {
+-+		brcmf_err("Failed to get bss info (%d)\n", err);
+-+		return;
+-+	}
+-+	si->filled |= BIT(NL80211_STA_INFO_BSS_PARAM);
+-+	si->bss_param.beacon_interval = le16_to_cpu(buf->bss_le.beacon_period);
+-+	si->bss_param.dtim_period = buf->bss_le.dtim_period;
+-+	capability = le16_to_cpu(buf->bss_le.capability);
+-+	if (capability & IEEE80211_HT_STBC_PARAM_DUAL_CTS_PROT)
+-+		si->bss_param.flags |= BSS_PARAM_FLAGS_CTS_PROT;
+-+	if (capability & WLAN_CAPABILITY_SHORT_PREAMBLE)
+-+		si->bss_param.flags |= BSS_PARAM_FLAGS_SHORT_PREAMBLE;
+-+	if (capability & WLAN_CAPABILITY_SHORT_SLOT_TIME)
+-+		si->bss_param.flags |= BSS_PARAM_FLAGS_SHORT_SLOT_TIME;
+-+}
+-+
+- static s32
+- brcmf_cfg80211_get_station(struct wiphy *wiphy, struct net_device *ndev,
+- 			   const u8 *mac, struct station_info *sinfo)
+- {
+- 	struct brcmf_if *ifp = netdev_priv(ndev);
+--	struct brcmf_cfg80211_profile *profile = &ifp->vif->profile;
+--	struct brcmf_scb_val_le scb_val;
+--	int rssi;
+--	s32 rate;
+- 	s32 err = 0;
+--	u8 *bssid = profile->bssid;
+- 	struct brcmf_sta_info_le sta_info_le;
+--	u32 beacon_period;
+--	u32 dtim_period;
+-+	u32 sta_flags;
+-+	u32 is_tdls_peer;
+- 
+- 	brcmf_dbg(TRACE, "Enter, MAC %pM\n", mac);
+- 	if (!check_vif_up(ifp->vif))
+- 		return -EIO;
+- 
+--	if (brcmf_is_apmode(ifp->vif)) {
+--		memcpy(&sta_info_le, mac, ETH_ALEN);
+-+	memset(&sta_info_le, 0, sizeof(sta_info_le));
+-+	memcpy(&sta_info_le, mac, ETH_ALEN);
+-+	err = brcmf_fil_iovar_data_get(ifp, "tdls_sta_info",
+-+				       &sta_info_le,
+-+				       sizeof(sta_info_le));
+-+	is_tdls_peer = !err;
+-+	if (err) {
+- 		err = brcmf_fil_iovar_data_get(ifp, "sta_info",
+- 					       &sta_info_le,
+- 					       sizeof(sta_info_le));
+-@@ -2423,73 +2476,48 @@ brcmf_cfg80211_get_station(struct wiphy
+- 			brcmf_err("GET STA INFO failed, %d\n", err);
+- 			goto done;
+- 		}
+--		sinfo->filled = BIT(NL80211_STA_INFO_INACTIVE_TIME);
+--		sinfo->inactive_time = le32_to_cpu(sta_info_le.idle) * 1000;
+--		if (le32_to_cpu(sta_info_le.flags) & BRCMF_STA_ASSOC) {
+--			sinfo->filled |= BIT(NL80211_STA_INFO_CONNECTED_TIME);
+--			sinfo->connected_time = le32_to_cpu(sta_info_le.in);
+--		}
+--		brcmf_dbg(TRACE, "STA idle time : %d ms, connected time :%d sec\n",
+--			  sinfo->inactive_time, sinfo->connected_time);
+--	} else if (ifp->vif->wdev.iftype == NL80211_IFTYPE_STATION) {
+--		if (memcmp(mac, bssid, ETH_ALEN)) {
+--			brcmf_err("Wrong Mac address cfg_mac-%pM wl_bssid-%pM\n",
+--				  mac, bssid);
+--			err = -ENOENT;
+--			goto done;
+--		}
+--		/* Report the current tx rate */
+--		err = brcmf_fil_cmd_int_get(ifp, BRCMF_C_GET_RATE, &rate);
+--		if (err) {
+--			brcmf_err("Could not get rate (%d)\n", err);
+--			goto done;
+--		} else {
+-+	}
+-+	brcmf_dbg(TRACE, "version %d\n", le16_to_cpu(sta_info_le.ver));
+-+	sinfo->filled = BIT(NL80211_STA_INFO_INACTIVE_TIME);
+-+	sinfo->inactive_time = le32_to_cpu(sta_info_le.idle) * 1000;
+-+	sta_flags = le32_to_cpu(sta_info_le.flags);
+-+	brcmf_convert_sta_flags(sta_flags, sinfo);
+-+	sinfo->sta_flags.mask |= BIT(NL80211_STA_FLAG_TDLS_PEER);
+-+	if (is_tdls_peer)
+-+		sinfo->sta_flags.set |= BIT(NL80211_STA_FLAG_TDLS_PEER);
+-+	else
+-+		sinfo->sta_flags.set &= ~BIT(NL80211_STA_FLAG_TDLS_PEER);
+-+	if (sta_flags & BRCMF_STA_ASSOC) {
+-+		sinfo->filled |= BIT(NL80211_STA_INFO_CONNECTED_TIME);
+-+		sinfo->connected_time = le32_to_cpu(sta_info_le.in);
+-+		brcmf_fill_bss_param(ifp, sinfo);
+-+	}
+-+	if (sta_flags & BRCMF_STA_SCBSTATS) {
+-+		sinfo->filled |= BIT(NL80211_STA_INFO_TX_FAILED);
+-+		sinfo->tx_failed = le32_to_cpu(sta_info_le.tx_failures);
+-+		sinfo->filled |= BIT(NL80211_STA_INFO_TX_PACKETS);
+-+		sinfo->tx_packets = le32_to_cpu(sta_info_le.tx_pkts);
+-+		sinfo->tx_packets += le32_to_cpu(sta_info_le.tx_mcast_pkts);
+-+		sinfo->filled |= BIT(NL80211_STA_INFO_RX_PACKETS);
+-+		sinfo->rx_packets = le32_to_cpu(sta_info_le.rx_ucast_pkts);
+-+		sinfo->rx_packets += le32_to_cpu(sta_info_le.rx_mcast_pkts);
+-+		if (sinfo->tx_packets) {
+- 			sinfo->filled |= BIT(NL80211_STA_INFO_TX_BITRATE);
+--			sinfo->txrate.legacy = rate * 5;
+--			brcmf_dbg(CONN, "Rate %d Mbps\n", rate / 2);
+-+			sinfo->txrate.legacy = le32_to_cpu(sta_info_le.tx_rate);
+-+			sinfo->txrate.legacy /= 100;
+- 		}
+--
+--		if (test_bit(BRCMF_VIF_STATUS_CONNECTED,
+--			     &ifp->vif->sme_state)) {
+--			memset(&scb_val, 0, sizeof(scb_val));
+--			err = brcmf_fil_cmd_data_get(ifp, BRCMF_C_GET_RSSI,
+--						     &scb_val, sizeof(scb_val));
+--			if (err) {
+--				brcmf_err("Could not get rssi (%d)\n", err);
+--				goto done;
+--			} else {
+--				rssi = le32_to_cpu(scb_val.val);
+--				sinfo->filled |= BIT(NL80211_STA_INFO_SIGNAL);
+--				sinfo->signal = rssi;
+--				brcmf_dbg(CONN, "RSSI %d dBm\n", rssi);
+--			}
+--			err = brcmf_fil_cmd_int_get(ifp, BRCMF_C_GET_BCNPRD,
+--						    &beacon_period);
+--			if (err) {
+--				brcmf_err("Could not get beacon period (%d)\n",
+--					  err);
+--				goto done;
+--			} else {
+--				sinfo->bss_param.beacon_interval =
+--					beacon_period;
+--				brcmf_dbg(CONN, "Beacon peroid %d\n",
+--					  beacon_period);
+--			}
+--			err = brcmf_fil_cmd_int_get(ifp, BRCMF_C_GET_DTIMPRD,
+--						    &dtim_period);
+--			if (err) {
+--				brcmf_err("Could not get DTIM period (%d)\n",
+--					  err);
+--				goto done;
+--			} else {
+--				sinfo->bss_param.dtim_period = dtim_period;
+--				brcmf_dbg(CONN, "DTIM peroid %d\n",
+--					  dtim_period);
+--			}
+--			sinfo->filled |= BIT(NL80211_STA_INFO_BSS_PARAM);
+-+		if (sinfo->rx_packets) {
+-+			sinfo->filled |= BIT(NL80211_STA_INFO_RX_BITRATE);
+-+			sinfo->rxrate.legacy = le32_to_cpu(sta_info_le.rx_rate);
+-+			sinfo->rxrate.legacy /= 100;
+-+		}
+-+		if (le16_to_cpu(sta_info_le.ver) >= 4) {
+-+			sinfo->filled |= BIT(NL80211_STA_INFO_TX_BYTES);
+-+			sinfo->tx_bytes = le64_to_cpu(sta_info_le.tx_tot_bytes);
+-+			sinfo->filled |= BIT(NL80211_STA_INFO_RX_BYTES);
+-+			sinfo->rx_bytes = le64_to_cpu(sta_info_le.rx_tot_bytes);
+- 		}
+--	} else
+--		err = -EPERM;
+-+	}
+- done:
+- 	brcmf_dbg(TRACE, "Exit\n");
+- 	return err;
+---- a/drivers/net/wireless/brcm80211/brcmfmac/fwil_types.h
+-+++ b/drivers/net/wireless/brcm80211/brcmfmac/fwil_types.h
+-@@ -32,7 +32,11 @@
+- #define	BRCMF_BSS_INFO_VERSION	109 /* curr ver of brcmf_bss_info_le struct */
+- #define BRCMF_BSS_RSSI_ON_CHANNEL	0x0002
+- 
+--#define BRCMF_STA_ASSOC			0x10		/* Associated */
+-+#define BRCMF_STA_WME              0x00000002      /* WMM association */
+-+#define BRCMF_STA_AUTHE            0x00000008      /* Authenticated */
+-+#define BRCMF_STA_ASSOC            0x00000010      /* Associated */
+-+#define BRCMF_STA_AUTHO            0x00000020      /* Authorized */
+-+#define BRCMF_STA_SCBSTATS         0x00004000      /* Per STA debug stats */
+- 
+- /* size of brcmf_scan_params not including variable length array */
+- #define BRCMF_SCAN_PARAMS_FIXED_SIZE	64
+-@@ -113,6 +117,7 @@
+- #define BRCMF_WOWL_MAXPATTERNSIZE	128
+- 
+- #define BRCMF_COUNTRY_BUF_SZ		4
+-+#define BRCMF_ANT_MAX			4
+- 
+- /* join preference types for join_pref iovar */
+- enum brcmf_join_pref_types {
+-@@ -456,25 +461,61 @@ struct brcmf_channel_info_le {
+- };
+- 
+- struct brcmf_sta_info_le {
+--	__le16	ver;		/* version of this struct */
+--	__le16	len;		/* length in bytes of this structure */
+--	__le16	cap;		/* sta's advertised capabilities */
+--	__le32	flags;		/* flags defined below */
+--	__le32	idle;		/* time since data pkt rx'd from sta */
+--	u8	ea[ETH_ALEN];		/* Station address */
+--	__le32	count;			/* # rates in this set */
+--	u8	rates[BRCMF_MAXRATES_IN_SET];	/* rates in 500kbps units */
+-+	__le16 ver;		/* version of this struct */
+-+	__le16 len;		/* length in bytes of this structure */
+-+	__le16 cap;		/* sta's advertised capabilities */
+-+	__le32 flags;		/* flags defined below */
+-+	__le32 idle;		/* time since data pkt rx'd from sta */
+-+	u8 ea[ETH_ALEN];		/* Station address */
+-+	__le32 count;			/* # rates in this set */
+-+	u8 rates[BRCMF_MAXRATES_IN_SET];	/* rates in 500kbps units */
+- 						/* w/hi bit set if basic */
+--	__le32	in;		/* seconds elapsed since associated */
+--	__le32	listen_interval_inms; /* Min Listen interval in ms for STA */
+--	__le32	tx_pkts;	/* # of packets transmitted */
+--	__le32	tx_failures;	/* # of packets failed */
+--	__le32	rx_ucast_pkts;	/* # of unicast packets received */
+--	__le32	rx_mcast_pkts;	/* # of multicast packets received */
+--	__le32	tx_rate;	/* Rate of last successful tx frame */
+--	__le32	rx_rate;	/* Rate of last successful rx frame */
+--	__le32	rx_decrypt_succeeds;	/* # of packet decrypted successfully */
+--	__le32	rx_decrypt_failures;	/* # of packet decrypted failed */
+-+	__le32 in;		/* seconds elapsed since associated */
+-+	__le32 listen_interval_inms; /* Min Listen interval in ms for STA */
+-+	__le32 tx_pkts;	/* # of packets transmitted */
+-+	__le32 tx_failures;	/* # of packets failed */
+-+	__le32 rx_ucast_pkts;	/* # of unicast packets received */
+-+	__le32 rx_mcast_pkts;	/* # of multicast packets received */
+-+	__le32 tx_rate;	/* Rate of last successful tx frame */
+-+	__le32 rx_rate;	/* Rate of last successful rx frame */
+-+	__le32 rx_decrypt_succeeds;	/* # of packet decrypted successfully */
+-+	__le32 rx_decrypt_failures;	/* # of packet decrypted failed */
+-+	__le32 tx_tot_pkts;    /* # of tx pkts (ucast + mcast) */
+-+	__le32 rx_tot_pkts;    /* # of data packets recvd (uni + mcast) */
+-+	__le32 tx_mcast_pkts;  /* # of mcast pkts txed */
+-+	__le64 tx_tot_bytes;   /* data bytes txed (ucast + mcast) */
+-+	__le64 rx_tot_bytes;   /* data bytes recvd (ucast + mcast) */
+-+	__le64 tx_ucast_bytes; /* data bytes txed (ucast) */
+-+	__le64 tx_mcast_bytes; /* # data bytes txed (mcast) */
+-+	__le64 rx_ucast_bytes; /* data bytes recvd (ucast) */
+-+	__le64 rx_mcast_bytes; /* data bytes recvd (mcast) */
+-+	s8 rssi[BRCMF_ANT_MAX];   /* per antenna rssi */
+-+	s8 nf[BRCMF_ANT_MAX];     /* per antenna noise floor */
+-+	__le16 aid;                    /* association ID */
+-+	__le16 ht_capabilities;        /* advertised ht caps */
+-+	__le16 vht_flags;              /* converted vht flags */
+-+	__le32 tx_pkts_retry_cnt;      /* # of frames where a retry was
+-+					 * exhausted.
+-+					 */
+-+	__le32 tx_pkts_retry_exhausted; /* # of user frames where a retry
+-+					 * was exhausted
+-+					 */
+-+	s8 rx_lastpkt_rssi[BRCMF_ANT_MAX]; /* Per antenna RSSI of last
+-+					    * received data frame.
+-+					    */
+-+	/* TX WLAN retry/failure statistics:
+-+	 * Separated for host requested frames and locally generated frames.
+-+	 * Include unicast frame only where the retries/failures can be counted.
+-+	 */
+-+	__le32 tx_pkts_total;          /* # user frames sent successfully */
+-+	__le32 tx_pkts_retries;        /* # user frames retries */
+-+	__le32 tx_pkts_fw_total;       /* # FW generated sent successfully */
+-+	__le32 tx_pkts_fw_retries;     /* # retries for FW generated frames */
+-+	__le32 tx_pkts_fw_retry_exhausted;     /* # FW generated where a retry
+-+						* was exhausted
+-+						*/
+-+	__le32 rx_pkts_retried;        /* # rx with retry bit set */
+-+	__le32 tx_rate_fallback;       /* lowest fallback TX rate */
+- };
+- 
+- struct brcmf_chanspec_list {
+diff --git a/package/kernel/mac80211/patches/389-0004-brcmfmac-have-sdio-return-EIO-when-device-communicat.patch b/package/kernel/mac80211/patches/389-0004-brcmfmac-have-sdio-return-EIO-when-device-communicat.patch
+deleted file mode 100644
+index 302bc3e..0000000
+--- a/package/kernel/mac80211/patches/389-0004-brcmfmac-have-sdio-return-EIO-when-device-communicat.patch
++++ /dev/null
+@@ -1,56 +0,0 @@
+-From: Arend van Spriel <arend@broadcom.com>
+-Date: Thu, 11 Jun 2015 00:12:20 +0200
+-Subject: [PATCH] brcmfmac: have sdio return -EIO when device communication
+- is not possible
+-
+-The bus interface functions txctl and rxctl may be used while the device
+-can not be accessed, eg. upon driver .remove() callback. This patch will
+-immediately return -EIO when this is the case which speeds up the module
+-unload.
+-
+-Reviewed-by: Hante Meuleman <meuleman@broadcom.com>
+-Reviewed-by: Franky (Zhenhui) Lin <frankyl@broadcom.com>
+-Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
+-Signed-off-by: Arend van Spriel <arend@broadcom.com>
+-Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
+----
+-
+---- a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c
+-+++ b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c
+-@@ -988,6 +988,7 @@ static void brcmf_sdiod_freezer_detach(s
+- 
+- static int brcmf_sdiod_remove(struct brcmf_sdio_dev *sdiodev)
+- {
+-+	sdiodev->state = BRCMF_SDIOD_DOWN;
+- 	if (sdiodev->bus) {
+- 		brcmf_sdio_remove(sdiodev->bus);
+- 		sdiodev->bus = NULL;
+---- a/drivers/net/wireless/brcm80211/brcmfmac/sdio.c
+-+++ b/drivers/net/wireless/brcm80211/brcmfmac/sdio.c
+-@@ -2820,6 +2820,8 @@ static int brcmf_sdio_bus_txdata(struct
+- 	struct brcmf_sdio *bus = sdiodev->bus;
+- 
+- 	brcmf_dbg(TRACE, "Enter: pkt: data %p len %d\n", pkt->data, pkt->len);
+-+	if (sdiodev->state != BRCMF_SDIOD_DATA)
+-+		return -EIO;
+- 
+- 	/* Add space for the header */
+- 	skb_push(pkt, bus->tx_hdrlen);
+-@@ -2948,6 +2950,8 @@ brcmf_sdio_bus_txctl(struct device *dev,
+- 	int ret;
+- 
+- 	brcmf_dbg(TRACE, "Enter\n");
+-+	if (sdiodev->state != BRCMF_SDIOD_DATA)
+-+		return -EIO;
+- 
+- 	/* Send from dpc */
+- 	bus->ctrl_frame_buf = msg;
+-@@ -3238,6 +3242,8 @@ brcmf_sdio_bus_rxctl(struct device *dev,
+- 	struct brcmf_sdio *bus = sdiodev->bus;
+- 
+- 	brcmf_dbg(TRACE, "Enter\n");
+-+	if (sdiodev->state != BRCMF_SDIOD_DATA)
+-+		return -EIO;
+- 
+- 	/* Wait until control frame is available */
+- 	timeleft = brcmf_sdio_dcmd_resp_wait(bus, &bus->rxlen, &pending);
+diff --git a/package/kernel/mac80211/patches/389-0005-ath9k-make-DMA-stop-related-messages-debug-only.patch b/package/kernel/mac80211/patches/389-0005-ath9k-make-DMA-stop-related-messages-debug-only.patch
+deleted file mode 100644
+index 34af6d2..0000000
+--- a/package/kernel/mac80211/patches/389-0005-ath9k-make-DMA-stop-related-messages-debug-only.patch
++++ /dev/null
+@@ -1,74 +0,0 @@
+-From: Felix Fietkau <nbd@openwrt.org>
+-Date: Thu, 2 Jul 2015 13:35:05 +0200
+-Subject: [PATCH] ath9k: make DMA stop related messages debug-only
+-
+-A long time ago, ath9k had issues during reset where the DMA engine
+-would stay active and could potentially corrupt memory.
+-To debug those issues, the driver would print warnings whenever they
+-occur.
+-
+-Nowadays, these issues are gone and the primary cause of these messages
+-is if the MAC is stuck during reset or busy processing a long
+-transmission. This is fairly harmless, yet these messages continue to
+-worry users.
+-
+-To reduce the number of bogus bug reports, turn these messages into
+-debug messages and count their occurence in the "reset" debugfs file.
+-
+-Signed-off-by: Felix Fietkau <nbd@openwrt.org>
+----
+-
+---- a/drivers/net/wireless/ath/ath9k/debug.c
+-+++ b/drivers/net/wireless/ath/ath9k/debug.c
+-@@ -765,6 +765,8 @@ static int read_file_reset(struct seq_fi
+- 		[RESET_TYPE_BEACON_STUCK] = "Stuck Beacon",
+- 		[RESET_TYPE_MCI] = "MCI Reset",
+- 		[RESET_TYPE_CALIBRATION] = "Calibration error",
+-+		[RESET_TX_DMA_ERROR] = "Tx DMA stop error",
+-+		[RESET_RX_DMA_ERROR] = "Rx DMA stop error",
+- 	};
+- 	int i;
+- 
+---- a/drivers/net/wireless/ath/ath9k/debug.h
+-+++ b/drivers/net/wireless/ath/ath9k/debug.h
+-@@ -50,6 +50,8 @@ enum ath_reset_type {
+- 	RESET_TYPE_BEACON_STUCK,
+- 	RESET_TYPE_MCI,
+- 	RESET_TYPE_CALIBRATION,
+-+	RESET_TX_DMA_ERROR,
+-+	RESET_RX_DMA_ERROR,
+- 	__RESET_TYPE_MAX
+- };
+- 
+---- a/drivers/net/wireless/ath/ath9k/recv.c
+-+++ b/drivers/net/wireless/ath/ath9k/recv.c
+-@@ -496,10 +496,9 @@ bool ath_stoprecv(struct ath_softc *sc)
+- 
+- 	if (!(ah->ah_flags & AH_UNPLUGGED) &&
+- 	    unlikely(!stopped)) {
+--		ath_err(ath9k_hw_common(sc->sc_ah),
+--			"Could not stop RX, we could be "
+--			"confusing the DMA engine when we start RX up\n");
+--		ATH_DBG_WARN_ON_ONCE(!stopped);
+-+		ath_dbg(ath9k_hw_common(sc->sc_ah), RESET,
+-+			"Failed to stop Rx DMA\n");
+-+		RESET_STAT_INC(sc, RESET_RX_DMA_ERROR);
+- 	}
+- 	return stopped && !reset;
+- }
+---- a/drivers/net/wireless/ath/ath9k/xmit.c
+-+++ b/drivers/net/wireless/ath/ath9k/xmit.c
+-@@ -1896,8 +1896,11 @@ bool ath_drain_all_txq(struct ath_softc
+- 			npend |= BIT(i);
+- 	}
+- 
+--	if (npend)
+--		ath_err(common, "Failed to stop TX DMA, queues=0x%03x!\n", npend);
+-+	if (npend) {
+-+		RESET_STAT_INC(sc, RESET_TX_DMA_ERROR);
+-+		ath_dbg(common, RESET,
+-+			"Failed to stop TX DMA, queues=0x%03x!\n", npend);
+-+	}
+- 
+- 	for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) {
+- 		if (!ATH_TXQ_SETUP(sc, i))
+diff --git a/package/kernel/mac80211/patches/389-0006-brcmfmac-free-ifp-for-non-netdev-interface-in-p2p-mo.patch b/package/kernel/mac80211/patches/389-0006-brcmfmac-free-ifp-for-non-netdev-interface-in-p2p-mo.patch
+deleted file mode 100644
+index 06f2dce..0000000
+--- a/package/kernel/mac80211/patches/389-0006-brcmfmac-free-ifp-for-non-netdev-interface-in-p2p-mo.patch
++++ /dev/null
+@@ -1,44 +0,0 @@
+-From: Arend van Spriel <arend@broadcom.com>
+-Date: Thu, 11 Jun 2015 00:12:21 +0200
+-Subject: [PATCH] brcmfmac: free ifp for non-netdev interface in p2p module
+-
+-Making it more clear by freeing the ifp in same place where the
+-vif object is freed.
+-
+-Reviewed-by: Hante Meuleman <meuleman@broadcom.com>
+-Reviewed-by: Franky (Zhenhui) Lin <frankyl@broadcom.com>
+-Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
+-Signed-off-by: Arend van Spriel <arend@broadcom.com>
+-Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
+----
+-
+---- a/drivers/net/wireless/brcm80211/brcmfmac/core.c
+-+++ b/drivers/net/wireless/brcm80211/brcmfmac/core.c
+-@@ -867,8 +867,6 @@ static void brcmf_del_if(struct brcmf_pu
+- 		}
+- 		/* unregister will take care of freeing it */
+- 		unregister_netdev(ifp->ndev);
+--	} else {
+--		kfree(ifp);
+- 	}
+- }
+- 
+---- a/drivers/net/wireless/brcm80211/brcmfmac/p2p.c
+-+++ b/drivers/net/wireless/brcm80211/brcmfmac/p2p.c
+-@@ -2238,6 +2238,7 @@ static void brcmf_p2p_delete_p2pdev(stru
+- {
+- 	cfg80211_unregister_wdev(&vif->wdev);
+- 	p2p->bss_idx[P2PAPI_BSSCFG_DEVICE].vif = NULL;
+-+	kfree(vif->ifp);
+- 	brcmf_free_vif(vif);
+- }
+- 
+-@@ -2361,6 +2362,8 @@ int brcmf_p2p_del_vif(struct wiphy *wiph
+- 		break;
+- 
+- 	case NL80211_IFTYPE_P2P_DEVICE:
+-+		brcmf_p2p_cancel_remain_on_channel(vif->ifp);
+-+		brcmf_p2p_deinit_discovery(p2p);
+- 		brcmf_p2p_delete_p2pdev(p2p, vif);
+- 		return 0;
+- 	default:
+diff --git a/package/kernel/mac80211/patches/389-0007-brcmfmac-move-p2p-attach-detach-functions.patch b/package/kernel/mac80211/patches/389-0007-brcmfmac-move-p2p-attach-detach-functions.patch
+deleted file mode 100644
+index 0a6e093..0000000
+--- a/package/kernel/mac80211/patches/389-0007-brcmfmac-move-p2p-attach-detach-functions.patch
++++ /dev/null
+@@ -1,225 +0,0 @@
+-From: Arend van Spriel <arend@broadcom.com>
+-Date: Thu, 11 Jun 2015 00:12:22 +0200
+-Subject: [PATCH] brcmfmac: move p2p attach/detach functions
+-
+-Moving two functions in p2p.c as is so next change will be
+-easier to review.
+-
+-Reviewed-by: Hante Meuleman <meuleman@broadcom.com>
+-Reviewed-by: Franky (Zhenhui) Lin <frankyl@broadcom.com>
+-Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
+-Signed-off-by: Arend van Spriel <arend@broadcom.com>
+-Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
+----
+-
+---- a/drivers/net/wireless/brcm80211/brcmfmac/p2p.c
+-+++ b/drivers/net/wireless/brcm80211/brcmfmac/p2p.c
+-@@ -1908,105 +1908,6 @@ s32 brcmf_p2p_notify_rx_mgmt_p2p_probere
+- 
+- 
+- /**
+-- * brcmf_p2p_attach() - attach for P2P.
+-- *
+-- * @cfg: driver private data for cfg80211 interface.
+-- */
+--s32 brcmf_p2p_attach(struct brcmf_cfg80211_info *cfg)
+--{
+--	struct brcmf_if *pri_ifp;
+--	struct brcmf_if *p2p_ifp;
+--	struct brcmf_cfg80211_vif *p2p_vif;
+--	struct brcmf_p2p_info *p2p;
+--	struct brcmf_pub *drvr;
+--	s32 bssidx;
+--	s32 err = 0;
+--
+--	p2p = &cfg->p2p;
+--	p2p->cfg = cfg;
+--
+--	drvr = cfg->pub;
+--
+--	pri_ifp = drvr->iflist[0];
+--	p2p_ifp = drvr->iflist[1];
+--
+--	p2p->bss_idx[P2PAPI_BSSCFG_PRIMARY].vif = pri_ifp->vif;
+--
+--	if (p2p_ifp) {
+--		p2p_vif = brcmf_alloc_vif(cfg, NL80211_IFTYPE_P2P_DEVICE,
+--					  false);
+--		if (IS_ERR(p2p_vif)) {
+--			brcmf_err("could not create discovery vif\n");
+--			err = -ENOMEM;
+--			goto exit;
+--		}
+--
+--		p2p_vif->ifp = p2p_ifp;
+--		p2p_ifp->vif = p2p_vif;
+--		p2p_vif->wdev.netdev = p2p_ifp->ndev;
+--		p2p_ifp->ndev->ieee80211_ptr = &p2p_vif->wdev;
+--		SET_NETDEV_DEV(p2p_ifp->ndev, wiphy_dev(cfg->wiphy));
+--
+--		p2p->bss_idx[P2PAPI_BSSCFG_DEVICE].vif = p2p_vif;
+--
+--		brcmf_p2p_generate_bss_mac(p2p, NULL);
+--		memcpy(p2p_ifp->mac_addr, p2p->dev_addr, ETH_ALEN);
+--		brcmf_p2p_set_firmware(pri_ifp, p2p->dev_addr);
+--
+--		/* Initialize P2P Discovery in the firmware */
+--		err = brcmf_fil_iovar_int_set(pri_ifp, "p2p_disc", 1);
+--		if (err < 0) {
+--			brcmf_err("set p2p_disc error\n");
+--			brcmf_free_vif(p2p_vif);
+--			goto exit;
+--		}
+--		/* obtain bsscfg index for P2P discovery */
+--		err = brcmf_fil_iovar_int_get(pri_ifp, "p2p_dev", &bssidx);
+--		if (err < 0) {
+--			brcmf_err("retrieving discover bsscfg index failed\n");
+--			brcmf_free_vif(p2p_vif);
+--			goto exit;
+--		}
+--		/* Verify that firmware uses same bssidx as driver !! */
+--		if (p2p_ifp->bssidx != bssidx) {
+--			brcmf_err("Incorrect bssidx=%d, compared to p2p_ifp->bssidx=%d\n",
+--				  bssidx, p2p_ifp->bssidx);
+--			brcmf_free_vif(p2p_vif);
+--			goto exit;
+--		}
+--
+--		init_completion(&p2p->send_af_done);
+--		INIT_WORK(&p2p->afx_hdl.afx_work, brcmf_p2p_afx_handler);
+--		init_completion(&p2p->afx_hdl.act_frm_scan);
+--		init_completion(&p2p->wait_next_af);
+--	}
+--exit:
+--	return err;
+--}
+--
+--
+--/**
+-- * brcmf_p2p_detach() - detach P2P.
+-- *
+-- * @p2p: P2P specific data.
+-- */
+--void brcmf_p2p_detach(struct brcmf_p2p_info *p2p)
+--{
+--	struct brcmf_cfg80211_vif *vif;
+--
+--	vif = p2p->bss_idx[P2PAPI_BSSCFG_DEVICE].vif;
+--	if (vif != NULL) {
+--		brcmf_p2p_cancel_remain_on_channel(vif->ifp);
+--		brcmf_p2p_deinit_discovery(p2p);
+--		/* remove discovery interface */
+--		brcmf_free_vif(vif);
+--		p2p->bss_idx[P2PAPI_BSSCFG_DEVICE].vif = NULL;
+--	}
+--	/* just set it all to zero */
+--	memset(p2p, 0, sizeof(*p2p));
+--}
+--
+--/**
+-  * brcmf_p2p_get_current_chanspec() - Get current operation channel.
+-  *
+-  * @p2p: P2P specific data.
+-@@ -2425,3 +2326,102 @@ void brcmf_p2p_stop_device(struct wiphy
+- 	clear_bit(BRCMF_VIF_STATUS_READY, &vif->sme_state);
+- 	mutex_unlock(&cfg->usr_sync);
+- }
+-+
+-+/**
+-+ * brcmf_p2p_attach() - attach for P2P.
+-+ *
+-+ * @cfg: driver private data for cfg80211 interface.
+-+ */
+-+s32 brcmf_p2p_attach(struct brcmf_cfg80211_info *cfg)
+-+{
+-+	struct brcmf_if *pri_ifp;
+-+	struct brcmf_if *p2p_ifp;
+-+	struct brcmf_cfg80211_vif *p2p_vif;
+-+	struct brcmf_p2p_info *p2p;
+-+	struct brcmf_pub *drvr;
+-+	s32 bssidx;
+-+	s32 err = 0;
+-+
+-+	p2p = &cfg->p2p;
+-+	p2p->cfg = cfg;
+-+
+-+	drvr = cfg->pub;
+-+
+-+	pri_ifp = drvr->iflist[0];
+-+	p2p_ifp = drvr->iflist[1];
+-+
+-+	p2p->bss_idx[P2PAPI_BSSCFG_PRIMARY].vif = pri_ifp->vif;
+-+
+-+	if (p2p_ifp) {
+-+		p2p_vif = brcmf_alloc_vif(cfg, NL80211_IFTYPE_P2P_DEVICE,
+-+					  false);
+-+		if (IS_ERR(p2p_vif)) {
+-+			brcmf_err("could not create discovery vif\n");
+-+			err = -ENOMEM;
+-+			goto exit;
+-+		}
+-+
+-+		p2p_vif->ifp = p2p_ifp;
+-+		p2p_ifp->vif = p2p_vif;
+-+		p2p_vif->wdev.netdev = p2p_ifp->ndev;
+-+		p2p_ifp->ndev->ieee80211_ptr = &p2p_vif->wdev;
+-+		SET_NETDEV_DEV(p2p_ifp->ndev, wiphy_dev(cfg->wiphy));
+-+
+-+		p2p->bss_idx[P2PAPI_BSSCFG_DEVICE].vif = p2p_vif;
+-+
+-+		brcmf_p2p_generate_bss_mac(p2p, NULL);
+-+		memcpy(p2p_ifp->mac_addr, p2p->dev_addr, ETH_ALEN);
+-+		brcmf_p2p_set_firmware(pri_ifp, p2p->dev_addr);
+-+
+-+		/* Initialize P2P Discovery in the firmware */
+-+		err = brcmf_fil_iovar_int_set(pri_ifp, "p2p_disc", 1);
+-+		if (err < 0) {
+-+			brcmf_err("set p2p_disc error\n");
+-+			brcmf_free_vif(p2p_vif);
+-+			goto exit;
+-+		}
+-+		/* obtain bsscfg index for P2P discovery */
+-+		err = brcmf_fil_iovar_int_get(pri_ifp, "p2p_dev", &bssidx);
+-+		if (err < 0) {
+-+			brcmf_err("retrieving discover bsscfg index failed\n");
+-+			brcmf_free_vif(p2p_vif);
+-+			goto exit;
+-+		}
+-+		/* Verify that firmware uses same bssidx as driver !! */
+-+		if (p2p_ifp->bssidx != bssidx) {
+-+			brcmf_err("Incorrect bssidx=%d, compared to p2p_ifp->bssidx=%d\n",
+-+				  bssidx, p2p_ifp->bssidx);
+-+			brcmf_free_vif(p2p_vif);
+-+			goto exit;
+-+		}
+-+
+-+		init_completion(&p2p->send_af_done);
+-+		INIT_WORK(&p2p->afx_hdl.afx_work, brcmf_p2p_afx_handler);
+-+		init_completion(&p2p->afx_hdl.act_frm_scan);
+-+		init_completion(&p2p->wait_next_af);
+-+	}
+-+exit:
+-+	return err;
+-+}
+-+
+-+/**
+-+ * brcmf_p2p_detach() - detach P2P.
+-+ *
+-+ * @p2p: P2P specific data.
+-+ */
+-+void brcmf_p2p_detach(struct brcmf_p2p_info *p2p)
+-+{
+-+	struct brcmf_cfg80211_vif *vif;
+-+
+-+	vif = p2p->bss_idx[P2PAPI_BSSCFG_DEVICE].vif;
+-+	if (vif != NULL) {
+-+		brcmf_p2p_cancel_remain_on_channel(vif->ifp);
+-+		brcmf_p2p_deinit_discovery(p2p);
+-+		/* remove discovery interface */
+-+		brcmf_free_vif(vif);
+-+		p2p->bss_idx[P2PAPI_BSSCFG_DEVICE].vif = NULL;
+-+	}
+-+	/* just set it all to zero */
+-+	memset(p2p, 0, sizeof(*p2p));
+-+}
+-+
+diff --git a/package/kernel/mac80211/patches/389-0008-brcmfmac-assure-p2pdev-is-unregistered-upon-driver-u.patch b/package/kernel/mac80211/patches/389-0008-brcmfmac-assure-p2pdev-is-unregistered-upon-driver-u.patch
+deleted file mode 100644
+index 72e8eed..0000000
+--- a/package/kernel/mac80211/patches/389-0008-brcmfmac-assure-p2pdev-is-unregistered-upon-driver-u.patch
++++ /dev/null
+@@ -1,63 +0,0 @@
+-From: Arend van Spriel <arend@broadcom.com>
+-Date: Thu, 11 Jun 2015 00:12:23 +0200
+-Subject: [PATCH] brcmfmac: assure p2pdev is unregistered upon driver
+- unload
+-
+-When unloading the driver with a p2pdev interface it resulted in
+-a warning upon calling wiphy_unregister() and subsequently a crash
+-in the driver. This patch assures the p2pdev is unregistered calling
+-unregister_wdev() before doing the wiphy_unregister().
+-
+-Reviewed-by: Hante Meuleman <meuleman@broadcom.com>
+-Reviewed-by: Franky (Zhenhui) Lin <frankyl@broadcom.com>
+-Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
+-Signed-off-by: Arend van Spriel <arend@broadcom.com>
+-Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
+----
+-
+---- a/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c
+-+++ b/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c
+-@@ -6206,10 +6206,8 @@ void brcmf_cfg80211_detach(struct brcmf_
+- 	if (!cfg)
+- 		return;
+- 
+--	WARN_ON(!list_empty(&cfg->vif_list));
+--	wiphy_unregister(cfg->wiphy);
+- 	brcmf_btcoex_detach(cfg);
+--	brcmf_p2p_detach(&cfg->p2p);
+-+	wiphy_unregister(cfg->wiphy);
+- 	wl_deinit_priv(cfg);
+- 	brcmf_free_wiphy(cfg->wiphy);
+- }
+---- a/drivers/net/wireless/brcm80211/brcmfmac/core.c
+-+++ b/drivers/net/wireless/brcm80211/brcmfmac/core.c
+-@@ -1098,6 +1098,7 @@ void brcmf_detach(struct device *dev)
+- 
+- 	/* stop firmware event handling */
+- 	brcmf_fweh_detach(drvr);
+-+	brcmf_p2p_detach(&drvr->config->p2p);
+- 
+- 	brcmf_bus_change_state(bus_if, BRCMF_BUS_DOWN);
+- 
+---- a/drivers/net/wireless/brcm80211/brcmfmac/p2p.c
+-+++ b/drivers/net/wireless/brcm80211/brcmfmac/p2p.c
+-@@ -16,6 +16,7 @@
+- #include <linux/slab.h>
+- #include <linux/netdevice.h>
+- #include <linux/etherdevice.h>
+-+#include <linux/rtnetlink.h>
+- #include <net/cfg80211.h>
+- 
+- #include <brcmu_wifi.h>
+-@@ -2418,8 +2419,9 @@ void brcmf_p2p_detach(struct brcmf_p2p_i
+- 		brcmf_p2p_cancel_remain_on_channel(vif->ifp);
+- 		brcmf_p2p_deinit_discovery(p2p);
+- 		/* remove discovery interface */
+--		brcmf_free_vif(vif);
+--		p2p->bss_idx[P2PAPI_BSSCFG_DEVICE].vif = NULL;
+-+		rtnl_lock();
+-+		brcmf_p2p_delete_p2pdev(p2p, vif);
+-+		rtnl_unlock();
+- 	}
+- 	/* just set it all to zero */
+- 	memset(p2p, 0, sizeof(*p2p));
+diff --git a/package/kernel/mac80211/patches/390-0001-brcmfmac-fix-double-free-of-p2pdev-interface.patch b/package/kernel/mac80211/patches/390-0001-brcmfmac-fix-double-free-of-p2pdev-interface.patch
+deleted file mode 100644
+index 179c77e..0000000
+--- a/package/kernel/mac80211/patches/390-0001-brcmfmac-fix-double-free-of-p2pdev-interface.patch
++++ /dev/null
+@@ -1,27 +0,0 @@
+-From: Arend van Spriel <arend@broadcom.com>
+-Date: Mon, 15 Jun 2015 22:48:38 +0200
+-Subject: [PATCH] brcmfmac: fix double free of p2pdev interface
+-
+-When freeing the driver ifp pointer it should also be removed from
+-the driver interface list, which is what brcmf_remove_interface()
+-does. Otherwise, the ifp pointer will be freed twice triggering
+-a kernel oops.
+-
+-Fixes: f37d69a4babc ("brcmfmac: free ifp for non-netdev interface in p2p module")
+-Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
+-Reviewed-by: Hante Meuleman <meuleman@broadcom.com>
+-Signed-off-by: Arend van Spriel <arend@broadcom.com>
+-Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
+----
+-
+---- a/drivers/net/wireless/brcm80211/brcmfmac/p2p.c
+-+++ b/drivers/net/wireless/brcm80211/brcmfmac/p2p.c
+-@@ -2140,7 +2140,7 @@ static void brcmf_p2p_delete_p2pdev(stru
+- {
+- 	cfg80211_unregister_wdev(&vif->wdev);
+- 	p2p->bss_idx[P2PAPI_BSSCFG_DEVICE].vif = NULL;
+--	kfree(vif->ifp);
+-+	brcmf_remove_interface(vif->ifp->drvr, vif->ifp->bssidx);
+- 	brcmf_free_vif(vif);
+- }
+- 
+diff --git a/package/kernel/mac80211/patches/390-0002-brcmfmac-make-brcmf_p2p_detach-call-conditional.patch b/package/kernel/mac80211/patches/390-0002-brcmfmac-make-brcmf_p2p_detach-call-conditional.patch
+deleted file mode 100644
+index e4f88b5..0000000
+--- a/package/kernel/mac80211/patches/390-0002-brcmfmac-make-brcmf_p2p_detach-call-conditional.patch
++++ /dev/null
+@@ -1,29 +0,0 @@
+-From: Arend van Spriel <arend@broadcom.com>
+-Date: Mon, 15 Jun 2015 22:48:39 +0200
+-Subject: [PATCH] brcmfmac: make brcmf_p2p_detach() call conditional
+-
+-During verification of error handling in brcmf_cfg80211_attach() a
+-null pointer dereference occurred upon calling brcmf_p2p_detach()
+-from brcmf_detach(). This should only be called when the
+-brcmf_cfg80211_attach() has succeeded.
+-
+-Fixes: f7a40873d2fa ("brcmfmac: assure p2pdev is unregistered upon driver unload")
+-Reviewed-by: Hante Meuleman <meuleman@broadcom.com>
+-Reviewed-by: Franky (Zhenhui) Lin <frankyl@broadcom.com>
+-Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
+-Signed-off-by: Arend van Spriel <arend@broadcom.com>
+-Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
+----
+-
+---- a/drivers/net/wireless/brcm80211/brcmfmac/core.c
+-+++ b/drivers/net/wireless/brcm80211/brcmfmac/core.c
+-@@ -1098,7 +1098,8 @@ void brcmf_detach(struct device *dev)
+- 
+- 	/* stop firmware event handling */
+- 	brcmf_fweh_detach(drvr);
+--	brcmf_p2p_detach(&drvr->config->p2p);
+-+	if (drvr->config)
+-+		brcmf_p2p_detach(&drvr->config->p2p);
+- 
+- 	brcmf_bus_change_state(bus_if, BRCMF_BUS_DOWN);
+- 
+diff --git a/package/kernel/mac80211/patches/391-brcmfmac-set-wiphy-s-addresses-to-provide-valid-MACs.patch b/package/kernel/mac80211/patches/391-brcmfmac-set-wiphy-s-addresses-to-provide-valid-MACs.patch
+deleted file mode 100644
+index 0a81237..0000000
+--- a/package/kernel/mac80211/patches/391-brcmfmac-set-wiphy-s-addresses-to-provide-valid-MACs.patch
++++ /dev/null
+@@ -1,67 +0,0 @@
+-From: Rafa? Mi?ecki <zajec5@gmail.com>
+-Date: Thu, 9 Jul 2015 17:07:08 +0200
+-Subject: [PATCH] brcmfmac: set wiphy's addresses to provide valid MACs
+-
+-Broadcom's firmware requires every BSS to use MAC address with unique
+-last few bits. The amount of bits may depend on a particular firmware,
+-it was verified to be 2 for BCM43602 one.
+-If this condition won't be fulfilled firmware will reject such MAC:
+-brcmfmac: _brcmf_set_mac_address: Setting cur_etheraddr failed, -52
+-
+-We don't want to simply set addr_mask as it would also disallow using
+-locally administrated bit. Instead let's build a list of addresses
+-manually enabling 0x2 bit for extra interfaces.
+-
+-Signed-off-by: Rafa? Mi?ecki <zajec5@gmail.com>
+-Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
+----
+-
+---- a/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c
+-+++ b/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c
+-@@ -5784,6 +5784,7 @@ static void brcmf_wiphy_wowl_params(stru
+- 
+- static int brcmf_setup_wiphy(struct wiphy *wiphy, struct brcmf_if *ifp)
+- {
+-+	struct brcmf_pub *drvr = ifp->drvr;
+- 	struct ieee80211_supported_band *band;
+- 	__le32 bandlist[3];
+- 	u32 n_bands;
+-@@ -5797,6 +5798,19 @@ static int brcmf_setup_wiphy(struct wiph
+- 	if (err)
+- 		return err;
+- 
+-+	for (i = 0; i < wiphy->iface_combinations->max_interfaces &&
+-+	     i < ARRAY_SIZE(drvr->addresses); i++) {
+-+		u8 *addr = drvr->addresses[i].addr;
+-+
+-+		memcpy(addr, drvr->mac, ETH_ALEN);
+-+		if (i) {
+-+			addr[0] |= BIT(1);
+-+			addr[ETH_ALEN - 1] ^= i;
+-+		}
+-+	}
+-+	wiphy->addresses = drvr->addresses;
+-+	wiphy->n_addresses = i;
+-+
+- 	wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
+- 	wiphy->cipher_suites = __wl_cipher_suites;
+- 	wiphy->n_cipher_suites = ARRAY_SIZE(__wl_cipher_suites);
+---- a/drivers/net/wireless/brcm80211/brcmfmac/core.h
+-+++ b/drivers/net/wireless/brcm80211/brcmfmac/core.h
+-@@ -21,6 +21,7 @@
+- #ifndef BRCMFMAC_CORE_H
+- #define BRCMFMAC_CORE_H
+- 
+-+#include <net/cfg80211.h>
+- #include "fweh.h"
+- 
+- #define TOE_TX_CSUM_OL		0x00000001
+-@@ -118,6 +119,8 @@ struct brcmf_pub {
+- 	/* Multicast data packets sent to dongle */
+- 	unsigned long tx_multicast;
+- 
+-+	struct mac_address addresses[BRCMF_MAX_IFS];
+-+
+- 	struct brcmf_if *iflist[BRCMF_MAX_IFS];
+- 
+- 	struct mutex proto_block;
+diff --git a/package/kernel/mac80211/patches/392-brcmfmac-dhd_sdio.c-use-existing-atomic_or-primitive.patch b/package/kernel/mac80211/patches/392-brcmfmac-dhd_sdio.c-use-existing-atomic_or-primitive.patch
+deleted file mode 100644
+index e44f121..0000000
+--- a/package/kernel/mac80211/patches/392-brcmfmac-dhd_sdio.c-use-existing-atomic_or-primitive.patch
++++ /dev/null
+@@ -1,45 +0,0 @@
+-From: Vineet Gupta <Vineet.Gupta1@synopsys.com>
+-Date: Thu, 9 Jul 2015 13:43:18 +0530
+-Subject: [PATCH] brcmfmac: dhd_sdio.c: use existing atomic_or primitive
+-
+-There's already a generic implementation so use that instead.
+-
+-Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
+----
+-
+---- a/drivers/net/wireless/brcm80211/brcmfmac/sdio.c
+-+++ b/drivers/net/wireless/brcm80211/brcmfmac/sdio.c
+-@@ -2564,15 +2564,6 @@ static inline void brcmf_sdio_clrintr(st
+- 	}
+- }
+- 
+--static void atomic_orr(int val, atomic_t *v)
+--{
+--	int old_val;
+--
+--	old_val = atomic_read(v);
+--	while (atomic_cmpxchg(v, old_val, val | old_val) != old_val)
+--		old_val = atomic_read(v);
+--}
+--
+- static int brcmf_sdio_intr_rstatus(struct brcmf_sdio *bus)
+- {
+- 	struct brcmf_core *buscore;
+-@@ -2595,7 +2586,7 @@ static int brcmf_sdio_intr_rstatus(struc
+- 	if (val) {
+- 		brcmf_sdiod_regwl(bus->sdiodev, addr, val, &ret);
+- 		bus->sdcnt.f1regdata++;
+--		atomic_orr(val, &bus->intstatus);
+-+		atomic_or(val, &bus->intstatus);
+- 	}
+- 
+- 	return ret;
+-@@ -2712,7 +2703,7 @@ static void brcmf_sdio_dpc(struct brcmf_
+- 
+- 	/* Keep still-pending events for next scheduling */
+- 	if (intstatus)
+--		atomic_orr(intstatus, &bus->intstatus);
+-+		atomic_or(intstatus, &bus->intstatus);
+- 
+- 	brcmf_sdio_clrintr(bus);
+- 
+diff --git a/package/kernel/mac80211/patches/393-0001-brcmfmac-check-all-combinations-when-setting-wiphy-s.patch b/package/kernel/mac80211/patches/393-0001-brcmfmac-check-all-combinations-when-setting-wiphy-s.patch
+deleted file mode 100644
+index 76ca143..0000000
+--- a/package/kernel/mac80211/patches/393-0001-brcmfmac-check-all-combinations-when-setting-wiphy-s.patch
++++ /dev/null
+@@ -1,46 +0,0 @@
+-From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <zajec5@gmail.com>
+-Date: Thu, 20 Aug 2015 00:16:42 +0200
+-Subject: [PATCH] brcmfmac: check all combinations when setting wiphy's
+- addresses
+-MIME-Version: 1.0
+-Content-Type: text/plain; charset=UTF-8
+-Content-Transfer-Encoding: 8bit
+-
+-Broadcom is working on better reflection of interface combinations. With
+-upcoming patches we may have 1st combination supporting less interfaces
+-than others.
+-To don't run out of addresses check all combinations to find the one
+-with the greatest max_interfaces value.
+-
+-Signed-off-by: Rafał Miłecki <zajec5@gmail.com>
+-Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
+----
+-
+---- a/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c
+-+++ b/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c
+-@@ -5785,7 +5785,9 @@ static void brcmf_wiphy_wowl_params(stru
+- static int brcmf_setup_wiphy(struct wiphy *wiphy, struct brcmf_if *ifp)
+- {
+- 	struct brcmf_pub *drvr = ifp->drvr;
+-+	const struct ieee80211_iface_combination *combo;
+- 	struct ieee80211_supported_band *band;
+-+	u16 max_interfaces = 0;
+- 	__le32 bandlist[3];
+- 	u32 n_bands;
+- 	int err, i;
+-@@ -5798,8 +5800,13 @@ static int brcmf_setup_wiphy(struct wiph
+- 	if (err)
+- 		return err;
+- 
+--	for (i = 0; i < wiphy->iface_combinations->max_interfaces &&
+--	     i < ARRAY_SIZE(drvr->addresses); i++) {
+-+	for (i = 0, combo = wiphy->iface_combinations;
+-+	     i < wiphy->n_iface_combinations; i++, combo++) {
+-+		max_interfaces = max(max_interfaces, combo->max_interfaces);
+-+	}
+-+
+-+	for (i = 0; i < max_interfaces && i < ARRAY_SIZE(drvr->addresses);
+-+	     i++) {
+- 		u8 *addr = drvr->addresses[i].addr;
+- 
+- 		memcpy(addr, drvr->mac, ETH_ALEN);
+diff --git a/package/kernel/mac80211/patches/393-0002-brcmfmac-correct-interface-combination-info.patch b/package/kernel/mac80211/patches/393-0002-brcmfmac-correct-interface-combination-info.patch
+deleted file mode 100644
+index c4a0720..0000000
+--- a/package/kernel/mac80211/patches/393-0002-brcmfmac-correct-interface-combination-info.patch
++++ /dev/null
+@@ -1,204 +0,0 @@
+-From: Arend van Spriel <arend@broadcom.com>
+-Date: Thu, 20 Aug 2015 22:06:03 +0200
+-Subject: [PATCH] brcmfmac: correct interface combination info
+-
+-The interface combination provided by brcmfmac did not truly reflect
+-the combinations supported by driver and/or firmware.
+-
+-Reviewed-by: Hante Meuleman <meuleman@broadcom.com>
+-Reviewed-by: Franky (Zhenhui) Lin <frankyl@broadcom.com>
+-Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
+-Reviewed-by: Pontus Fuchs <pontusf@broadcom.com>
+-Signed-off-by: Arend van Spriel <arend@broadcom.com>
+-Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
+----
+-
+---- a/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c
+-+++ b/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c
+-@@ -5694,63 +5694,132 @@ brcmf_txrx_stypes[NUM_NL80211_IFTYPES] =
+- 	}
+- };
+- 
+-+/**
+-+ * brcmf_setup_ifmodes() - determine interface modes and combinations.
+-+ *
+-+ * @wiphy: wiphy object.
+-+ * @ifp: interface object needed for feat module api.
+-+ *
+-+ * The interface modes and combinations are determined dynamically here
+-+ * based on firmware functionality.
+-+ *
+-+ * no p2p and no mbss:
+-+ *
+-+ *	#STA <= 1, #AP <= 1, channels = 1, 2 total
+-+ *
+-+ * no p2p and mbss:
+-+ *
+-+ *	#STA <= 1, #AP <= 1, channels = 1, 2 total
+-+ *	#AP <= 4, matching BI, channels = 1, 4 total
+-+ *
+-+ * p2p, no mchan, and mbss:
+-+ *
+-+ *	#STA <= 1, #P2P-DEV <= 1, #{P2P-CL, P2P-GO} <= 1, channels = 1, 3 total
+-+ *	#STA <= 1, #P2P-DEV <= 1, #AP <= 1, #P2P-CL <= 1, channels = 1, 4 total
+-+ *	#AP <= 4, matching BI, channels = 1, 4 total
+-+ *
+-+ * p2p, mchan, and mbss:
+-+ *
+-+ *	#STA <= 1, #P2P-DEV <= 1, #{P2P-CL, P2P-GO} <= 1, channels = 2, 3 total
+-+ *	#STA <= 1, #P2P-DEV <= 1, #AP <= 1, #P2P-CL <= 1, channels = 1, 4 total
+-+ *	#AP <= 4, matching BI, channels = 1, 4 total
+-+ */
+- static int brcmf_setup_ifmodes(struct wiphy *wiphy, struct brcmf_if *ifp)
+- {
+- 	struct ieee80211_iface_combination *combo = NULL;
+--	struct ieee80211_iface_limit *limits = NULL;
+--	int i = 0, max_iface_cnt;
+-+	struct ieee80211_iface_limit *c0_limits = NULL;
+-+	struct ieee80211_iface_limit *p2p_limits = NULL;
+-+	struct ieee80211_iface_limit *mbss_limits = NULL;
+-+	bool mbss, p2p;
+-+	int i, c, n_combos;
+- 
+--	combo = kzalloc(sizeof(*combo), GFP_KERNEL);
+-+	mbss = brcmf_feat_is_enabled(ifp, BRCMF_FEAT_MBSS);
+-+	p2p = brcmf_feat_is_enabled(ifp, BRCMF_FEAT_P2P);
+-+
+-+	n_combos = 1 + !!p2p + !!mbss;
+-+	combo = kcalloc(n_combos, sizeof(*combo), GFP_KERNEL);
+- 	if (!combo)
+- 		goto err;
+- 
+--	limits = kzalloc(sizeof(*limits) * 4, GFP_KERNEL);
+--	if (!limits)
+-+	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);
+- 
+--	if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_MCHAN))
+--		combo->num_different_channels = 2;
+--	else
+--		combo->num_different_channels = 1;
+--
+--	if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_MBSS)) {
+--		limits[i].max = 1;
+--		limits[i++].types = BIT(NL80211_IFTYPE_STATION);
+--		limits[i].max = 4;
+--		limits[i++].types = BIT(NL80211_IFTYPE_AP);
+--		max_iface_cnt = 5;
+--	} else {
+--		limits[i].max = 2;
+--		limits[i++].types = BIT(NL80211_IFTYPE_STATION) |
+--				    BIT(NL80211_IFTYPE_AP);
+--		max_iface_cnt = 2;
+--	}
+--
+--	if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_P2P)) {
+-+	c = 0;
+-+	i = 0;
+-+	combo[c].num_different_channels = 1;
+-+	c0_limits[i].max = 1;
+-+	c0_limits[i++].types = BIT(NL80211_IFTYPE_STATION);
+-+	if (p2p) {
+-+		if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_MCHAN))
+-+			combo[c].num_different_channels = 2;
+- 		wiphy->interface_modes |= BIT(NL80211_IFTYPE_P2P_CLIENT) |
+- 					  BIT(NL80211_IFTYPE_P2P_GO) |
+- 					  BIT(NL80211_IFTYPE_P2P_DEVICE);
+--		limits[i].max = 1;
+--		limits[i++].types = BIT(NL80211_IFTYPE_P2P_CLIENT) |
+--				    BIT(NL80211_IFTYPE_P2P_GO);
+--		limits[i].max = 1;
+--		limits[i++].types = BIT(NL80211_IFTYPE_P2P_DEVICE);
+--		max_iface_cnt += 2;
+--	}
+--	combo->max_interfaces = max_iface_cnt;
+--	combo->limits = limits;
+--	combo->n_limits = i;
+-+		c0_limits[i].max = 1;
+-+		c0_limits[i++].types = BIT(NL80211_IFTYPE_P2P_DEVICE);
+-+		c0_limits[i].max = 1;
+-+		c0_limits[i++].types = BIT(NL80211_IFTYPE_P2P_CLIENT) |
+-+				       BIT(NL80211_IFTYPE_P2P_GO);
+-+	} else {
+-+		c0_limits[i].max = 1;
+-+		c0_limits[i++].types = BIT(NL80211_IFTYPE_AP);
+-+	}
+-+	combo[c].max_interfaces = i;
+-+	combo[c].n_limits = i;
+-+	combo[c].limits = c0_limits;
+-+
+-+	if (p2p) {
+-+		c++;
+-+		i = 0;
+-+		combo[c].num_different_channels = 1;
+-+		p2p_limits[i].max = 1;
+-+		p2p_limits[i++].types = BIT(NL80211_IFTYPE_STATION);
+-+		p2p_limits[i].max = 1;
+-+		p2p_limits[i++].types = BIT(NL80211_IFTYPE_AP);
+-+		p2p_limits[i].max = 1;
+-+		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].max_interfaces = i;
+-+		combo[c].n_limits = i;
+-+		combo[c].limits = p2p_limits;
+-+	}
+- 
+-+	if (mbss) {
+-+		c++;
+-+		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].limits = mbss_limits;
+-+	}
+-+	wiphy->n_iface_combinations = n_combos;
+- 	wiphy->iface_combinations = combo;
+--	wiphy->n_iface_combinations = 1;
+- 	return 0;
+- 
+- err:
+--	kfree(limits);
+-+	kfree(c0_limits);
+-+	kfree(p2p_limits);
+-+	kfree(mbss_limits);
+- 	kfree(combo);
+- 	return -ENOMEM;
+- }
+-@@ -6079,11 +6148,15 @@ static void brcmf_cfg80211_reg_notifier(
+- 
+- static void brcmf_free_wiphy(struct wiphy *wiphy)
+- {
+-+	int i;
+-+
+- 	if (!wiphy)
+- 		return;
+- 
+--	if (wiphy->iface_combinations)
+--		kfree(wiphy->iface_combinations->limits);
+-+	if (wiphy->iface_combinations) {
+-+		for (i = 0; i < wiphy->n_iface_combinations; i++)
+-+			kfree(wiphy->iface_combinations[i].limits);
+-+	}
+- 	kfree(wiphy->iface_combinations);
+- 	if (wiphy->bands[IEEE80211_BAND_2GHZ]) {
+- 		kfree(wiphy->bands[IEEE80211_BAND_2GHZ]->channels);
+diff --git a/package/kernel/mac80211/patches/393-0003-brcmfmac-add-debugfs-entry-for-msgbuf-statistics.patch b/package/kernel/mac80211/patches/393-0003-brcmfmac-add-debugfs-entry-for-msgbuf-statistics.patch
+deleted file mode 100644
+index 9768ef2..0000000
+--- a/package/kernel/mac80211/patches/393-0003-brcmfmac-add-debugfs-entry-for-msgbuf-statistics.patch
++++ /dev/null
+@@ -1,87 +0,0 @@
+-From: Franky Lin <frankyl@broadcom.com>
+-Date: Thu, 20 Aug 2015 22:06:04 +0200
+-Subject: [PATCH] brcmfmac: add debugfs entry for msgbuf statistics
+-
+-Expose ring buffer read/write pointers and other useful statistics
+-through debugfs.
+-
+-Reviewed-by: Arend Van Spriel <arend@broadcom.com>
+-Reviewed-by: Hante Meuleman <meuleman@broadcom.com>
+-Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
+-Signed-off-by: Franky Lin <frankyl@broadcom.com>
+-Signed-off-by: Arend van Spriel <arend@broadcom.com>
+-Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
+----
+-
+---- a/drivers/net/wireless/brcm80211/brcmfmac/msgbuf.c
+-+++ b/drivers/net/wireless/brcm80211/brcmfmac/msgbuf.c
+-@@ -1360,6 +1360,60 @@ void brcmf_msgbuf_delete_flowring(struct
+- 	}
+- }
+- 
+-+#ifdef DEBUG
+-+static int brcmf_msgbuf_stats_read(struct seq_file *seq, void *data)
+-+{
+-+	struct brcmf_bus *bus_if = dev_get_drvdata(seq->private);
+-+	struct brcmf_pub *drvr = bus_if->drvr;
+-+	struct brcmf_msgbuf *msgbuf = (struct brcmf_msgbuf *)drvr->proto->pd;
+-+	struct brcmf_commonring *commonring;
+-+	u16 i;
+-+	struct brcmf_flowring_ring *ring;
+-+	struct brcmf_flowring_hash *hash;
+-+
+-+	commonring = msgbuf->commonrings[BRCMF_H2D_MSGRING_CONTROL_SUBMIT];
+-+	seq_printf(seq, "h2d_ctl_submit: rp %4u, wp %4u, depth %4u\n",
+-+		   commonring->r_ptr, commonring->w_ptr, commonring->depth);
+-+	commonring = msgbuf->commonrings[BRCMF_H2D_MSGRING_RXPOST_SUBMIT];
+-+	seq_printf(seq, "h2d_rx_submit:  rp %4u, wp %4u, depth %4u\n",
+-+		   commonring->r_ptr, commonring->w_ptr, commonring->depth);
+-+	commonring = msgbuf->commonrings[BRCMF_D2H_MSGRING_CONTROL_COMPLETE];
+-+	seq_printf(seq, "d2h_ctl_cmplt:  rp %4u, wp %4u, depth %4u\n",
+-+		   commonring->r_ptr, commonring->w_ptr, commonring->depth);
+-+	commonring = msgbuf->commonrings[BRCMF_D2H_MSGRING_TX_COMPLETE];
+-+	seq_printf(seq, "d2h_tx_cmplt:   rp %4u, wp %4u, depth %4u\n",
+-+		   commonring->r_ptr, commonring->w_ptr, commonring->depth);
+-+	commonring = msgbuf->commonrings[BRCMF_D2H_MSGRING_RX_COMPLETE];
+-+	seq_printf(seq, "d2h_rx_cmplt:   rp %4u, wp %4u, depth %4u\n",
+-+		   commonring->r_ptr, commonring->w_ptr, commonring->depth);
+-+
+-+	seq_printf(seq, "\nh2d_flowrings: depth %u\n",
+-+		   BRCMF_H2D_TXFLOWRING_MAX_ITEM);
+-+	seq_puts(seq, "Active flowrings:\n");
+-+	hash = msgbuf->flow->hash;
+-+	for (i = 0; i < msgbuf->flow->nrofrings; i++) {
+-+		if (!msgbuf->flow->rings[i])
+-+			continue;
+-+		ring = msgbuf->flow->rings[i];
+-+		if (ring->status != RING_OPEN)
+-+			continue;
+-+		commonring = msgbuf->flowrings[i];
+-+		hash = &msgbuf->flow->hash[ring->hash_id];
+-+		seq_printf(seq, "id %3u: rp %4u, wp %4u, qlen %4u, blocked %u\n"
+-+				"        ifidx %u, fifo %u, da %pM\n",
+-+				i, commonring->r_ptr, commonring->w_ptr,
+-+				skb_queue_len(&ring->skblist), ring->blocked,
+-+				hash->ifidx, hash->fifo, hash->mac);
+-+	}
+-+
+-+	return 0;
+-+}
+-+#else
+-+static int brcmf_msgbuf_stats_read(struct seq_file *seq, void *data)
+-+{
+-+	return 0;
+-+}
+-+#endif
+- 
+- int brcmf_proto_msgbuf_attach(struct brcmf_pub *drvr)
+- {
+-@@ -1460,6 +1514,8 @@ int brcmf_proto_msgbuf_attach(struct brc
+- 	spin_lock_init(&msgbuf->flowring_work_lock);
+- 	INIT_LIST_HEAD(&msgbuf->work_queue);
+- 
+-+	brcmf_debugfs_add_entry(drvr, "msgbuf_stats", brcmf_msgbuf_stats_read);
+-+
+- 	return 0;
+- 
+- fail:
+diff --git a/package/kernel/mac80211/patches/393-0004-brcmfmac-make-use-of-cfg80211_check_combinations.patch b/package/kernel/mac80211/patches/393-0004-brcmfmac-make-use-of-cfg80211_check_combinations.patch
+deleted file mode 100644
+index 2b84cf9..0000000
+--- a/package/kernel/mac80211/patches/393-0004-brcmfmac-make-use-of-cfg80211_check_combinations.patch
++++ /dev/null
+@@ -1,83 +0,0 @@
+-From: Arend van Spriel <arend@broadcom.com>
+-Date: Thu, 20 Aug 2015 22:06:05 +0200
+-Subject: [PATCH] brcmfmac: make use of cfg80211_check_combinations()
+-
+-Use cfg80211_check_combinations() so we can bail out early when an
+-interface add or change results in an invalid combination.
+-
+-Reviewed-by: Hante Meuleman <meuleman@broadcom.com>
+-Reviewed-by: Franky (Zhenhui) Lin <frankyl@broadcom.com>
+-Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
+-Signed-off-by: Arend van Spriel <arend@broadcom.com>
+-Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
+----
+-
+---- a/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c
+-+++ b/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c
+-@@ -469,6 +469,36 @@ brcmf_find_wpsie(const u8 *parse, u32 le
+- 	return NULL;
+- }
+- 
+-+static int brcmf_vif_change_validate(struct brcmf_cfg80211_info *cfg,
+-+				     struct brcmf_cfg80211_vif *vif,
+-+				     enum nl80211_iftype new_type)
+-+{
+-+	int iftype_num[NUM_NL80211_IFTYPES];
+-+	struct brcmf_cfg80211_vif *pos;
+-+
+-+	memset(&iftype_num[0], 0, sizeof(iftype_num));
+-+	list_for_each_entry(pos, &cfg->vif_list, list)
+-+		if (pos == vif)
+-+			iftype_num[new_type]++;
+-+		else
+-+			iftype_num[pos->wdev.iftype]++;
+-+
+-+	return cfg80211_check_combinations(cfg->wiphy, 1, 0, iftype_num);
+-+}
+-+
+-+static int brcmf_vif_add_validate(struct brcmf_cfg80211_info *cfg,
+-+				  enum nl80211_iftype new_type)
+-+{
+-+	int iftype_num[NUM_NL80211_IFTYPES];
+-+	struct brcmf_cfg80211_vif *pos;
+-+
+-+	memset(&iftype_num[0], 0, sizeof(iftype_num));
+-+	list_for_each_entry(pos, &cfg->vif_list, list)
+-+		iftype_num[pos->wdev.iftype]++;
+-+
+-+	iftype_num[new_type]++;
+-+	return cfg80211_check_combinations(cfg->wiphy, 1, 0, iftype_num);
+-+}
+- 
+- static void convert_key_from_CPU(struct brcmf_wsec_key *key,
+- 				 struct brcmf_wsec_key_le *key_le)
+-@@ -662,8 +692,14 @@ static struct wireless_dev *brcmf_cfg802
+- 						     struct vif_params *params)
+- {
+- 	struct wireless_dev *wdev;
+-+	int err;
+- 
+- 	brcmf_dbg(TRACE, "enter: %s type %d\n", name, type);
+-+	err = brcmf_vif_add_validate(wiphy_to_cfg(wiphy), type);
+-+	if (err) {
+-+		brcmf_err("iface validation failed: err=%d\n", err);
+-+		return ERR_PTR(err);
+-+	}
+- 	switch (type) {
+- 	case NL80211_IFTYPE_ADHOC:
+- 	case NL80211_IFTYPE_STATION:
+-@@ -822,8 +858,12 @@ brcmf_cfg80211_change_iface(struct wiphy
+- 	s32 ap = 0;
+- 	s32 err = 0;
+- 
+--	brcmf_dbg(TRACE, "Enter, ndev=%p, type=%d\n", ndev, type);
+--
+-+	brcmf_dbg(TRACE, "Enter, idx=%d, type=%d\n", ifp->bssidx, type);
+-+	err = brcmf_vif_change_validate(wiphy_to_cfg(wiphy), vif, type);
+-+	if (err) {
+-+		brcmf_err("iface validation failed: err=%d\n", err);
+-+		return err;
+-+	}
+- 	switch (type) {
+- 	case NL80211_IFTYPE_MONITOR:
+- 	case NL80211_IFTYPE_WDS:
+diff --git a/package/kernel/mac80211/patches/393-0005-brcmfmac-block-the-correct-flowring-when-backup-queu.patch b/package/kernel/mac80211/patches/393-0005-brcmfmac-block-the-correct-flowring-when-backup-queu.patch
+deleted file mode 100644
+index 2d5f7b9..0000000
+--- a/package/kernel/mac80211/patches/393-0005-brcmfmac-block-the-correct-flowring-when-backup-queu.patch
++++ /dev/null
+@@ -1,48 +0,0 @@
+-From: Franky Lin <frankyl@broadcom.com>
+-Date: Thu, 20 Aug 2015 22:06:06 +0200
+-Subject: [PATCH] brcmfmac: block the correct flowring when backup queue
+- overflow
+-
+-brcmf_flowring_block blocks the last active flowring under the same
+-interface instead of the one provided by caller. This could lead to a
+-dead lock of netif stop if there are more than one flowring under the
+-interface and the traffic is high enough so brcmf_flowring_enqueue can
+-not unblock the ring right away.
+-
+-Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
+-Reviewed-by: Hante Meuleman <meuleman@broadcom.com>
+-Signed-off-by: Franky Lin <frankyl@broadcom.com>
+-Signed-off-by: Arend van Spriel <arend@broadcom.com>
+-Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
+----
+-
+---- a/drivers/net/wireless/brcm80211/brcmfmac/flowring.c
+-+++ b/drivers/net/wireless/brcm80211/brcmfmac/flowring.c
+-@@ -194,11 +194,15 @@ static void brcmf_flowring_block(struct
+- 	spin_lock_irqsave(&flow->block_lock, flags);
+- 
+- 	ring = flow->rings[flowid];
+-+	if (ring->blocked == blocked) {
+-+		spin_unlock_irqrestore(&flow->block_lock, flags);
+-+		return;
+-+	}
+- 	ifidx = brcmf_flowring_ifidx_get(flow, flowid);
+- 
+- 	currently_blocked = false;
+- 	for (i = 0; i < flow->nrofrings; i++) {
+--		if (flow->rings[i]) {
+-+		if ((flow->rings[i]) && (i != flowid)) {
+- 			ring = flow->rings[i];
+- 			if ((ring->status == RING_OPEN) &&
+- 			    (brcmf_flowring_ifidx_get(flow, i) == ifidx)) {
+-@@ -209,8 +213,8 @@ static void brcmf_flowring_block(struct
+- 			}
+- 		}
+- 	}
+--	ring->blocked = blocked;
+--	if (currently_blocked == blocked) {
+-+	flow->rings[flowid]->blocked = blocked;
+-+	if (currently_blocked) {
+- 		spin_unlock_irqrestore(&flow->block_lock, flags);
+- 		return;
+- 	}
+diff --git a/package/kernel/mac80211/patches/393-0006-brcmfmac-bump-highest-event-number-for-4339-firmware.patch b/package/kernel/mac80211/patches/393-0006-brcmfmac-bump-highest-event-number-for-4339-firmware.patch
+deleted file mode 100644
+index 7378401..0000000
+--- a/package/kernel/mac80211/patches/393-0006-brcmfmac-bump-highest-event-number-for-4339-firmware.patch
++++ /dev/null
+@@ -1,52 +0,0 @@
+-From: Arend van Spriel <arend@broadcom.com>
+-Date: Thu, 20 Aug 2015 22:06:07 +0200
+-Subject: [PATCH] brcmfmac: bump highest event number for 4339 firmware
+-
+-The event mask length is determined by the highest event number
+-that is specified in the driver. When this length is shorter than
+-firmware expects setting event mask will fail and device becomes
+-pretty useless. This issue was reported with bcm4339 firmware that
+-was recently released.
+-
+-Reported-by: Pontus Fuchs <pontusf@broadcom.com>
+-Reviewed-by: Hante Meuleman <meuleman@broadcom.com>
+-Reviewed-by: Franky (Zhenhui) Lin <frankyl@broadcom.com>
+-Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
+-Reviewed-by: Pontus Fuchs <pontusf@broadcom.com>
+-Signed-off-by: Arend van Spriel <arend@broadcom.com>
+-Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
+----
+-
+---- a/drivers/net/wireless/brcm80211/brcmfmac/fweh.h
+-+++ b/drivers/net/wireless/brcm80211/brcmfmac/fweh.h
+-@@ -85,7 +85,6 @@ struct brcmf_event;
+- 	BRCMF_ENUM_DEF(IF, 54) \
+- 	BRCMF_ENUM_DEF(P2P_DISC_LISTEN_COMPLETE, 55) \
+- 	BRCMF_ENUM_DEF(RSSI, 56) \
+--	BRCMF_ENUM_DEF(PFN_SCAN_COMPLETE, 57) \
+- 	BRCMF_ENUM_DEF(EXTLOG_MSG, 58) \
+- 	BRCMF_ENUM_DEF(ACTION_FRAME, 59) \
+- 	BRCMF_ENUM_DEF(ACTION_FRAME_COMPLETE, 60) \
+-@@ -103,8 +102,7 @@ struct brcmf_event;
+- 	BRCMF_ENUM_DEF(FIFO_CREDIT_MAP, 74) \
+- 	BRCMF_ENUM_DEF(ACTION_FRAME_RX, 75) \
+- 	BRCMF_ENUM_DEF(TDLS_PEER_EVENT, 92) \
+--	BRCMF_ENUM_DEF(BCMC_CREDIT_SUPPORT, 127) \
+--	BRCMF_ENUM_DEF(PSTA_PRIMARY_INTF_IND, 128)
+-+	BRCMF_ENUM_DEF(BCMC_CREDIT_SUPPORT, 127)
+- 
+- #define BRCMF_ENUM_DEF(id, val) \
+- 	BRCMF_E_##id = (val),
+-@@ -112,7 +110,11 @@ struct brcmf_event;
+- /* firmware event codes sent by the dongle */
+- enum brcmf_fweh_event_code {
+- 	BRCMF_FWEH_EVENT_ENUM_DEFLIST
+--	BRCMF_E_LAST
+-+	/* this determines event mask length which must match
+-+	 * minimum length check in device firmware so it is
+-+	 * hard-coded here.
+-+	 */
+-+	BRCMF_E_LAST = 139
+- };
+- #undef BRCMF_ENUM_DEF
+- 
+diff --git a/package/kernel/mac80211/patches/394-0001-brcmfmac-consolidate-ifp-lookup-in-driver-core.patch b/package/kernel/mac80211/patches/394-0001-brcmfmac-consolidate-ifp-lookup-in-driver-core.patch
+deleted file mode 100644
+index 97444b3..0000000
+--- a/package/kernel/mac80211/patches/394-0001-brcmfmac-consolidate-ifp-lookup-in-driver-core.patch
++++ /dev/null
+@@ -1,138 +0,0 @@
+-From: Arend van Spriel <arend@broadcom.com>
+-Date: Wed, 26 Aug 2015 22:14:53 +0200
+-Subject: [PATCH] brcmfmac: consolidate ifp lookup in driver core
+-
+-In rx path the firmware provide an interface index which is used to
+-map to a struct brcmf_if instance. However, this involves some trick
+-that is done in two places. This is changed by having driver core
+-providing brcmf_get_ifp() function.
+-
+-Reviewed-by: Hante Meuleman <meuleman@broadcom.com>
+-Reviewed-by: Franky (Zhenhui) Lin <frankyl@broadcom.com>
+-Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
+-Signed-off-by: Arend van Spriel <arend@broadcom.com>
+----
+-
+---- a/drivers/net/wireless/brcm80211/brcmfmac/bcdc.c
+-+++ b/drivers/net/wireless/brcm80211/brcmfmac/bcdc.c
+-@@ -276,6 +276,7 @@ brcmf_proto_bcdc_hdrpull(struct brcmf_pu
+- 			 struct sk_buff *pktbuf)
+- {
+- 	struct brcmf_proto_bcdc_header *h;
+-+	struct brcmf_if *ifp;
+- 
+- 	brcmf_dbg(BCDC, "Enter\n");
+- 
+-@@ -289,30 +290,21 @@ brcmf_proto_bcdc_hdrpull(struct brcmf_pu
+- 	trace_brcmf_bcdchdr(pktbuf->data);
+- 	h = (struct brcmf_proto_bcdc_header *)(pktbuf->data);
+- 
+--	*ifidx = BCDC_GET_IF_IDX(h);
+--	if (*ifidx >= BRCMF_MAX_IFS) {
+--		brcmf_err("rx data ifnum out of range (%d)\n", *ifidx);
+-+	ifp = brcmf_get_ifp(drvr, BCDC_GET_IF_IDX(h));
+-+	if (IS_ERR_OR_NULL(ifp)) {
+-+		brcmf_dbg(INFO, "no matching ifp found\n");
+- 		return -EBADE;
+- 	}
+--	/* The ifidx is the idx to map to matching netdev/ifp. When receiving
+--	 * events this is easy because it contains the bssidx which maps
+--	 * 1-on-1 to the netdev/ifp. But for data frames the ifidx is rcvd.
+--	 * bssidx 1 is used for p2p0 and no data can be received or
+--	 * transmitted on it. Therefor bssidx is ifidx + 1 if ifidx > 0
+--	 */
+--	if (*ifidx)
+--		(*ifidx)++;
+--
+- 	if (((h->flags & BCDC_FLAG_VER_MASK) >> BCDC_FLAG_VER_SHIFT) !=
+- 	    BCDC_PROTO_VER) {
+- 		brcmf_err("%s: non-BCDC packet received, flags 0x%x\n",
+--			  brcmf_ifname(drvr, *ifidx), h->flags);
+-+			  brcmf_ifname(drvr, ifp->ifidx), h->flags);
+- 		return -EBADE;
+- 	}
+- 
+- 	if (h->flags & BCDC_FLAG_SUM_GOOD) {
+- 		brcmf_dbg(BCDC, "%s: BDC rcv, good checksum, flags 0x%x\n",
+--			  brcmf_ifname(drvr, *ifidx), h->flags);
+-+			  brcmf_ifname(drvr, ifp->ifidx), h->flags);
+- 		pktbuf->ip_summed = CHECKSUM_UNNECESSARY;
+- 	}
+- 
+-@@ -320,12 +312,15 @@ brcmf_proto_bcdc_hdrpull(struct brcmf_pu
+- 
+- 	skb_pull(pktbuf, BCDC_HEADER_LEN);
+- 	if (do_fws)
+--		brcmf_fws_hdrpull(drvr, *ifidx, h->data_offset << 2, pktbuf);
+-+		brcmf_fws_hdrpull(drvr, ifp->ifidx, h->data_offset << 2,
+-+				  pktbuf);
+- 	else
+- 		skb_pull(pktbuf, h->data_offset << 2);
+- 
+- 	if (pktbuf->len == 0)
+- 		return -ENODATA;
+-+
+-+	*ifidx = ifp->ifidx;
+- 	return 0;
+- }
+- 
+---- a/drivers/net/wireless/brcm80211/brcmfmac/core.c
+-+++ b/drivers/net/wireless/brcm80211/brcmfmac/core.c
+-@@ -83,6 +83,25 @@ char *brcmf_ifname(struct brcmf_pub *drv
+- 	return "<if_none>";
+- }
+- 
+-+struct brcmf_if *brcmf_get_ifp(struct brcmf_pub *drvr, int ifidx)
+-+{
+-+	if (ifidx < 0 || ifidx >= BRCMF_MAX_IFS) {
+-+		brcmf_err("ifidx %d out of range\n", ifidx);
+-+		return ERR_PTR(-ERANGE);
+-+	}
+-+
+-+	/* The ifidx is the idx to map to matching netdev/ifp. When receiving
+-+	 * events this is easy because it contains the bssidx which maps
+-+	 * 1-on-1 to the netdev/ifp. But for data frames the ifidx is rcvd.
+-+	 * bssidx 1 is used for p2p0 and no data can be received or
+-+	 * transmitted on it. Therefor bssidx is ifidx + 1 if ifidx > 0
+-+	 */
+-+	if (ifidx)
+-+		ifidx++;
+-+
+-+	return drvr->iflist[ifidx];
+-+}
+-+
+- static void _brcmf_set_multicast_list(struct work_struct *work)
+- {
+- 	struct brcmf_if *ifp;
+---- a/drivers/net/wireless/brcm80211/brcmfmac/core.h
+-+++ b/drivers/net/wireless/brcm80211/brcmfmac/core.h
+-@@ -202,7 +202,7 @@ int brcmf_netdev_wait_pend8021x(struct b
+- 
+- /* Return pointer to interface name */
+- char *brcmf_ifname(struct brcmf_pub *drvr, int idx);
+--
+-+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 bssidx, s32 ifidx,
+- 			      char *name, u8 *mac_addr);
+---- a/drivers/net/wireless/brcm80211/brcmfmac/msgbuf.c
+-+++ b/drivers/net/wireless/brcm80211/brcmfmac/msgbuf.c
+-@@ -1081,16 +1081,8 @@ brcmf_msgbuf_rx_skb(struct brcmf_msgbuf
+- {
+- 	struct brcmf_if *ifp;
+- 
+--	/* The ifidx is the idx to map to matching netdev/ifp. When receiving
+--	 * events this is easy because it contains the bssidx which maps
+--	 * 1-on-1 to the netdev/ifp. But for data frames the ifidx is rcvd.
+--	 * bssidx 1 is used for p2p0 and no data can be received or
+--	 * transmitted on it. Therefor bssidx is ifidx + 1 if ifidx > 0
+--	 */
+--	if (ifidx)
+--		(ifidx)++;
+--	ifp = msgbuf->drvr->iflist[ifidx];
+--	if (!ifp || !ifp->ndev) {
+-+	ifp = brcmf_get_ifp(msgbuf->drvr, ifidx);
+-+	if (IS_ERR_OR_NULL(ifp) || !ifp->ndev) {
+- 		brcmf_err("Received pkt for invalid ifidx %d\n", ifidx);
+- 		brcmu_pkt_buf_free_skb(skb);
+- 		return;
+diff --git a/package/kernel/mac80211/patches/394-0002-brcmfmac-make-brcmf_proto_hdrpull-return-struct-brcm.patch b/package/kernel/mac80211/patches/394-0002-brcmfmac-make-brcmf_proto_hdrpull-return-struct-brcm.patch
+deleted file mode 100644
+index 632714c..0000000
+--- a/package/kernel/mac80211/patches/394-0002-brcmfmac-make-brcmf_proto_hdrpull-return-struct-brcm.patch
++++ /dev/null
+@@ -1,222 +0,0 @@
+-From: Arend van Spriel <arend@broadcom.com>
+-Date: Wed, 26 Aug 2015 22:14:54 +0200
+-Subject: [PATCH] brcmfmac: make brcmf_proto_hdrpull() return struct
+- brcmf_if instance
+-
+-Avoid spreading the ifidx in the driver, but have it return the
+-struct brcmf_if instance.
+-
+-Reviewed-by: Hante Meuleman <meuleman@broadcom.com>
+-Reviewed-by: Franky (Zhenhui) Lin <frankyl@broadcom.com>
+-Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
+-Signed-off-by: Arend van Spriel <arend@broadcom.com>
+----
+-
+---- a/drivers/net/wireless/brcm80211/brcmfmac/bcdc.c
+-+++ b/drivers/net/wireless/brcm80211/brcmfmac/bcdc.c
+-@@ -272,11 +272,11 @@ brcmf_proto_bcdc_hdrpush(struct brcmf_pu
+- }
+- 
+- static int
+--brcmf_proto_bcdc_hdrpull(struct brcmf_pub *drvr, bool do_fws, u8 *ifidx,
+--			 struct sk_buff *pktbuf)
+-+brcmf_proto_bcdc_hdrpull(struct brcmf_pub *drvr, bool do_fws,
+-+			 struct sk_buff *pktbuf, struct brcmf_if **ifp)
+- {
+- 	struct brcmf_proto_bcdc_header *h;
+--	struct brcmf_if *ifp;
+-+	struct brcmf_if *tmp_if;
+- 
+- 	brcmf_dbg(BCDC, "Enter\n");
+- 
+-@@ -290,21 +290,21 @@ brcmf_proto_bcdc_hdrpull(struct brcmf_pu
+- 	trace_brcmf_bcdchdr(pktbuf->data);
+- 	h = (struct brcmf_proto_bcdc_header *)(pktbuf->data);
+- 
+--	ifp = brcmf_get_ifp(drvr, BCDC_GET_IF_IDX(h));
+--	if (IS_ERR_OR_NULL(ifp)) {
+-+	tmp_if = brcmf_get_ifp(drvr, BCDC_GET_IF_IDX(h));
+-+	if (!tmp_if) {
+- 		brcmf_dbg(INFO, "no matching ifp found\n");
+- 		return -EBADE;
+- 	}
+- 	if (((h->flags & BCDC_FLAG_VER_MASK) >> BCDC_FLAG_VER_SHIFT) !=
+- 	    BCDC_PROTO_VER) {
+- 		brcmf_err("%s: non-BCDC packet received, flags 0x%x\n",
+--			  brcmf_ifname(drvr, ifp->ifidx), h->flags);
+-+			  brcmf_ifname(drvr, tmp_if->ifidx), h->flags);
+- 		return -EBADE;
+- 	}
+- 
+- 	if (h->flags & BCDC_FLAG_SUM_GOOD) {
+- 		brcmf_dbg(BCDC, "%s: BDC rcv, good checksum, flags 0x%x\n",
+--			  brcmf_ifname(drvr, ifp->ifidx), h->flags);
+-+			  brcmf_ifname(drvr, tmp_if->ifidx), h->flags);
+- 		pktbuf->ip_summed = CHECKSUM_UNNECESSARY;
+- 	}
+- 
+-@@ -312,7 +312,7 @@ brcmf_proto_bcdc_hdrpull(struct brcmf_pu
+- 
+- 	skb_pull(pktbuf, BCDC_HEADER_LEN);
+- 	if (do_fws)
+--		brcmf_fws_hdrpull(drvr, ifp->ifidx, h->data_offset << 2,
+-+		brcmf_fws_hdrpull(drvr, tmp_if->ifidx, h->data_offset << 2,
+- 				  pktbuf);
+- 	else
+- 		skb_pull(pktbuf, h->data_offset << 2);
+-@@ -320,7 +320,7 @@ brcmf_proto_bcdc_hdrpull(struct brcmf_pu
+- 	if (pktbuf->len == 0)
+- 		return -ENODATA;
+- 
+--	*ifidx = ifp->ifidx;
+-+	*ifp = tmp_if;
+- 	return 0;
+- }
+- 
+---- a/drivers/net/wireless/brcm80211/brcmfmac/core.c
+-+++ b/drivers/net/wireless/brcm80211/brcmfmac/core.c
+-@@ -87,7 +87,7 @@ struct brcmf_if *brcmf_get_ifp(struct br
+- {
+- 	if (ifidx < 0 || ifidx >= BRCMF_MAX_IFS) {
+- 		brcmf_err("ifidx %d out of range\n", ifidx);
+--		return ERR_PTR(-ERANGE);
+-+		return NULL;
+- 	}
+- 
+- 	/* The ifidx is the idx to map to matching netdev/ifp. When receiving
+-@@ -539,17 +539,15 @@ void brcmf_rx_frame(struct device *dev,
+- 	struct brcmf_bus *bus_if = dev_get_drvdata(dev);
+- 	struct brcmf_pub *drvr = bus_if->drvr;
+- 	struct brcmf_skb_reorder_data *rd;
+--	u8 ifidx;
+- 	int ret;
+- 
+- 	brcmf_dbg(DATA, "Enter: %s: rxp=%p\n", dev_name(dev), skb);
+- 
+- 	/* process and remove protocol-specific header */
+--	ret = brcmf_proto_hdrpull(drvr, true, &ifidx, skb);
+--	ifp = drvr->iflist[ifidx];
+-+	ret = brcmf_proto_hdrpull(drvr, true, skb, &ifp);
+- 
+- 	if (ret || !ifp || !ifp->ndev) {
+--		if ((ret != -ENODATA) && ifp)
+-+		if (ret != -ENODATA && ifp)
+- 			ifp->stats.rx_errors++;
+- 		brcmu_pkt_buf_free_skb(skb);
+- 		return;
+-@@ -592,17 +590,17 @@ void brcmf_txcomplete(struct device *dev
+- {
+- 	struct brcmf_bus *bus_if = dev_get_drvdata(dev);
+- 	struct brcmf_pub *drvr = bus_if->drvr;
+--	u8 ifidx;
+-+	struct brcmf_if *ifp;
+- 
+- 	/* await txstatus signal for firmware if active */
+- 	if (brcmf_fws_fc_active(drvr->fws)) {
+- 		if (!success)
+- 			brcmf_fws_bustxfail(drvr->fws, txp);
+- 	} else {
+--		if (brcmf_proto_hdrpull(drvr, false, &ifidx, txp))
+-+		if (brcmf_proto_hdrpull(drvr, false, txp, &ifp))
+- 			brcmu_pkt_buf_free_skb(txp);
+- 		else
+--			brcmf_txfinalize(drvr, txp, ifidx, success);
+-+			brcmf_txfinalize(drvr, txp, ifp->ifidx, success);
+- 	}
+- }
+- 
+---- a/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c
+-+++ b/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c
+-@@ -1448,7 +1448,7 @@ brcmf_fws_txs_process(struct brcmf_fws_i
+- 	struct sk_buff *skb;
+- 	struct brcmf_skbuff_cb *skcb;
+- 	struct brcmf_fws_mac_descriptor *entry = NULL;
+--	u8 ifidx;
+-+	struct brcmf_if *ifp;
+- 
+- 	brcmf_dbg(DATA, "flags %d\n", flags);
+- 
+-@@ -1497,15 +1497,16 @@ brcmf_fws_txs_process(struct brcmf_fws_i
+- 	}
+- 	brcmf_fws_macdesc_return_req_credit(skb);
+- 
+--	if (brcmf_proto_hdrpull(fws->drvr, false, &ifidx, skb)) {
+-+	ret = brcmf_proto_hdrpull(fws->drvr, false, skb, &ifp);
+-+	if (ret) {
+- 		brcmu_pkt_buf_free_skb(skb);
+- 		return -EINVAL;
+- 	}
+- 	if (!remove_from_hanger)
+--		ret = brcmf_fws_txstatus_suppressed(fws, fifo, skb, ifidx,
+-+		ret = brcmf_fws_txstatus_suppressed(fws, fifo, skb, ifp->ifidx,
+- 						    genbit, seq);
+- 	if (remove_from_hanger || ret)
+--		brcmf_txfinalize(fws->drvr, skb, ifidx, true);
+-+		brcmf_txfinalize(fws->drvr, skb, ifp->ifidx, true);
+- 
+- 	return 0;
+- }
+-@@ -1848,7 +1849,7 @@ static int brcmf_fws_commit_skb(struct b
+- 		entry->transit_count--;
+- 		if (entry->suppressed)
+- 			entry->suppr_transit_count--;
+--		brcmf_proto_hdrpull(fws->drvr, false, &ifidx, skb);
+-+		(void)brcmf_proto_hdrpull(fws->drvr, false, skb, NULL);
+- 		goto rollback;
+- 	}
+- 
+---- a/drivers/net/wireless/brcm80211/brcmfmac/msgbuf.c
+-+++ b/drivers/net/wireless/brcm80211/brcmfmac/msgbuf.c
+-@@ -522,7 +522,7 @@ static int brcmf_msgbuf_set_dcmd(struct
+- 
+- 
+- static int brcmf_msgbuf_hdrpull(struct brcmf_pub *drvr, bool do_fws,
+--				u8 *ifidx, struct sk_buff *skb)
+-+				struct sk_buff *skb, struct brcmf_if **ifp)
+- {
+- 	return -ENODEV;
+- }
+-@@ -1082,7 +1082,7 @@ brcmf_msgbuf_rx_skb(struct brcmf_msgbuf
+- 	struct brcmf_if *ifp;
+- 
+- 	ifp = brcmf_get_ifp(msgbuf->drvr, ifidx);
+--	if (IS_ERR_OR_NULL(ifp) || !ifp->ndev) {
+-+	if (!ifp || !ifp->ndev) {
+- 		brcmf_err("Received pkt for invalid ifidx %d\n", ifidx);
+- 		brcmu_pkt_buf_free_skb(skb);
+- 		return;
+---- a/drivers/net/wireless/brcm80211/brcmfmac/proto.h
+-+++ b/drivers/net/wireless/brcm80211/brcmfmac/proto.h
+-@@ -24,8 +24,8 @@ enum proto_addr_mode {
+- 
+- 
+- struct brcmf_proto {
+--	int (*hdrpull)(struct brcmf_pub *drvr, bool do_fws, u8 *ifidx,
+--		       struct sk_buff *skb);
+-+	int (*hdrpull)(struct brcmf_pub *drvr, bool do_fws,
+-+		       struct sk_buff *skb, struct brcmf_if **ifp);
+- 	int (*query_dcmd)(struct brcmf_pub *drvr, int ifidx, uint cmd,
+- 			  void *buf, uint len);
+- 	int (*set_dcmd)(struct brcmf_pub *drvr, int ifidx, uint cmd, void *buf,
+-@@ -46,9 +46,19 @@ int brcmf_proto_attach(struct brcmf_pub
+- void brcmf_proto_detach(struct brcmf_pub *drvr);
+- 
+- static inline int brcmf_proto_hdrpull(struct brcmf_pub *drvr, bool do_fws,
+--				      u8 *ifidx, struct sk_buff *skb)
+-+				      struct sk_buff *skb,
+-+				      struct brcmf_if **ifp)
+- {
+--	return drvr->proto->hdrpull(drvr, do_fws, ifidx, skb);
+-+	struct brcmf_if *tmp = NULL;
+-+
+-+	/* assure protocol is always called with
+-+	 * non-null initialized pointer.
+-+	 */
+-+	if (ifp)
+-+		*ifp = NULL;
+-+	else
+-+		ifp = &tmp;
+-+	return drvr->proto->hdrpull(drvr, do_fws, skb, ifp);
+- }
+- static inline int brcmf_proto_query_dcmd(struct brcmf_pub *drvr, int ifidx,
+- 					 uint cmd, void *buf, uint len)
+diff --git a/package/kernel/mac80211/patches/394-0003-brcmfmac-change-parameters-for-brcmf_remove_interfac.patch b/package/kernel/mac80211/patches/394-0003-brcmfmac-change-parameters-for-brcmf_remove_interfac.patch
+deleted file mode 100644
+index 2d15a77..0000000
+--- a/package/kernel/mac80211/patches/394-0003-brcmfmac-change-parameters-for-brcmf_remove_interfac.patch
++++ /dev/null
+@@ -1,87 +0,0 @@
+-From: Arend van Spriel <arend@broadcom.com>
+-Date: Wed, 26 Aug 2015 22:14:55 +0200
+-Subject: [PATCH] brcmfmac: change parameters for
+- brcmf_remove_interface()
+-
+-Just pass the interface to be removed, ie. the struct brcmf_if instance.
+-
+-Reviewed-by: Hante Meuleman <meuleman@broadcom.com>
+-Reviewed-by: Franky (Zhenhui) Lin <frankyl@broadcom.com>
+-Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
+-Signed-off-by: Arend van Spriel <arend@broadcom.com>
+----
+-
+---- a/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c
+-+++ b/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c
+-@@ -4982,7 +4982,7 @@ brcmf_notify_connect_status_ap(struct br
+- 		brcmf_dbg(CONN, "AP mode link down\n");
+- 		complete(&cfg->vif_disabled);
+- 		if (ifp->vif->mbss)
+--			brcmf_remove_interface(ifp->drvr, ifp->bssidx);
+-+			brcmf_remove_interface(ifp);
+- 		return 0;
+- 	}
+- 
+---- a/drivers/net/wireless/brcm80211/brcmfmac/core.c
+-+++ b/drivers/net/wireless/brcm80211/brcmfmac/core.c
+-@@ -887,12 +887,13 @@ static void brcmf_del_if(struct brcmf_pu
+- 	}
+- }
+- 
+--void brcmf_remove_interface(struct brcmf_pub *drvr, u32 bssidx)
+-+void brcmf_remove_interface(struct brcmf_if *ifp)
+- {
+--	if (drvr->iflist[bssidx]) {
+--		brcmf_fws_del_interface(drvr->iflist[bssidx]);
+--		brcmf_del_if(drvr, bssidx);
+--	}
+-+	if (!ifp || WARN_ON(ifp->drvr->iflist[ifp->bssidx] != ifp))
+-+		return;
+-+
+-+	brcmf_fws_del_interface(ifp);
+-+	brcmf_del_if(ifp->drvr, ifp->bssidx);
+- }
+- 
+- int brcmf_get_next_free_bsscfgidx(struct brcmf_pub *drvr)
+-@@ -1122,7 +1123,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, i);
+-+		brcmf_remove_interface(drvr->iflist[i]);
+- 
+- 	brcmf_cfg80211_detach(drvr->config);
+- 
+---- a/drivers/net/wireless/brcm80211/brcmfmac/core.h
+-+++ b/drivers/net/wireless/brcm80211/brcmfmac/core.h
+-@@ -206,7 +206,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 bssidx, s32 ifidx,
+- 			      char *name, u8 *mac_addr);
+--void brcmf_remove_interface(struct brcmf_pub *drvr, u32 bssidx);
+-+void brcmf_remove_interface(struct brcmf_if *ifp);
+- int brcmf_get_next_free_bsscfgidx(struct brcmf_pub *drvr);
+- void brcmf_txflowblock_if(struct brcmf_if *ifp,
+- 			  enum brcmf_netif_stop_reason reason, bool state);
+---- a/drivers/net/wireless/brcm80211/brcmfmac/fweh.c
+-+++ b/drivers/net/wireless/brcm80211/brcmfmac/fweh.c
+-@@ -222,7 +222,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(drvr, ifevent->bssidx);
+-+		brcmf_remove_interface(ifp);
+- }
+- 
+- /**
+---- a/drivers/net/wireless/brcm80211/brcmfmac/p2p.c
+-+++ b/drivers/net/wireless/brcm80211/brcmfmac/p2p.c
+-@@ -2140,7 +2140,7 @@ static void brcmf_p2p_delete_p2pdev(stru
+- {
+- 	cfg80211_unregister_wdev(&vif->wdev);
+- 	p2p->bss_idx[P2PAPI_BSSCFG_DEVICE].vif = NULL;
+--	brcmf_remove_interface(vif->ifp->drvr, vif->ifp->bssidx);
+-+	brcmf_remove_interface(vif->ifp);
+- 	brcmf_free_vif(vif);
+- }
+- 
+diff --git a/package/kernel/mac80211/patches/394-0004-brcmfmac-only-call-brcmf_cfg80211_detach-when-attach.patch b/package/kernel/mac80211/patches/394-0004-brcmfmac-only-call-brcmf_cfg80211_detach-when-attach.patch
+deleted file mode 100644
+index 2b61f4e..0000000
+--- a/package/kernel/mac80211/patches/394-0004-brcmfmac-only-call-brcmf_cfg80211_detach-when-attach.patch
++++ /dev/null
+@@ -1,92 +0,0 @@
+-From: Arend van Spriel <arend@broadcom.com>
+-Date: Wed, 26 Aug 2015 22:14:56 +0200
+-Subject: [PATCH] brcmfmac: only call brcmf_cfg80211_detach() when attach
+- was successful
+-
+-In brcmf_bus_start() the function brcmf_cfg80211_attach() is called which
+-may fail. If this happens we should not call brcmf_cfg80211_detach() in
+-the failure path as it will result in NULL pointer dereference:
+-
+-  brcmf_fweh_activate_events: Set event_msgs error (-5)
+-  brcmf_bus_start: failed: -5
+-  brcmf_sdio_firmware_callback: dongle is not responding
+-  BUG: unable to handle kernel NULL pointer dereference at 0000000000000068
+-  IP: [<ffffffff811e8f08>] kernfs_find_ns+0x18/0xd0
+-  PGD 0
+-  Oops: 0000 [#1] SMP
+-  Modules linked in: brcmfmac(O) brcmutil(O) cfg80211 auth_rpcgss
+-  CPU: 1 PID: 45 Comm: kworker/1:1 Tainted: G           O
+-  Hardware name: Dell Inc. Latitude E6410/07XJP9, BIOS A07 02/15/2011
+-  Workqueue: events request_firmware_work_func
+-  task: ffff880036c09ac0 ti: ffff880036dd4000 task.ti: ffff880036dd4000
+-  RIP: 0010:[<ffffffff811e8f08>]  [<ffffffff811e8f08>] kernfs_find_ns+0x18/0xd0
+-  RSP: 0018:ffff880036dd7a28  EFLAGS: 00010246
+-  RAX: ffff880036c09ac0 RBX: 0000000000000000 RCX: 000000007fffffff
+-  RDX: 0000000000000000 RSI: ffffffff816578b9 RDI: 0000000000000000
+-  RBP: ffff880036dd7a48 R08: 0000000000000000 R09: ffff880036c0b340
+-  R10: 00000000000002ec R11: ffff880036dd7b08 R12: ffffffff816578b9
+-  R13: 0000000000000000 R14: ffffffff816578b9 R15: ffff8800c6c87000
+-  FS:  0000000000000000(0000) GS:ffff88012bc40000(0000) knlGS:0000000000000000
+-  CS:  0010 DS: 0000 ES: 0000 CR0: 000000008005003b
+-  CR2: 0000000000000068 CR3: 0000000001a0b000 CR4: 00000000000006e0
+-  Stack:
+-   0000000000000000 ffffffff816578b9 0000000000000000 ffff8800c0d003c8
+-   ffff880036dd7a78 ffffffff811e8ff5 0000000ffffffff1 ffffffff81a9b060
+-   ffff8800c789f880 ffff8800c0d00000 ffff880036dd7a98 ffffffff811ebe0d
+-  Call Trace:
+-   [<ffffffff811e8ff5>] kernfs_find_and_get_ns+0x35/0x60
+-   [<ffffffff811ebe0d>] sysfs_unmerge_group+0x1d/0x60
+-   [<ffffffff81404ef2>] dpm_sysfs_remove+0x22/0x60
+-   [<ffffffff813f9db9>] device_del+0x49/0x240
+-   [<ffffffff815da768>] rfkill_unregister+0x58/0xc0
+-   [<ffffffffa06bd91b>] wiphy_unregister+0xab/0x2f0 [cfg80211]
+-   [<ffffffffa0742fe3>] brcmf_cfg80211_detach+0x23/0x50 [brcmfmac]
+-   [<ffffffffa074d986>] brcmf_detach+0x86/0xe0 [brcmfmac]
+-   [<ffffffffa0757de8>] brcmf_sdio_remove+0x48/0x120 [brcmfmac]
+-   [<ffffffffa0758ed9>] brcmf_sdiod_remove+0x29/0xd0 [brcmfmac]
+-   [<ffffffffa0759031>] brcmf_ops_sdio_remove+0xb1/0x110 [brcmfmac]
+-   [<ffffffffa001c267>] sdio_bus_remove+0x37/0x100 [mmc_core]
+-   [<ffffffff813fe026>] __device_release_driver+0x96/0x130
+-   [<ffffffff813fe0e3>] device_release_driver+0x23/0x30
+-   [<ffffffffa0754bc8>] brcmf_sdio_firmware_callback+0x2a8/0x5d0 [brcmfmac]
+-   [<ffffffffa074deaf>] brcmf_fw_request_nvram_done+0x15f/0x5e0 [brcmfmac]
+-   [<ffffffff8140142f>] ? devres_add+0x3f/0x50
+-   [<ffffffff810642b5>] ? usermodehelper_read_unlock+0x15/0x20
+-   [<ffffffff81400000>] ? platform_match+0x70/0xa0
+-   [<ffffffff8140f400>] request_firmware_work_func+0x30/0x60
+-   [<ffffffff8106828c>] process_one_work+0x14c/0x3d0
+-   [<ffffffff8106862a>] worker_thread+0x11a/0x450
+-   [<ffffffff81068510>] ? process_one_work+0x3d0/0x3d0
+-   [<ffffffff8106d692>] kthread+0xd2/0xf0
+-   [<ffffffff8106d5c0>] ? kthread_create_on_node+0x180/0x180
+-   [<ffffffff815ed35f>] ret_from_fork+0x3f/0x70
+-   [<ffffffff8106d5c0>] ? kthread_create_on_node+0x180/0x180
+-  Code: e9 40 fe ff ff 48 89 d8 eb 87 66 0f 1f 84 00 00 00 00 00 66 66 66 66
+-	90 55 48 89 e5 41 56 49 89 f6 41 55 49 89 d5 31 d2 41 54 53 <0f> b7
+-	47 68 48 8b 5f 48 66 c1 e8 05 83 e0 01 4d 85 ed 0f b6 c8
+-  RIP  [<ffffffff811e8f08>] kernfs_find_ns+0x18/0xd0
+-   RSP <ffff880036dd7a28>
+-  CR2: 0000000000000068
+-  ---[ end trace 87d6ec0d3fe46740 ]---
+-
+-Reported-by: Daniel (Deognyoun) Kim <dekim@broadcom.com>
+-Reviewed-by: Hante Meuleman <meuleman@broadcom.com>
+-Reviewed-by: Franky (Zhenhui) Lin <frankyl@broadcom.com>
+-Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
+-Signed-off-by: Arend van Spriel <arend@broadcom.com>
+----
+-
+---- a/drivers/net/wireless/brcm80211/brcmfmac/core.c
+-+++ b/drivers/net/wireless/brcm80211/brcmfmac/core.c
+-@@ -1049,7 +1049,10 @@ int brcmf_bus_start(struct device *dev)
+- fail:
+- 	if (ret < 0) {
+- 		brcmf_err("failed: %d\n", ret);
+--		brcmf_cfg80211_detach(drvr->config);
+-+		if (drvr->config) {
+-+			brcmf_cfg80211_detach(drvr->config);
+-+			drvr->config = NULL;
+-+		}
+- 		if (drvr->fws) {
+- 			brcmf_fws_del_interface(ifp);
+- 			brcmf_fws_deinit(drvr);
+diff --git a/package/kernel/mac80211/patches/394-0005-brcmfmac-correct-detection-of-p2pdev-interface-event.patch b/package/kernel/mac80211/patches/394-0005-brcmfmac-correct-detection-of-p2pdev-interface-event.patch
+deleted file mode 100644
+index 868b0a8..0000000
+--- a/package/kernel/mac80211/patches/394-0005-brcmfmac-correct-detection-of-p2pdev-interface-event.patch
++++ /dev/null
+@@ -1,105 +0,0 @@
+-From: Arend van Spriel <arend@broadcom.com>
+-Date: Wed, 26 Aug 2015 22:14:57 +0200
+-Subject: [PATCH] brcmfmac: correct detection of p2pdev interface event
+-
+-The p2pdev interface is setup in firmware resulting in a interface
+-event. This event has role and no-if flag. When role is p2p client
+-and no-if flag is set it indicates that this is the p2pdev interface.
+-This info is used in handling the event and adding interface in the
+-driver.
+-
+-Reviewed-by: Hante Meuleman <meuleman@broadcom.com>
+-Reviewed-by: Franky (Zhenhui) Lin <frankyl@broadcom.com>
+-Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
+-Signed-off-by: Arend van Spriel <arend@broadcom.com>
+----
+-
+---- a/drivers/net/wireless/brcm80211/brcmfmac/core.c
+-+++ b/drivers/net/wireless/brcm80211/brcmfmac/core.c
+-@@ -795,7 +795,7 @@ fail:
+- }
+- 
+- struct brcmf_if *brcmf_add_if(struct brcmf_pub *drvr, s32 bssidx, s32 ifidx,
+--			      char *name, u8 *mac_addr)
+-+			      bool is_p2pdev, char *name, u8 *mac_addr)
+- {
+- 	struct brcmf_if *ifp;
+- 	struct net_device *ndev;
+-@@ -821,7 +821,7 @@ struct brcmf_if *brcmf_add_if(struct brc
+- 		}
+- 	}
+- 
+--	if (!brcmf_p2p_enable && bssidx == 1) {
+-+	if (!brcmf_p2p_enable && is_p2pdev) {
+- 		/* this is P2P_DEVICE interface */
+- 		brcmf_dbg(INFO, "allocate non-netdev interface\n");
+- 		ifp = kzalloc(sizeof(*ifp), GFP_KERNEL);
+-@@ -999,12 +999,12 @@ int brcmf_bus_start(struct device *dev)
+- 	brcmf_dbg(TRACE, "\n");
+- 
+- 	/* add primary networking interface */
+--	ifp = brcmf_add_if(drvr, 0, 0, "wlan%d", NULL);
+-+	ifp = brcmf_add_if(drvr, 0, 0, false, "wlan%d", NULL);
+- 	if (IS_ERR(ifp))
+- 		return PTR_ERR(ifp);
+- 
+- 	if (brcmf_p2p_enable)
+--		p2p_ifp = brcmf_add_if(drvr, 1, 0, "p2p%d", NULL);
+-+		p2p_ifp = brcmf_add_if(drvr, 1, 0, false, "p2p%d", NULL);
+- 	else
+- 		p2p_ifp = NULL;
+- 	if (IS_ERR(p2p_ifp))
+---- a/drivers/net/wireless/brcm80211/brcmfmac/core.h
+-+++ b/drivers/net/wireless/brcm80211/brcmfmac/core.h
+-@@ -205,7 +205,7 @@ char *brcmf_ifname(struct brcmf_pub *drv
+- 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 bssidx, s32 ifidx,
+--			      char *name, u8 *mac_addr);
+-+			      bool is_p2pdev, char *name, u8 *mac_addr);
+- void brcmf_remove_interface(struct brcmf_if *ifp);
+- int brcmf_get_next_free_bsscfgidx(struct brcmf_pub *drvr);
+- void brcmf_txflowblock_if(struct brcmf_if *ifp,
+---- a/drivers/net/wireless/brcm80211/brcmfmac/fweh.c
+-+++ b/drivers/net/wireless/brcm80211/brcmfmac/fweh.c
+-@@ -179,6 +179,7 @@ static void brcmf_fweh_handle_if_event(s
+- {
+- 	struct brcmf_if_event *ifevent = data;
+- 	struct brcmf_if *ifp;
+-+	bool is_p2pdev;
+- 	int err = 0;
+- 
+- 	brcmf_dbg(EVENT, "action: %u idx: %u bsscfg: %u flags: %u role: %u\n",
+-@@ -186,18 +187,16 @@ static void brcmf_fweh_handle_if_event(s
+- 		  ifevent->flags, ifevent->role);
+- 
+- 	/* The P2P Device interface event must not be ignored
+--	 * contrary to what firmware tells us. The only way to
+--	 * distinguish the P2P Device is by looking at the ifidx
+--	 * and bssidx received.
+-+	 * contrary to what firmware tells us.
+- 	 */
+--	if (!(ifevent->ifidx == 0 && ifevent->bssidx == 1) &&
+--	    (ifevent->flags & BRCMF_E_IF_FLAG_NOIF)) {
+-+	is_p2pdev = (ifevent->flags & BRCMF_E_IF_FLAG_NOIF) &&
+-+		    ifevent->role == BRCMF_E_IF_ROLE_P2P_CLIENT;
+-+	if (!is_p2pdev && (ifevent->flags & BRCMF_E_IF_FLAG_NOIF)) {
+- 		brcmf_dbg(EVENT, "event can be ignored\n");
+- 		return;
+- 	}
+- 	if (ifevent->ifidx >= BRCMF_MAX_IFS) {
+--		brcmf_err("invalid interface index: %u\n",
+--			  ifevent->ifidx);
+-+		brcmf_err("invalid interface index: %u\n", ifevent->ifidx);
+- 		return;
+- 	}
+- 
+-@@ -207,7 +206,7 @@ static void brcmf_fweh_handle_if_event(s
+- 		brcmf_dbg(EVENT, "adding %s (%pM)\n", emsg->ifname,
+- 			  emsg->addr);
+- 		ifp = brcmf_add_if(drvr, ifevent->bssidx, ifevent->ifidx,
+--				   emsg->ifname, emsg->addr);
+-+				   is_p2pdev, emsg->ifname, emsg->addr);
+- 		if (IS_ERR(ifp))
+- 			return;
+- 		brcmf_fws_add_interface(ifp);
+diff --git a/package/kernel/mac80211/patches/394-0006-brcmfmac-use-brcmf_get_ifp-to-map-ifidx-to-struct-br.patch b/package/kernel/mac80211/patches/394-0006-brcmfmac-use-brcmf_get_ifp-to-map-ifidx-to-struct-br.patch
+deleted file mode 100644
+index aebbfa6..0000000
+--- a/package/kernel/mac80211/patches/394-0006-brcmfmac-use-brcmf_get_ifp-to-map-ifidx-to-struct-br.patch
++++ /dev/null
+@@ -1,126 +0,0 @@
+-From: Arend van Spriel <arend@broadcom.com>
+-Date: Wed, 26 Aug 2015 22:14:58 +0200
+-Subject: [PATCH] brcmfmac: use brcmf_get_ifp() to map ifidx to struct
+- brcmf_if instance
+-
+-The knowledge on how to map the interface index to a struct brcmf_if
+-instance is in brcmf_get_ifp() so use that function when only the
+-interface index is known instead of accessing brcmf_pub::iflist
+-directly.
+-
+-Reviewed-by: Hante Meuleman <meuleman@broadcom.com>
+-Reviewed-by: Franky (Zhenhui) Lin <frankyl@broadcom.com>
+-Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
+-Signed-off-by: Arend van Spriel <arend@broadcom.com>
+----
+-
+---- a/drivers/net/wireless/brcm80211/brcmfmac/btcoex.c
+-+++ b/drivers/net/wireless/brcm80211/brcmfmac/btcoex.c
+-@@ -149,7 +149,7 @@ static s32 brcmf_btcoex_params_read(stru
+- static void brcmf_btcoex_boost_wifi(struct brcmf_btcoex_info *btci,
+- 				    bool trump_sco)
+- {
+--	struct brcmf_if *ifp = btci->cfg->pub->iflist[0];
+-+	struct brcmf_if *ifp = brcmf_get_ifp(btci->cfg->pub, 0);
+- 
+- 	if (trump_sco && !btci->saved_regs_part2) {
+- 		/* this should reduce eSCO agressive
+-@@ -468,7 +468,7 @@ int brcmf_btcoex_set_mode(struct brcmf_c
+- {
+- 	struct brcmf_cfg80211_info *cfg = wiphy_priv(vif->wdev.wiphy);
+- 	struct brcmf_btcoex_info *btci = cfg->btcoex;
+--	struct brcmf_if *ifp = cfg->pub->iflist[0];
+-+	struct brcmf_if *ifp = brcmf_get_ifp(cfg->pub, 0);
+- 
+- 	switch (mode) {
+- 	case BRCMF_BTCOEX_DISABLED:
+---- a/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c
+-+++ b/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c
+-@@ -6212,7 +6212,7 @@ static void brcmf_free_wiphy(struct wiph
+- struct brcmf_cfg80211_info *brcmf_cfg80211_attach(struct brcmf_pub *drvr,
+- 						  struct device *busdev)
+- {
+--	struct net_device *ndev = drvr->iflist[0]->ndev;
+-+	struct net_device *ndev = brcmf_get_ifp(drvr, 0)->ndev;
+- 	struct brcmf_cfg80211_info *cfg;
+- 	struct wiphy *wiphy;
+- 	struct brcmf_cfg80211_vif *vif;
+---- a/drivers/net/wireless/brcm80211/brcmfmac/feature.c
+-+++ b/drivers/net/wireless/brcm80211/brcmfmac/feature.c
+-@@ -121,7 +121,7 @@ static void brcmf_feat_iovar_int_set(str
+- 
+- void brcmf_feat_attach(struct brcmf_pub *drvr)
+- {
+--	struct brcmf_if *ifp = drvr->iflist[0];
+-+	struct brcmf_if *ifp = brcmf_get_ifp(drvr, 0);
+- 
+- 	brcmf_feat_iovar_int_get(ifp, BRCMF_FEAT_MCHAN, "mchan");
+- 	brcmf_feat_iovar_int_get(ifp, BRCMF_FEAT_PNO, "pfn");
+---- a/drivers/net/wireless/brcm80211/brcmfmac/flowring.c
+-+++ b/drivers/net/wireless/brcm80211/brcmfmac/flowring.c
+-@@ -221,7 +221,7 @@ static void brcmf_flowring_block(struct
+- 
+- 	bus_if = dev_get_drvdata(flow->dev);
+- 	drvr = bus_if->drvr;
+--	ifp = drvr->iflist[ifidx];
+-+	ifp = brcmf_get_ifp(drvr, ifidx);
+- 	brcmf_txflowblock_if(ifp, BRCMF_NETIF_STOP_REASON_FLOW, blocked);
+- 
+- 	spin_unlock_irqrestore(&flow->block_lock, flags);
+---- a/drivers/net/wireless/brcm80211/brcmfmac/fweh.c
+-+++ b/drivers/net/wireless/brcm80211/brcmfmac/fweh.c
+-@@ -334,7 +334,7 @@ void brcmf_fweh_attach(struct brcmf_pub
+- void brcmf_fweh_detach(struct brcmf_pub *drvr)
+- {
+- 	struct brcmf_fweh_info *fweh = &drvr->fweh;
+--	struct brcmf_if *ifp = drvr->iflist[0];
+-+	struct brcmf_if *ifp = brcmf_get_ifp(drvr, 0);
+- 	s8 eventmask[BRCMF_EVENTING_MASK_LEN];
+- 
+- 	if (ifp) {
+---- a/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c
+-+++ b/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c
+-@@ -972,7 +972,7 @@ static void
+- brcmf_fws_flow_control_check(struct brcmf_fws_info *fws, struct pktq *pq,
+- 			     u8 if_id)
+- {
+--	struct brcmf_if *ifp = fws->drvr->iflist[!if_id ? 0 : if_id + 1];
+-+	struct brcmf_if *ifp = brcmf_get_ifp(fws->drvr, if_id);
+- 
+- 	if (WARN_ON(!ifp))
+- 		return;
+-@@ -2118,6 +2118,7 @@ static int brcmf_debugfs_fws_stats_read(
+- int brcmf_fws_init(struct brcmf_pub *drvr)
+- {
+- 	struct brcmf_fws_info *fws;
+-+	struct brcmf_if *ifp;
+- 	u32 tlv = BRCMF_FWS_FLAGS_RSSI_SIGNALS;
+- 	int rc;
+- 	u32 mode;
+-@@ -2177,21 +2178,22 @@ int brcmf_fws_init(struct brcmf_pub *drv
+- 	 * continue. Set mode back to none indicating not enabled.
+- 	 */
+- 	fws->fw_signals = true;
+--	if (brcmf_fil_iovar_int_set(drvr->iflist[0], "tlv", tlv)) {
+-+	ifp = brcmf_get_ifp(drvr, 0);
+-+	if (brcmf_fil_iovar_int_set(ifp, "tlv", tlv)) {
+- 		brcmf_err("failed to set bdcv2 tlv signaling\n");
+- 		fws->fcmode = BRCMF_FWS_FCMODE_NONE;
+- 		fws->fw_signals = false;
+- 	}
+- 
+--	if (brcmf_fil_iovar_int_set(drvr->iflist[0], "ampdu_hostreorder", 1))
+-+	if (brcmf_fil_iovar_int_set(ifp, "ampdu_hostreorder", 1))
+- 		brcmf_dbg(INFO, "enabling AMPDU host-reorder failed\n");
+- 
+- 	/* Enable seq number reuse, if supported */
+--	if (brcmf_fil_iovar_int_get(drvr->iflist[0], "wlfc_mode", &mode) == 0) {
+-+	if (brcmf_fil_iovar_int_get(ifp, "wlfc_mode", &mode) == 0) {
+- 		if (BRCMF_FWS_MODE_GET_REUSESEQ(mode)) {
+- 			mode = 0;
+- 			BRCMF_FWS_MODE_SET_REUSESEQ(mode, 1);
+--			if (brcmf_fil_iovar_int_set(drvr->iflist[0],
+-+			if (brcmf_fil_iovar_int_set(ifp,
+- 						    "wlfc_mode", mode) == 0) {
+- 				BRCMF_FWS_MODE_SET_REUSESEQ(fws->mode, 1);
+- 			}
+diff --git a/package/kernel/mac80211/patches/394-0007-brcmfmac-pass-struct-brcmf_if-instance-in-brcmf_txfi.patch b/package/kernel/mac80211/patches/394-0007-brcmfmac-pass-struct-brcmf_if-instance-in-brcmf_txfi.patch
+deleted file mode 100644
+index 23a7b6f..0000000
+--- a/package/kernel/mac80211/patches/394-0007-brcmfmac-pass-struct-brcmf_if-instance-in-brcmf_txfi.patch
++++ /dev/null
+@@ -1,122 +0,0 @@
+-From: Arend van Spriel <arend@broadcom.com>
+-Date: Wed, 26 Aug 2015 22:14:59 +0200
+-Subject: [PATCH] brcmfmac: pass struct brcmf_if instance in
+- brcmf_txfinalize()
+-
+-Most call sites of brcmf_txfinalize already have struct brcmf_if
+-instance so pass that to brcmf_txfinalize() as the function
+-needs it anyway.
+-
+-Reviewed-by: Hante Meuleman <meuleman@broadcom.com>
+-Reviewed-by: Franky (Zhenhui) Lin <frankyl@broadcom.com>
+-Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
+-Signed-off-by: Arend van Spriel <arend@broadcom.com>
+----
+-
+---- a/drivers/net/wireless/brcm80211/brcmfmac/core.c
+-+++ b/drivers/net/wireless/brcm80211/brcmfmac/core.c
+-@@ -560,17 +560,11 @@ void brcmf_rx_frame(struct device *dev,
+- 		brcmf_netif_rx(ifp, skb);
+- }
+- 
+--void brcmf_txfinalize(struct brcmf_pub *drvr, struct sk_buff *txp, u8 ifidx,
+--		      bool success)
+-+void brcmf_txfinalize(struct brcmf_if *ifp, struct sk_buff *txp, bool success)
+- {
+--	struct brcmf_if *ifp;
+- 	struct ethhdr *eh;
+- 	u16 type;
+- 
+--	ifp = drvr->iflist[ifidx];
+--	if (!ifp)
+--		goto done;
+--
+- 	eh = (struct ethhdr *)(txp->data);
+- 	type = ntohs(eh->h_proto);
+- 
+-@@ -582,7 +576,7 @@ void brcmf_txfinalize(struct brcmf_pub *
+- 
+- 	if (!success)
+- 		ifp->stats.tx_errors++;
+--done:
+-+
+- 	brcmu_pkt_buf_free_skb(txp);
+- }
+- 
+-@@ -600,7 +594,7 @@ void brcmf_txcomplete(struct device *dev
+- 		if (brcmf_proto_hdrpull(drvr, false, txp, &ifp))
+- 			brcmu_pkt_buf_free_skb(txp);
+- 		else
+--			brcmf_txfinalize(drvr, txp, ifp->ifidx, success);
+-+			brcmf_txfinalize(ifp, txp, success);
+- 	}
+- }
+- 
+---- a/drivers/net/wireless/brcm80211/brcmfmac/core.h
+-+++ b/drivers/net/wireless/brcm80211/brcmfmac/core.h
+-@@ -210,8 +210,7 @@ void brcmf_remove_interface(struct brcmf
+- int brcmf_get_next_free_bsscfgidx(struct brcmf_pub *drvr);
+- void brcmf_txflowblock_if(struct brcmf_if *ifp,
+- 			  enum brcmf_netif_stop_reason reason, bool state);
+--void brcmf_txfinalize(struct brcmf_pub *drvr, struct sk_buff *txp, u8 ifidx,
+--		      bool success);
+-+void brcmf_txfinalize(struct brcmf_if *ifp, struct sk_buff *txp, bool success);
+- void brcmf_netif_rx(struct brcmf_if *ifp, struct sk_buff *skb);
+- 
+- /* Sets dongle media info (drv_version, mac address). */
+---- a/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c
+-+++ b/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c
+-@@ -1506,7 +1506,7 @@ brcmf_fws_txs_process(struct brcmf_fws_i
+- 		ret = brcmf_fws_txstatus_suppressed(fws, fifo, skb, ifp->ifidx,
+- 						    genbit, seq);
+- 	if (remove_from_hanger || ret)
+--		brcmf_txfinalize(fws->drvr, skb, ifp->ifidx, true);
+-+		brcmf_txfinalize(ifp, skb, true);
+- 
+- 	return 0;
+- }
+-@@ -1905,7 +1905,7 @@ int brcmf_fws_process_skb(struct brcmf_i
+- 	if (fws->avoid_queueing) {
+- 		rc = brcmf_proto_txdata(drvr, ifp->ifidx, 0, skb);
+- 		if (rc < 0)
+--			brcmf_txfinalize(drvr, skb, ifp->ifidx, false);
+-+			brcmf_txfinalize(ifp, skb, false);
+- 		return rc;
+- 	}
+- 
+-@@ -1929,7 +1929,7 @@ int brcmf_fws_process_skb(struct brcmf_i
+- 		brcmf_fws_schedule_deq(fws);
+- 	} else {
+- 		brcmf_err("drop skb: no hanger slot\n");
+--		brcmf_txfinalize(drvr, skb, ifp->ifidx, false);
+-+		brcmf_txfinalize(ifp, skb, false);
+- 		rc = -ENOMEM;
+- 	}
+- 	brcmf_fws_unlock(fws);
+-@@ -2009,8 +2009,9 @@ static void brcmf_fws_dequeue_worker(str
+- 				ret = brcmf_proto_txdata(drvr, ifidx, 0, skb);
+- 				brcmf_fws_lock(fws);
+- 				if (ret < 0)
+--					brcmf_txfinalize(drvr, skb, ifidx,
+--							 false);
+-+					brcmf_txfinalize(brcmf_get_ifp(drvr,
+-+								       ifidx),
+-+							 skb, false);
+- 				if (fws->bus_flow_blocked)
+- 					break;
+- 			}
+---- a/drivers/net/wireless/brcm80211/brcmfmac/msgbuf.c
+-+++ b/drivers/net/wireless/brcm80211/brcmfmac/msgbuf.c
+-@@ -873,7 +873,11 @@ brcmf_msgbuf_process_txstatus(struct brc
+- 	commonring = msgbuf->flowrings[flowid];
+- 	atomic_dec(&commonring->outstanding_tx);
+- 
+--	brcmf_txfinalize(msgbuf->drvr, skb, tx_status->msg.ifidx, true);
+-+	/* Hante: i believe this was a bug as tx_status->msg.ifidx was used
+-+	 * in brcmf_txfinalize as index in drvr->iflist. Can you confirm/deny?
+-+	 */
+-+	brcmf_txfinalize(brcmf_get_ifp(msgbuf->drvr, tx_status->msg.ifidx),
+-+			 skb, true);
+- }
+- 
+- 
+diff --git a/package/kernel/mac80211/patches/394-0008-brcmfmac-add-mapping-for-interface-index-to-bsscfg-i.patch b/package/kernel/mac80211/patches/394-0008-brcmfmac-add-mapping-for-interface-index-to-bsscfg-i.patch
+deleted file mode 100644
+index 8ddc0a6..0000000
+--- a/package/kernel/mac80211/patches/394-0008-brcmfmac-add-mapping-for-interface-index-to-bsscfg-i.patch
++++ /dev/null
+@@ -1,92 +0,0 @@
+-From: Arend van Spriel <arend@broadcom.com>
+-Date: Wed, 26 Aug 2015 22:15:00 +0200
+-Subject: [PATCH] brcmfmac: add mapping for interface index to bsscfg
+- index
+-
+-Because the P2P Device interface in firmware uses the same interface
+-index as the primary interface we use the bsscfg index as index in the
+-struct brcmf_pub::iflist. However, in the data path we get the interface
+-index and not the bsscfg index. So we need a mapping of interface index
+-to bsscfg index, which can be determined upon handle adding the interface.
+-
+-Reviewed-by: Hante Meuleman <meuleman@broadcom.com>
+-Reviewed-by: Franky (Zhenhui) Lin <frankyl@broadcom.com>
+-Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
+-Signed-off-by: Arend van Spriel <arend@broadcom.com>
+----
+-
+---- a/drivers/net/wireless/brcm80211/brcmfmac/core.c
+-+++ b/drivers/net/wireless/brcm80211/brcmfmac/core.c
+-@@ -85,21 +85,20 @@ char *brcmf_ifname(struct brcmf_pub *drv
+- 
+- struct brcmf_if *brcmf_get_ifp(struct brcmf_pub *drvr, int ifidx)
+- {
+-+	struct brcmf_if *ifp;
+-+	s32 bssidx;
+-+
+- 	if (ifidx < 0 || ifidx >= BRCMF_MAX_IFS) {
+- 		brcmf_err("ifidx %d out of range\n", ifidx);
+- 		return NULL;
+- 	}
+- 
+--	/* The ifidx is the idx to map to matching netdev/ifp. When receiving
+--	 * events this is easy because it contains the bssidx which maps
+--	 * 1-on-1 to the netdev/ifp. But for data frames the ifidx is rcvd.
+--	 * bssidx 1 is used for p2p0 and no data can be received or
+--	 * transmitted on it. Therefor bssidx is ifidx + 1 if ifidx > 0
+--	 */
+--	if (ifidx)
+--		ifidx++;
+-+	ifp = NULL;
+-+	bssidx = drvr->if2bss[ifidx];
+-+	if (bssidx >= 0)
+-+		ifp = drvr->iflist[bssidx];
+- 
+--	return drvr->iflist[ifidx];
+-+	return ifp;
+- }
+- 
+- static void _brcmf_set_multicast_list(struct work_struct *work)
+-@@ -831,6 +830,8 @@ struct brcmf_if *brcmf_add_if(struct brc
+- 
+- 		ifp = netdev_priv(ndev);
+- 		ifp->ndev = ndev;
+-+		/* store mapping ifidx to bssidx */
+-+		drvr->if2bss[ifidx] = bssidx;
+- 	}
+- 
+- 	ifp->drvr = drvr;
+-@@ -855,6 +856,7 @@ static void brcmf_del_if(struct brcmf_pu
+- 	struct brcmf_if *ifp;
+- 
+- 	ifp = drvr->iflist[bssidx];
+-+	drvr->if2bss[ifp->ifidx] = -1;
+- 	drvr->iflist[bssidx] = NULL;
+- 	if (!ifp) {
+- 		brcmf_err("Null interface, idx=%d\n", bssidx);
+-@@ -862,6 +864,7 @@ static void brcmf_del_if(struct brcmf_pu
+- 	}
+- 	brcmf_dbg(TRACE, "Enter, idx=%d, ifidx=%d\n", bssidx, ifp->ifidx);
+- 	if (ifp->ndev) {
+-+		drvr->if2bss[ifp->ifidx] = -1;
+- 		if (bssidx == 0) {
+- 			if (ifp->ndev->netdev_ops == &brcmf_netdev_ops_pri) {
+- 				rtnl_lock();
+-@@ -926,6 +929,7 @@ int brcmf_attach(struct device *dev)
+- 	if (!drvr)
+- 		return -ENOMEM;
+- 
+-+	memset(drvr->if2bss, 0xFF, sizeof(drvr->if2bss));
+- 	mutex_init(&drvr->proto_block);
+- 
+- 	/* Link to bus module */
+---- a/drivers/net/wireless/brcm80211/brcmfmac/core.h
+-+++ b/drivers/net/wireless/brcm80211/brcmfmac/core.h
+-@@ -122,6 +122,7 @@ struct brcmf_pub {
+- 	struct mac_address addresses[BRCMF_MAX_IFS];
+- 
+- 	struct brcmf_if *iflist[BRCMF_MAX_IFS];
+-+	s32 if2bss[BRCMF_MAX_IFS];
+- 
+- 	struct mutex proto_block;
+- 	unsigned char proto_buf[BRCMF_DCMD_MAXLEN];
+diff --git a/package/kernel/mac80211/patches/394-0009-brcmfmac-add-dedicated-debug-level-for-firmware-cons.patch b/package/kernel/mac80211/patches/394-0009-brcmfmac-add-dedicated-debug-level-for-firmware-cons.patch
+deleted file mode 100644
+index a0a798b..0000000
+--- a/package/kernel/mac80211/patches/394-0009-brcmfmac-add-dedicated-debug-level-for-firmware-cons.patch
++++ /dev/null
+@@ -1,103 +0,0 @@
+-From: Arend van Spriel <arend@broadcom.com>
+-Date: Wed, 26 Aug 2015 22:15:01 +0200
+-Subject: [PATCH] brcmfmac: add dedicated debug level for firmware
+- console logging
+-
+-Both PCIe and SDIO devices have the possibility to log the firmware
+-console output in kernel log. For PCIe it is logged when PCIE debug
+-level is enabled. For SDIO it is logged when user specifies a non-zero
+-console interval through debugfs. This patch tries to make it a
+-bit more consistent. The firmware console output is only logged when
+-FWCON debug level is enabled.
+-
+-Reviewed-by: Hante Meuleman <meuleman@broadcom.com>
+-Reviewed-by: Franky (Zhenhui) Lin <frankyl@broadcom.com>
+-Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
+-Reviewed-by: Pontus Fuchs <pontusf@broadcom.com>
+-Signed-off-by: Arend van Spriel <arend@broadcom.com>
+----
+-
+---- a/drivers/net/wireless/brcm80211/brcmfmac/debug.h
+-+++ b/drivers/net/wireless/brcm80211/brcmfmac/debug.h
+-@@ -37,6 +37,7 @@
+- #define BRCMF_SDIO_VAL		0x00020000
+- #define BRCMF_MSGBUF_VAL	0x00040000
+- #define BRCMF_PCIE_VAL		0x00080000
+-+#define BRCMF_FWCON_VAL		0x00100000
+- 
+- /* set default print format */
+- #undef pr_fmt
+-@@ -78,6 +79,7 @@ do {								\
+- #define BRCMF_GLOM_ON()		(brcmf_msg_level & BRCMF_GLOM_VAL)
+- #define BRCMF_EVENT_ON()	(brcmf_msg_level & BRCMF_EVENT_VAL)
+- #define BRCMF_FIL_ON()		(brcmf_msg_level & BRCMF_FIL_VAL)
+-+#define BRCMF_FWCON_ON()	(brcmf_msg_level & BRCMF_FWCON_VAL)
+- 
+- #else /* defined(DEBUG) || defined(CPTCFG_BRCM_TRACING) */
+- 
+-@@ -90,6 +92,7 @@ do {								\
+- #define BRCMF_GLOM_ON()		0
+- #define BRCMF_EVENT_ON()	0
+- #define BRCMF_FIL_ON()		0
+-+#define BRCMF_FWCON_ON()	0
+- 
+- #endif /* defined(DEBUG) || defined(CPTCFG_BRCM_TRACING) */
+- 
+---- a/drivers/net/wireless/brcm80211/brcmfmac/pcie.c
+-+++ b/drivers/net/wireless/brcm80211/brcmfmac/pcie.c
+-@@ -644,7 +644,7 @@ static void brcmf_pcie_bus_console_init(
+- 	addr = console->base_addr + BRCMF_CONSOLE_BUFSIZE_OFFSET;
+- 	console->bufsize = brcmf_pcie_read_tcm32(devinfo, addr);
+- 
+--	brcmf_dbg(PCIE, "Console: base %x, buf %x, size %d\n",
+-+	brcmf_dbg(FWCON, "Console: base %x, buf %x, size %d\n",
+- 		  console->base_addr, console->buf_addr, console->bufsize);
+- }
+- 
+-@@ -656,6 +656,9 @@ static void brcmf_pcie_bus_console_read(
+- 	u8 ch;
+- 	u32 newidx;
+- 
+-+	if (!BRCMF_FWCON_ON())
+-+		return;
+-+
+- 	console = &devinfo->shared.console;
+- 	addr = console->base_addr + BRCMF_CONSOLE_WRITEIDX_OFFSET;
+- 	newidx = brcmf_pcie_read_tcm32(devinfo, addr);
+-@@ -677,7 +680,7 @@ static void brcmf_pcie_bus_console_read(
+- 		}
+- 		if (ch == '\n') {
+- 			console->log_str[console->log_idx] = 0;
+--			brcmf_dbg(PCIE, "CONSOLE: %s", console->log_str);
+-+			pr_debug("CONSOLE: %s", console->log_str);
+- 			console->log_idx = 0;
+- 		}
+- 	}
+---- a/drivers/net/wireless/brcm80211/brcmfmac/sdio.c
+-+++ b/drivers/net/wireless/brcm80211/brcmfmac/sdio.c
+-@@ -123,6 +123,7 @@ struct rte_console {
+- 
+- #define BRCMF_FIRSTREAD	(1 << 6)
+- 
+-+#define BRCMF_CONSOLE	10	/* watchdog interval to poll console */
+- 
+- /* SBSDIO_DEVICE_CTL */
+- 
+-@@ -3204,6 +3205,8 @@ static void brcmf_sdio_debugfs_create(st
+- 	if (IS_ERR_OR_NULL(dentry))
+- 		return;
+- 
+-+	bus->console_interval = BRCMF_CONSOLE;
+-+
+- 	brcmf_debugfs_add_entry(drvr, "forensics", brcmf_sdio_forensic_read);
+- 	brcmf_debugfs_add_entry(drvr, "counters",
+- 				brcmf_debugfs_sdio_count_read);
+-@@ -3613,7 +3616,7 @@ static void brcmf_sdio_bus_watchdog(stru
+- 	}
+- #ifdef DEBUG
+- 	/* Poll for console output periodically */
+--	if (bus->sdiodev->state == BRCMF_SDIOD_DATA &&
+-+	if (bus->sdiodev->state == BRCMF_SDIOD_DATA && BRCMF_FWCON_ON() &&
+- 	    bus->console_interval != 0) {
+- 		bus->console.count += BRCMF_WD_POLL_MS;
+- 		if (bus->console.count >= bus->console_interval) {
+diff --git a/package/kernel/mac80211/patches/394-0010-brcmfmac-remove-ifidx-parameter-from-brcmf_fws_txsta.patch b/package/kernel/mac80211/patches/394-0010-brcmfmac-remove-ifidx-parameter-from-brcmf_fws_txsta.patch
+deleted file mode 100644
+index 53e7ede..0000000
+--- a/package/kernel/mac80211/patches/394-0010-brcmfmac-remove-ifidx-parameter-from-brcmf_fws_txsta.patch
++++ /dev/null
+@@ -1,34 +0,0 @@
+-From: Arend van Spriel <arend@broadcom.com>
+-Date: Wed, 26 Aug 2015 22:15:02 +0200
+-Subject: [PATCH] brcmfmac: remove ifidx parameter from
+- brcmf_fws_txstatus_suppressed()
+-
+-The brcmf_fws_txstatus_suppressed() function prototype specifies an
+-ifidx parameter which is not used within the function implementation.
+-
+-Reviewed-by: Hante Meuleman <meuleman@broadcom.com>
+-Reviewed-by: Franky (Zhenhui) Lin <frankyl@broadcom.com>
+-Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
+-Signed-off-by: Arend van Spriel <arend@broadcom.com>
+----
+-
+---- a/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c
+-+++ b/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c
+-@@ -1398,7 +1398,7 @@ done:
+- }
+- 
+- static int brcmf_fws_txstatus_suppressed(struct brcmf_fws_info *fws, int fifo,
+--					 struct sk_buff *skb, u8 ifidx,
+-+					 struct sk_buff *skb,
+- 					 u32 genbit, u16 seq)
+- {
+- 	struct brcmf_fws_mac_descriptor *entry = brcmf_skbcb(skb)->mac;
+-@@ -1503,7 +1503,7 @@ brcmf_fws_txs_process(struct brcmf_fws_i
+- 		return -EINVAL;
+- 	}
+- 	if (!remove_from_hanger)
+--		ret = brcmf_fws_txstatus_suppressed(fws, fifo, skb, ifp->ifidx,
+-+		ret = brcmf_fws_txstatus_suppressed(fws, fifo, skb,
+- 						    genbit, seq);
+- 	if (remove_from_hanger || ret)
+- 		brcmf_txfinalize(ifp, skb, true);
+diff --git a/package/kernel/mac80211/patches/394-0011-brcmfmac-change-prototype-for-brcmf_fws_hdrpull.patch b/package/kernel/mac80211/patches/394-0011-brcmfmac-change-prototype-for-brcmf_fws_hdrpull.patch
+deleted file mode 100644
+index bb05235..0000000
+--- a/package/kernel/mac80211/patches/394-0011-brcmfmac-change-prototype-for-brcmf_fws_hdrpull.patch
++++ /dev/null
+@@ -1,97 +0,0 @@
+-From: Arend van Spriel <arend@broadcom.com>
+-Date: Wed, 26 Aug 2015 22:15:03 +0200
+-Subject: [PATCH] brcmfmac: change prototype for brcmf_fws_hdrpull()
+-
+-Instead of passing ifidx and drvr just pass struct brcmf_if pointer
+-which holds both parameters.
+-
+-Reviewed-by: Hante Meuleman <meuleman@broadcom.com>
+-Reviewed-by: Franky (Zhenhui) Lin <frankyl@broadcom.com>
+-Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
+-Signed-off-by: Arend van Spriel <arend@broadcom.com>
+----
+-
+---- a/drivers/net/wireless/brcm80211/brcmfmac/bcdc.c
+-+++ b/drivers/net/wireless/brcm80211/brcmfmac/bcdc.c
+-@@ -312,8 +312,7 @@ brcmf_proto_bcdc_hdrpull(struct brcmf_pu
+- 
+- 	skb_pull(pktbuf, BCDC_HEADER_LEN);
+- 	if (do_fws)
+--		brcmf_fws_hdrpull(drvr, tmp_if->ifidx, h->data_offset << 2,
+--				  pktbuf);
+-+		brcmf_fws_hdrpull(tmp_if, h->data_offset << 2, pktbuf);
+- 	else
+- 		skb_pull(pktbuf, h->data_offset << 2);
+- 
+---- a/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c
+-+++ b/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c
+-@@ -1616,11 +1616,10 @@ static int brcmf_fws_notify_bcmc_credit_
+- 	return 0;
+- }
+- 
+--int brcmf_fws_hdrpull(struct brcmf_pub *drvr, int ifidx, s16 signal_len,
+--		      struct sk_buff *skb)
+-+void brcmf_fws_hdrpull(struct brcmf_if *ifp, s16 siglen, struct sk_buff *skb)
+- {
+- 	struct brcmf_skb_reorder_data *rd;
+--	struct brcmf_fws_info *fws = drvr->fws;
+-+	struct brcmf_fws_info *fws = ifp->drvr->fws;
+- 	u8 *signal_data;
+- 	s16 data_len;
+- 	u8 type;
+-@@ -1630,20 +1629,20 @@ int brcmf_fws_hdrpull(struct brcmf_pub *
+- 	s32 err;
+- 
+- 	brcmf_dbg(HDRS, "enter: ifidx %d, skblen %u, sig %d\n",
+--		  ifidx, skb->len, signal_len);
+-+		  ifp->ifidx, skb->len, siglen);
+- 
+--	WARN_ON(signal_len > skb->len);
+-+	WARN_ON(siglen > skb->len);
+- 
+--	if (!signal_len)
+--		return 0;
+-+	if (!siglen)
+-+		return;
+- 	/* if flow control disabled, skip to packet data and leave */
+- 	if ((!fws) || (!fws->fw_signals)) {
+--		skb_pull(skb, signal_len);
+--		return 0;
+-+		skb_pull(skb, siglen);
+-+		return;
+- 	}
+- 
+- 	fws->stats.header_pulls++;
+--	data_len = signal_len;
+-+	data_len = siglen;
+- 	signal_data = skb->data;
+- 
+- 	status = BRCMF_FWS_RET_OK_NOSCHEDULE;
+-@@ -1731,14 +1730,12 @@ int brcmf_fws_hdrpull(struct brcmf_pub *
+- 	/* signalling processing result does
+- 	 * not affect the actual ethernet packet.
+- 	 */
+--	skb_pull(skb, signal_len);
+-+	skb_pull(skb, siglen);
+- 
+- 	/* this may be a signal-only packet
+- 	 */
+- 	if (skb->len == 0)
+- 		fws->stats.header_only_pkt++;
+--
+--	return 0;
+- }
+- 
+- static u8 brcmf_fws_precommit_skb(struct brcmf_fws_info *fws, int fifo,
+---- a/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.h
+-+++ b/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.h
+-@@ -21,8 +21,7 @@
+- int brcmf_fws_init(struct brcmf_pub *drvr);
+- void brcmf_fws_deinit(struct brcmf_pub *drvr);
+- bool brcmf_fws_fc_active(struct brcmf_fws_info *fws);
+--int brcmf_fws_hdrpull(struct brcmf_pub *drvr, int ifidx, s16 signal_len,
+--		      struct sk_buff *skb);
+-+void brcmf_fws_hdrpull(struct brcmf_if *ifp, s16 siglen, struct sk_buff *skb);
+- int brcmf_fws_process_skb(struct brcmf_if *ifp, struct sk_buff *skb);
+- 
+- void brcmf_fws_reset_interface(struct brcmf_if *ifp);
+diff --git a/package/kernel/mac80211/patches/394-0012-brcmfmac-introduce-brcmf_net_detach-function.patch b/package/kernel/mac80211/patches/394-0012-brcmfmac-introduce-brcmf_net_detach-function.patch
+deleted file mode 100644
+index ba92c67..0000000
+--- a/package/kernel/mac80211/patches/394-0012-brcmfmac-introduce-brcmf_net_detach-function.patch
++++ /dev/null
+@@ -1,99 +0,0 @@
+-From: Arend van Spriel <arend@broadcom.com>
+-Date: Wed, 26 Aug 2015 22:15:04 +0200
+-Subject: [PATCH] brcmfmac: introduce brcmf_net_detach() function
+-
+-In case of error during brcmf_bus_start() the network interfaces were
+-freed using free_netdev(). However, the interfaces may have additional
+-memory allocated which is not freed. The netdev has destructor set to
+-brcmf_cfg80211_free_netdev() which frees the additional memory if
+-allocated and call free_netdev(). The brcmf_net_detach() either calls
+-brcmf_cfg80211_free_netdev() directly or uses unregister_netdev() when
+-struct net_device::reg_state indicates the netdev was registered.
+-
+-Reported-by: Daniel (Deognyoun) Kim <dekim@broadcom.com>
+-Reviewed-by: Hante Meuleman <meuleman@broadcom.com>
+-Reviewed-by: Franky (Zhenhui) Lin <frankyl@broadcom.com>
+-Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
+-Signed-off-by: Arend van Spriel <arend@broadcom.com>
+----
+-
+---- a/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c
+-+++ b/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c
+-@@ -4746,7 +4746,8 @@ void brcmf_cfg80211_free_netdev(struct n
+- 	ifp = netdev_priv(ndev);
+- 	vif = ifp->vif;
+- 
+--	brcmf_free_vif(vif);
+-+	if (vif)
+-+		brcmf_free_vif(vif);
+- 	free_netdev(ndev);
+- }
+- 
+---- a/drivers/net/wireless/brcm80211/brcmfmac/core.c
+-+++ b/drivers/net/wireless/brcm80211/brcmfmac/core.c
+-@@ -718,8 +718,6 @@ int brcmf_net_attach(struct brcmf_if *if
+- 	}
+- 
+- 	brcmf_dbg(INFO, "%s: Broadcom Dongle Host Driver\n", ndev->name);
+--
+--	ndev->destructor = brcmf_cfg80211_free_netdev;
+- 	return 0;
+- 
+- fail:
+-@@ -729,6 +727,14 @@ fail:
+- 	return -EBADE;
+- }
+- 
+-+static void brcmf_net_detach(struct net_device *ndev)
+-+{
+-+	if (ndev->reg_state == NETREG_REGISTERED)
+-+		unregister_netdev(ndev);
+-+	else
+-+		brcmf_cfg80211_free_netdev(ndev);
+-+}
+-+
+- static int brcmf_net_p2p_open(struct net_device *ndev)
+- {
+- 	brcmf_dbg(TRACE, "Enter\n");
+-@@ -805,8 +811,7 @@ struct brcmf_if *brcmf_add_if(struct brc
+- 			  ifp->ndev->name);
+- 		if (ifidx) {
+- 			netif_stop_queue(ifp->ndev);
+--			unregister_netdev(ifp->ndev);
+--			free_netdev(ifp->ndev);
+-+			brcmf_net_detach(ifp->ndev);
+- 			drvr->iflist[bssidx] = NULL;
+- 		} else {
+- 			brcmf_err("ignore IF event\n");
+-@@ -828,6 +833,7 @@ struct brcmf_if *brcmf_add_if(struct brc
+- 		if (!ndev)
+- 			return ERR_PTR(-ENOMEM);
+- 
+-+		ndev->destructor = brcmf_cfg80211_free_netdev;
+- 		ifp = netdev_priv(ndev);
+- 		ifp->ndev = ndev;
+- 		/* store mapping ifidx to bssidx */
+-@@ -879,8 +885,7 @@ static void brcmf_del_if(struct brcmf_pu
+- 			cancel_work_sync(&ifp->setmacaddr_work);
+- 			cancel_work_sync(&ifp->multicast_work);
+- 		}
+--		/* unregister will take care of freeing it */
+--		unregister_netdev(ifp->ndev);
+-+		brcmf_net_detach(ifp->ndev);
+- 	}
+- }
+- 
+-@@ -1056,11 +1061,11 @@ fail:
+- 			brcmf_fws_deinit(drvr);
+- 		}
+- 		if (drvr->iflist[0]) {
+--			free_netdev(ifp->ndev);
+-+			brcmf_net_detach(ifp->ndev);
+- 			drvr->iflist[0] = NULL;
+- 		}
+- 		if (p2p_ifp) {
+--			free_netdev(p2p_ifp->ndev);
+-+			brcmf_net_detach(p2p_ifp->ndev);
+- 			drvr->iflist[1] = NULL;
+- 		}
+- 		return ret;
+diff --git a/package/kernel/mac80211/patches/395-brcmfmac-Reset-PCIE-devices-after-recognition.patch b/package/kernel/mac80211/patches/395-brcmfmac-Reset-PCIE-devices-after-recognition.patch
+deleted file mode 100644
+index 5a7e447..0000000
+--- a/package/kernel/mac80211/patches/395-brcmfmac-Reset-PCIE-devices-after-recognition.patch
++++ /dev/null
+@@ -1,193 +0,0 @@
+-From: Hante Meuleman <meuleman@broadcom.com>
+-Date: Thu, 27 Aug 2015 16:14:06 +0200
+-Subject: [PATCH] brcmfmac: Reset PCIE devices after recognition.
+-
+-When PCIE type devices are being FW reloaded without being properly
+-reset then the device ends up in a locked state, requiring the
+-device to be completely powered down. This patch adds a reset
+-through watchdog at the moment the device (cores) has been
+-recognized. This will solve warm reboot issues.
+-
+-Cc: Rafal Milecki <zajec5@gmail.com>
+-Reviewed-by: Arend Van Spriel <arend@broadcom.com>
+-Reviewed-by: Franky (Zhenhui) Lin <frankyl@broadcom.com>
+-Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
+-Signed-off-by: Hante Meuleman <meuleman@broadcom.com>
+-Signed-off-by: Arend van Spriel <arend@broadcom.com>
+----
+-
+---- a/drivers/net/wireless/brcm80211/brcmfmac/chip.c
+-+++ b/drivers/net/wireless/brcm80211/brcmfmac/chip.c
+-@@ -101,6 +101,9 @@
+- /* ARM Cortex M3 core, ID 0x82a */
+- #define BCM4329_CORE_ARM_BASE		0x18002000
+- 
+-+/* Max possibly supported memory size (limited by IO mapped memory) */
+-+#define BRCMF_CHIP_MAX_MEMSIZE		(4 * 1024 * 1024)
+-+
+- #define CORE_SB(base, field) \
+- 		(base + SBCONFIGOFF + offsetof(struct sbconfig, field))
+- #define	SBCOREREV(sbidh) \
+-@@ -687,6 +690,12 @@ static int brcmf_chip_get_raminfo(struct
+- 		brcmf_err("RAM size is undetermined\n");
+- 		return -ENOMEM;
+- 	}
+-+
+-+	if (ci->pub.ramsize > BRCMF_CHIP_MAX_MEMSIZE) {
+-+		brcmf_err("RAM size is incorrect\n");
+-+		return -ENOMEM;
+-+	}
+-+
+- 	return 0;
+- }
+- 
+-@@ -899,6 +908,15 @@ static int brcmf_chip_recognition(struct
+- 
+- 	/* assure chip is passive for core access */
+- 	brcmf_chip_set_passive(&ci->pub);
+-+
+-+	/* Call bus specific reset function now. Cores have been determined
+-+	 * but further access may require a chip specific reset at this point.
+-+	 */
+-+	if (ci->ops->reset) {
+-+		ci->ops->reset(ci->ctx, &ci->pub);
+-+		brcmf_chip_set_passive(&ci->pub);
+-+	}
+-+
+- 	return brcmf_chip_get_raminfo(ci);
+- }
+- 
+---- a/drivers/net/wireless/brcm80211/brcmfmac/chip.h
+-+++ b/drivers/net/wireless/brcm80211/brcmfmac/chip.h
+-@@ -73,6 +73,7 @@ struct brcmf_buscore_ops {
+- 	u32 (*read32)(void *ctx, u32 addr);
+- 	void (*write32)(void *ctx, u32 addr, u32 value);
+- 	int (*prepare)(void *ctx);
+-+	int (*reset)(void *ctx, struct brcmf_chip *chip);
+- 	int (*setup)(void *ctx, struct brcmf_chip *chip);
+- 	void (*activate)(void *ctx, struct brcmf_chip *chip, u32 rstvec);
+- };
+---- a/drivers/net/wireless/brcm80211/brcmfmac/pcie.c
+-+++ b/drivers/net/wireless/brcm80211/brcmfmac/pcie.c
+-@@ -74,6 +74,8 @@ enum brcmf_pcie_state {
+- #define BRCMF_PCIE_REG_INTMASK			0x94
+- #define BRCMF_PCIE_REG_SBMBX			0x98
+- 
+-+#define BRCMF_PCIE_REG_LINK_STATUS_CTRL		0xBC
+-+
+- #define BRCMF_PCIE_PCIE2REG_INTMASK		0x24
+- #define BRCMF_PCIE_PCIE2REG_MAILBOXINT		0x48
+- #define BRCMF_PCIE_PCIE2REG_MAILBOXMASK		0x4C
+-@@ -466,6 +468,7 @@ brcmf_pcie_select_core(struct brcmf_pcie
+- 
+- static void brcmf_pcie_reset_device(struct brcmf_pciedev_info *devinfo)
+- {
+-+	struct brcmf_core *core;
+- 	u16 cfg_offset[] = { BRCMF_PCIE_CFGREG_STATUS_CMD,
+- 			     BRCMF_PCIE_CFGREG_PM_CSR,
+- 			     BRCMF_PCIE_CFGREG_MSI_CAP,
+-@@ -484,32 +487,38 @@ static void brcmf_pcie_reset_device(stru
+- 	if (!devinfo->ci)
+- 		return;
+- 
+-+	/* Disable ASPM */
+- 	brcmf_pcie_select_core(devinfo, BCMA_CORE_PCIE2);
+--	brcmf_pcie_write_reg32(devinfo, BRCMF_PCIE_PCIE2REG_CONFIGADDR,
+--			       BRCMF_PCIE_CFGREG_LINK_STATUS_CTRL);
+--	lsc = brcmf_pcie_read_reg32(devinfo, BRCMF_PCIE_PCIE2REG_CONFIGDATA);
+-+	pci_read_config_dword(devinfo->pdev, BRCMF_PCIE_REG_LINK_STATUS_CTRL,
+-+			      &lsc);
+- 	val = lsc & (~BRCMF_PCIE_LINK_STATUS_CTRL_ASPM_ENAB);
+--	brcmf_pcie_write_reg32(devinfo, BRCMF_PCIE_PCIE2REG_CONFIGDATA, val);
+-+	pci_write_config_dword(devinfo->pdev, BRCMF_PCIE_REG_LINK_STATUS_CTRL,
+-+			       val);
+- 
+-+	/* Watchdog reset */
+- 	brcmf_pcie_select_core(devinfo, BCMA_CORE_CHIPCOMMON);
+- 	WRITECC32(devinfo, watchdog, 4);
+- 	msleep(100);
+- 
+-+	/* Restore ASPM */
+- 	brcmf_pcie_select_core(devinfo, BCMA_CORE_PCIE2);
+--	brcmf_pcie_write_reg32(devinfo, BRCMF_PCIE_PCIE2REG_CONFIGADDR,
+--			       BRCMF_PCIE_CFGREG_LINK_STATUS_CTRL);
+--	brcmf_pcie_write_reg32(devinfo, BRCMF_PCIE_PCIE2REG_CONFIGDATA, lsc);
+-+	pci_write_config_dword(devinfo->pdev, BRCMF_PCIE_REG_LINK_STATUS_CTRL,
+-+			       lsc);
+- 
+--	brcmf_pcie_select_core(devinfo, BCMA_CORE_PCIE2);
+--	for (i = 0; i < ARRAY_SIZE(cfg_offset); i++) {
+--		brcmf_pcie_write_reg32(devinfo, BRCMF_PCIE_PCIE2REG_CONFIGADDR,
+--				       cfg_offset[i]);
+--		val = brcmf_pcie_read_reg32(devinfo,
+--					    BRCMF_PCIE_PCIE2REG_CONFIGDATA);
+--		brcmf_dbg(PCIE, "config offset 0x%04x, value 0x%04x\n",
+--			  cfg_offset[i], val);
+--		brcmf_pcie_write_reg32(devinfo, BRCMF_PCIE_PCIE2REG_CONFIGDATA,
+--				       val);
+-+	core = brcmf_chip_get_core(devinfo->ci, BCMA_CORE_PCIE2);
+-+	if (core->rev <= 13) {
+-+		for (i = 0; i < ARRAY_SIZE(cfg_offset); i++) {
+-+			brcmf_pcie_write_reg32(devinfo,
+-+					       BRCMF_PCIE_PCIE2REG_CONFIGADDR,
+-+					       cfg_offset[i]);
+-+			val = brcmf_pcie_read_reg32(devinfo,
+-+				BRCMF_PCIE_PCIE2REG_CONFIGDATA);
+-+			brcmf_dbg(PCIE, "config offset 0x%04x, value 0x%04x\n",
+-+				  cfg_offset[i], val);
+-+			brcmf_pcie_write_reg32(devinfo,
+-+					       BRCMF_PCIE_PCIE2REG_CONFIGDATA,
+-+					       val);
+-+		}
+- 	}
+- }
+- 
+-@@ -519,8 +528,6 @@ static void brcmf_pcie_attach(struct brc
+- 	u32 config;
+- 
+- 	brcmf_pcie_select_core(devinfo, BCMA_CORE_PCIE2);
+--	if (brcmf_pcie_read_reg32(devinfo, BRCMF_PCIE_PCIE2REG_INTMASK) != 0)
+--		brcmf_pcie_reset_device(devinfo);
+- 	/* BAR1 window may not be sized properly */
+- 	brcmf_pcie_select_core(devinfo, BCMA_CORE_PCIE2);
+- 	brcmf_pcie_write_reg32(devinfo, BRCMF_PCIE_PCIE2REG_CONFIGADDR, 0x4e0);
+-@@ -1636,6 +1643,23 @@ static int brcmf_pcie_buscoreprep(void *
+- }
+- 
+- 
+-+static int brcmf_pcie_buscore_reset(void *ctx, struct brcmf_chip *chip)
+-+{
+-+	struct brcmf_pciedev_info *devinfo = (struct brcmf_pciedev_info *)ctx;
+-+	u32 val;
+-+
+-+	devinfo->ci = chip;
+-+	brcmf_pcie_reset_device(devinfo);
+-+
+-+	val = brcmf_pcie_read_reg32(devinfo, BRCMF_PCIE_PCIE2REG_MAILBOXINT);
+-+	if (val != 0xffffffff)
+-+		brcmf_pcie_write_reg32(devinfo, BRCMF_PCIE_PCIE2REG_MAILBOXINT,
+-+				       val);
+-+
+-+	return 0;
+-+}
+-+
+-+
+- static void brcmf_pcie_buscore_activate(void *ctx, struct brcmf_chip *chip,
+- 					u32 rstvec)
+- {
+-@@ -1647,6 +1671,7 @@ static void brcmf_pcie_buscore_activate(
+- 
+- static const struct brcmf_buscore_ops brcmf_pcie_buscore_ops = {
+- 	.prepare = brcmf_pcie_buscoreprep,
+-+	.reset = brcmf_pcie_buscore_reset,
+- 	.activate = brcmf_pcie_buscore_activate,
+- 	.read32 = brcmf_pcie_buscore_read32,
+- 	.write32 = brcmf_pcie_buscore_write32,
+-@@ -1814,7 +1839,6 @@ brcmf_pcie_remove(struct pci_dev *pdev)
+- 		brcmf_pcie_intr_disable(devinfo);
+- 
+- 	brcmf_detach(&pdev->dev);
+--	brcmf_pcie_reset_device(devinfo);
+- 
+- 	kfree(bus->bus_priv.pcie);
+- 	kfree(bus->msgbuf->flowrings);
+diff --git a/package/kernel/mac80211/patches/396-ath10k-fix-DMA-related-firmware-crashes-on-multiple-.patch b/package/kernel/mac80211/patches/396-ath10k-fix-DMA-related-firmware-crashes-on-multiple-.patch
+deleted file mode 100644
+index f7b3e40..0000000
+--- a/package/kernel/mac80211/patches/396-ath10k-fix-DMA-related-firmware-crashes-on-multiple-.patch
++++ /dev/null
+@@ -1,24 +0,0 @@
+-From: Felix Fietkau <nbd@openwrt.org>
+-Date: Sun, 13 Sep 2015 22:26:10 +0200
+-Subject: [PATCH] ath10k: fix DMA related firmware crashes on multiple devices
+-
+-Some platforms really don't like DMA bursts of 256 bytes, and this
+-causes the firmware to crash when sending beacons.
+-Also, changing this based on the firmware version does not seem to make
+-much sense, so use 128 bytes for all versions.
+-
+-Cc: stable@vger.kernel.org
+-Signed-off-by: Felix Fietkau <nbd@openwrt.org>
+----
+-
+---- a/drivers/net/wireless/ath/ath10k/hw.h
+-+++ b/drivers/net/wireless/ath/ath10k/hw.h
+-@@ -253,7 +253,7 @@ struct ath10k_pktlog_hdr {
+- #define TARGET_10X_MAX_FRAG_ENTRIES		0
+- 
+- /* 10.2 parameters */
+--#define TARGET_10_2_DMA_BURST_SIZE		1
+-+#define TARGET_10_2_DMA_BURST_SIZE		0
+- 
+- /* Target specific defines for WMI-TLV firmware */
+- #define TARGET_TLV_NUM_VDEVS			3
+diff --git a/package/kernel/mac80211/patches/397-ath9k-declare-required-extra-tx-headroom.patch b/package/kernel/mac80211/patches/397-ath9k-declare-required-extra-tx-headroom.patch
+deleted file mode 100644
+index c420d20..0000000
+--- a/package/kernel/mac80211/patches/397-ath9k-declare-required-extra-tx-headroom.patch
++++ /dev/null
+@@ -1,22 +0,0 @@
+-From: Felix Fietkau <nbd@openwrt.org>
+-Date: Thu, 24 Sep 2015 16:57:37 +0200
+-Subject: [PATCH] ath9k: declare required extra tx headroom
+-
+-ath9k inserts padding between the 802.11 header and the data area (to
+-align it). Since it didn't declare this extra required headroom, this
+-led to some nasty issues like randomly dropped packets in some setups.
+-
+-Cc: stable@vger.kernel.org
+-Signed-off-by: Felix Fietkau <nbd@openwrt.org>
+----
+-
+---- a/drivers/net/wireless/ath/ath9k/init.c
+-+++ b/drivers/net/wireless/ath/ath9k/init.c
+-@@ -867,6 +867,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->extra_tx_headroom = 4;
+- 
+- 	hw->wiphy->available_antennas_rx = BIT(ah->caps.max_rxchains) - 1;
+- 	hw->wiphy->available_antennas_tx = BIT(ah->caps.max_txchains) - 1;
+diff --git a/package/kernel/mac80211/patches/398-mac80211-initialize-tid-field-in-struct-ieee80211_tx.patch b/package/kernel/mac80211/patches/398-mac80211-initialize-tid-field-in-struct-ieee80211_tx.patch
+deleted file mode 100644
+index 1478efa..0000000
+--- a/package/kernel/mac80211/patches/398-mac80211-initialize-tid-field-in-struct-ieee80211_tx.patch
++++ /dev/null
+@@ -1,21 +0,0 @@
+-From: Felix Fietkau <nbd@openwrt.org>
+-Date: Mon, 5 Oct 2015 17:41:25 +0200
+-Subject: [PATCH] mac80211: initialize tid field in struct ieee80211_txq
+-
+-Signed-off-by: Felix Fietkau <nbd@openwrt.org>
+----
+-
+---- a/net/mac80211/util.c
+-+++ b/net/mac80211/util.c
+-@@ -3323,9 +3323,11 @@ void ieee80211_init_tx_queue(struct ieee
+- 	if (sta) {
+- 		txqi->txq.sta = &sta->sta;
+- 		sta->sta.txq[tid] = &txqi->txq;
+-+		txqi->txq.tid = tid;
+- 		txqi->txq.ac = ieee802_1d_to_ac[tid & 7];
+- 	} else {
+- 		sdata->vif.txq = &txqi->txq;
+-+		txqi->txq.tid = 0;
+- 		txqi->txq.ac = IEEE80211_AC_BE;
+- 	}
+- }
+diff --git a/package/kernel/mac80211/patches/400-ath_move_debug_code.patch b/package/kernel/mac80211/patches/400-ath_move_debug_code.patch
+index 298f722..72e9a41 100644
+--- a/package/kernel/mac80211/patches/400-ath_move_debug_code.patch
++++ b/package/kernel/mac80211/patches/400-ath_move_debug_code.patch
+@@ -14,7 +14,7 @@
+  ccflags-y += -D__CHECK_ENDIAN__
+ --- a/drivers/net/wireless/ath/ath.h
+ +++ b/drivers/net/wireless/ath/ath.h
+-@@ -316,13 +316,6 @@ void _ath_dbg(struct ath_common *common,
++@@ -318,13 +318,6 @@ void _ath_dbg(struct ath_common *common,
+  #endif /* CPTCFG_ATH_DEBUG */
+  
+  /** Returns string describing opmode, or NULL if unknown mode. */
+diff --git a/package/kernel/mac80211/patches/402-ath_regd_optional.patch b/package/kernel/mac80211/patches/402-ath_regd_optional.patch
+index 2dac505..f918c18 100644
+--- a/package/kernel/mac80211/patches/402-ath_regd_optional.patch
++++ b/package/kernel/mac80211/patches/402-ath_regd_optional.patch
+@@ -59,7 +59,7 @@
+  	---help---
+ --- a/.local-symbols
+ +++ b/.local-symbols
+-@@ -89,6 +89,7 @@ RTL8187_LEDS=
++@@ -137,6 +137,7 @@ RTL8187_LEDS=
+  ATH_COMMON=
+  ATH_CARDS=
+  ATH_DEBUG=
+diff --git a/package/kernel/mac80211/patches/404-regd_no_assoc_hints.patch b/package/kernel/mac80211/patches/404-regd_no_assoc_hints.patch
+index 1476953..8b52ac3 100644
+--- a/package/kernel/mac80211/patches/404-regd_no_assoc_hints.patch
++++ b/package/kernel/mac80211/patches/404-regd_no_assoc_hints.patch
+@@ -1,6 +1,6 @@
+ --- a/net/wireless/reg.c
+ +++ b/net/wireless/reg.c
+-@@ -2368,6 +2368,8 @@ void regulatory_hint_country_ie(struct w
++@@ -2390,6 +2390,8 @@ void regulatory_hint_country_ie(struct w
+  	enum environment_cap env = ENVIRON_ANY;
+  	struct regulatory_request *request = NULL, *lr;
+  
+@@ -9,7 +9,7 @@
+  	/* IE len must be evenly divisible by 2 */
+  	if (country_ie_len & 0x01)
+  		return;
+-@@ -2571,6 +2573,7 @@ static void restore_regulatory_settings(
++@@ -2596,6 +2598,7 @@ static void restore_regulatory_settings(
+  
+  void regulatory_hint_disconnect(void)
+  {
+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 93760f9..1a62484 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
+-@@ -715,6 +715,7 @@ static const struct ieee80211_iface_limi
++@@ -722,6 +722,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/440-ath5k_channel_bw_debugfs.patch b/package/kernel/mac80211/patches/440-ath5k_channel_bw_debugfs.patch
+index aa521d2..42d43a4 100644
+--- a/package/kernel/mac80211/patches/440-ath5k_channel_bw_debugfs.patch
++++ b/package/kernel/mac80211/patches/440-ath5k_channel_bw_debugfs.patch
+@@ -121,7 +121,7 @@ drivers/net/wireless/ath/ath5k/debug.c |   86 ++++++++++++++++++++++++++++++++
+  	debugfs_create_file("antenna", S_IWUSR | S_IRUSR, phydir, ah,
+ --- a/drivers/net/wireless/ath/ath5k/ath5k.h
+ +++ b/drivers/net/wireless/ath/ath5k/ath5k.h
+-@@ -1371,6 +1371,7 @@ struct ath5k_hw {
++@@ -1370,6 +1370,7 @@ struct ath5k_hw {
+  	u8			ah_coverage_class;
+  	bool			ah_ack_bitrate_high;
+  	u8			ah_bwmode;
+diff --git a/package/kernel/mac80211/patches/501-ath9k_ahb_init.patch b/package/kernel/mac80211/patches/501-ath9k_ahb_init.patch
+index 5892c3e..5a3e37c 100644
+--- a/package/kernel/mac80211/patches/501-ath9k_ahb_init.patch
++++ b/package/kernel/mac80211/patches/501-ath9k_ahb_init.patch
+@@ -1,6 +1,6 @@
+ --- a/drivers/net/wireless/ath/ath9k/init.c
+ +++ b/drivers/net/wireless/ath/ath9k/init.c
+-@@ -1024,23 +1024,23 @@ static int __init ath9k_init(void)
++@@ -1032,23 +1032,23 @@ static int __init ath9k_init(void)
+  {
+  	int error;
+  
+diff --git a/package/kernel/mac80211/patches/510-ath9k_intr_mitigation_tweak.patch b/package/kernel/mac80211/patches/510-ath9k_intr_mitigation_tweak.patch
+index ed2cfee..d2a3b96 100644
+--- a/package/kernel/mac80211/patches/510-ath9k_intr_mitigation_tweak.patch
++++ b/package/kernel/mac80211/patches/510-ath9k_intr_mitigation_tweak.patch
+@@ -1,6 +1,6 @@
+ --- a/drivers/net/wireless/ath/ath9k/hw.c
+ +++ b/drivers/net/wireless/ath/ath9k/hw.c
+-@@ -389,13 +389,8 @@ static void ath9k_hw_init_config(struct
++@@ -390,13 +390,8 @@ static void ath9k_hw_init_config(struct
+  
+  	ah->config.rx_intr_mitigation = true;
+  
+@@ -14,5 +14,5 @@
+ +	ah->config.rimt_last = 250;
+ +	ah->config.rimt_first = 500;
+  
+- 	/*
+- 	 * We need this for PCI devices only (Cardbus, PCI, miniPCI)
++ 	if (AR_SREV_9462(ah) || AR_SREV_9565(ah))
++ 		ah->config.pll_pwrsave = 7;
+diff --git a/package/kernel/mac80211/patches/511-ath9k_reduce_rxbuf.patch b/package/kernel/mac80211/patches/511-ath9k_reduce_rxbuf.patch
+index d4104f0..6766111 100644
+--- a/package/kernel/mac80211/patches/511-ath9k_reduce_rxbuf.patch
++++ b/package/kernel/mac80211/patches/511-ath9k_reduce_rxbuf.patch
+@@ -1,6 +1,6 @@
+ --- a/drivers/net/wireless/ath/ath9k/ath9k.h
+ +++ b/drivers/net/wireless/ath/ath9k/ath9k.h
+-@@ -87,7 +87,7 @@ int ath_descdma_setup(struct ath_softc *
++@@ -88,7 +88,7 @@ int ath_descdma_setup(struct ath_softc *
+  		(_l) &= ((_sz) - 1);		\
+  	} while (0)
+  
+diff --git a/package/kernel/mac80211/patches/513-ath9k_add_pci_ids.patch b/package/kernel/mac80211/patches/513-ath9k_add_pci_ids.patch
+index 40b5c81..c84d1bc 100644
+--- a/package/kernel/mac80211/patches/513-ath9k_add_pci_ids.patch
++++ b/package/kernel/mac80211/patches/513-ath9k_add_pci_ids.patch
+@@ -1,6 +1,6 @@
+ --- a/drivers/net/wireless/ath/ath9k/hw.c
+ +++ b/drivers/net/wireless/ath/ath9k/hw.c
+-@@ -647,6 +647,7 @@ int ath9k_hw_init(struct ath_hw *ah)
++@@ -651,6 +651,7 @@ int ath9k_hw_init(struct ath_hw *ah)
+  
+  	/* These are all the AR5008/AR9001/AR9002/AR9003 hardware family of chipsets */
+  	switch (ah->hw_version.devid) {
+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 0c50a0b..99bf7e8 100644
+--- a/package/kernel/mac80211/patches/522-mac80211_configure_antenna_gain.patch
++++ b/package/kernel/mac80211/patches/522-mac80211_configure_antenna_gain.patch
+@@ -18,7 +18,7 @@
+  				const u8 *addr);
+ --- a/include/net/mac80211.h
+ +++ b/include/net/mac80211.h
+-@@ -1171,6 +1171,7 @@ enum ieee80211_smps_mode {
++@@ -1252,6 +1252,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
+@@ -26,7 +26,7 @@
+   *
+   * @chandef: the channel definition to tune to
+   * @radar_enabled: whether radar detection is enabled
+-@@ -1192,6 +1193,7 @@ struct ieee80211_conf {
++@@ -1273,6 +1274,7 @@ struct ieee80211_conf {
+  	u32 flags;
+  	int power_level, dynamic_ps_timeout;
+  	int max_sleep_period;
+@@ -36,7 +36,7 @@
+  	u8 ps_dtim_period;
+ --- a/include/uapi/linux/nl80211.h
+ +++ b/include/uapi/linux/nl80211.h
+-@@ -1760,6 +1760,9 @@ enum nl80211_commands {
++@@ -1761,6 +1761,9 @@ enum nl80211_commands {
+   * @NL80211_ATTR_REG_INDOOR: flag attribute, if set indicates that the device
+   *      is operating in an indoor environment.
+   *
+@@ -46,7 +46,7 @@
+   * @NUM_NL80211_ATTR: total number of nl80211_attrs available
+   * @NL80211_ATTR_MAX: highest attribute number currently defined
+   * @__NL80211_ATTR_AFTER_LAST: internal use
+-@@ -2129,6 +2132,8 @@ enum nl80211_attrs {
++@@ -2130,6 +2133,8 @@ enum nl80211_attrs {
+  
+  	NL80211_ATTR_REG_INDOOR,
+  
+@@ -57,7 +57,7 @@
+  	__NL80211_ATTR_AFTER_LAST,
+ --- a/net/mac80211/cfg.c
+ +++ b/net/mac80211/cfg.c
+-@@ -2208,6 +2208,19 @@ static int ieee80211_get_tx_power(struct
++@@ -2233,6 +2233,19 @@ static int ieee80211_get_tx_power(struct
+  	return 0;
+  }
+  
+@@ -77,7 +77,7 @@
+  static int ieee80211_set_wds_peer(struct wiphy *wiphy, struct net_device *dev,
+  				  const u8 *addr)
+  {
+-@@ -3771,6 +3784,7 @@ const struct cfg80211_ops mac80211_confi
++@@ -3845,6 +3858,7 @@ const struct cfg80211_ops mac80211_confi
+  	.set_wiphy_params = ieee80211_set_wiphy_params,
+  	.set_tx_power = ieee80211_set_tx_power,
+  	.get_tx_power = ieee80211_get_tx_power,
+@@ -87,7 +87,7 @@
+  	CFG80211_TESTMODE_CMD(ieee80211_testmode_cmd)
+ --- a/net/mac80211/ieee80211_i.h
+ +++ b/net/mac80211/ieee80211_i.h
+-@@ -1333,6 +1333,7 @@ struct ieee80211_local {
++@@ -1318,6 +1318,7 @@ struct ieee80211_local {
+  	int dynamic_ps_forced_timeout;
+  
+  	int user_power_level; /* in dBm, for all interfaces */
+@@ -97,7 +97,7 @@
+  
+ --- a/net/mac80211/main.c
+ +++ b/net/mac80211/main.c
+-@@ -98,7 +98,7 @@ static u32 ieee80211_hw_conf_chan(struct
++@@ -95,7 +95,7 @@ static u32 ieee80211_hw_conf_chan(struct
+  	struct ieee80211_sub_if_data *sdata;
+  	struct cfg80211_chan_def chandef = {};
+  	u32 changed = 0;
+@@ -106,7 +106,7 @@
+  	u32 offchannel_flag;
+  
+  	offchannel_flag = local->hw.conf.flags & IEEE80211_CONF_OFFCHANNEL;
+-@@ -155,6 +155,12 @@ static u32 ieee80211_hw_conf_chan(struct
++@@ -152,6 +152,12 @@ static u32 ieee80211_hw_conf_chan(struct
+  	}
+  	rcu_read_unlock();
+  
+@@ -119,7 +119,7 @@
+  	if (local->hw.conf.power_level != power) {
+  		changed |= IEEE80211_CONF_CHANGE_POWER;
+  		local->hw.conf.power_level = power;
+-@@ -578,6 +584,7 @@ struct ieee80211_hw *ieee80211_alloc_hw_
++@@ -581,6 +587,7 @@ struct ieee80211_hw *ieee80211_alloc_hw_
+  					 IEEE80211_RADIOTAP_MCS_HAVE_BW;
+  	local->hw.radiotap_vht_details = IEEE80211_RADIOTAP_VHT_KNOWN_GI |
+  					 IEEE80211_RADIOTAP_VHT_KNOWN_BANDWIDTH;
+@@ -129,7 +129,7 @@
+  	local->user_power_level = IEEE80211_UNSET_POWER_LEVEL;
+ --- a/net/wireless/nl80211.c
+ +++ b/net/wireless/nl80211.c
+-@@ -400,6 +400,7 @@ static const struct nla_policy nl80211_p
++@@ -402,6 +402,7 @@ static const struct nla_policy nl80211_p
+  	[NL80211_ATTR_NETNS_FD] = { .type = NLA_U32 },
+  	[NL80211_ATTR_SCHED_SCAN_DELAY] = { .type = NLA_U32 },
+  	[NL80211_ATTR_REG_INDOOR] = { .type = NLA_FLAG },
+@@ -137,7 +137,7 @@
+  };
+  
+  /* policy for the key attributes */
+-@@ -2206,6 +2207,20 @@ static int nl80211_set_wiphy(struct sk_b
++@@ -2207,6 +2208,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 7512811..3cfffa0 100644
+--- a/package/kernel/mac80211/patches/530-ath9k_extra_leds.patch
++++ b/package/kernel/mac80211/patches/530-ath9k_extra_leds.patch
+@@ -1,6 +1,6 @@
+ --- 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
++@@ -806,6 +806,9 @@ static inline int ath9k_dump_btcoex(stru
+  void ath_init_leds(struct ath_softc *sc);
+  void ath_deinit_leds(struct ath_softc *sc);
+  void ath_fill_led_pin(struct ath_softc *sc);
+@@ -10,7 +10,7 @@
+  #else
+  static inline void ath_init_leds(struct ath_softc *sc)
+  {
+-@@ -953,6 +956,13 @@ void ath_ant_comb_scan(struct ath_softc
++@@ -945,6 +948,13 @@ void ath_ant_comb_scan(struct ath_softc
+  
+  #define ATH9K_NUM_CHANCTX  2 /* supports 2 operating channels */
+  
+@@ -24,7 +24,7 @@
+  struct ath_softc {
+  	struct ieee80211_hw *hw;
+  	struct device *dev;
+-@@ -1004,9 +1014,8 @@ struct ath_softc {
++@@ -996,9 +1006,8 @@ struct ath_softc {
+  	spinlock_t chan_lock;
+  
+  #ifdef CPTCFG_MAC80211_LEDS
+@@ -165,7 +165,7 @@
+  void ath_fill_led_pin(struct ath_softc *sc)
+ --- a/drivers/net/wireless/ath/ath9k/init.c
+ +++ b/drivers/net/wireless/ath/ath9k/init.c
+-@@ -936,7 +936,7 @@ int ath9k_init_device(u16 devid, struct
++@@ -944,7 +944,7 @@ int ath9k_init_device(u16 devid, struct
+  
+  #ifdef CPTCFG_MAC80211_LEDS
+  	/* must be initialized before ieee80211_register_hw */
+diff --git a/package/kernel/mac80211/patches/542-ath9k_debugfs_diag.patch b/package/kernel/mac80211/patches/542-ath9k_debugfs_diag.patch
+index 08c5a0f..2b2c763 100644
+--- a/package/kernel/mac80211/patches/542-ath9k_debugfs_diag.patch
++++ b/package/kernel/mac80211/patches/542-ath9k_debugfs_diag.patch
+@@ -62,7 +62,7 @@
+  	debugfs_create_devm_seqfile(sc->dev, "interrupt", sc->debug.debugfs_phy,
+ --- a/drivers/net/wireless/ath/ath9k/hw.h
+ +++ b/drivers/net/wireless/ath/ath9k/hw.h
+-@@ -513,6 +513,12 @@ enum {
++@@ -519,6 +519,12 @@ enum {
+  	ATH9K_RESET_COLD,
+  };
+  
+@@ -75,7 +75,7 @@
+  struct ath9k_hw_version {
+  	u32 magic;
+  	u16 devid;
+-@@ -794,6 +800,8 @@ struct ath_hw {
++@@ -804,6 +810,8 @@ struct ath_hw {
+  	u32 rfkill_polarity;
+  	u32 ah_flags;
+  
+@@ -84,7 +84,7 @@
+  	bool reset_power_on;
+  	bool htc_reset_init;
+  
+-@@ -1055,6 +1063,7 @@ void ath9k_hw_check_nav(struct ath_hw *a
++@@ -1066,6 +1074,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);
+@@ -94,7 +94,7 @@
+  struct ath_gen_timer *ath_gen_timer_alloc(struct ath_hw *ah,
+ --- a/drivers/net/wireless/ath/ath9k/hw.c
+ +++ b/drivers/net/wireless/ath/ath9k/hw.c
+-@@ -1804,6 +1804,20 @@ u32 ath9k_hw_get_tsf_offset(struct times
++@@ -1808,6 +1808,20 @@ u32 ath9k_hw_get_tsf_offset(struct times
+  }
+  EXPORT_SYMBOL(ath9k_hw_get_tsf_offset);
+  
+@@ -115,7 +115,7 @@
+  int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,
+  		   struct ath9k_hw_cal_data *caldata, bool fastcc)
+  {
+-@@ -2012,6 +2026,7 @@ int ath9k_hw_reset(struct ath_hw *ah, st
++@@ -2016,6 +2030,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 8c9b34c..fddaf56 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 @@
+ --- a/drivers/net/wireless/ath/ath9k/hw.h
+ +++ b/drivers/net/wireless/ath/ath9k/hw.h
+-@@ -710,6 +710,7 @@ struct ath_spec_scan {
++@@ -720,6 +720,7 @@ struct ath_spec_scan {
+   * @config_pci_powersave:
+   * @calibrate: periodic calibration for NF, ANI, IQ, ADC gain, ADC-DC
+   *
+@@ -8,7 +8,7 @@
+   * @spectral_scan_config: set parameters for spectral scan and enable/disable it
+   * @spectral_scan_trigger: trigger a spectral scan run
+   * @spectral_scan_wait: wait for a spectral scan run to finish
+-@@ -732,6 +733,7 @@ struct ath_hw_ops {
++@@ -742,6 +743,7 @@ struct ath_hw_ops {
+  			struct ath_hw_antcomb_conf *antconf);
+  	void (*antdiv_comb_conf_set)(struct ath_hw *ah,
+  			struct ath_hw_antcomb_conf *antconf);
+@@ -55,7 +55,7 @@
+  	ops->spectral_scan_config = ar9003_hw_spectral_scan_config;
+ --- a/drivers/net/wireless/ath/ath9k/init.c
+ +++ b/drivers/net/wireless/ath/ath9k/init.c
+-@@ -703,7 +703,8 @@ static void ath9k_init_txpower_limits(st
++@@ -710,7 +710,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);
+  
+@@ -65,7 +65,7 @@
+  }
+  
+  static const struct ieee80211_iface_limit if_limits[] = {
+-@@ -896,6 +897,18 @@ static void ath9k_set_hw_capab(struct at
++@@ -904,6 +905,18 @@ static void ath9k_set_hw_capab(struct at
+  	SET_IEEE80211_PERM_ADDR(hw, common->macaddr);
+  }
+  
+@@ -84,7 +84,7 @@
+  int ath9k_init_device(u16 devid, struct ath_softc *sc,
+  		    const struct ath_bus_ops *bus_ops)
+  {
+-@@ -941,6 +954,8 @@ int ath9k_init_device(u16 devid, struct
++@@ -949,6 +962,8 @@ int ath9k_init_device(u16 devid, struct
+  		ARRAY_SIZE(ath9k_tpt_blink));
+  #endif
+  
+@@ -110,7 +110,7 @@
+  static inline void ath9k_hw_set_bt_ant_diversity(struct ath_hw *ah, bool enable)
+ --- a/drivers/net/wireless/ath/ath9k/ar5008_phy.c
+ +++ b/drivers/net/wireless/ath/ath9k/ar5008_phy.c
+-@@ -1316,9 +1316,30 @@ void ar5008_hw_init_rate_txpower(struct
++@@ -1327,9 +1327,30 @@ void ar5008_hw_init_rate_txpower(struct
+  	}
+  }
+  
+@@ -141,7 +141,7 @@
+  	static const u32 ar5416_cca_regs[6] = {
+  		AR_PHY_CCA,
+  		AR_PHY_CH1_CCA,
+-@@ -1333,6 +1354,8 @@ int ar5008_hw_attach_phy_ops(struct ath_
++@@ -1344,6 +1365,8 @@ int ar5008_hw_attach_phy_ops(struct ath_
+  	if (ret)
+  	    return ret;
+  
+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 240b898..6ca642a 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
+@@ -1,6 +1,6 @@
+ --- a/drivers/net/wireless/ath/ath9k/hw.c
+ +++ b/drivers/net/wireless/ath/ath9k/hw.c
+-@@ -245,6 +245,19 @@ void ath9k_hw_get_channel_centers(struct
++@@ -246,6 +246,19 @@ void ath9k_hw_get_channel_centers(struct
+  		centers->synth_center + (extoff * HT40_CHANNEL_CENTER_SHIFT);
+  }
+  
+@@ -20,7 +20,7 @@
+  /******************/
+  /* Chip Revisions */
+  /******************/
+-@@ -1382,6 +1395,9 @@ static bool ath9k_hw_set_reset(struct at
++@@ -1386,6 +1399,9 @@ static bool ath9k_hw_set_reset(struct at
+  	if (AR_SREV_9100(ah))
+  		udelay(50);
+  
+@@ -30,7 +30,7 @@
+  	return true;
+  }
+  
+-@@ -1481,6 +1497,9 @@ static bool ath9k_hw_chip_reset(struct a
++@@ -1485,6 +1501,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;
+  }
+  
+-@@ -1782,8 +1801,14 @@ static int ath9k_hw_do_fastcc(struct ath
++@@ -1786,8 +1805,14 @@ static int ath9k_hw_do_fastcc(struct ath
+  	if (AR_SREV_9271(ah))
+  		ar9002_hw_load_ani_reg(ah, chan);
+  
+@@ -55,7 +55,7 @@
+  	return -EINVAL;
+  }
+  
+-@@ -2037,6 +2062,9 @@ int ath9k_hw_reset(struct ath_hw *ah, st
++@@ -2041,6 +2066,9 @@ int ath9k_hw_reset(struct ath_hw *ah, st
+  		ath9k_hw_set_radar_params(ah);
+  	}
+  
+diff --git a/package/kernel/mac80211/patches/545-ath9k_ani_ws_detect.patch b/package/kernel/mac80211/patches/545-ath9k_ani_ws_detect.patch
+index 9610372..bc0aca6 100644
+--- a/package/kernel/mac80211/patches/545-ath9k_ani_ws_detect.patch
++++ b/package/kernel/mac80211/patches/545-ath9k_ani_ws_detect.patch
+@@ -1,6 +1,6 @@
+ --- a/drivers/net/wireless/ath/ath9k/ar5008_phy.c
+ +++ b/drivers/net/wireless/ath/ath9k/ar5008_phy.c
+-@@ -945,55 +945,6 @@ static bool ar5008_hw_ani_control_new(st
++@@ -956,55 +956,6 @@ static bool ar5008_hw_ani_control_new(st
+  		 * on == 0 means more noise imm
+  		 */
+  		u32 on = param ? 1 : 0;
+diff --git a/package/kernel/mac80211/patches/600-0001-rt2x00-rt2800lib-move-rt2800_drv_data-declaration-in.patch b/package/kernel/mac80211/patches/600-0001-rt2x00-rt2800lib-move-rt2800_drv_data-declaration-in.patch
+index c0dc4fe..15863a6 100644
+--- a/package/kernel/mac80211/patches/600-0001-rt2x00-rt2800lib-move-rt2800_drv_data-declaration-in.patch
++++ b/package/kernel/mac80211/patches/600-0001-rt2x00-rt2800lib-move-rt2800_drv_data-declaration-in.patch
+@@ -20,32 +20,14 @@ Changes since v1: ---
+  drivers/net/wireless/rt2x00/rt2800lib.h |   11 +++++++++++
+  2 files changed, 11 insertions(+), 13 deletions(-)
+ 
+---- a/drivers/net/wireless/rt2x00/rt2800.h
+-+++ b/drivers/net/wireless/rt2x00/rt2800.h
+-@@ -2960,17 +2960,4 @@ enum rt2800_eeprom_word {
+-  */
+- #define BCN_TBTT_OFFSET 64
+- 
+--/*
+-- * RT2800 driver data structure
+-- */
+--struct rt2800_drv_data {
+--	u8 calibration_bw20;
+--	u8 calibration_bw40;
+--	u8 bbp25;
+--	u8 bbp26;
+--	u8 txmixer_gain_24g;
+--	u8 txmixer_gain_5g;
+--	unsigned int tbtt_tick;
+--};
+--
+- #endif /* RT2800_H */
+ --- a/drivers/net/wireless/rt2x00/rt2800lib.h
+ +++ b/drivers/net/wireless/rt2x00/rt2800lib.h
+-@@ -20,6 +20,17 @@
++@@ -20,6 +20,20 @@
+  #ifndef RT2800LIB_H
+  #define RT2800LIB_H
+  
+++#include "rt2800.h"
+++
+ +/* RT2800 driver data structure */
+ +struct rt2800_drv_data {
+ +	u8 calibration_bw20;
+@@ -55,8 +37,30 @@ Changes since v1: ---
+ +	u8 txmixer_gain_24g;
+ +	u8 txmixer_gain_5g;
+ +	unsigned int tbtt_tick;
+++	DECLARE_BITMAP(sta_ids, STA_IDS_SIZE);
+ +};
+ +
+  struct rt2800_ops {
+  	void (*register_read)(struct rt2x00_dev *rt2x00dev,
+  			      const unsigned int offset, u32 *value);
++--- a/drivers/net/wireless/rt2x00/rt2800.h
+++++ b/drivers/net/wireless/rt2x00/rt2800.h
++@@ -2969,18 +2969,4 @@ enum rt2800_eeprom_word {
++ #define WCID_END	222
++ #define STA_IDS_SIZE	(WCID_END - WCID_START + 2)
++ 
++-/*
++- * RT2800 driver data structure
++- */
++-struct rt2800_drv_data {
++-	u8 calibration_bw20;
++-	u8 calibration_bw40;
++-	u8 bbp25;
++-	u8 bbp26;
++-	u8 txmixer_gain_24g;
++-	u8 txmixer_gain_5g;
++-	unsigned int tbtt_tick;
++-	DECLARE_BITMAP(sta_ids, STA_IDS_SIZE);
++-};
++-
++ #endif /* RT2800_H */
+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 6bad6ac..9165eec 100644
+--- 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
+@@ -24,7 +24,7 @@ Changes since v1:
+ 
+ --- a/drivers/net/wireless/rt2x00/rt2800lib.c
+ +++ b/drivers/net/wireless/rt2x00/rt2800lib.c
+-@@ -7747,6 +7747,7 @@ static int rt2800_probe_rt(struct rt2x00
++@@ -7721,6 +7721,7 @@ static int rt2800_probe_rt(struct rt2x00
+  
+  int rt2800_probe_hw(struct rt2x00_dev *rt2x00dev)
+  {
+@@ -32,7 +32,7 @@ Changes since v1:
+  	int retval;
+  	u32 reg;
+  
+-@@ -7754,6 +7755,9 @@ int rt2800_probe_hw(struct rt2x00_dev *r
++@@ -7728,6 +7729,9 @@ int rt2800_probe_hw(struct rt2x00_dev *r
+  	if (retval)
+  		return retval;
+  
+@@ -44,9 +44,9 @@ Changes since v1:
+  	 */
+ --- a/drivers/net/wireless/rt2x00/rt2800lib.h
+ +++ b/drivers/net/wireless/rt2x00/rt2800lib.h
+-@@ -20,6 +20,10 @@
+- #ifndef RT2800LIB_H
+- #define RT2800LIB_H
++@@ -22,6 +22,10 @@
++ 
++ #include "rt2800.h"
+  
+ +enum rt2800_flag {
+ +	RT2800_HAS_HIGH_SHARED_MEM,
+@@ -55,16 +55,16 @@ Changes since v1:
+  /* RT2800 driver data structure */
+  struct rt2800_drv_data {
+  	u8 calibration_bw20;
+-@@ -29,6 +33,8 @@ struct rt2800_drv_data {
+- 	u8 txmixer_gain_24g;
++@@ -32,6 +36,8 @@ struct rt2800_drv_data {
+  	u8 txmixer_gain_5g;
+  	unsigned int tbtt_tick;
++ 	DECLARE_BITMAP(sta_ids, STA_IDS_SIZE);
+ +
+ +	unsigned long rt2800_flags;
+  };
+  
+  struct rt2800_ops {
+-@@ -61,6 +67,13 @@ struct rt2800_ops {
++@@ -64,6 +70,13 @@ struct rt2800_ops {
+  	__le32 *(*drv_get_txwi)(struct queue_entry *entry);
+  };
+  
+diff --git a/package/kernel/mac80211/patches/600-0003-rt2x00-rt2800-serialize-shared-memory-access.patch b/package/kernel/mac80211/patches/600-0003-rt2x00-rt2800-serialize-shared-memory-access.patch
+index 9f8dfcc..5671515 100644
+--- a/package/kernel/mac80211/patches/600-0003-rt2x00-rt2800-serialize-shared-memory-access.patch
++++ b/package/kernel/mac80211/patches/600-0003-rt2x00-rt2800-serialize-shared-memory-access.patch
+@@ -175,7 +175,7 @@ Changes since v1: ---
+  
+  	/*
+  	 * Update WCID information
+-@@ -1437,8 +1467,11 @@ int rt2800_config_pairwise_key(struct rt
++@@ -1405,8 +1435,11 @@ int rt2800_config_pairwise_key(struct rt
+  		       sizeof(key_entry.rx_mic));
+  
+  		offset = PAIRWISE_KEY_ENTRY(key->hw_key_idx);
+@@ -187,7 +187,7 @@ Changes since v1: ---
+  	}
+  
+  	/*
+-@@ -4908,14 +4941,19 @@ static int rt2800_init_registers(struct
++@@ -4884,14 +4917,19 @@ static int rt2800_init_registers(struct
+  	/*
+  	 * ASIC will keep garbage value after boot, clear encryption keys.
+  	 */
+@@ -207,7 +207,7 @@ Changes since v1: ---
+  	}
+  
+  	/*
+-@@ -5041,8 +5079,10 @@ static int rt2800_wait_bbp_ready(struct
++@@ -5017,8 +5055,10 @@ static int rt2800_wait_bbp_ready(struct
+  	 * BBP was enabled after firmware was loaded,
+  	 * but we need to reactivate it now.
+  	 */
+@@ -218,7 +218,7 @@ Changes since v1: ---
+  	msleep(1);
+  
+  	for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
+-@@ -6738,11 +6778,19 @@ int rt2800_enable_radio(struct rt2x00_de
++@@ -6714,11 +6754,19 @@ int rt2800_enable_radio(struct rt2x00_de
+  	/*
+  	 * Send signal during boot time to initialize firmware.
+  	 */
+@@ -239,7 +239,7 @@ Changes since v1: ---
+  	msleep(1);
+  
+  	/*
+-@@ -7751,6 +7799,8 @@ int rt2800_probe_hw(struct rt2x00_dev *r
++@@ -7725,6 +7773,8 @@ int rt2800_probe_hw(struct rt2x00_dev *r
+  	int retval;
+  	u32 reg;
+  
+@@ -248,22 +248,22 @@ Changes since v1: ---
+  	retval = rt2800_probe_rt(rt2x00dev);
+  	if (retval)
+  		return retval;
+-@@ -7830,8 +7880,11 @@ void rt2800_get_tkip_seq(struct ieee8021
+- 	u32 offset;
++@@ -7808,8 +7858,11 @@ void rt2800_get_key_seq(struct ieee80211
++ 		return;
+  
+- 	offset = MAC_IVEIV_ENTRY(hw_key_idx);
++ 	offset = MAC_IVEIV_ENTRY(key->hw_key_idx);
+ +
+ +	rt2800_shared_mem_lock(rt2x00dev);
+  	rt2800_register_multiread(rt2x00dev, offset,
+  				      &iveiv_entry, sizeof(iveiv_entry));
+ +	rt2800_shared_mem_unlock(rt2x00dev);
+  
+- 	memcpy(iv16, &iveiv_entry.iv[0], sizeof(*iv16));
+- 	memcpy(iv32, &iveiv_entry.iv[4], sizeof(*iv32));
++ 	memcpy(&seq->tkip.iv16, &iveiv_entry.iv[0], 2);
++ 	memcpy(&seq->tkip.iv32, &iveiv_entry.iv[4], 4);
+ --- a/drivers/net/wireless/rt2x00/rt2800lib.h
+ +++ b/drivers/net/wireless/rt2x00/rt2800lib.h
+-@@ -35,6 +35,11 @@ struct rt2800_drv_data {
+- 	unsigned int tbtt_tick;
++@@ -38,6 +38,11 @@ struct rt2800_drv_data {
++ 	DECLARE_BITMAP(sta_ids, STA_IDS_SIZE);
+  
+  	unsigned long rt2800_flags;
+ +
+@@ -274,7 +274,7 @@ Changes since v1: ---
+  };
+  
+  struct rt2800_ops {
+-@@ -65,6 +70,10 @@ struct rt2800_ops {
++@@ -68,6 +73,10 @@ struct rt2800_ops {
+  				  const u8 *data, const size_t len);
+  	int (*drv_init_registers)(struct rt2x00_dev *rt2x00dev);
+  	__le32 *(*drv_get_txwi)(struct queue_entry *entry);
+@@ -285,7 +285,7 @@ Changes since v1: ---
+  };
+  
+  static inline bool rt2800_has_high_shared_mem(struct rt2x00_dev *rt2x00dev)
+-@@ -74,6 +83,29 @@ static inline bool rt2800_has_high_share
++@@ -77,6 +86,29 @@ static inline bool rt2800_has_high_share
+  	return test_bit(RT2800_HAS_HIGH_SHARED_MEM, &drv_data->rt2800_flags);
+  }
+  
+@@ -486,7 +486,7 @@ Changes since v1: ---
+  /*
+   * Queue handlers.
+   */
+-@@ -294,8 +315,10 @@ static int rt2800usb_write_firmware(stru
++@@ -299,8 +320,10 @@ static int rt2800usb_write_firmware(stru
+  					      data + offset, length);
+  	}
+  
+@@ -497,7 +497,7 @@ Changes since v1: ---
+  
+  	/*
+  	 * Send firmware request to device to load firmware,
+-@@ -310,7 +333,10 @@ static int rt2800usb_write_firmware(stru
++@@ -315,7 +338,10 @@ static int rt2800usb_write_firmware(stru
+  	}
+  
+  	msleep(10);
+@@ -508,7 +508,7 @@ Changes since v1: ---
+  
+  	return 0;
+  }
+-@@ -328,8 +354,10 @@ static int rt2800usb_init_registers(stru
++@@ -333,8 +359,10 @@ static int rt2800usb_init_registers(stru
+  	if (rt2800_wait_csr_ready(rt2x00dev))
+  		return -EBUSY;
+  
+@@ -519,7 +519,7 @@ Changes since v1: ---
+  
+  	reg = 0;
+  	rt2x00_set_field32(&reg, MAC_SYS_CTRL_RESET_CSR, 1);
+-@@ -859,6 +887,9 @@ static const struct rt2800_ops rt2800usb
++@@ -863,6 +891,9 @@ static const struct rt2800_ops rt2800usb
+  	.drv_write_firmware	= rt2800usb_write_firmware,
+  	.drv_init_registers	= rt2800usb_init_registers,
+  	.drv_get_txwi		= rt2800usb_get_txwi,
+diff --git a/package/kernel/mac80211/patches/600-0005-rt2x00-rt2800lib-add-hw_beacon_count-field-to-struct.patch b/package/kernel/mac80211/patches/600-0005-rt2x00-rt2800lib-add-hw_beacon_count-field-to-struct.patch
+index e7eb630..d04998a 100644
+--- a/package/kernel/mac80211/patches/600-0005-rt2x00-rt2800lib-add-hw_beacon_count-field-to-struct.patch
++++ b/package/kernel/mac80211/patches/600-0005-rt2x00-rt2800lib-add-hw_beacon_count-field-to-struct.patch
+@@ -24,7 +24,7 @@ Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
+ 
+ --- a/drivers/net/wireless/rt2x00/rt2800lib.c
+ +++ b/drivers/net/wireless/rt2x00/rt2800lib.c
+-@@ -4638,6 +4638,7 @@ EXPORT_SYMBOL_GPL(rt2800_link_tuner);
++@@ -4614,6 +4614,7 @@ EXPORT_SYMBOL_GPL(rt2800_link_tuner);
+   */
+  static int rt2800_init_registers(struct rt2x00_dev *rt2x00dev)
+  {
+@@ -32,7 +32,7 @@ Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
+  	u32 reg;
+  	u16 eeprom;
+  	unsigned int i;
+-@@ -5003,7 +5004,7 @@ static int rt2800_init_registers(struct
++@@ -4979,7 +4980,7 @@ static int rt2800_init_registers(struct
+  	/*
+  	 * Clear all beacons
+  	 */
+@@ -41,7 +41,7 @@ Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
+  		rt2800_clear_beacon_register(rt2x00dev, i);
+  
+  	if (rt2x00_is_usb(rt2x00dev)) {
+-@@ -7852,6 +7853,8 @@ int rt2800_probe_hw(struct rt2x00_dev *r
++@@ -7826,6 +7827,8 @@ int rt2800_probe_hw(struct rt2x00_dev *r
+  	if (rt2x00_rt(rt2x00dev, RT3593))
+  		__set_bit(RT2800_HAS_HIGH_SHARED_MEM, &drv_data->rt2800_flags);
+  
+@@ -52,11 +52,11 @@ Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
+  	 */
+ --- a/drivers/net/wireless/rt2x00/rt2800lib.h
+ +++ b/drivers/net/wireless/rt2x00/rt2800lib.h
+-@@ -33,6 +33,7 @@ struct rt2800_drv_data {
++@@ -35,6 +35,7 @@ struct rt2800_drv_data {
+  	u8 txmixer_gain_24g;
+  	u8 txmixer_gain_5g;
+  	unsigned int tbtt_tick;
+ +	unsigned int hw_beacon_count;
++ 	DECLARE_BITMAP(sta_ids, STA_IDS_SIZE);
+  
+  	unsigned long rt2800_flags;
+- 
+diff --git a/package/kernel/mac80211/patches/600-0006-rt2x00-rt2800lib-init-additional-beacon-offset-regis.patch b/package/kernel/mac80211/patches/600-0006-rt2x00-rt2800lib-init-additional-beacon-offset-regis.patch
+index b79b4be..f5231f0 100644
+--- a/package/kernel/mac80211/patches/600-0006-rt2x00-rt2800lib-init-additional-beacon-offset-regis.patch
++++ b/package/kernel/mac80211/patches/600-0006-rt2x00-rt2800lib-init-additional-beacon-offset-regis.patch
+@@ -34,7 +34,7 @@ Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
+   */
+ --- a/drivers/net/wireless/rt2x00/rt2800lib.c
+ +++ b/drivers/net/wireless/rt2x00/rt2800lib.c
+-@@ -4650,6 +4650,30 @@ static int rt2800_init_registers(struct
++@@ -4626,6 +4626,30 @@ static int rt2800_init_registers(struct
+  	if (ret)
+  		return ret;
+  
+diff --git a/package/kernel/mac80211/patches/600-0007-rt2x00-rt2800lib-fix-max-supported-beacon-count-for-.patch b/package/kernel/mac80211/patches/600-0007-rt2x00-rt2800lib-fix-max-supported-beacon-count-for-.patch
+index 180c5e3..4b21eae 100644
+--- a/package/kernel/mac80211/patches/600-0007-rt2x00-rt2800lib-fix-max-supported-beacon-count-for-.patch
++++ b/package/kernel/mac80211/patches/600-0007-rt2x00-rt2800lib-fix-max-supported-beacon-count-for-.patch
+@@ -10,7 +10,7 @@ Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
+ 
+ --- a/drivers/net/wireless/rt2x00/rt2800lib.c
+ +++ b/drivers/net/wireless/rt2x00/rt2800lib.c
+-@@ -7877,7 +7877,10 @@ int rt2800_probe_hw(struct rt2x00_dev *r
++@@ -7851,7 +7851,10 @@ int rt2800_probe_hw(struct rt2x00_dev *r
+  	if (rt2x00_rt(rt2x00dev, RT3593))
+  		__set_bit(RT2800_HAS_HIGH_SHARED_MEM, &drv_data->rt2800_flags);
+  
+diff --git a/package/kernel/mac80211/patches/600-0009-rt2x00-rt2800lib-enable-support-for-RT3883.patch b/package/kernel/mac80211/patches/600-0009-rt2x00-rt2800lib-enable-support-for-RT3883.patch
+index 31aa34a..e77cd86 100644
+--- a/package/kernel/mac80211/patches/600-0009-rt2x00-rt2800lib-enable-support-for-RT3883.patch
++++ b/package/kernel/mac80211/patches/600-0009-rt2x00-rt2800lib-enable-support-for-RT3883.patch
+@@ -10,7 +10,7 @@ Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
+ 
+ --- a/drivers/net/wireless/rt2x00/rt2800lib.c
+ +++ b/drivers/net/wireless/rt2x00/rt2800lib.c
+-@@ -7847,6 +7847,7 @@ static int rt2800_probe_rt(struct rt2x00
++@@ -7821,6 +7821,7 @@ static int rt2800_probe_rt(struct rt2x00
+  	case RT3390:
+  	case RT3572:
+  	case RT3593:
+diff --git a/package/kernel/mac80211/patches/600-0010-rt2x00-rt2800lib-add-rf_vals-for-RF3853.patch b/package/kernel/mac80211/patches/600-0010-rt2x00-rt2800lib-add-rf_vals-for-RF3853.patch
+index a90c590..780c1dd 100644
+--- a/package/kernel/mac80211/patches/600-0010-rt2x00-rt2800lib-add-rf_vals-for-RF3853.patch
++++ b/package/kernel/mac80211/patches/600-0010-rt2x00-rt2800lib-add-rf_vals-for-RF3853.patch
+@@ -31,7 +31,7 @@ Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
+  #define RF5370				0x5370
+ --- a/drivers/net/wireless/rt2x00/rt2800lib.c
+ +++ b/drivers/net/wireless/rt2x00/rt2800lib.c
+-@@ -7465,6 +7465,66 @@ static const struct rf_channel rf_vals_3
++@@ -7441,6 +7441,66 @@ static const struct rf_channel rf_vals_3
+  	{173, 0x61, 0, 9},
+  };
+  
+@@ -98,7 +98,7 @@ Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
+  static const struct rf_channel rf_vals_5592_xtal20[] = {
+  	/* Channel, N, K, mod, R */
+  	{1, 482, 4, 10, 3},
+-@@ -7694,6 +7754,11 @@ static int rt2800_probe_hw_mode(struct r
++@@ -7668,6 +7728,11 @@ static int rt2800_probe_hw_mode(struct r
+  		spec->channels = rf_vals_3x;
+  		break;
+  
+diff --git a/package/kernel/mac80211/patches/600-0011-rt2x00-rt2800lib-enable-VCO-calibration-for-RF3853.patch b/package/kernel/mac80211/patches/600-0011-rt2x00-rt2800lib-enable-VCO-calibration-for-RF3853.patch
+index ab2673b..858dece 100644
+--- a/package/kernel/mac80211/patches/600-0011-rt2x00-rt2800lib-enable-VCO-calibration-for-RF3853.patch
++++ b/package/kernel/mac80211/patches/600-0011-rt2x00-rt2800lib-enable-VCO-calibration-for-RF3853.patch
+@@ -10,7 +10,7 @@ Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
+ 
+ --- a/drivers/net/wireless/rt2x00/rt2800lib.c
+ +++ b/drivers/net/wireless/rt2x00/rt2800lib.c
+-@@ -4402,6 +4402,7 @@ void rt2800_vco_calibration(struct rt2x0
++@@ -4378,6 +4378,7 @@ void rt2800_vco_calibration(struct rt2x0
+  	case RF3053:
+  	case RF3070:
+  	case RF3290:
+@@ -18,7 +18,7 @@ Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
+  	case RF5360:
+  	case RF5362:
+  	case RF5370:
+-@@ -7873,6 +7874,7 @@ static int rt2800_probe_hw_mode(struct r
++@@ -7847,6 +7848,7 @@ static int rt2800_probe_hw_mode(struct r
+  	case RF3053:
+  	case RF3070:
+  	case RF3290:
+diff --git a/package/kernel/mac80211/patches/600-0012-rt2x00-rt2800lib-add-channel-configuration-function-.patch b/package/kernel/mac80211/patches/600-0012-rt2x00-rt2800lib-add-channel-configuration-function-.patch
+index 05ed444..ed82e44 100644
+--- a/package/kernel/mac80211/patches/600-0012-rt2x00-rt2800lib-add-channel-configuration-function-.patch
++++ b/package/kernel/mac80211/patches/600-0012-rt2x00-rt2800lib-add-channel-configuration-function-.patch
+@@ -11,7 +11,7 @@ Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
+ 
+ --- a/drivers/net/wireless/rt2x00/rt2800lib.c
+ +++ b/drivers/net/wireless/rt2x00/rt2800lib.c
+-@@ -2649,6 +2649,211 @@ static void rt2800_config_channel_rf3053
++@@ -2625,6 +2625,211 @@ static void rt2800_config_channel_rf3053
+  	}
+  }
+  
+@@ -223,7 +223,7 @@ Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
+  #define POWER_BOUND		0x27
+  #define POWER_BOUND_5G		0x2b
+  
+-@@ -3261,6 +3466,9 @@ static void rt2800_config_channel(struct
++@@ -3237,6 +3442,9 @@ static void rt2800_config_channel(struct
+  	case RF3322:
+  		rt2800_config_channel_rf3322(rt2x00dev, conf, rf, info);
+  		break;
+diff --git a/package/kernel/mac80211/patches/600-0013-rt2x00-rt2800lib-enable-RF3853-support.patch b/package/kernel/mac80211/patches/600-0013-rt2x00-rt2800lib-enable-RF3853-support.patch
+index 3b50775..33cbc4c 100644
+--- a/package/kernel/mac80211/patches/600-0013-rt2x00-rt2800lib-enable-RF3853-support.patch
++++ b/package/kernel/mac80211/patches/600-0013-rt2x00-rt2800lib-enable-RF3853-support.patch
+@@ -10,7 +10,7 @@ Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
+ 
+ --- a/drivers/net/wireless/rt2x00/rt2800lib.c
+ +++ b/drivers/net/wireless/rt2x00/rt2800lib.c
+-@@ -7430,6 +7430,7 @@ static int rt2800_init_eeprom(struct rt2
++@@ -7406,6 +7406,7 @@ static int rt2800_init_eeprom(struct rt2
+  	case RF3290:
+  	case RF3320:
+  	case RF3322:
+diff --git a/package/kernel/mac80211/patches/600-0014-rt2x00-rt2800lib-add-MAC-register-initialization-for.patch b/package/kernel/mac80211/patches/600-0014-rt2x00-rt2800lib-add-MAC-register-initialization-for.patch
+index 4dfb068..c3a4798 100644
+--- a/package/kernel/mac80211/patches/600-0014-rt2x00-rt2800lib-add-MAC-register-initialization-for.patch
++++ b/package/kernel/mac80211/patches/600-0014-rt2x00-rt2800lib-add-MAC-register-initialization-for.patch
+@@ -35,7 +35,7 @@ Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
+  #define RX_FILTER_CFG			0x1400
+ --- a/drivers/net/wireless/rt2x00/rt2800lib.c
+ +++ b/drivers/net/wireless/rt2x00/rt2800lib.c
+-@@ -5005,6 +5005,12 @@ static int rt2800_init_registers(struct
++@@ -4981,6 +4981,12 @@ static int rt2800_init_registers(struct
+  			rt2800_register_write(rt2x00dev, TX_SW_CFG2,
+  					      0x00000000);
+  		}
+@@ -48,7 +48,7 @@ Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
+  	} else if (rt2x00_rt(rt2x00dev, RT5390) ||
+  		   rt2x00_rt(rt2x00dev, RT5392) ||
+  		   rt2x00_rt(rt2x00dev, RT5592)) {
+-@@ -5035,9 +5041,11 @@ static int rt2800_init_registers(struct
++@@ -5011,9 +5017,11 @@ static int rt2800_init_registers(struct
+  
+  	rt2800_register_read(rt2x00dev, MAX_LEN_CFG, &reg);
+  	rt2x00_set_field32(&reg, MAX_LEN_CFG_MAX_MPDU, AGGREGATION_SIZE);
+@@ -63,7 +63,7 @@ Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
+  		rt2x00_set_field32(&reg, MAX_LEN_CFG_MAX_PSDU, 2);
+  	else
+  		rt2x00_set_field32(&reg, MAX_LEN_CFG_MAX_PSDU, 1);
+-@@ -5190,6 +5198,11 @@ static int rt2800_init_registers(struct
++@@ -5166,6 +5174,11 @@ static int rt2800_init_registers(struct
+  	reg = rt2x00_rt(rt2x00dev, RT5592) ? 0x00000082 : 0x00000002;
+  	rt2800_register_write(rt2x00dev, TXOP_HLDR_ET, reg);
+  
+diff --git a/package/kernel/mac80211/patches/600-0016-rt2x00-rt2800lib-add-BBP-register-initialization-for.patch b/package/kernel/mac80211/patches/600-0016-rt2x00-rt2800lib-add-BBP-register-initialization-for.patch
+index 6663b78..e647777 100644
+--- a/package/kernel/mac80211/patches/600-0016-rt2x00-rt2800lib-add-BBP-register-initialization-for.patch
++++ b/package/kernel/mac80211/patches/600-0016-rt2x00-rt2800lib-add-BBP-register-initialization-for.patch
+@@ -11,7 +11,7 @@ Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
+ 
+ --- a/drivers/net/wireless/rt2x00/rt2800lib.c
+ +++ b/drivers/net/wireless/rt2x00/rt2800lib.c
+-@@ -5808,6 +5808,47 @@ static void rt2800_init_bbp_3593(struct
++@@ -5784,6 +5784,47 @@ static void rt2800_init_bbp_3593(struct
+  		rt2800_bbp_write(rt2x00dev, 103, 0xc0);
+  }
+  
+@@ -59,7 +59,7 @@ Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
+  static void rt2800_init_bbp_53xx(struct rt2x00_dev *rt2x00dev)
+  {
+  	int ant, div_mode;
+-@@ -6026,6 +6067,9 @@ static void rt2800_init_bbp(struct rt2x0
++@@ -6002,6 +6043,9 @@ static void rt2800_init_bbp(struct rt2x0
+  	case RT3593:
+  		rt2800_init_bbp_3593(rt2x00dev);
+  		return;
+diff --git a/package/kernel/mac80211/patches/600-0017-rt2x00-rt2800lib-add-RFCSR-initialization-for-RT3883.patch b/package/kernel/mac80211/patches/600-0017-rt2x00-rt2800lib-add-RFCSR-initialization-for-RT3883.patch
+index 6e66f14..0fec3cd 100644
+--- a/package/kernel/mac80211/patches/600-0017-rt2x00-rt2800lib-add-RFCSR-initialization-for-RT3883.patch
++++ b/package/kernel/mac80211/patches/600-0017-rt2x00-rt2800lib-add-RFCSR-initialization-for-RT3883.patch
+@@ -21,7 +21,7 @@ Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
+  /*
+ --- a/drivers/net/wireless/rt2x00/rt2800lib.c
+ +++ b/drivers/net/wireless/rt2x00/rt2800lib.c
+-@@ -6843,6 +6843,144 @@ static void rt2800_init_rfcsr_3593(struc
++@@ -6819,6 +6819,144 @@ static void rt2800_init_rfcsr_3593(struc
+  	/* TODO: enable stream mode support */
+  }
+  
+@@ -166,7 +166,7 @@ Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
+  static void rt2800_init_rfcsr_5390(struct rt2x00_dev *rt2x00dev)
+  {
+  	rt2800_rf_init_calibration(rt2x00dev, 2);
+-@@ -7074,6 +7212,9 @@ static void rt2800_init_rfcsr(struct rt2
++@@ -7050,6 +7188,9 @@ static void rt2800_init_rfcsr(struct rt2
+  	case RT3390:
+  		rt2800_init_rfcsr_3390(rt2x00dev);
+  		break;
+diff --git a/package/kernel/mac80211/patches/600-0019-rt2x00-rt2800lib-force-rf-type-to-RF3853-on-RT3883.patch b/package/kernel/mac80211/patches/600-0019-rt2x00-rt2800lib-force-rf-type-to-RF3853-on-RT3883.patch
+index 9390f7e..c9d1e06 100644
+--- a/package/kernel/mac80211/patches/600-0019-rt2x00-rt2800lib-force-rf-type-to-RF3853-on-RT3883.patch
++++ b/package/kernel/mac80211/patches/600-0019-rt2x00-rt2800lib-force-rf-type-to-RF3853-on-RT3883.patch
+@@ -10,7 +10,7 @@ Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
+ 
+ --- a/drivers/net/wireless/rt2x00/rt2800lib.c
+ +++ b/drivers/net/wireless/rt2x00/rt2800lib.c
+-@@ -7611,6 +7611,8 @@ static int rt2800_init_eeprom(struct rt2
++@@ -7587,6 +7587,8 @@ static int rt2800_init_eeprom(struct rt2
+  	    rt2x00_rt(rt2x00dev, RT5390) ||
+  	    rt2x00_rt(rt2x00dev, RT5392))
+  		rt2800_eeprom_read(rt2x00dev, EEPROM_CHIP_ID, &rf);
+diff --git a/package/kernel/mac80211/patches/600-0020-rt2x00-rt2800lib-add-channel-configuration-code-for-.patch b/package/kernel/mac80211/patches/600-0020-rt2x00-rt2800lib-add-channel-configuration-code-for-.patch
+index 1cba4f6..12b9c33 100644
+--- a/package/kernel/mac80211/patches/600-0020-rt2x00-rt2800lib-add-channel-configuration-code-for-.patch
++++ b/package/kernel/mac80211/patches/600-0020-rt2x00-rt2800lib-add-channel-configuration-code-for-.patch
+@@ -10,7 +10,7 @@ Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
+ 
+ --- a/drivers/net/wireless/rt2x00/rt2800lib.c
+ +++ b/drivers/net/wireless/rt2x00/rt2800lib.c
+-@@ -3429,6 +3429,36 @@ static char rt2800_txpower_to_dev(struct
++@@ -3405,6 +3405,36 @@ static char rt2800_txpower_to_dev(struct
+  		return clamp_t(char, txpower, MIN_A_TXPOWER, MAX_A_TXPOWER);
+  }
+  
+@@ -47,7 +47,7 @@ Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
+  static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev,
+  				  struct ieee80211_conf *conf,
+  				  struct rf_channel *rf,
+-@@ -3447,6 +3477,12 @@ static void rt2800_config_channel(struct
++@@ -3423,6 +3453,12 @@ static void rt2800_config_channel(struct
+  			rt2800_txpower_to_dev(rt2x00dev, rf->channel,
+  					      info->default_power3);
+  
+@@ -60,7 +60,7 @@ Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
+  	switch (rt2x00dev->chip.rf) {
+  	case RF2020:
+  	case RF3020:
+-@@ -3530,6 +3566,15 @@ static void rt2800_config_channel(struct
++@@ -3506,6 +3542,15 @@ static void rt2800_config_channel(struct
+  		rt2800_bbp_write(rt2x00dev, 63, 0x37 - rt2x00dev->lna_gain);
+  		rt2800_bbp_write(rt2x00dev, 64, 0x37 - rt2x00dev->lna_gain);
+  		rt2800_bbp_write(rt2x00dev, 77, 0x98);
+@@ -76,7 +76,7 @@ Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
+  	} else {
+  		rt2800_bbp_write(rt2x00dev, 62, 0x37 - rt2x00dev->lna_gain);
+  		rt2800_bbp_write(rt2x00dev, 63, 0x37 - rt2x00dev->lna_gain);
+-@@ -3542,6 +3587,7 @@ static void rt2800_config_channel(struct
++@@ -3518,6 +3563,7 @@ static void rt2800_config_channel(struct
+  		    !rt2x00_rt(rt2x00dev, RT5392)) {
+  			if (rt2x00_has_cap_external_lna_bg(rt2x00dev)) {
+  				rt2800_bbp_write(rt2x00dev, 82, 0x62);
+@@ -84,7 +84,7 @@ Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
+  				rt2800_bbp_write(rt2x00dev, 75, 0x46);
+  			} else {
+  				if (rt2x00_rt(rt2x00dev, RT3593))
+-@@ -3550,19 +3596,22 @@ static void rt2800_config_channel(struct
++@@ -3526,19 +3572,22 @@ static void rt2800_config_channel(struct
+  					rt2800_bbp_write(rt2x00dev, 82, 0x84);
+  				rt2800_bbp_write(rt2x00dev, 75, 0x50);
+  			}
+@@ -110,7 +110,7 @@ Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
+  			rt2800_bbp_write(rt2x00dev, 83, 0x9a);
+  
+  		if (rt2x00_has_cap_external_lna_a(rt2x00dev))
+-@@ -3684,6 +3733,23 @@ static void rt2800_config_channel(struct
++@@ -3660,6 +3709,23 @@ static void rt2800_config_channel(struct
+  
+  		rt2800_bbp_write_with_rx_chain(rt2x00dev, 66, reg);
+  
+diff --git a/package/kernel/mac80211/patches/600-0021-rt2x00-rt2800lib-fix-txpower_to_dev-function-for-RT3.patch b/package/kernel/mac80211/patches/600-0021-rt2x00-rt2800lib-fix-txpower_to_dev-function-for-RT3.patch
+index 1773128..3f40b4e 100644
+--- a/package/kernel/mac80211/patches/600-0021-rt2x00-rt2800lib-fix-txpower_to_dev-function-for-RT3.patch
++++ b/package/kernel/mac80211/patches/600-0021-rt2x00-rt2800lib-fix-txpower_to_dev-function-for-RT3.patch
+@@ -10,7 +10,7 @@ Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
+ 
+ --- a/drivers/net/wireless/rt2x00/rt2800lib.c
+ +++ b/drivers/net/wireless/rt2x00/rt2800lib.c
+-@@ -3416,13 +3416,15 @@ static char rt2800_txpower_to_dev(struct
++@@ -3392,13 +3392,15 @@ static char rt2800_txpower_to_dev(struct
+  				  unsigned int channel,
+  				  char txpower)
+  {
+diff --git a/package/kernel/mac80211/patches/600-0022-rt2x00-rt2800lib-use-correct-txpower-calculation-fun.patch b/package/kernel/mac80211/patches/600-0022-rt2x00-rt2800lib-use-correct-txpower-calculation-fun.patch
+index 36f0a4c..52baeec 100644
+--- a/package/kernel/mac80211/patches/600-0022-rt2x00-rt2800lib-use-correct-txpower-calculation-fun.patch
++++ b/package/kernel/mac80211/patches/600-0022-rt2x00-rt2800lib-use-correct-txpower-calculation-fun.patch
+@@ -11,7 +11,7 @@ Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
+ 
+ --- a/drivers/net/wireless/rt2x00/rt2800lib.c
+ +++ b/drivers/net/wireless/rt2x00/rt2800lib.c
+-@@ -4635,7 +4635,8 @@ static void rt2800_config_txpower(struct
++@@ -4611,7 +4611,8 @@ static void rt2800_config_txpower(struct
+  				  struct ieee80211_channel *chan,
+  				  int power_level)
+  {
+diff --git a/package/kernel/mac80211/patches/600-0023-rt2x00-rt2800lib-hardcode-txmixer-gain-values-to-zer.patch b/package/kernel/mac80211/patches/600-0023-rt2x00-rt2800lib-hardcode-txmixer-gain-values-to-zer.patch
+index 8119f97..b9dafc6 100644
+--- a/package/kernel/mac80211/patches/600-0023-rt2x00-rt2800lib-hardcode-txmixer-gain-values-to-zer.patch
++++ b/package/kernel/mac80211/patches/600-0023-rt2x00-rt2800lib-hardcode-txmixer-gain-values-to-zer.patch
+@@ -11,7 +11,7 @@ Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
+ 
+ --- a/drivers/net/wireless/rt2x00/rt2800lib.c
+ +++ b/drivers/net/wireless/rt2x00/rt2800lib.c
+-@@ -7493,7 +7493,8 @@ static u8 rt2800_get_txmixer_gain_24g(st
++@@ -7469,7 +7469,8 @@ static u8 rt2800_get_txmixer_gain_24g(st
+  {
+  	u16 word;
+  
+@@ -21,7 +21,7 @@ Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
+  		return 0;
+  
+  	rt2800_eeprom_read(rt2x00dev, EEPROM_TXMIXER_GAIN_BG, &word);
+-@@ -7507,7 +7508,8 @@ static u8 rt2800_get_txmixer_gain_5g(str
++@@ -7483,7 +7484,8 @@ static u8 rt2800_get_txmixer_gain_5g(str
+  {
+  	u16 word;
+  
+diff --git a/package/kernel/mac80211/patches/600-0026-rt2x00-rt2800lib-use-correct-beacon-count-for-RT3883.patch b/package/kernel/mac80211/patches/600-0026-rt2x00-rt2800lib-use-correct-beacon-count-for-RT3883.patch
+index dfbdee7..f09f803 100644
+--- a/package/kernel/mac80211/patches/600-0026-rt2x00-rt2800lib-use-correct-beacon-count-for-RT3883.patch
++++ b/package/kernel/mac80211/patches/600-0026-rt2x00-rt2800lib-use-correct-beacon-count-for-RT3883.patch
+@@ -10,7 +10,7 @@ Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
+ 
+ --- a/drivers/net/wireless/rt2x00/rt2800lib.c
+ +++ b/drivers/net/wireless/rt2x00/rt2800lib.c
+-@@ -8428,7 +8428,8 @@ int rt2800_probe_hw(struct rt2x00_dev *r
++@@ -8402,7 +8402,8 @@ int rt2800_probe_hw(struct rt2x00_dev *r
+  	if (rt2x00_rt(rt2x00dev, RT3593))
+  		__set_bit(RT2800_HAS_HIGH_SHARED_MEM, &drv_data->rt2800_flags);
+  
+diff --git a/package/kernel/mac80211/patches/600-0027-rt2x00-rt2800lib-fix-antenna-configuration-for-RT388.patch b/package/kernel/mac80211/patches/600-0027-rt2x00-rt2800lib-fix-antenna-configuration-for-RT388.patch
+index 22f7110..f7d23fc 100644
+--- a/package/kernel/mac80211/patches/600-0027-rt2x00-rt2800lib-fix-antenna-configuration-for-RT388.patch
++++ b/package/kernel/mac80211/patches/600-0027-rt2x00-rt2800lib-fix-antenna-configuration-for-RT388.patch
+@@ -10,7 +10,7 @@ Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
+ 
+ --- a/drivers/net/wireless/rt2x00/rt2800lib.c
+ +++ b/drivers/net/wireless/rt2x00/rt2800lib.c
+-@@ -1961,7 +1961,8 @@ void rt2800_config_ant(struct rt2x00_dev
++@@ -1937,7 +1937,8 @@ void rt2800_config_ant(struct rt2x00_dev
+  	rt2800_bbp_write(rt2x00dev, 3, r3);
+  	rt2800_bbp_write(rt2x00dev, 1, r1);
+  
+diff --git a/package/kernel/mac80211/patches/600-0028-rt2x00-rt2800lib-fix-LNA-gain-configuration-for-RT38.patch b/package/kernel/mac80211/patches/600-0028-rt2x00-rt2800lib-fix-LNA-gain-configuration-for-RT38.patch
+index 9945f38..4da750e 100644
+--- a/package/kernel/mac80211/patches/600-0028-rt2x00-rt2800lib-fix-LNA-gain-configuration-for-RT38.patch
++++ b/package/kernel/mac80211/patches/600-0028-rt2x00-rt2800lib-fix-LNA-gain-configuration-for-RT38.patch
+@@ -10,7 +10,7 @@ Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
+ 
+ --- a/drivers/net/wireless/rt2x00/rt2800lib.c
+ +++ b/drivers/net/wireless/rt2x00/rt2800lib.c
+-@@ -1984,7 +1984,8 @@ static void rt2800_config_lna_gain(struc
++@@ -1960,7 +1960,8 @@ static void rt2800_config_lna_gain(struc
+  		rt2800_eeprom_read(rt2x00dev, EEPROM_LNA, &eeprom);
+  		lna_gain = rt2x00_get_field16(eeprom, EEPROM_LNA_A0);
+  	} else if (libconf->rf.channel <= 128) {
+@@ -20,7 +20,7 @@ Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
+  			rt2800_eeprom_read(rt2x00dev, EEPROM_EXT_LNA2, &eeprom);
+  			lna_gain = rt2x00_get_field16(eeprom,
+  						      EEPROM_EXT_LNA2_A1);
+-@@ -1994,7 +1995,8 @@ static void rt2800_config_lna_gain(struc
++@@ -1970,7 +1971,8 @@ static void rt2800_config_lna_gain(struc
+  						      EEPROM_RSSI_BG2_LNA_A1);
+  		}
+  	} else {
+diff --git a/package/kernel/mac80211/patches/600-0029-rt2x00-rt2800lib-fix-VGC-setup-for-RT3883.patch b/package/kernel/mac80211/patches/600-0029-rt2x00-rt2800lib-fix-VGC-setup-for-RT3883.patch
+index beadea8..628b237 100644
+--- a/package/kernel/mac80211/patches/600-0029-rt2x00-rt2800lib-fix-VGC-setup-for-RT3883.patch
++++ b/package/kernel/mac80211/patches/600-0029-rt2x00-rt2800lib-fix-VGC-setup-for-RT3883.patch
+@@ -10,7 +10,7 @@ Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
+ 
+ --- a/drivers/net/wireless/rt2x00/rt2800lib.c
+ +++ b/drivers/net/wireless/rt2x00/rt2800lib.c
+-@@ -4835,7 +4835,8 @@ static u8 rt2800_get_default_vgc(struct
++@@ -4811,7 +4811,8 @@ static u8 rt2800_get_default_vgc(struct
+  		else
+  			vgc = 0x2e + rt2x00dev->lna_gain;
+  	} else { /* 5GHZ band */
+@@ -20,7 +20,7 @@ Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
+  			vgc = 0x20 + (rt2x00dev->lna_gain * 5) / 3;
+  		else if (rt2x00_rt(rt2x00dev, RT5592))
+  			vgc = 0x24 + (2 * rt2x00dev->lna_gain);
+-@@ -4855,7 +4856,8 @@ static inline void rt2800_set_vgc(struct
++@@ -4831,7 +4832,8 @@ static inline void rt2800_set_vgc(struct
+  {
+  	if (qual->vgc_level != vgc_level) {
+  		if (rt2x00_rt(rt2x00dev, RT3572) ||
+@@ -30,7 +30,7 @@ Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
+  			rt2800_bbp_write_with_rx_chain(rt2x00dev, 66,
+  						       vgc_level);
+  		} else if (rt2x00_rt(rt2x00dev, RT5592)) {
+-@@ -4902,6 +4904,11 @@ void rt2800_link_tuner(struct rt2x00_dev
++@@ -4878,6 +4880,11 @@ void rt2800_link_tuner(struct rt2x00_dev
+  		}
+  		break;
+  
+diff --git a/package/kernel/mac80211/patches/600-0030-rt2x00-rt2800lib-fix-EEPROM-LNA-validation-for-RT388.patch b/package/kernel/mac80211/patches/600-0030-rt2x00-rt2800lib-fix-EEPROM-LNA-validation-for-RT388.patch
+index a6c0f58..216b8b6 100644
+--- a/package/kernel/mac80211/patches/600-0030-rt2x00-rt2800lib-fix-EEPROM-LNA-validation-for-RT388.patch
++++ b/package/kernel/mac80211/patches/600-0030-rt2x00-rt2800lib-fix-EEPROM-LNA-validation-for-RT388.patch
+@@ -10,7 +10,7 @@ Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
+ 
+ --- a/drivers/net/wireless/rt2x00/rt2800lib.c
+ +++ b/drivers/net/wireless/rt2x00/rt2800lib.c
+-@@ -7630,7 +7630,8 @@ static int rt2800_validate_eeprom(struct
++@@ -7606,7 +7606,8 @@ static int rt2800_validate_eeprom(struct
+  	rt2800_eeprom_read(rt2x00dev, EEPROM_RSSI_BG2, &word);
+  	if (abs(rt2x00_get_field16(word, EEPROM_RSSI_BG2_OFFSET2)) > 10)
+  		rt2x00_set_field16(&word, EEPROM_RSSI_BG2_OFFSET2, 0);
+@@ -20,7 +20,7 @@ Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
+  		if (rt2x00_get_field16(word, EEPROM_RSSI_BG2_LNA_A1) == 0x00 ||
+  		    rt2x00_get_field16(word, EEPROM_RSSI_BG2_LNA_A1) == 0xff)
+  			rt2x00_set_field16(&word, EEPROM_RSSI_BG2_LNA_A1,
+-@@ -7650,7 +7651,8 @@ static int rt2800_validate_eeprom(struct
++@@ -7626,7 +7627,8 @@ static int rt2800_validate_eeprom(struct
+  	rt2800_eeprom_read(rt2x00dev, EEPROM_RSSI_A2, &word);
+  	if (abs(rt2x00_get_field16(word, EEPROM_RSSI_A2_OFFSET2)) > 10)
+  		rt2x00_set_field16(&word, EEPROM_RSSI_A2_OFFSET2, 0);
+@@ -30,7 +30,7 @@ Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
+  		if (rt2x00_get_field16(word, EEPROM_RSSI_A2_LNA_A2) == 0x00 ||
+  		    rt2x00_get_field16(word, EEPROM_RSSI_A2_LNA_A2) == 0xff)
+  			rt2x00_set_field16(&word, EEPROM_RSSI_A2_LNA_A2,
+-@@ -7658,7 +7660,8 @@ static int rt2800_validate_eeprom(struct
++@@ -7634,7 +7636,8 @@ static int rt2800_validate_eeprom(struct
+  	}
+  	rt2800_eeprom_write(rt2x00dev, EEPROM_RSSI_A2, word);
+  
+diff --git a/package/kernel/mac80211/patches/600-0031-rt2x00-rt2800lib-fix-txpower-compensation-for-RT3883.patch b/package/kernel/mac80211/patches/600-0031-rt2x00-rt2800lib-fix-txpower-compensation-for-RT3883.patch
+index 910f9ec..515086f 100644
+--- a/package/kernel/mac80211/patches/600-0031-rt2x00-rt2800lib-fix-txpower-compensation-for-RT3883.patch
++++ b/package/kernel/mac80211/patches/600-0031-rt2x00-rt2800lib-fix-txpower-compensation-for-RT3883.patch
+@@ -10,7 +10,7 @@ Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
+ 
+ --- a/drivers/net/wireless/rt2x00/rt2800lib.c
+ +++ b/drivers/net/wireless/rt2x00/rt2800lib.c
+-@@ -4005,6 +4005,9 @@ static u8 rt2800_compensate_txpower(stru
++@@ -3981,6 +3981,9 @@ static u8 rt2800_compensate_txpower(stru
+  	if (rt2x00_rt(rt2x00dev, RT3593))
+  		return min_t(u8, txpower, 0xc);
+  
+diff --git a/package/kernel/mac80211/patches/600-0032-rt2x00-rt2800lib-enable-RT2800_HAS_HIGH_SHARED_MEM-f.patch b/package/kernel/mac80211/patches/600-0032-rt2x00-rt2800lib-enable-RT2800_HAS_HIGH_SHARED_MEM-f.patch
+index bcdfc67..77e3f1b 100644
+--- a/package/kernel/mac80211/patches/600-0032-rt2x00-rt2800lib-enable-RT2800_HAS_HIGH_SHARED_MEM-f.patch
++++ b/package/kernel/mac80211/patches/600-0032-rt2x00-rt2800lib-enable-RT2800_HAS_HIGH_SHARED_MEM-f.patch
+@@ -11,7 +11,7 @@ Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
+ 
+ --- a/drivers/net/wireless/rt2x00/rt2800lib.c
+ +++ b/drivers/net/wireless/rt2x00/rt2800lib.c
+-@@ -8441,7 +8441,8 @@ int rt2800_probe_hw(struct rt2x00_dev *r
++@@ -8415,7 +8415,8 @@ int rt2800_probe_hw(struct rt2x00_dev *r
+  	if (retval)
+  		return retval;
+  
+diff --git a/package/kernel/mac80211/patches/603-rt2x00-introduce-rt2x00eeprom.patch b/package/kernel/mac80211/patches/603-rt2x00-introduce-rt2x00eeprom.patch
+index 8f650a2..44b629f 100644
+--- a/package/kernel/mac80211/patches/603-rt2x00-introduce-rt2x00eeprom.patch
++++ b/package/kernel/mac80211/patches/603-rt2x00-introduce-rt2x00eeprom.patch
+@@ -1,13 +1,13 @@
+ --- a/.local-symbols
+ +++ b/.local-symbols
+-@@ -263,6 +263,7 @@ RT2X00_LIB_FIRMWARE=
++@@ -312,6 +312,7 @@ RT2X00_LIB_FIRMWARE=
+  RT2X00_LIB_CRYPTO=
+  RT2X00_LIB_LEDS=
+  RT2X00_LIB_DEBUGFS=
+ +RT2X00_LIB_EEPROM=
+  RT2X00_DEBUG=
+- RTL_CARDS=
+- RTL8192CE=
++ WL_MEDIATEK=
++ MT7601U=
+ --- a/drivers/net/wireless/rt2x00/Kconfig
+ +++ b/drivers/net/wireless/rt2x00/Kconfig
+ @@ -69,6 +69,7 @@ config RT2800PCI
+@@ -48,7 +48,7 @@
+  obj-$(CPTCFG_RT2X00_LIB_MMIO)		+= rt2x00mmio.o
+ --- a/drivers/net/wireless/rt2x00/rt2800lib.h
+ +++ b/drivers/net/wireless/rt2x00/rt2800lib.h
+-@@ -43,6 +43,8 @@ struct rt2800_drv_data {
++@@ -46,6 +46,8 @@ struct rt2800_drv_data {
+  	} shmem_lock;
+  };
+  
+@@ -57,7 +57,7 @@
+  struct rt2800_ops {
+  	void (*register_read)(struct rt2x00_dev *rt2x00dev,
+  			      const unsigned int offset, u32 *value);
+-@@ -176,6 +178,15 @@ static inline int rt2800_read_eeprom(str
++@@ -179,6 +181,15 @@ static inline int rt2800_read_eeprom(str
+  {
+  	const struct rt2800_ops *rt2800ops = rt2x00dev->ops->drv;
+  
+diff --git a/package/kernel/mac80211/patches/608-add_platform_data_mac_addr.patch b/package/kernel/mac80211/patches/608-add_platform_data_mac_addr.patch
+index a35bd55..16a579d 100644
+--- a/package/kernel/mac80211/patches/608-add_platform_data_mac_addr.patch
++++ b/package/kernel/mac80211/patches/608-add_platform_data_mac_addr.patch
+@@ -41,7 +41,7 @@
+   * Interrupt context handlers.
+ --- a/drivers/net/wireless/rt2x00/rt61pci.c
+ +++ b/drivers/net/wireless/rt2x00/rt61pci.c
+-@@ -2392,6 +2392,7 @@ static int rt61pci_validate_eeprom(struc
++@@ -2390,6 +2390,7 @@ static int rt61pci_validate_eeprom(struc
+  	u32 reg;
+  	u16 word;
+  	u8 *mac;
+@@ -49,7 +49,7 @@
+  	s8 value;
+  
+  	rt2x00mmio_register_read(rt2x00dev, E2PROM_CSR, &reg);
+-@@ -2412,7 +2413,11 @@ static int rt61pci_validate_eeprom(struc
++@@ -2410,7 +2411,11 @@ static int rt61pci_validate_eeprom(struc
+  	/*
+  	 * Start validation of the data that has been read.
+  	 */
+diff --git a/package/kernel/mac80211/patches/610-rt2x00-fix-rt3352-ext-pa.patch b/package/kernel/mac80211/patches/610-rt2x00-fix-rt3352-ext-pa.patch
+index 067d2ea..39b1ccc 100644
+--- a/package/kernel/mac80211/patches/610-rt2x00-fix-rt3352-ext-pa.patch
++++ b/package/kernel/mac80211/patches/610-rt2x00-fix-rt3352-ext-pa.patch
+@@ -1,6 +1,6 @@
+ --- a/drivers/net/wireless/rt2x00/rt2800lib.c
+ +++ b/drivers/net/wireless/rt2x00/rt2800lib.c
+-@@ -3552,11 +3552,18 @@ static void rt2800_config_channel(struct
++@@ -3528,11 +3528,18 @@ static void rt2800_config_channel(struct
+  	/*
+  	 * Change BBP settings
+  	 */
+@@ -19,7 +19,7 @@
+  	} else if (rt2x00_rt(rt2x00dev, RT3593)) {
+  		if (rf->channel > 14) {
+  			/* Disable CCK Packet detection on 5GHz */
+-@@ -6618,6 +6625,12 @@ static void rt2800_init_rfcsr_3290(struc
++@@ -6594,6 +6601,12 @@ static void rt2800_init_rfcsr_3290(struc
+  
+  static void rt2800_init_rfcsr_3352(struct rt2x00_dev *rt2x00dev)
+  {
+@@ -32,7 +32,7 @@
+  	rt2800_rf_init_calibration(rt2x00dev, 30);
+  
+  	rt2800_rfcsr_write(rt2x00dev, 0, 0xf0);
+-@@ -6653,15 +6666,30 @@ static void rt2800_init_rfcsr_3352(struc
++@@ -6629,15 +6642,30 @@ static void rt2800_init_rfcsr_3352(struc
+  	rt2800_rfcsr_write(rt2x00dev, 31, 0x80);
+  	rt2800_rfcsr_write(rt2x00dev, 32, 0x80);
+  	rt2800_rfcsr_write(rt2x00dev, 33, 0x00);
+@@ -66,7 +66,7 @@
+  	rt2800_rfcsr_write(rt2x00dev, 43, 0xdb);
+  	rt2800_rfcsr_write(rt2x00dev, 44, 0xdb);
+  	rt2800_rfcsr_write(rt2x00dev, 45, 0xdb);
+-@@ -6669,15 +6697,20 @@ static void rt2800_init_rfcsr_3352(struc
++@@ -6645,15 +6673,20 @@ static void rt2800_init_rfcsr_3352(struc
+  	rt2800_rfcsr_write(rt2x00dev, 47, 0x0d);
+  	rt2800_rfcsr_write(rt2x00dev, 48, 0x14);
+  	rt2800_rfcsr_write(rt2x00dev, 49, 0x00);
+@@ -96,7 +96,7 @@
+  	rt2800_rfcsr_write(rt2x00dev, 59, 0x00);
+  	rt2800_rfcsr_write(rt2x00dev, 60, 0x00);
+  	rt2800_rfcsr_write(rt2x00dev, 61, 0x00);
+-@@ -7698,6 +7731,7 @@ static int rt2800_init_eeprom(struct rt2
++@@ -7674,6 +7707,7 @@ static int rt2800_init_eeprom(struct rt2
+  	 * RT53xx: defined in "EEPROM_CHIP_ID" field
+  	 */
+  	if (rt2x00_rt(rt2x00dev, RT3290) ||
+@@ -104,7 +104,7 @@
+  	    rt2x00_rt(rt2x00dev, RT5390) ||
+  	    rt2x00_rt(rt2x00dev, RT5392))
+  		rt2800_eeprom_read(rt2x00dev, EEPROM_CHIP_ID, &rf);
+-@@ -7793,7 +7827,8 @@ static int rt2800_init_eeprom(struct rt2
++@@ -7769,7 +7803,8 @@ static int rt2800_init_eeprom(struct rt2
+  	/*
+  	 * Detect if this device has Bluetooth co-existence.
+  	 */
+@@ -114,7 +114,7 @@
+  		__set_bit(CAPABILITY_BT_COEXIST, &rt2x00dev->cap_flags);
+  
+  	/*
+-@@ -7822,6 +7857,22 @@ static int rt2800_init_eeprom(struct rt2
++@@ -7798,6 +7833,22 @@ static int rt2800_init_eeprom(struct rt2
+  					EIRP_MAX_TX_POWER_LIMIT)
+  		__set_bit(CAPABILITY_POWER_LIMIT, &rt2x00dev->cap_flags);
+  
+diff --git a/package/kernel/mac80211/patches/611-rt2x00-rf_vals-rt3352-xtal20.patch b/package/kernel/mac80211/patches/611-rt2x00-rf_vals-rt3352-xtal20.patch
+index 1dcca36..dcecba4 100644
+--- a/package/kernel/mac80211/patches/611-rt2x00-rf_vals-rt3352-xtal20.patch
++++ b/package/kernel/mac80211/patches/611-rt2x00-rf_vals-rt3352-xtal20.patch
+@@ -1,6 +1,6 @@
+ --- a/drivers/net/wireless/rt2x00/rt2800lib.c
+ +++ b/drivers/net/wireless/rt2x00/rt2800lib.c
+-@@ -8209,6 +8209,27 @@ static const struct rf_channel rf_vals_5
++@@ -8185,6 +8185,27 @@ static const struct rf_channel rf_vals_5
+  	{196, 83, 0, 12, 1},
+  };
+  
+@@ -28,7 +28,7 @@
+  static int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
+  {
+  	struct hw_mode_spec *spec = &rt2x00dev->spec;
+-@@ -8297,7 +8318,10 @@ static int rt2800_probe_hw_mode(struct r
++@@ -8271,7 +8292,10 @@ static int rt2800_probe_hw_mode(struct r
+  	case RF5390:
+  	case RF5392:
+  		spec->num_channels = 14;
+@@ -40,7 +40,7 @@
+  		break;
+  
+  	case RF3052:
+-@@ -8481,6 +8505,19 @@ static int rt2800_probe_rt(struct rt2x00
++@@ -8455,6 +8479,19 @@ static int rt2800_probe_rt(struct rt2x00
+  	return 0;
+  }
+  
+@@ -60,7 +60,7 @@
+  int rt2800_probe_hw(struct rt2x00_dev *rt2x00dev)
+  {
+  	struct rt2800_drv_data *drv_data = rt2x00dev->drv_data;
+-@@ -8523,6 +8560,15 @@ int rt2800_probe_hw(struct rt2x00_dev *r
++@@ -8497,6 +8534,15 @@ int rt2800_probe_hw(struct rt2x00_dev *r
+  	rt2800_register_write(rt2x00dev, GPIO_CTRL, reg);
+  
+  	/*
+diff --git a/package/kernel/mac80211/patches/615-rt2x00-fix_20mhz_clk.patch b/package/kernel/mac80211/patches/615-rt2x00-fix_20mhz_clk.patch
+index c779a17..9f11862 100644
+--- a/package/kernel/mac80211/patches/615-rt2x00-fix_20mhz_clk.patch
++++ b/package/kernel/mac80211/patches/615-rt2x00-fix_20mhz_clk.patch
+@@ -8,7 +8,7 @@
+  
+  #include "rt2x00.h"
+  #include "rt2800lib.h"
+-@@ -8507,13 +8508,14 @@ static int rt2800_probe_rt(struct rt2x00
++@@ -8481,13 +8482,14 @@ static int rt2800_probe_rt(struct rt2x00
+  
+  int rt2800_probe_clk(struct rt2x00_dev *rt2x00dev)
+  {
+diff --git a/package/kernel/mac80211/patches/616-rt2x00-support-rt5350.patch b/package/kernel/mac80211/patches/616-rt2x00-support-rt5350.patch
+index 840b3bc..9679d71 100644
+--- a/package/kernel/mac80211/patches/616-rt2x00-support-rt5350.patch
++++ b/package/kernel/mac80211/patches/616-rt2x00-support-rt5350.patch
+@@ -10,7 +10,7 @@
+  #define RF5370				0x5370
+ --- a/drivers/net/wireless/rt2x00/rt2800lib.c
+ +++ b/drivers/net/wireless/rt2x00/rt2800lib.c
+-@@ -3038,6 +3038,13 @@ static void rt2800_config_channel_rf53xx
++@@ -3014,6 +3014,13 @@ static void rt2800_config_channel_rf53xx
+  
+  				rt2800_rfcsr_write(rt2x00dev, 59,
+  						   r59_non_bt[idx]);
+@@ -24,7 +24,7 @@
+  			}
+  		}
+  	}
+-@@ -3516,6 +3523,7 @@ static void rt2800_config_channel(struct
++@@ -3492,6 +3499,7 @@ static void rt2800_config_channel(struct
+  		rt2800_config_channel_rf3853(rt2x00dev, conf, rf, info);
+  		break;
+  	case RF3070:
+@@ -32,7 +32,7 @@
+  	case RF5360:
+  	case RF5362:
+  	case RF5370:
+-@@ -3534,6 +3542,7 @@ static void rt2800_config_channel(struct
++@@ -3510,6 +3518,7 @@ static void rt2800_config_channel(struct
+  	if (rt2x00_rf(rt2x00dev, RF3070) ||
+  	    rt2x00_rf(rt2x00dev, RF3290) ||
+  	    rt2x00_rf(rt2x00dev, RF3322) ||
+@@ -40,7 +40,7 @@
+  	    rt2x00_rf(rt2x00dev, RF5360) ||
+  	    rt2x00_rf(rt2x00dev, RF5362) ||
+  	    rt2x00_rf(rt2x00dev, RF5370) ||
+-@@ -3812,7 +3821,8 @@ static void rt2800_config_channel(struct
++@@ -3788,7 +3797,8 @@ static void rt2800_config_channel(struct
+  	/*
+  	 * Clear update flag
+  	 */
+@@ -50,7 +50,7 @@
+  		rt2800_bbp_read(rt2x00dev, 49, &bbp);
+  		rt2x00_set_field8(&bbp, BBP49_UPDATE_FLAG, 0);
+  		rt2800_bbp_write(rt2x00dev, 49, bbp);
+-@@ -4698,6 +4708,7 @@ void rt2800_vco_calibration(struct rt2x0
++@@ -4674,6 +4684,7 @@ void rt2800_vco_calibration(struct rt2x0
+  	case RF3070:
+  	case RF3290:
+  	case RF3853:
+@@ -58,7 +58,7 @@
+  	case RF5360:
+  	case RF5362:
+  	case RF5370:
+-@@ -5111,6 +5122,8 @@ static int rt2800_init_registers(struct
++@@ -5087,6 +5098,8 @@ static int rt2800_init_registers(struct
+  		rt2800_register_write(rt2x00dev, TX_SW_CFG0, 0x00000404);
+  		rt2800_register_write(rt2x00dev, TX_SW_CFG1, 0x00080606);
+  		rt2800_register_write(rt2x00dev, TX_SW_CFG2, 0x00000000);
+@@ -67,7 +67,7 @@
+  	} else {
+  		rt2800_register_write(rt2x00dev, TX_SW_CFG0, 0x00000000);
+  		rt2800_register_write(rt2x00dev, TX_SW_CFG1, 0x00080606);
+-@@ -5766,9 +5779,13 @@ static void rt2800_init_bbp_3352(struct
++@@ -5742,9 +5755,13 @@ static void rt2800_init_bbp_3352(struct
+  
+  	rt2800_bbp_write(rt2x00dev, 82, 0x62);
+  
+@@ -84,7 +84,7 @@
+  
+  	rt2800_bbp_write(rt2x00dev, 86, 0x38);
+  
+-@@ -5782,9 +5799,13 @@ static void rt2800_init_bbp_3352(struct
++@@ -5758,9 +5775,13 @@ static void rt2800_init_bbp_3352(struct
+  
+  	rt2800_bbp_write(rt2x00dev, 104, 0x92);
+  
+@@ -101,7 +101,7 @@
+  
+  	rt2800_bbp_write(rt2x00dev, 120, 0x50);
+  
+-@@ -5809,6 +5830,13 @@ static void rt2800_init_bbp_3352(struct
++@@ -5785,6 +5806,13 @@ static void rt2800_init_bbp_3352(struct
+  	rt2800_bbp_write(rt2x00dev, 143, 0xa2);
+  
+  	rt2800_bbp_write(rt2x00dev, 148, 0xc8);
+@@ -115,7 +115,7 @@
+  }
+  
+  static void rt2800_init_bbp_3390(struct rt2x00_dev *rt2x00dev)
+-@@ -6150,6 +6178,7 @@ static void rt2800_init_bbp(struct rt2x0
++@@ -6126,6 +6154,7 @@ static void rt2800_init_bbp(struct rt2x0
+  		rt2800_init_bbp_3290(rt2x00dev);
+  		break;
+  	case RT3352:
+@@ -123,7 +123,7 @@
+  		rt2800_init_bbp_3352(rt2x00dev);
+  		break;
+  	case RT3390:
+-@@ -7101,6 +7130,76 @@ static void rt2800_init_rfcsr_3883(struc
++@@ -7077,6 +7106,76 @@ static void rt2800_init_rfcsr_3883(struc
+  	rt2800_rfcsr_write(rt2x00dev, 20, rfcsr);
+  }
+  
+@@ -200,7 +200,7 @@
+  static void rt2800_init_rfcsr_5390(struct rt2x00_dev *rt2x00dev)
+  {
+  	rt2800_rf_init_calibration(rt2x00dev, 2);
+-@@ -7341,6 +7440,9 @@ static void rt2800_init_rfcsr(struct rt2
++@@ -7317,6 +7416,9 @@ static void rt2800_init_rfcsr(struct rt2
+  	case RT3593:
+  		rt2800_init_rfcsr_3593(rt2x00dev);
+  		break;
+@@ -210,7 +210,7 @@
+  	case RT5390:
+  		rt2800_init_rfcsr_5390(rt2x00dev);
+  		break;
+-@@ -7600,6 +7702,12 @@ static int rt2800_validate_eeprom(struct
++@@ -7576,6 +7678,12 @@ static int rt2800_validate_eeprom(struct
+  		rt2x00_set_field16(&word, EEPROM_NIC_CONF0_RF_TYPE, RF2820);
+  		rt2800_eeprom_write(rt2x00dev, EEPROM_NIC_CONF0, word);
+  		rt2x00_eeprom_dbg(rt2x00dev, "Antenna: 0x%04x\n", word);
+@@ -223,7 +223,7 @@
+  	} else if (rt2x00_rt(rt2x00dev, RT2860) ||
+  		   rt2x00_rt(rt2x00dev, RT2872)) {
+  		/*
+-@@ -7738,6 +7846,8 @@ static int rt2800_init_eeprom(struct rt2
++@@ -7714,6 +7822,8 @@ static int rt2800_init_eeprom(struct rt2
+  		rt2800_eeprom_read(rt2x00dev, EEPROM_CHIP_ID, &rf);
+  	else if (rt2x00_rt(rt2x00dev, RT3883))
+  		rf = RF3853;
+@@ -232,7 +232,7 @@
+  	else
+  		rf = rt2x00_get_field16(eeprom, EEPROM_NIC_CONF0_RF_TYPE);
+  
+-@@ -7757,6 +7867,7 @@ static int rt2800_init_eeprom(struct rt2
++@@ -7733,6 +7843,7 @@ static int rt2800_init_eeprom(struct rt2
+  	case RF3320:
+  	case RF3322:
+  	case RF3853:
+@@ -240,7 +240,7 @@
+  	case RF5360:
+  	case RF5362:
+  	case RF5370:
+-@@ -8312,6 +8423,7 @@ static int rt2800_probe_hw_mode(struct r
++@@ -8286,6 +8397,7 @@ static int rt2800_probe_hw_mode(struct r
+  	case RF3290:
+  	case RF3320:
+  	case RF3322:
+@@ -248,7 +248,7 @@
+  	case RF5360:
+  	case RF5362:
+  	case RF5370:
+-@@ -8451,6 +8563,7 @@ static int rt2800_probe_hw_mode(struct r
++@@ -8425,6 +8537,7 @@ static int rt2800_probe_hw_mode(struct r
+  	case RF3070:
+  	case RF3290:
+  	case RF3853:
+@@ -256,7 +256,7 @@
+  	case RF5360:
+  	case RF5362:
+  	case RF5370:
+-@@ -8491,6 +8604,7 @@ static int rt2800_probe_rt(struct rt2x00
++@@ -8465,6 +8578,7 @@ static int rt2800_probe_rt(struct rt2x00
+  	case RT3572:
+  	case RT3593:
+  	case RT3883:
+diff --git a/package/kernel/mac80211/patches/619-rt2x00-change-led-polarity-from-OF.patch b/package/kernel/mac80211/patches/619-rt2x00-change-led-polarity-from-OF.patch
+index 13f2048..b085c5e 100644
+--- a/package/kernel/mac80211/patches/619-rt2x00-change-led-polarity-from-OF.patch
++++ b/package/kernel/mac80211/patches/619-rt2x00-change-led-polarity-from-OF.patch
+@@ -8,7 +8,7 @@
+  
+  #include "rt2x00.h"
+  #include "rt2800lib.h"
+-@@ -7957,6 +7958,17 @@ static int rt2800_init_eeprom(struct rt2
++@@ -7933,6 +7934,17 @@ static int rt2800_init_eeprom(struct rt2
+  	rt2800_init_led(rt2x00dev, &rt2x00dev->led_assoc, LED_TYPE_ASSOC);
+  	rt2800_init_led(rt2x00dev, &rt2x00dev->led_qual, LED_TYPE_QUALITY);
+  
+diff --git a/package/kernel/mac80211/patches/620-rt2x00-rt3352-rf-id.patch b/package/kernel/mac80211/patches/620-rt2x00-rt3352-rf-id.patch
+index aaa8367..259cb1f 100644
+--- a/package/kernel/mac80211/patches/620-rt2x00-rt3352-rf-id.patch
++++ b/package/kernel/mac80211/patches/620-rt2x00-rt3352-rf-id.patch
+@@ -1,6 +1,6 @@
+ --- a/drivers/net/wireless/rt2x00/rt2800lib.c
+ +++ b/drivers/net/wireless/rt2x00/rt2800lib.c
+-@@ -7841,10 +7841,11 @@ static int rt2800_init_eeprom(struct rt2
++@@ -7817,10 +7817,11 @@ static int rt2800_init_eeprom(struct rt2
+  	 * RT53xx: defined in "EEPROM_CHIP_ID" field
+  	 */
+  	if (rt2x00_rt(rt2x00dev, RT3290) ||
+diff --git a/package/kernel/mac80211/patches/621-rt2x00-ht20_40_fix.patch b/package/kernel/mac80211/patches/621-rt2x00-ht20_40_fix.patch
+index bb2fc1c..77d63fe 100644
+--- a/package/kernel/mac80211/patches/621-rt2x00-ht20_40_fix.patch
++++ b/package/kernel/mac80211/patches/621-rt2x00-ht20_40_fix.patch
+@@ -11,7 +11,7 @@
+   * RFCSR 31:
+ --- a/drivers/net/wireless/rt2x00/rt2800lib.c
+ +++ b/drivers/net/wireless/rt2x00/rt2800lib.c
+-@@ -3551,8 +3551,13 @@ static void rt2800_config_channel(struct
++@@ -3527,8 +3527,13 @@ static void rt2800_config_channel(struct
+  	    rt2x00_rf(rt2x00dev, RF5390) ||
+  	    rt2x00_rf(rt2x00dev, RF5392)) {
+  		rt2800_rfcsr_read(rt2x00dev, 30, &rfcsr);
+diff --git a/package/kernel/mac80211/patches/801-libertas-configure-sysfs-links.patch b/package/kernel/mac80211/patches/801-libertas-configure-sysfs-links.patch
+index 9e29034..3b8b756 100644
+--- a/package/kernel/mac80211/patches/801-libertas-configure-sysfs-links.patch
++++ b/package/kernel/mac80211/patches/801-libertas-configure-sysfs-links.patch
+@@ -1,6 +1,6 @@
+ --- a/drivers/net/wireless/libertas/cfg.c
+ +++ b/drivers/net/wireless/libertas/cfg.c
+-@@ -2084,6 +2084,8 @@ struct wireless_dev *lbs_cfg_alloc(struc
++@@ -2083,6 +2083,8 @@ struct wireless_dev *lbs_cfg_alloc(struc
+  		goto err_wiphy_new;
+  	}
+  
+diff --git a/package/kernel/mac80211/patches/802-libertas-set-wireless-macaddr.patch b/package/kernel/mac80211/patches/802-libertas-set-wireless-macaddr.patch
+index 252fa81..dace56b 100644
+--- a/package/kernel/mac80211/patches/802-libertas-set-wireless-macaddr.patch
++++ b/package/kernel/mac80211/patches/802-libertas-set-wireless-macaddr.patch
+@@ -1,6 +1,6 @@
+ --- a/drivers/net/wireless/libertas/cfg.c
+ +++ b/drivers/net/wireless/libertas/cfg.c
+-@@ -2174,6 +2174,8 @@ int lbs_cfg_register(struct lbs_private
++@@ -2173,6 +2173,8 @@ int lbs_cfg_register(struct lbs_private
+  	wdev->wiphy->n_cipher_suites = ARRAY_SIZE(cipher_suites);
+  	wdev->wiphy->reg_notifier = lbs_reg_notifier;
+  
+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 ac58dba..dd82ce5 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. */
+-@@ -3302,8 +3302,8 @@ static int b43_chip_init(struct b43_wlde
++@@ -3300,8 +3300,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);
+-@@ -4003,7 +4003,6 @@ static int b43_op_config(struct ieee8021
++@@ -4001,7 +4001,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);
+-@@ -4046,11 +4045,9 @@ static int b43_op_config(struct ieee8021
++@@ -4044,11 +4043,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) {
+-@@ -5213,6 +5210,47 @@ static int b43_op_get_survey(struct ieee
++@@ -5209,6 +5206,47 @@ static int b43_op_get_survey(struct ieee
+  	return 0;
+  }
+  
+@@ -90,7 +90,7 @@
+  static const struct ieee80211_ops b43_hw_ops = {
+  	.tx			= b43_op_tx,
+  	.conf_tx		= b43_op_conf_tx,
+-@@ -5234,6 +5272,8 @@ static const struct ieee80211_ops b43_hw
++@@ -5230,6 +5268,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,
+@@ -99,7 +99,7 @@
+  };
+  
+  /* Hard-reset the chip. Do not call this directly.
+-@@ -5542,6 +5582,8 @@ static int b43_one_core_attach(struct b4
++@@ -5538,6 +5578,8 @@ static int b43_one_core_attach(struct b4
+  	if (!wldev)
+  		goto out;
+  
+@@ -108,7 +108,7 @@
+  	wldev->use_pio = b43_modparam_pio;
+  	wldev->dev = dev;
+  	wldev->wl = wl;
+-@@ -5632,6 +5674,9 @@ static struct b43_wl *b43_wireless_init(
++@@ -5628,6 +5670,9 @@ static struct b43_wl *b43_wireless_init(
+  
+  	hw->wiphy->flags |= WIPHY_FLAG_IBSS_RSN;
+  
+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 1cba2b3..5fdfa37 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/brcm80211/brcmfmac/cfg80211.c
+ +++ b/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c
+-@@ -691,9 +691,37 @@ static struct wireless_dev *brcmf_cfg802
++@@ -692,9 +692,37 @@ static struct wireless_dev *brcmf_cfg802
+  						     u32 *flags,
+  						     struct vif_params *params)
+  {
+diff --git a/package/kernel/mac80211/patches/900-wlcore-Add-support-for-DT-platform-data.patch b/package/kernel/mac80211/patches/900-wlcore-Add-support-for-DT-platform-data.patch
+deleted file mode 100644
+index 856dea8..0000000
+--- a/package/kernel/mac80211/patches/900-wlcore-Add-support-for-DT-platform-data.patch
++++ /dev/null
+@@ -1,139 +0,0 @@
+-When running with DT, we no longer have a board file that can set up the
+-platform data for wlcore. Allow this data to be passed from DT.
+-
+-Since some platforms use a gpio-irq, add support for passing either the
+-irq number or the gpio number. For the latter case, the driver will
+-request the gpio and convert it to the irq number. If an irq is
+-specified, it'll be used as is.
+-
+-[Arik - the pdev_data pointer does not belong to us and is freed when
+-the device is released. Dereference to our private data first.]
+-
+-Signed-off-by: Ido Yariv <ido@wizery.com>
+-Signed-off-by: Arik Nemtsov <arik@wizery.com>
+----
+- drivers/net/wireless/ti/wlcore/sdio.c | 71 ++++++++++++++++++++++++++++++++---
+- include/linux/wl12xx.h                |  3 +-
+- 2 files changed, 67 insertions(+), 7 deletions(-)
+-
+---- a/drivers/net/wireless/ti/wlcore/sdio.c
+-+++ b/drivers/net/wireless/ti/wlcore/sdio.c
+-@@ -34,6 +34,7 @@
+- #include <linux/wl12xx.h>
+- #include <linux/pm_runtime.h>
+- #include <linux/printk.h>
+-+#include <linux/of.h>
+- 
+- #include "wlcore.h"
+- #include "wl12xx_80211.h"
+-@@ -214,6 +215,61 @@ static struct wl1271_if_operations sdio_
+- 	.set_block_size = wl1271_sdio_set_block_size,
+- };
+- 
+-+static const struct of_device_id wlcore_of_match[] = {
+-+	{
+-+		.compatible = "wlcore",
+-+	},
+-+	{}
+-+};
+-+MODULE_DEVICE_TABLE(of, wlcore_of_match);
+-+
+-+static struct wl12xx_platform_data *get_platform_data(struct device *dev)
+-+{
+-+	struct wl12xx_platform_data *pdata;
+-+	struct device_node *np;
+-+	u32 gpio;
+-+
+-+	pdata = wl12xx_get_platform_data();
+-+	if (!IS_ERR(pdata))
+-+		return kmemdup(pdata, sizeof(*pdata), GFP_KERNEL);
+-+
+-+	np = of_find_matching_node(NULL, wlcore_of_match);
+-+	if (!np) {
+-+		dev_err(dev, "No platform data set\n");
+-+		return NULL;
+-+	}
+-+
+-+	pdata = kzalloc(sizeof(*pdata), GFP_KERNEL);
+-+	if (!pdata) {
+-+		dev_err(dev, "Can't allocate platform data\n");
+-+		return NULL;
+-+	}
+-+
+-+	if (of_property_read_u32(np, "irq", &pdata->irq)) {
+-+		if (!of_property_read_u32(np, "gpio", &gpio) &&
+-+		    !gpio_request_one(gpio, GPIOF_IN, "wlcore_irq")) {
+-+			pdata->gpio = gpio;
+-+			pdata->irq = gpio_to_irq(gpio);
+-+		}
+-+	}
+-+
+-+	/* Optional fields */
+-+	pdata->use_eeprom = of_property_read_bool(np, "use-eeprom");
+-+	of_property_read_u32(np, "board-ref-clock", &pdata->board_ref_clock);
+-+	of_property_read_u32(np, "board-tcxo-clock", &pdata->board_tcxo_clock);
+-+	of_property_read_u32(np, "platform-quirks", &pdata->platform_quirks);
+-+
+-+	return pdata;
+-+}
+-+
+-+static void del_platform_data(struct wl12xx_platform_data *pdata)
+-+{
+-+	if (pdata->gpio)
+-+		gpio_free(pdata->gpio);
+-+
+-+	kfree(pdata);
+-+}
+-+
+- static int wl1271_probe(struct sdio_func *func,
+- 				  const struct sdio_device_id *id)
+- {
+-@@ -245,10 +301,10 @@ static int wl1271_probe(struct sdio_func
+- 	/* Use block mode for transferring over one block size of data */
+- 	func->card->quirks |= MMC_QUIRK_BLKSZ_FOR_BYTE_MODE;
+- 
+--	pdev_data.pdata = wl12xx_get_platform_data();
+--	if (IS_ERR(pdev_data.pdata)) {
+--		ret = PTR_ERR(pdev_data.pdata);
+--		dev_err(glue->dev, "missing wlan platform data: %d\n", ret);
+-+	pdev_data.pdata = get_platform_data(&func->dev);
+-+	if (!pdev_data.pdata) {
+-+		ret = -EINVAL;
+-+		dev_err(glue->dev, "missing wlan platform data\n");
+- 		goto out_free_glue;
+- 	}
+- 
+-@@ -279,7 +335,7 @@ static int wl1271_probe(struct sdio_func
+- 	if (!glue->core) {
+- 		dev_err(glue->dev, "can't allocate platform_device");
+- 		ret = -ENOMEM;
+--		goto out_free_glue;
+-+		goto out_free_pdata;
+- 	}
+- 
+- 	glue->core->dev.parent = &func->dev;
+-@@ -313,6 +369,9 @@ static int wl1271_probe(struct sdio_func
+- out_dev_put:
+- 	platform_device_put(glue->core);
+- 
+-+out_free_pdata:
+-+	del_platform_data(pdev_data->pdata);
+-+
+- out_free_glue:
+- 	kfree(glue);
+- 
+-@@ -323,11 +382,14 @@ out:
+- static void wl1271_remove(struct sdio_func *func)
+- {
+- 	struct wl12xx_sdio_glue *glue = sdio_get_drvdata(func);
+-+	struct wlcore_platdev_data *pdev_data = glue->core->dev.platform_data;
+-+	struct wl12xx_platform_data *pdata = pdev_data->pdata;
+- 
+- 	/* Undo decrement done above in wl1271_probe */
+- 	pm_runtime_get_noresume(&func->dev);
+- 
+- 	platform_device_unregister(glue->core);
+-+	del_platform_data(pdata);
+- 	kfree(glue);
+- }
+- 
+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 501910f..b0536ce 100644
+--- a/package/kernel/mac80211/patches/910-01-add-support-for-mt7620.patch
++++ b/package/kernel/mac80211/patches/910-01-add-support-for-mt7620.patch
+@@ -210,7 +210,7 @@
+  	case RT5592:
+  		*txwi_size = TXWI_DESC_SIZE_5WORDS;
+  		*rxwi_size = RXWI_DESC_SIZE_6WORDS;
+-@@ -3326,6 +3399,312 @@ static void rt2800_config_channel_rf55xx
++@@ -3302,6 +3375,312 @@ static void rt2800_config_channel_rf55xx
+  	rt2800_bbp_write(rt2x00dev, 196, (rf->channel <= 14) ? 0x19 : 0x7F);
+  }
+  
+@@ -258,6 +258,7 @@
+ +	u32 mac_sys_ctrl, mac_status;
+ +	u32 tx_pin = 0x00150F0F;
+ +	struct hw_mode_spec *spec = &rt2x00dev->spec;
+++	struct rt2800_drv_data *drv_data = rt2x00dev->drv_data;
+ +
+ +	/* Frequeny plan setting */
+ +	/*	
+@@ -383,7 +384,6 @@
+ +		rfcsr &= (~0x4);
+ +	rt2800_rfcsr_write(rt2x00dev, 28, rfcsr);
+ +
+-+	struct rt2800_drv_data *drv_data = rt2x00dev->drv_data;
+ +	/*if (bScan == FALSE)*/
+ +	if (conf_is_ht40(conf)) {
+ +		txrx_agc_fc = rt2x00_get_field8(drv_data->calibration_bw40,
+@@ -523,7 +523,7 @@
+  static void rt2800_bbp_write_with_rx_chain(struct rt2x00_dev *rt2x00dev,
+  					   const unsigned int word,
+  					   const u8 value)
+-@@ -3482,7 +3861,7 @@ static void rt2800_config_channel(struct
++@@ -3458,7 +3837,7 @@ static void rt2800_config_channel(struct
+  				  struct channel_info *info)
+  {
+  	u32 reg;
+@@ -532,7 +532,7 @@
+  	u8 bbp, rfcsr;
+  
+  	info->default_power1 = rt2800_txpower_to_dev(rt2x00dev, rf->channel,
+-@@ -3536,6 +3915,9 @@ static void rt2800_config_channel(struct
++@@ -3512,6 +3891,9 @@ static void rt2800_config_channel(struct
+  	case RF5592:
+  		rt2800_config_channel_rf55xx(rt2x00dev, conf, rf, info);
+  		break;
+@@ -542,7 +542,7 @@
+  	default:
+  		rt2800_config_channel_rf2xxx(rt2x00dev, conf, rf, info);
+  	}
+-@@ -3638,7 +4020,7 @@ static void rt2800_config_channel(struct
++@@ -3614,7 +3996,7 @@ static void rt2800_config_channel(struct
+  		else if (rt2x00_rt(rt2x00dev, RT3593) ||
+  			 rt2x00_rt(rt2x00dev, RT3883))
+  			rt2800_bbp_write(rt2x00dev, 82, 0x82);
+@@ -551,7 +551,7 @@
+  			rt2800_bbp_write(rt2x00dev, 82, 0xf2);
+  
+  		if (rt2x00_rt(rt2x00dev, RT3593) ||
+-@@ -3660,7 +4042,7 @@ static void rt2800_config_channel(struct
++@@ -3636,7 +4018,7 @@ static void rt2800_config_channel(struct
+  	if (rt2x00_rt(rt2x00dev, RT3572))
+  		rt2800_rfcsr_write(rt2x00dev, 8, 0);
+  
+@@ -560,7 +560,7 @@
+  
+  	switch (rt2x00dev->default_ant.tx_chain_num) {
+  	case 3:
+-@@ -3709,6 +4091,7 @@ static void rt2800_config_channel(struct
++@@ -3685,6 +4067,7 @@ static void rt2800_config_channel(struct
+  
+  	rt2x00_set_field32(&tx_pin, TX_PIN_CFG_RFTR_EN, 1);
+  	rt2x00_set_field32(&tx_pin, TX_PIN_CFG_TRSW_EN, 1);
+@@ -568,7 +568,7 @@
+  
+  	rt2800_register_write(rt2x00dev, TX_PIN_CFG, tx_pin);
+  
+-@@ -4725,6 +5108,14 @@ void rt2800_vco_calibration(struct rt2x0
++@@ -4701,6 +5084,14 @@ void rt2800_vco_calibration(struct rt2x0
+  		rt2x00_set_field8(&rfcsr, RFCSR3_VCOCAL_EN, 1);
+  		rt2800_rfcsr_write(rt2x00dev, 3, rfcsr);
+  		break;
+@@ -583,7 +583,7 @@
+  	default:
+  		return;
+  	}
+-@@ -5125,9 +5516,42 @@ static int rt2800_init_registers(struct
++@@ -5101,9 +5492,42 @@ static int rt2800_init_registers(struct
+  	} else if (rt2x00_rt(rt2x00dev, RT5390) ||
+  		   rt2x00_rt(rt2x00dev, RT5392) ||
+  		   rt2x00_rt(rt2x00dev, RT5592)) {
+@@ -629,7 +629,7 @@
+  	} else if (rt2x00_rt(rt2x00dev, RT5350)) {
+  		rt2800_register_write(rt2x00dev, TX_SW_CFG0, 0x00000404);
+  	} else {
+-@@ -6159,6 +6583,225 @@ static void rt2800_init_bbp_5592(struct
++@@ -6135,6 +6559,225 @@ static void rt2800_init_bbp_5592(struct
+  		rt2800_bbp_write(rt2x00dev, 103, 0xc0);
+  }
+  
+@@ -855,7 +855,7 @@
+  static void rt2800_init_bbp(struct rt2x00_dev *rt2x00dev)
+  {
+  	unsigned int i;
+-@@ -6201,7 +6844,10 @@ static void rt2800_init_bbp(struct rt2x0
++@@ -6177,7 +6820,10 @@ static void rt2800_init_bbp(struct rt2x0
+  		return;
+  	case RT5390:
+  	case RT5392:
+@@ -867,7 +867,7 @@
+  		break;
+  	case RT5592:
+  		rt2800_init_bbp_5592(rt2x00dev);
+-@@ -7415,6 +8061,295 @@ static void rt2800_init_rfcsr_5592(struc
++@@ -7391,6 +8037,296 @@ static void rt2800_init_rfcsr_5592(struc
+  	rt2800_led_open_drain_enable(rt2x00dev);
+  }
+  
+@@ -875,6 +875,8 @@
+ +{
+ +	u16 freq;
+ +	u8 rfvalue;
+++	struct hw_mode_spec *spec = &rt2x00dev->spec;
+++
+ +	/* Initialize RF central register to default value */
+ +	rt2800_rfcsr_write(rt2x00dev, 0, 0x02);
+ +	rt2800_rfcsr_write(rt2x00dev, 1, 0x03);
+@@ -921,7 +923,6 @@
+ +	rt2800_rfcsr_write(rt2x00dev, 42, 0x5B);
+ +	rt2800_rfcsr_write(rt2x00dev, 43, 0x00);
+ +
+-+	struct hw_mode_spec *spec = &rt2x00dev->spec;
+ +	rt2800_rfcsr_write(rt2x00dev, 11, 0x21);
+ +	if (spec->clk_is_20mhz)
+ +		rt2800_rfcsr_write(rt2x00dev, 13, 0x03);
+@@ -1163,7 +1164,7 @@
+  static void rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev)
+  {
+  	if (rt2800_is_305x_soc(rt2x00dev)) {
+-@@ -7450,7 +8385,10 @@ static void rt2800_init_rfcsr(struct rt2
++@@ -7426,7 +8362,10 @@ static void rt2800_init_rfcsr(struct rt2
+  		rt2800_init_rfcsr_5350(rt2x00dev);
+  		break;
+  	case RT5390:
+@@ -1175,7 +1176,7 @@
+  		break;
+  	case RT5392:
+  		rt2800_init_rfcsr_5392(rt2x00dev);
+-@@ -7882,6 +8820,7 @@ static int rt2800_init_eeprom(struct rt2
++@@ -7858,6 +8797,7 @@ static int rt2800_init_eeprom(struct rt2
+  	case RF5390:
+  	case RF5392:
+  	case RF5592:
+@@ -1183,7 +1184,7 @@
+  		break;
+  	default:
+  		rt2x00_err(rt2x00dev, "Invalid RF chipset 0x%04x detected\n",
+-@@ -8448,6 +9387,7 @@ static int rt2800_probe_hw_mode(struct r
++@@ -8422,6 +9362,7 @@ static int rt2800_probe_hw_mode(struct r
+  	case RF5372:
+  	case RF5390:
+  	case RF5392:
+@@ -1191,7 +1192,7 @@
+  		spec->num_channels = 14;
+  		if (spec->clk_is_20mhz)
+  			spec->channels = rf_vals_xtal20mhz_3x;
+-@@ -8588,6 +9528,7 @@ static int rt2800_probe_hw_mode(struct r
++@@ -8562,6 +9503,7 @@ static int rt2800_probe_hw_mode(struct r
+  	case RF5372:
+  	case RF5390:
+  	case RF5392:
+diff --git a/package/kernel/mac80211/patches/920-ath10k_allow_fallback_to_board_bin_on_empty_otp_stream.patch b/package/kernel/mac80211/patches/920-ath10k_allow_fallback_to_board_bin_on_empty_otp_stream.patch
+deleted file mode 100644
+index 4c04d4f..0000000
+--- a/package/kernel/mac80211/patches/920-ath10k_allow_fallback_to_board_bin_on_empty_otp_stream.patch
++++ /dev/null
+@@ -1,20 +0,0 @@
+---- a/drivers/net/wireless/ath/ath10k/core.c
+-+++ b/drivers/net/wireless/ath/ath10k/core.c
+-@@ -387,9 +387,14 @@ static int ath10k_download_and_run_otp(s
+- 
+- 	ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot otp execute result %d\n", result);
+- 
+--	if (!skip_otp && result != 0) {
+--		ath10k_err(ar, "otp calibration failed: %d", result);
+--		return -EINVAL;
+-+	if (!skip_otp) {
+-+		if (result == 2) {
+-+			ath10k_warn(ar, "otp stream is empty, using board.bin contents");
+-+			return 0;
+-+		} else if (result != 0) {
+-+			ath10k_err(ar, "otp calibration failed: %d", result);
+-+			return -EINVAL;
+-+		}
+- 	}
+- 
+- 	return 0;
+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 eed3814..93196e1 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>
+ 
+ --- a/drivers/net/wireless/ath/ath10k/core.c
+ +++ b/drivers/net/wireless/ath/ath10k/core.c
+-@@ -1323,6 +1323,16 @@ int ath10k_core_register(struct ath10k *
++@@ -1520,6 +1520,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 8003f86..34910a0 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
+-@@ -5416,6 +5416,21 @@ struct ath10k_vif *ath10k_get_arvif(stru
++@@ -6804,6 +6804,21 @@ struct ath10k_vif *ath10k_get_arvif(stru
+  	return arvif_iter.arvif;
+  }
+  
+@@ -22,7 +22,7 @@
+  int ath10k_mac_register(struct ath10k *ar)
+  {
+  	static const u32 cipher_suites[] = {
+-@@ -5590,6 +5605,12 @@ int ath10k_mac_register(struct ath10k *a
++@@ -7025,6 +7040,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);
+  
+diff --git a/package/kernel/mac80211/patches/940-mwl8k_init_devices_synchronously.patch b/package/kernel/mac80211/patches/940-mwl8k_init_devices_synchronously.patch
+new file mode 100644
+index 0000000..75d8212
+--- /dev/null
++++ b/package/kernel/mac80211/patches/940-mwl8k_init_devices_synchronously.patch
+@@ -0,0 +1,20 @@
++--- a/drivers/net/wireless/mwl8k.c
+++++ b/drivers/net/wireless/mwl8k.c
++@@ -6261,6 +6261,8 @@ static int mwl8k_probe(struct pci_dev *p
++ 
++ 	priv->running_bsses = 0;
++ 
+++	wait_for_completion(&priv->firmware_loading_complete);
+++
++ 	return rc;
++ 
++ err_stop_firmware:
++@@ -6294,8 +6296,6 @@ static void mwl8k_remove(struct pci_dev
++ 		return;
++ 	priv = hw->priv;
++ 
++-	wait_for_completion(&priv->firmware_loading_complete);
++-
++ 	if (priv->fw_state == FW_STATE_ERROR) {
++ 		mwl8k_hw_reset(priv);
++ 		goto unmap;
+diff --git a/package/kernel/mt76/patches/001-backport_ieee80211_hw_set.patch b/package/kernel/mt76/patches/001-backport_ieee80211_hw_set.patch
+deleted file mode 100644
+index e94574d..0000000
+--- a/package/kernel/mt76/patches/001-backport_ieee80211_hw_set.patch
++++ /dev/null
+@@ -1,12 +0,0 @@
+---- a/init.c
+-+++ b/init.c
+-@@ -16,6 +16,9 @@
+- #include "eeprom.h"
+- #include "mcu.h"
+- 
+-+#define ieee80211_hw_set(hw, flag) \
+-+	do { (hw)->flags |= IEEE80211_HW_##flag; } while(0)
+-+
+- static bool
+- mt76_wait_for_mac(struct mt76_dev *dev)
+- {

+ 1 - 1
patches/openwrt/0016-mac80211-set-mcast-rate-for-mesh-point-interfaces.patch

@@ -14,7 +14,7 @@ later in mac80211_setup_vif() by starting authsae.
 Signed-off-by: Nils Schneider <nils@nilsschneider.net>
 
 diff --git a/package/kernel/mac80211/files/lib/netifd/wireless/mac80211.sh b/package/kernel/mac80211/files/lib/netifd/wireless/mac80211.sh
-index c9bc3d6..8137b24 100644
+index 2a8d2f9..8d31a80 100644
 --- a/package/kernel/mac80211/files/lib/netifd/wireless/mac80211.sh
 +++ b/package/kernel/mac80211/files/lib/netifd/wireless/mac80211.sh
 @@ -455,12 +455,7 @@ mac80211_prepare_vif() {

+ 82 - 0
patches/openwrt/0033-mac80211-fix-crash-when-using-mesh-11s-VIF-together-with-another-VIF.patch

@@ -0,0 +1,82 @@
+From: Matthias Schiffer <mschiffer@universe-factory.net>
+Date: Sat, 24 Oct 2015 21:53:10 +0200
+Subject: mac80211: fix crash when using mesh (11s) VIF together with another VIF
+
+Using a 802.11s mesh VIF together with a different VIF (e.g. IBSS) led to
+a panic.
+
+Steps to reproduce:
+
+    rmmod mac80211_hwsim
+    insmod /lib/modules/3.18.21/mac80211_hwsim.ko channels=2
+    iw phy phy2 interface add ibss2 type ibss
+    iw phy phy2 interface add mesh2 type mp
+    iw phy phy3 interface add ibss3 type ibss
+    iw phy phy3 interface add mesh3 type mp
+    ip link set ibss2 up
+    ip link set mesh2 up
+    ip link set ibss3 up
+    ip link set mesh3 up
+    iw dev ibss2 ibss join foo 2412
+    iw dev ibss3 ibss join foo 2412
+    # Ensure that ibss2 and ibss3 are associated, otherwise leave and join
+    # on ibss3 again
+    iw dev mesh2 mesh join bar
+    iw dev mesh3 mesh join bar
+
+The patch has also been submitted upstream.
+
+Signed-off-by: Matthias Schiffer <mschiffer@universe-factory.net>
+
+diff --git a/package/kernel/mac80211/patches/339-mac80211-fix-crash-on-mesh-local-link-ID-generation-.patch b/package/kernel/mac80211/patches/339-mac80211-fix-crash-on-mesh-local-link-ID-generation-.patch
+new file mode 100644
+index 0000000..5784b98
+--- /dev/null
++++ b/package/kernel/mac80211/patches/339-mac80211-fix-crash-on-mesh-local-link-ID-generation-.patch
+@@ -0,0 +1,46 @@
++From 604f8b1964b8380eddf1f03dbdafa7a1c13d80d6 Mon Sep 17 00:00:00 2001
++Message-Id: <604f8b1964b8380eddf1f03dbdafa7a1c13d80d6.1445716231.git.mschiffer@universe-factory.net>
++From: Matthias Schiffer <mschiffer@universe-factory.net>
++Date: Sat, 24 Oct 2015 21:25:51 +0200
++Subject: [PATCH] mac80211: fix crash on mesh local link ID generation with
++ VIFs
++
++llid_in_use needs to be limited to stations of the same VIF, otherwise it
++will cause a NULL deref as the sta_info of non-mesh-VIFs don't have
++sta->mesh set.
++
++Steps to reproduce:
++
++   modprobe mac80211_hwsim channels=2
++   iw phy phy0 interface add ibss0 type ibss
++   iw phy phy0 interface add mesh0 type mp
++   iw phy phy1 interface add ibss1 type ibss
++   iw phy phy1 interface add mesh1 type mp
++   ip link set ibss0 up
++   ip link set mesh0 up
++   ip link set ibss1 up
++   ip link set mesh1 up
++   iw dev ibss0 ibss join foo 2412
++   iw dev ibss1 ibss join foo 2412
++   # Ensure that ibss0 and ibss1 are actually associated; I often need to
++   # leave and join the cell on ibss1 a second time.
++   iw dev mesh0 mesh join bar
++   iw dev mesh1 mesh join bar # crash
++
++Signed-off-by: Matthias Schiffer <mschiffer@universe-factory.net>
++---
++ net/mac80211/mesh_plink.c | 3 +++
++ 1 file changed, 3 insertions(+)
++
++--- a/net/mac80211/mesh_plink.c
+++++ b/net/mac80211/mesh_plink.c
++@@ -646,6 +646,9 @@ static bool llid_in_use(struct ieee80211
++ 
++ 	rcu_read_lock();
++ 	list_for_each_entry_rcu(sta, &local->sta_list, list) {
+++		if (sdata != sta->sdata)
+++			continue;
+++
++ 		if (!memcmp(&sta->mesh->llid, &llid, sizeof(llid))) {
++ 			in_use = true;
++ 			break;

+ 70 - 0
patches/openwrt/0034-ath10k-add-Candelatech-community-firmware-as-an-additional-choice.patch

@@ -0,0 +1,70 @@
+From: Matthias Schiffer <mschiffer@universe-factory.net>
+Date: Tue, 10 Mar 2015 13:17:14 +0100
+Subject: ath10k: add Candelatech community firmware as an additional choice
+
+diff --git a/package/kernel/mac80211/Makefile b/package/kernel/mac80211/Makefile
+index f332cbd..28f40c8 100644
+--- a/package/kernel/mac80211/Makefile
++++ b/package/kernel/mac80211/Makefile
+@@ -270,6 +270,29 @@ Atheros IEEE 802.11ac family of chipsets. For now only
+ PCI is supported.
+ endef
+ 
++define KernelPackage/ath10k/config
++  if PACKAGE_kmod-ath10k
++	choice
++		prompt "ath10k firmware flavour"
++		default ATH10K_AP_FW
++		help
++		This option allows you to choose between different ath10k firmwares.
++
++	config ATH10K_AP_FW
++		bool "Firmware optimized for AP operation"
++		help
++		Use the ath10k firmware optimized for access point operation.
++		Supports only AP mode, will crash in IBSS (ad-hoc) mode.
++
++	config ATH10K_CT_COMMUNITY_FW
++		bool "Firmware by Candela Technologies (community version)"
++		help
++		Supports both AP and IBSS (ad-hoc) mode. Doesn't support
++		encryption when using multiple VIFs.
++	endchoice
++   endif
++ endef
++
+ PKG_ATH10K_LINUX_FIRMWARE_NAME:=ath10k-firmware
+ PKG_ATH10K_LINUX_FIRMWARE_VERSION:=b46f3e01a6c1f9150fb4612ef53611d714565842
+ PKG_ATH10K_LINUX_FIRMWARE_SOURCE:=$(PKG_ATH10K_LINUX_FIRMWARE_NAME)-$(PKG_ATH10K_LINUX_FIRMWARE_VERSION).tar.bz2
+@@ -288,6 +311,14 @@ define Download/ath10k-firmware
+ endef
+ $(eval $(call Download,ath10k-firmware))
+ 
++ATH10K_CT_COMMUNITY_FW:=firmware-2-ct-full-community-14.bin
++define Download/ath10k-firmware-ct-community
++  FILE:=$(ATH10K_CT_COMMUNITY_FW)
++  URL:=http://www.candelatech.com/downloads/
++  MD5SUM:=800799459c20c1683138c74b3ba58f25
++endef
++$(eval $(call Download,ath10k-firmware-ct-community))
++
+ 
+ #Broadcom firmware
+ ifneq ($(CONFIG_B43_FW_6_30),)
+@@ -1854,9 +1885,16 @@ define KernelPackage/ath10k/install
+ 	$(INSTALL_DATA) \
+ 		$(PKG_BUILD_DIR)/$(PKG_ATH10K_LINUX_FIRMWARE_SUBDIR)/ath10k/QCA988X/hw2.0/board.bin \
+ 		$(1)/lib/firmware/ath10k/QCA988X/hw2.0/
++ifeq ($(CONFIG_ATH10K_AP_FW),y)
+ 	$(INSTALL_DATA) \
+ 		$(PKG_BUILD_DIR)/$(PKG_ATH10K_LINUX_FIRMWARE_SUBDIR)/10.2.4/untested/firmware-5.bin_10.2.4.70-2 \
+ 		$(1)/lib/firmware/ath10k/QCA988X/hw2.0/firmware-5.bin
++endif
++ifeq ($(CONFIG_ATH10K_CT_COMMUNITY_FW),y)
++	$(INSTALL_DATA) \
++		$(DL_DIR)/$(ATH10K_CT_COMMUNITY_FW) \
++		$(1)/lib/firmware/ath10k/QCA988X/hw2.0/firmware-2.bin
++endif
+ endef
+ 
+ define KernelPackage/b43/install