From 4e6628cebf059310f6f5217243994bc41f38b213 Mon Sep 17 00:00:00 2001
From: Matthias Schiffer <mschiffer@universe-factory.net>
Date: Tue, 20 May 2014 05:04:32 +0200
Subject: [PATCH] Update mac80211 backport to r40804

---
 ...ac80211-from-Barrier-Breaker-r40804.patch} | 7620 +++++++++++++----
 1 file changed, 5834 insertions(+), 1786 deletions(-)
 rename patches/openwrt/{0018-Backport-mac80211-from-Barrier-Breaker.patch => 0018-Backport-mac80211-from-Barrier-Breaker-r40804.patch} (65%)

diff --git a/patches/openwrt/0018-Backport-mac80211-from-Barrier-Breaker.patch b/patches/openwrt/0018-Backport-mac80211-from-Barrier-Breaker-r40804.patch
similarity index 65%
rename from patches/openwrt/0018-Backport-mac80211-from-Barrier-Breaker.patch
rename to patches/openwrt/0018-Backport-mac80211-from-Barrier-Breaker-r40804.patch
index 942ee3091..cb273fada 100644
--- a/patches/openwrt/0018-Backport-mac80211-from-Barrier-Breaker.patch
+++ b/patches/openwrt/0018-Backport-mac80211-from-Barrier-Breaker-r40804.patch
@@ -1,9 +1,9 @@
 From: Matthias Schiffer <mschiffer@universe-factory.net>
 Date: Mon, 19 May 2014 15:59:37 +0200
-Subject: Backport mac80211 from Barrier Breaker
+Subject: Backport mac80211 from Barrier Breaker (r40804)
 
 diff --git a/package/mac80211/Makefile b/package/mac80211/Makefile
-index 9a7093c..e19f30e 100644
+index 9a7093c..7eacf24 100644
 --- a/package/mac80211/Makefile
 +++ b/package/mac80211/Makefile
 @@ -1,5 +1,5 @@
@@ -18,12 +18,12 @@ index 9a7093c..e19f30e 100644
  PKG_NAME:=mac80211
  
 -PKG_VERSION:=2014-01-23.1
-+PKG_VERSION:=2014-03-31
++PKG_VERSION:=2014-05-19
  PKG_RELEASE:=1
  PKG_SOURCE_URL:=http://mirror2.openwrt.org/sources
  PKG_BACKPORT_VERSION:=
 -PKG_MD5SUM:=8db16edbdaf4abc2e9c2f3b6c86736a6
-+PKG_MD5SUM:=8b5cf82d6defc5867511014af4afc0b6
++PKG_MD5SUM:=ff5426bf85668c3c36c7f602adeb1e5b
  
  PKG_SOURCE:=compat-wireless-$(PKG_VERSION)$(PKG_BACKPORT_VERSION).tar.bz2
  PKG_BUILD_DIR:=$(KERNEL_BUILD_DIR)/compat-wireless-$(PKG_VERSION)
@@ -51,6 +51,15 @@ index 9a7093c..e19f30e 100644
  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
+@@ -363,7 +363,7 @@ define KernelPackage/rtl8180
+   $(call KernelPackage/rtl818x/Default)
+   DEPENDS+= @PCI_SUPPORT
+   TITLE+= (RTL8180 PCI)
+-  FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/rtl818x/rtl8180/rtl8180.ko
++  FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/rtl818x/rtl8180/rtl818x_pci.ko
+   AUTOLOAD:=$(call AutoLoad,27,rtl8180)
+ endef
+ 
 @@ -606,6 +606,19 @@ Atheros IEEE 802.11ac family of chipsets. For now only
  PCI is supported.
  endef
@@ -1602,6 +1611,40 @@ index 2badb21..fcab208 100644
 +	(5250 - 5330 @ 80), (20), DFS
 +	(5490 - 5710 @ 80), (27), DFS
  
+diff --git a/package/mac80211/patches/001-fix_build.patch b/package/mac80211/patches/001-fix_build.patch
+index 26b327a..99ef50e 100644
+--- a/package/mac80211/patches/001-fix_build.patch
++++ b/package/mac80211/patches/001-fix_build.patch
+@@ -131,7 +131,7 @@
+  .PHONY: defconfig-help
+ --- a/Makefile.real
+ +++ b/Makefile.real
+-@@ -54,7 +54,7 @@ defconfig-%::
++@@ -59,7 +59,7 @@ defconfig-%::
+  
+  backport-include/backport/autoconf.h: .config Kconfig.versions Kconfig.kernel
+  	@$(MAKE) oldconfig
+@@ -140,7 +140,7 @@
+  	@grep -f .local-symbols .config | (				\
+  		echo "#ifndef COMPAT_AUTOCONF_INCLUDED"			;\
+  		echo "#define COMPAT_AUTOCONF_INCLUDED"			;\
+-@@ -75,7 +75,12 @@ backport-include/backport/autoconf.h: .c
++@@ -80,7 +80,12 @@ backport-include/backport/autoconf.h: .c
+  			esac						;\
+  		done							;\
+  		echo "#endif /* COMPAT_AUTOCONF_INCLUDED */"		;\
+diff --git a/package/mac80211/patches/003-remove_bogus_modparams.patch b/package/mac80211/patches/003-remove_bogus_modparams.patch
+index c969b19..ffb730b 100644
+--- a/package/mac80211/patches/003-remove_bogus_modparams.patch
++++ b/package/mac80211/patches/003-remove_bogus_modparams.patch
+@@ -1,6 +1,6 @@
+ --- a/compat/main.c
+ +++ b/compat/main.c
+-@@ -21,31 +21,6 @@ MODULE_LICENSE("GPL");
++@@ -20,31 +20,6 @@ MODULE_LICENSE("GPL");
+  #error "You need a BACKPORTS_VERSION"
+  #endif
+  
 diff --git a/package/mac80211/patches/004-backports-add-led_trigger_blink-_oneshot.patch b/package/mac80211/patches/004-backports-add-led_trigger_blink-_oneshot.patch
 index 584fb05..8d97224 100644
 --- a/package/mac80211/patches/004-backports-add-led_trigger_blink-_oneshot.patch
@@ -1667,258 +1710,414 @@ index 0000000..55bffbc
 + 		flagstr = flagstr $i
 + 	split(flagstr, flagarray, ",")
 + 	flags = ""
+diff --git a/package/mac80211/patches/007-select_queue.patch b/package/mac80211/patches/007-select_queue.patch
+new file mode 100644
+index 0000000..0a1d292
+--- /dev/null
++++ b/package/mac80211/patches/007-select_queue.patch
+@@ -0,0 +1,11 @@
++--- a/drivers/net/wireless/mwifiex/main.c
+++++ b/drivers/net/wireless/mwifiex/main.c
++@@ -745,7 +745,7 @@ static struct net_device_stats *mwifiex_
++ 	return &priv->stats;
++ }
++ 
++-#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,15,0)
+++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,14,0)
++ static u16
++ mwifiex_netdev_select_wmm_queue(struct net_device *dev, struct sk_buff *skb,
++ 				void *accel_priv, select_queue_fallback_t fallback)
+diff --git a/package/mac80211/patches/020-disable_tty_set_termios.patch b/package/mac80211/patches/020-disable_tty_set_termios.patch
+deleted file mode 100644
+index e6d4ff6..0000000
+--- a/package/mac80211/patches/020-disable_tty_set_termios.patch
++++ /dev/null
+@@ -1,16 +0,0 @@
+---- a/compat/compat-2.6.39.c
+-+++ b/compat/compat-2.6.39.c
+-@@ -13,6 +13,7 @@
+- #include <linux/sched.h>
+- #include <linux/module.h>
+- 
+-+#ifdef CONFIG_COMPAT_BLUETOOTH
+- #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27))
+- #ifdef CONFIG_TTY
+- /*
+-@@ -114,4 +115,4 @@ int tty_set_termios(struct tty_struct *t
+- EXPORT_SYMBOL_GPL(tty_set_termios);
+- #endif /* CONFIG_TTY */
+- #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27)) */
+--
+-+#endif
+diff --git a/package/mac80211/patches/050-lib80211_option.patch b/package/mac80211/patches/050-lib80211_option.patch
+index 5372114..168871a 100644
+--- a/package/mac80211/patches/050-lib80211_option.patch
++++ b/package/mac80211/patches/050-lib80211_option.patch
+@@ -1,6 +1,6 @@
+ --- a/net/wireless/Kconfig
+ +++ b/net/wireless/Kconfig
+-@@ -123,7 +123,7 @@ config CFG80211_WEXT
++@@ -160,7 +160,7 @@ config CFG80211_WEXT
+  	  extensions with cfg80211-based drivers.
+  
+  config LIB80211
+@@ -9,7 +9,7 @@
+  	depends on m
+  	default n
+  	help
+-@@ -133,15 +133,15 @@ config LIB80211
++@@ -170,15 +170,15 @@ config LIB80211
+  	  Drivers should select this themselves if needed.
+  
+  config LIB80211_CRYPT_WEP
 diff --git a/package/mac80211/patches/060-no_local_ssb_bcma.patch b/package/mac80211/patches/060-no_local_ssb_bcma.patch
-index f4b9470..95f14f4 100644
+index f4b9470..d550bba 100644
 --- a/package/mac80211/patches/060-no_local_ssb_bcma.patch
 +++ b/package/mac80211/patches/060-no_local_ssb_bcma.patch
 @@ -1,6 +1,6 @@
  --- a/.local-symbols
  +++ b/.local-symbols
 -@@ -379,42 +379,6 @@ USB_CDC_PHONET=
-+@@ -402,42 +402,6 @@ USB_CDC_PHONET=
++@@ -403,42 +403,6 @@ USB_CDC_PHONET=
   USB_IPHETH=
   USB_SIERRA_NET=
   USB_VL600=
+@@ -68,7 +68,7 @@
+  obj-$(CPTCFG_NFC) += net/nfc/
+ --- a/drivers/net/wireless/b43/main.c
+ +++ b/drivers/net/wireless/b43/main.c
+-@@ -2734,7 +2734,7 @@ static struct ssb_device *b43_ssb_gpio_d
++@@ -2723,7 +2723,7 @@ static struct ssb_device *b43_ssb_gpio_d
+  {
+  	struct ssb_bus *bus = dev->dev->sdev->bus;
+  
+@@ -77,12 +77,12 @@
+  	return (bus->chipco.dev ? bus->chipco.dev : bus->pcicore.dev);
+  #else
+  	return bus->chipco.dev;
+-@@ -4751,7 +4751,7 @@ static int b43_wireless_core_init(struct
++@@ -4688,7 +4688,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. */
+--#ifdef CPTCFG_SSB_DRIVER_PCICORE
+-+#ifdef CONFIG_SSB_DRIVER_PCICORE
++-#if defined(CPTCFG_B43_SSB) && defined(CPTCFG_SSB_DRIVER_PCICORE)
+++#if defined(CPTCFG_B43_SSB) && defined(CONFIG_SSB_DRIVER_PCICORE)
+  	if (dev->dev->bus_type == B43_BUS_SSB &&
+  	    dev->dev->sdev->bus->bustype == SSB_BUSTYPE_PCI &&
+  	    dev->dev->sdev->bus->pcicore.dev->id.revision <= 10)
 diff --git a/package/mac80211/patches/070-add-missing-header.patch b/package/mac80211/patches/070-add-missing-header.patch
 new file mode 100644
-index 0000000..9307804
+index 0000000..e3ec780
 --- /dev/null
 +++ b/package/mac80211/patches/070-add-missing-header.patch
 @@ -0,0 +1,10 @@
 +--- a/compat/backport-3.15.c
 ++++ b/compat/backport-3.15.c
-+@@ -11,6 +11,7 @@
++@@ -12,6 +12,7 @@
 + #include <linux/kernel.h>
 + #include <linux/device.h>
 + #include <linux/of.h>
 ++#include <linux/string.h>
++ #include <net/net_namespace.h>
 + 
-+ /**
-+  * devm_kstrdup - Allocate resource managed space and
++ #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,5,0))
 diff --git a/package/mac80211/patches/100-revert_aes_ccm_port.patch b/package/mac80211/patches/100-revert_aes_ccm_port.patch
-index 4654bc8..ac7d6b3 100644
+index 4654bc8..640d34e 100644
 --- a/package/mac80211/patches/100-revert_aes_ccm_port.patch
 +++ b/package/mac80211/patches/100-revert_aes_ccm_port.patch
-@@ -1,3 +1,104 @@
-+--- a/net/mac80211/wpa.c
-++++ b/net/mac80211/wpa.c
-+@@ -301,15 +301,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;
+@@ -4,7 +4,7 @@
+  	depends on CRYPTO
+  	depends on CRYPTO_ARC4
+  	depends on CRYPTO_AES
+--	depends on CRYPTO_CCM
++-	select BACKPORT_CRYPTO_CCM
+  	depends on CRC32
+  	select BACKPORT_AVERAGE
+  	---help---
+@@ -19,35 +19,17 @@
+   * 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,75 +17,134 @@
++@@ -19,76 +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)
+ +static void aes_ccm_prepare(struct crypto_cipher *tfm, u8 *scratch, u8 *a)
+- {
+--	struct scatterlist assoc, pt, ct[2];
+--	struct {
+--		struct aead_request	req;
+--		u8			priv[crypto_aead_reqsize(tfm)];
+--	} aead_req;
+--
+--	memset(&aead_req, 0, sizeof(aead_req));
+--
+--	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_CCMP_MIC_LEN);
+--
+--	aead_request_set_tfm(&aead_req.req, tfm);
+--	aead_request_set_assoc(&aead_req.req, &assoc, assoc.length);
+--	aead_request_set_crypt(&aead_req.req, &pt, ct, data_len, b_0);
+++{
+ +	int i;
+ +	u8 *b_0, *aad, *b, *s_0;
+- 
+--	crypto_aead_encrypt(&aead_req.req);
+++
+ +	b_0 = scratch + 3 * AES_BLOCK_SIZE;
+ +	aad = scratch + 4 * AES_BLOCK_SIZE;
+ +	b = scratch;
+@@ -73,22 +55,23 @@
+ +	b_0[14] = 0;
+ +	b_0[15] = 0;
+ +	crypto_cipher_encrypt_one(tfm, s_0, b_0);
+- }
+- 
+--int ieee80211_aes_ccm_decrypt(struct crypto_aead *tfm, u8 *b_0, u8 *aad,
+--			      u8 *data, size_t data_len, u8 *mic)
+++}
 ++
-+ 	/*
-+ 	 * Mask FC: zero subtype b4 b5 b6 (if not mgmt)
-+ 	 * Retry, PwrMgt, MoreData; set Protected
-+@@ -331,21 +338,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] */
-+@@ -401,8 +407,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) &&
-+@@ -455,9 +460,9 @@ static int ccmp_encrypt_skb(struct ieee8
-+ 		return 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];
+--	struct {
+--		struct aead_request	req;
+--		u8			priv[crypto_aead_reqsize(tfm)];
+--	} aead_req;
+++	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));
++-	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));
+@@ -96,13 +79,9 @@
+ -	sg_set_buf(&ct[0], data, data_len);
+ -	sg_set_buf(&ct[1], mic, IEEE80211_CCMP_MIC_LEN);
+ -
+--	aead_request_set_tfm(&aead_req.req, tfm);
+--	aead_request_set_assoc(&aead_req.req, &assoc, assoc.length);
+--	aead_request_set_crypt(&aead_req.req, ct, &pt,
+--			       data_len + IEEE80211_CCMP_MIC_LEN, b_0);
+-+	int i, j, last_len, num_blocks;
+-+	u8 *pos, *cpos, *b, *s_0, *e, *b_0;
+-+
++-	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;
+@@ -131,30 +110,38 @@
+ +			*cpos++ = *pos++ ^ e[i];
+ +	}
+  
+--	return crypto_aead_decrypt(&aead_req.req);
++-	crypto_aead_encrypt(aead_req);
+ +	for (i = 0; i < IEEE80211_CCMP_MIC_LEN; i++)
+ +		mic[i] = b[i] ^ s_0[i];
+  }
+  
+--struct crypto_aead *ieee80211_aes_key_setup_encrypt(const u8 key[])
++-int ieee80211_aes_ccm_decrypt(struct crypto_aead *tfm, u8 *b_0, u8 *aad,
++-			      u8 *data, size_t data_len, u8 *mic)
+ +
+ +int ieee80211_aes_ccm_decrypt(struct crypto_cipher *tfm, u8 *scratch,
+ +			      u8 *cdata, size_t data_len, u8 *mic, u8 *data)
+  {
+--	struct crypto_aead *tfm;
+--	int err;
++-	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_CCMP_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_CCMP_MIC_LEN, b_0);
+ +	int i, j, last_len, num_blocks;
+ +	u8 *pos, *cpos, *b, *s_0, *a, *b_0;
+- 
+--	tfm = crypto_alloc_aead("ccm(aes)", 0, CRYPTO_ALG_ASYNC);
+--	if (IS_ERR(tfm))
+--		return tfm;
+--
+--	err = crypto_aead_setkey(tfm, key, WLAN_KEY_LEN_CCMP);
+--	if (!err)
+--		err = crypto_aead_setauthsize(tfm, IEEE80211_CCMP_MIC_LEN);
+--	if (!err)
+--		return tfm;
+++
+ +	b = scratch;
+ +	s_0 = scratch + AES_BLOCK_SIZE;
+ +	a = scratch + 2 * AES_BLOCK_SIZE;
+@@ -187,24 +174,37 @@
+ +			return -1;
+ +	}
+  
+--	crypto_free_aead(tfm);
+--	return ERR_PTR(err);
++-	return crypto_aead_decrypt(aead_req);
+ +	return 0;
+  }
+  
+--void ieee80211_aes_key_free(struct crypto_aead *tfm)
++-struct crypto_aead *ieee80211_aes_key_setup_encrypt(const u8 key[])
+ +
+ +struct crypto_cipher *ieee80211_aes_key_setup_encrypt(const u8 key[])
+-+{
++ {
++-	struct crypto_aead *tfm;
++-	int err;
+ +	struct crypto_cipher *tfm;
+-+
 + 
-+ 	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, IEEE80211_CCMP_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));
++-	tfm = crypto_alloc_aead("ccm(aes)", 0, CRYPTO_ALG_ASYNC);
++-	if (IS_ERR(tfm))
++-		return tfm;
++-
++-	err = crypto_aead_setkey(tfm, key, WLAN_KEY_LEN_CCMP);
++-	if (!err)
++-		err = crypto_aead_setauthsize(tfm, IEEE80211_CCMP_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);
+-+
 + 
-+ 	return 0;
++-	crypto_free_aead(tfm);
++-	return ERR_PTR(err);
+ +	return tfm;
+-+}
+-+
 + }
-+@@ -520,16 +525,16 @@ 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 - IEEE80211_CCMP_MIC_LEN))
-++			    skb->data + skb->len - IEEE80211_CCMP_MIC_LEN,
-++			    skb->data + hdrlen + IEEE80211_CCMP_HDR_LEN))
-+ 			return RX_DROP_UNUSABLE;
-+ 	}
 + 
- --- a/net/mac80211/Kconfig
- +++ b/net/mac80211/Kconfig
- @@ -5,7 +5,6 @@ config MAC80211
-@@ -244,104 +345,3 @@
-  			u32 replays; /* dot11RSNAStatsCCMPReplays */
-  		} ccmp;
++-void ieee80211_aes_key_free(struct crypto_aead *tfm)
+ +
+ +void ieee80211_aes_key_free(struct crypto_cipher *tfm)
+  {
+@@ -246,13 +246,13 @@
   		struct {
----- a/net/mac80211/wpa.c
--+++ b/net/mac80211/wpa.c
+ --- a/net/mac80211/wpa.c
+ +++ b/net/mac80211/wpa.c
 -@@ -301,16 +301,22 @@ ieee80211_crypto_tkip_decrypt(struct iee
-- }
-- 
-- 
++@@ -301,15 +301,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,
++-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
+++				int encrypted)
+  {
+  	__le16 mask_fc;
+  	int a4_included, mgmt;
+@@ -271,7 +271,7 @@
+  	/*
+  	 * Mask FC: zero subtype b4 b5 b6 (if not mgmt)
+  	 * Retry, PwrMgt, MoreData; set Protected
 -@@ -332,21 +338,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] */
++@@ -331,21 +338,20 @@ static void ccmp_special_blocks(struct s
+  	else
+  		qos_tid = 0;
+  
+@@ -300,7 +300,7 @@
+  
+  	/* AAD (extra authenticate-only data) / masked 802.11 header
+  	 * FC | A1 | A2 | A3 | SC | [A4] | [QC] */
 -@@ -402,8 +407,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) &&
++@@ -401,8 +407,7 @@ static int ccmp_encrypt_skb(struct ieee8
+  	u8 *pos;
+  	u8 pn[6];
+  	u64 pn64;
+@@ -310,11 +310,11 @@
+  
+  	if (info->control.hw_key &&
+  	    !(info->control.hw_key->flags & IEEE80211_KEY_FLAG_GENERATE_IV) &&
 -@@ -456,9 +460,9 @@ static int ccmp_encrypt_skb(struct ieee8
-- 		return 0;
-- 
-- 	pos += IEEE80211_CCMP_HDR_LEN;
++@@ -458,9 +463,9 @@ static int ccmp_encrypt_skb(struct ieee8
+  		return 0;
+  
+  	pos += IEEE80211_CCMP_HDR_LEN;
 --	ccmp_special_blocks(skb, pn, b_0, aad, 0);
---	ieee80211_aes_ccm_encrypt(key->u.ccmp.tfm, b_0, aad, pos, len,
---				  skb_put(skb, IEEE80211_CCMP_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;
-- }
++-	ccmp_special_blocks(skb, pn, b_0, aad);
+ -	ieee80211_aes_ccm_encrypt(key->u.ccmp.tfm, b_0, aad, pos, len,
+ -				  skb_put(skb, IEEE80211_CCMP_MIC_LEN));
+ +	ccmp_special_blocks(skb, pn, scratch, 0);
+@@ -323,7 +323,7 @@
+  
+  	return 0;
+  }
 -@@ -521,16 +525,16 @@ 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 */
++@@ -523,16 +528,16 @@ ieee80211_crypto_ccmp_decrypt(struct iee
+  	}
+  
+  	if (!(status->flag & RX_FLAG_DECRYPTED)) {
+@@ -331,7 +331,7 @@
+ -		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, 1);
--+		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 - IEEE80211_CCMP_MIC_LEN))
--+			    skb->data + skb->len - IEEE80211_CCMP_MIC_LEN,
--+			    skb->data + hdrlen + IEEE80211_CCMP_HDR_LEN))
-- 			return RX_DROP_UNUSABLE;
-- 	}
-- 
++-		ccmp_special_blocks(skb, pn, b_0, aad);
+ +		ccmp_special_blocks(skb, pn, scratch, 1);
+  
+  		if (ieee80211_aes_ccm_decrypt(
 diff --git a/package/mac80211/patches/150-disable_addr_notifier.patch b/package/mac80211/patches/150-disable_addr_notifier.patch
-index 7b50154..3f749e9 100644
+index 7b50154..c80b2bb 100644
 --- a/package/mac80211/patches/150-disable_addr_notifier.patch
 +++ b/package/mac80211/patches/150-disable_addr_notifier.patch
+@@ -1,6 +1,6 @@
+ --- a/net/mac80211/main.c
+ +++ b/net/mac80211/main.c
+-@@ -287,7 +287,7 @@ void ieee80211_restart_hw(struct ieee802
++@@ -285,7 +285,7 @@ void ieee80211_restart_hw(struct ieee802
+  }
+  EXPORT_SYMBOL(ieee80211_restart_hw);
+  
+@@ -9,7 +9,7 @@
+  static int ieee80211_ifa_changed(struct notifier_block *nb,
+  				 unsigned long data, void *arg)
+  {
+-@@ -346,7 +346,7 @@ static int ieee80211_ifa_changed(struct 
++@@ -344,7 +344,7 @@ static int ieee80211_ifa_changed(struct 
+  }
+  #endif
+  
 @@ -18,7 +18,7 @@
   static int ieee80211_ifa6_changed(struct notifier_block *nb,
   				  unsigned long data, void *arg)
   {
 -@@ -1031,14 +1031,14 @@ int ieee80211_register_hw(struct ieee802
-+@@ -1036,14 +1036,14 @@ int ieee80211_register_hw(struct ieee802
++@@ -1034,14 +1034,14 @@ int ieee80211_register_hw(struct ieee802
   		goto fail_pm_qos;
   	}
   
@@ -1927,7 +2126,7 @@ index 7b50154..3f749e9 100644
   	result = register_inet6addr_notifier(&local->ifa6_notifier);
   	if (result)
 -@@ -1047,13 +1047,13 @@ int ieee80211_register_hw(struct ieee802
-+@@ -1052,13 +1052,13 @@ int ieee80211_register_hw(struct ieee802
++@@ -1050,13 +1050,13 @@ int ieee80211_register_hw(struct ieee802
   
   	return 0;
   
@@ -1936,31 +2135,41 @@ index 7b50154..3f749e9 100644
   	pm_qos_remove_notifier(PM_QOS_NETWORK_LATENCY,
   			       &local->network_latency_notifier);
 -@@ -1086,10 +1086,10 @@ void ieee80211_unregister_hw(struct ieee
-+@@ -1103,10 +1103,10 @@ void ieee80211_unregister_hw(struct ieee
++@@ -1101,10 +1101,10 @@ void ieee80211_unregister_hw(struct ieee
   
   	pm_qos_remove_notifier(PM_QOS_NETWORK_LATENCY,
   			       &local->network_latency_notifier);
 diff --git a/package/mac80211/patches/300-pending_work.patch b/package/mac80211/patches/300-pending_work.patch
-index a1af6c2..892f51e 100644
+index a1af6c2..dc1e265 100644
 --- a/package/mac80211/patches/300-pending_work.patch
 +++ b/package/mac80211/patches/300-pending_work.patch
-@@ -1,4153 +1,543 @@
+@@ -1,4153 +1,4383 @@
 -commit 93f310a38a1d81a4bc8fcd9bf29628bd721cf2ef
--Author: Felix Fietkau <nbd@openwrt.org>
++commit ff9655bebd25d35ab13c2515a029723b69949720
+ Author: Felix Fietkau <nbd@openwrt.org>
 -Date:   Sun Apr 6 23:35:28 2014 +0200
--
++Date:   Mon May 19 21:20:49 2014 +0200
+ 
 -    ath9k_hw: reduce ANI firstep range for older chips
--    
++    ath9k: avoid passing buffers to the hardware during flush
+     
 -    Use 0-8 instead of 0-16, which is closer to the old implementation.
 -    Also drop the overwrite of the firstep_low parameter to improve
 -    stability.
--    
--    Signed-off-by: Felix Fietkau <nbd@openwrt.org>
--
++    The commit "ath9k: fix possible hang on flush" changed the receive code
++    to always link rx descriptors of processed frames, even when flushing.
++    In some cases, this leads to flushed rx buffers being passed to the
++    hardware while rx is already stopped.
+     
+     Signed-off-by: Felix Fietkau <nbd@openwrt.org>
+ 
 -commit 584d297fd29fb39c76af25ae74ff9d5fe74c8a14
 -Author: Helmut Schaa <helmut.schaa@googlemail.com>
 -Date:   Wed Mar 12 10:37:55 2014 +0100
--
++commit 46c5d7d207a2a0725066c0928fd19b8c578b7d4f
++Author: Oleksij Rempel <linux@rempel-privat.de>
++Date:   Tue May 20 00:02:03 2014 +0200
+ 
 -    ath9k: Fix sequence number assignment for non-data frames
 -    
 -    Since commit 558ff225de80ac95b132d3a115ddadcd64498b4f (ath9k: fix
@@ -2012,10 +2221,7 @@ index a1af6c2..892f51e 100644
 -    old table).
 -    
 -    Signed-off-by: Felix Fietkau <nbd@openwrt.org>
-+commit 4c8a3486cb577d40c1ef75f0a8dc9a04773eef83
-+Author: Nickolay Ledovskikh <nledovskikh@gmail.com>
-+Date:   Fri Apr 25 22:53:34 2014 +0400
- 
+-
 -commit c977493766310a825f406836636ffd66e1447783
 -Author: Felix Fietkau <nbd@openwrt.org>
 -Date:   Mon Mar 10 19:52:56 2014 +0100
@@ -2034,74 +2240,45 @@ index a1af6c2..892f51e 100644
 -Date:   Sun Mar 9 11:25:43 2014 +0100
 -
 -    ath9k: clean up and enhance ANI debugfs file
-+    ath5k: Fix AR5K_PHY_TXPOWER_RATE_MAX register value setting.
-     
+-    
 -    Unify scnprintf calls and include the current OFDM/CCK immunity level.
-+    I was reading ath5k power setting code and
-+    noticed typing error in ath5k_hw_txpower function.
-+    Invalid value was written to AR5K_PHY_TXPOWER_RATE_MAX
-+    register.
-     
+-    
 -    Signed-off-by: Felix Fietkau <nbd@openwrt.org>
-+    Signed-off-by: Nikolay Ledovskikh <nledovskikh@gmail.com>
-+    Acked-by: Nick Kossifidis <mickflemm@gmail.com>
-+    Signed-off-by: John W. Linville <linville@tuxdriver.com>
- 
+-
 -commit 22e298b5a3a8a49e33805d4e351965123dede35b
 -Author: Felix Fietkau <nbd@openwrt.org>
 -Date:   Sun Mar 9 10:58:47 2014 +0100
-+commit 4d76248013dbb1948429555208900a585b0f351d
-+Author: Janusz Dziedzic <janusz.dziedzic@tieto.com>
-+Date:   Tue Apr 8 13:38:43 2014 +0200
- 
+-
 -    ath9k: fix ready time of the multicast buffer queue
 -    
 -    qi->tqi_readyTime is written directly to registers that expect
 -    microseconds as unit instead of TU.
 -    When setting the CABQ ready time, cur_conf->beacon_interval is in TU, so
 -    convert it to microseconds before passing it to ath9k_hw.
-+    ath9k: Enable DFS only when ATH9K_DFS_CERTIFIED
-     
+-    
 -    This should hopefully fix some Tx DMA issues with buffered multicast
 -    frames in AP mode.
-+    Add DFS interface combination only when
-+    CONFIG_ATH9K_DFS_CERTIFIED is set. In other case
-+    user can run CAC/beaconing without proper handling
-+    of pulse events (without radar detection activated).
-     
+-    
 -    Cc: stable@vger.kernel.org
 -    Signed-off-by: Felix Fietkau <nbd@openwrt.org>
-+    Reported-by: Cedric Voncken <cedric.voncken@acksys.fr>
-+    Signed-off-by: Janusz Dziedzic <janusz.dziedzic@tieto.com>
-+    Signed-off-by: John W. Linville <linville@tuxdriver.com>
- 
+-
 -commit fcb064fdd5a27bec8d24099bc0172468f34c97cb
 -Author: Felix Fietkau <nbd@openwrt.org>
 -Date:   Sun Mar 9 09:43:09 2014 +0100
-+commit c83a4e5156a4b4dd22137d33a5625440982d6d37
-+Author: Rajkumar Manoharan <rmanohar@qti.qualcomm.com>
-+Date:   Mon Apr 28 21:17:08 2014 +0530
- 
+-
 -    ath9k_hw: fix unreachable code in baseband hang detection code
-+    ath9k_hw: fix worse EVM for 11b rates
-     
+-    
 -    The commit "ath9k: reduce baseband hang detection false positive rate"
 -    added a delay in the loop checking the baseband state, however it was
 -    unreachable due to previous 'continue' statements.
-+    Adjust FIR filter co-efficients to improve EVM for 11b rates.
-     
+-    
 -    Reported-by: Dan Carpenter <dan.carpenter@oracle.com>
 -    Signed-off-by: Felix Fietkau <nbd@openwrt.org>
-+    Signed-off-by: Rajkumar Manoharan <rmanohar@qti.qualcomm.com>
-+    Signed-off-by: John W. Linville <linville@tuxdriver.com>
- 
+-
 -commit 31959d8df39319e32c6d5ba9c135727be90cfad7
 -Author: Michal Kazior <michal.kazior@tieto.com>
 -Date:   Fri Mar 7 08:09:38 2014 +0100
-+commit 8aab2c7a2f4a957e344db429dfb1190ae59ce8b5
-+Author: Rajkumar Manoharan <rmanohar@qti.qualcomm.com>
-+Date:   Mon Apr 28 21:17:07 2014 +0530
- 
+-
 -    mac80211: fix possible NULL dereference
 -    
 -    If chanctx is missing on a given vif then the band
@@ -2113,37 +2290,23 @@ index a1af6c2..892f51e 100644
 -    
 -    [ 4605.207223] BUG: unable to handle kernel NULL pointer dereference at 0000000000000018
 -    [ 4605.210789] IP: [<ffffffffa07b5635>] ieee80211_parse_bitrates+0x65/0x110 [mac80211]
-+    ath9k_hw: update ar9300 initvals
-     
+-    
 -    The splat was preceeded by WARN_ON(!chanctx_conf)
 -    in ieee80211_get_sdata_band().
-+     * rfsat gainchange hysteresis of rf_gain stuck with large
-+       interference present.
-     
+-    
 -    Signed-off-by: Michal Kazior <michal.kazior@tieto.com>
-+    Signed-off-by: Rajkumar Manoharan <rmanohar@qti.qualcomm.com>
-+    Signed-off-by: John W. Linville <linville@tuxdriver.com>
- 
+-
 -commit 6c5a3ffa0a2d22c091a2717f427259bacf77ac5e
 -Author: Michael Braun <michael-dev@fami-braun.de>
 -Date:   Thu Mar 6 15:08:43 2014 +0100
-+commit 8c7ae357cc5b6bd037ad2d666e9f3789cf882925
-+Author: Rajkumar Manoharan <rmanohar@qti.qualcomm.com>
-+Date:   Wed Apr 23 15:07:57 2014 +0530
- 
+-
 -    mac80211: fix WPA with VLAN on AP side with ps-sta again
-+    ath9k: fix race in setting ATH_OP_INVALID
-     
+-    
 -    commit de74a1d9032f4d37ea453ad2a647e1aff4cd2591
 -      "mac80211: fix WPA with VLAN on AP side with ps-sta"
 -    fixed an issue where queued multicast packets would
 -    be sent out encrypted with the key of an other bss.
-+    The commit "ath9k: move sc_flags to ath_common" moved setting
-+    ATH_OP_INVALID flag below ieee80211_register_hw. This is causing
-+    the flag never being cleared randomly as the drv_start is called
-+    prior to setting flag. Fix this by setting the flag prior to
-+    register_hw.
-     
+-    
 -    commit "7cbf9d017dbb5e3276de7d527925d42d4c11e732"
 -      "mac80211: fix oops on mesh PS broadcast forwarding"
 -    essentially reverted it, because vif.type cannot be AP_VLAN
@@ -2160,109 +2323,92 @@ index a1af6c2..892f51e 100644
 -    Cc: <linux-wireless@vger.kernel.org>
 -    Cc: <projekt-wlan@fem.tu-ilmenau.de>
 -    Signed-off-by: Michael Braun <michael-dev@fami-braun.de>
-+    Signed-off-by: Rajkumar Manoharan <rmanohar@qti.qualcomm.com>
-+    Signed-off-by: John W. Linville <linville@tuxdriver.com>
++    ath9k_htc: fix build with disabled debug
++    
++      CC [M]  drivers/net/wireless/ath/ath9k/htc_drv_txrx.o
++    drivers/net/wireless/ath/ath9k/htc_drv_txrx.c: In function ‘ath9k_rx_prepare’:
++    drivers/net/wireless/ath/ath9k/htc_drv_txrx.c:1006:2: warning: passing argument 2 of ‘ath9k_htc_err_stat_rx’ from incompatible pointer type [enabled by default]
++      ath9k_htc_err_stat_rx(priv, &rx_stats);
++      ^
++    In file included from drivers/net/wireless/ath/ath9k/htc_drv_txrx.c:17:0:
++    drivers/net/wireless/ath/ath9k/htc.h:380:20: note: expected ‘struct ath_htc_rx_status *’ but argument is of type ‘struct ath_rx_status *’
++     static inline void ath9k_htc_err_stat_rx(struct ath9k_htc_priv *priv,
++    
++    Signed-off-by: Oleksij Rempel <linux@rempel-privat.de>
  
 -commit 9d6ab9bdb9b368a6cf9519f0f92509b5b2c297ec
--Author: Johannes Berg <johannes.berg@intel.com>
++commit 2d331334e9dc5659fdf9a89326c34c3db5a15279
+ Author: Johannes Berg <johannes.berg@intel.com>
 -Date:   Mon Mar 3 14:19:08 2014 +0100
-+commit c82552c5b0cb1735dbcbad78b1ffc6d3c212dc56
-+Author: Tim Harvey <tharvey@gateworks.com>
-+Date:   Mon Apr 21 16:14:57 2014 -0700
++Date:   Mon May 19 17:59:50 2014 +0200
  
 -    cfg80211: remove racy beacon_interval assignment
-+    ath9k: add a recv budget
++    cfg80211: constify wowlan/coalesce mask/pattern pointers
      
 -    In case of AP mode, the beacon interval is already reset to
 -    zero inside cfg80211_stop_ap(), and in the other modes it
 -    isn't relevant. Remove the assignment to remove a potential
 -    race since the assignment isn't properly locked.
-+    Implement a recv budget so that in cases of high traffic we still allow other
-+    taskets to get processed.
++    This requires changing the nl80211 parsing code a bit to use
++    intermediate pointers for the allocation, but clarifies the
++    API towards the drivers.
      
 -    Reported-by: Michal Kazior <michal.kazior@tieto.com>
--    Signed-off-by: Johannes Berg <johannes.berg@intel.com>
--
+     Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+ 
 -commit 1abdeca3c6fb9cf1f84f85e78ed8d1c33bd69db0
 -Author: Felix Fietkau <nbd@openwrt.org>
 -Date:   Fri Feb 28 18:52:56 2014 +0100
 -
 -    ath9k_hw: tweak noise immunity thresholds for older chipsets
-+    Without this, we can encounter a host of issues during high wireless traffic
-+    reception depending on system load including rcu stall's detected (ARM),
-+    soft lockups, failure to service critical tasks such as watchdog resets,
-+    and triggering of the tx stuck tasklet.
-     
+-    
 -    Older chipsets are more sensitive to high PHY error counts, and the
 -    current noise immunity thresholds were based on tests run at QCA with
 -    newer chipsets.
-+    The same thing was proposed previously by Ben:
-+     http://www.spinics.net/lists/linux-wireless/msg112891.html
-     
+-    
 -    This patch brings back the values from the old ANI implementation for
 -    old chipsets, and it also disables weak signal detection on an earlier
 -    noise immunity level, to improve overall radio stability on affected
 -    devices.
-+    The only difference here is that I make sure only processed packets are counted
-+    in the budget by checking at the end of the rx loop.
-     
+-    
 -    Signed-off-by: Felix Fietkau <nbd@openwrt.org>
-+    Signed-off-by: Tim Harvey <tharvey@gateworks.com>
-+    Acked-by: Felix Fietkau <nbd@openwrt.org>
-+    Signed-off-by: John W. Linville <linville@tuxdriver.com>
- 
+-
 -commit 431e506da5953adc3b65af25f4b90873d528c115
 -Author: Felix Fietkau <nbd@openwrt.org>
 -Date:   Fri Feb 28 18:44:13 2014 +0100
-+commit 3a758134e66ca74a9df792616b5288b2fa2cfd7f
-+Author: Tim Harvey <tharvey@gateworks.com>
-+Date:   Mon Apr 21 16:14:56 2014 -0700
- 
+-
 -    ath9k_hw: toggle weak signal detection in AP mode on older chipsets
 -    
 -    The commit 80b4205b "ath9k: Fix OFDM weak signal detection for AP mode"
 -    prevented weak signal detection changes from taking effect in AP mode on
 -    all chipsets, claiming it is "not allowed".
-+    ath9k: fix possible hang on flush
-     
+-    
 -    The main reason for not disabling weak signal detection in AP mode is
 -    that typically beacon RSSI is used to track whether it is needed to
 -    boost range, and this is unavailable in AP mode for obvious reasons.
-+    If a flush is requested, make sure to clear the descriptor once we've
-+    processed it.
-     
+-    
 -    The problem with not disabling weak signal detection is that older
 -    chipsets are very sensitive to high PHY error counts. When faced with
 -    heavy noise, this can lead to an excessive amount of "Failed to stop
 -    TX DMA" errors in the field.
-+    This resolves a hang that will occur if all RX descriptors are full when a
-+    flush is requested.
-     
+-    
 -    Signed-off-by: Felix Fietkau <nbd@openwrt.org>
-+    Signed-off-by: Tim Harvey <tharvey@gateworks.com>
-+    Acked-by: Felix Fietkau <nbd@openwrt.org>
-+    Signed-off-by: John W. Linville <linville@tuxdriver.com>
- 
+-
 -commit 98d1a6c5b14688ed030e81b889f607be308e0df9
-+commit eefb1d6adc4c60d219182b8917e4567484ce07fc
- Author: Felix Fietkau <nbd@openwrt.org>
+-Author: Felix Fietkau <nbd@openwrt.org>
 -Date:   Mon Feb 24 22:20:32 2014 +0100
-+Date:   Mon Apr 28 18:27:41 2014 +0200
- 
+-
 -    ath9k: fix invalid descriptor discarding
 -    
 -    Only set sc->rx.discard_next to rx_stats->rs_more when actually
 -    discarding the current descriptor.
-+    ath9k: remove tid->paused flag
-     
+-    
 -    Also, fix a detection of broken descriptors:
 -    First the code checks if the current descriptor is not done.
 -    Then it checks if the next descriptor is done.
 -    Add a check that afterwards checks the first descriptor again, because
 -    it might have been completed in the mean time.
-+    There are some corner cases where the driver could get stuck with a full
-+    tid queue that is paused, leading to a software tx queue hang.
-     
+-    
 -    This fixes a regression introduced in
 -    commit 723e711356b5a8a95728a890e254e8b0d47b55cf
 -    "ath9k: fix handling of broken descriptors"
@@ -2276,26 +2422,18 @@ index a1af6c2..892f51e 100644
 -Date:   Mon Feb 24 11:43:50 2014 +0100
 -
 -    ath9k: reduce baseband hang detection false positive rate
-+    Since the tx queueing rework, pausing per-tid queues on aggregation
-+    session setup is no longer necessary. The driver will assign sequence
-+    numbers to buffered frames when a new session is established, in order
-+    to get the correct starting sequence number.
-     
+-    
 -    Check if the baseband state remains stable, and add a small delay
 -    between register reads.
-+    mac80211 prevents new frames from entering the queue during setup.
-     
-     Signed-off-by: Felix Fietkau <nbd@openwrt.org>
- 
+-    
+-    Signed-off-by: Felix Fietkau <nbd@openwrt.org>
+-
 -commit 118945bb12082e9d4edddc868d88143164e0f440
-+commit 98a713933d8495f4078f561c1e651b738dd5b531
- Author: Felix Fietkau <nbd@openwrt.org>
+-Author: Felix Fietkau <nbd@openwrt.org>
 -Date:   Sat Feb 22 14:55:23 2014 +0100
-+Date:   Sun Apr 27 14:49:03 2014 +0200
- 
+-
 -    ath5k: set SURVEY_INFO_IN_USE on get_survey
-+    ath9k_hw: do not lower ANI setting below default on AR913x
-     
+-    
 -    Only one channel is returned - the one currently being used.
 -    
 -    Signed-off-by: Felix Fietkau <nbd@openwrt.org>
@@ -2305,88 +2443,65 @@ index a1af6c2..892f51e 100644
 -Date:   Sat Feb 22 14:44:52 2014 +0100
 -
 -    ath9k: make some hardware reset log messages debug-only
-+    When the amount of noise fluctuates strongly, low immunity settings
-+    can sometimes disrupt signal detection on AR913x chips. When that
-+    happens, no OFDM/CCK errors are reported anymore, and ANI tunes the
-+    radio to the lowest immunity settings.
-+    Usually rx/tx fails as well in that case.
-     
+-    
 -    On some chips, baseband watchdog hangs are more common than others, and
 -    the driver has support for handling them.
 -    Interrupts even after a watchdog hang are also quite common, so there's
 -    not much point in spamming the user's logfiles.
-+    To fix this, keep noise immunity settings at or above ANI default level,
-+    which will keep radio parameters at or above INI values.
-     
-     Signed-off-by: Felix Fietkau <nbd@openwrt.org>
- 
+-    
+-    Signed-off-by: Felix Fietkau <nbd@openwrt.org>
+-
 -commit b14fbb554fc65a2e0b5c41a319269b0350f187e7
-+commit 7cbb4c021bfd1e656f5b9953a947ab3c64e4e3b0
- Author: Felix Fietkau <nbd@openwrt.org>
+-Author: Felix Fietkau <nbd@openwrt.org>
 -Date:   Sat Feb 22 14:35:25 2014 +0100
-+Date:   Thu Apr 10 10:49:01 2014 +0200
- 
+-
 -    ath9k: do not set half/quarter channel flags in AR_PHY_MODE
 -    
 -    5/10 MHz channel bandwidth is configured via the PLL clock, instead of
 -    the AR_PHY_MODE register. Using that register is AR93xx specific, and
 -    makes the mode incompatible with earlier chipsets.
-+    mac80211: exclude AP_VLAN interfaces from tx power calculation
-     
+-    
 -    In some early versions, these flags were apparently applied at the wrong
 -    point in time and thus did not cause connectivity issues, however now
 -    they are causing problems, as pointed out in this OpenWrt ticket:
 -    
 -    https://dev.openwrt.org/ticket/14916
-+    Their power value is initialized to zero. This patch fixes an issue
-+    where the configured power drops to the minimum value when AP_VLAN
-+    interfaces are created/removed.
-     
-+    Cc: stable@vger.kernel.org
-     Signed-off-by: Felix Fietkau <nbd@openwrt.org>
- 
+-    
+-    Signed-off-by: Felix Fietkau <nbd@openwrt.org>
+-
 -commit 0f1cb7be2551b30b02cd54c897e0e29e483cfda5
-+commit 0ca13e26341733bf9577287fb04a3bef0d2f5cc9
- Author: Felix Fietkau <nbd@openwrt.org>
+-Author: Felix Fietkau <nbd@openwrt.org>
 -Date:   Sat Feb 22 13:43:29 2014 +0100
-+Date:   Wed Apr 9 00:07:01 2014 +0200
- 
+-
 -    ath9k: fix ps-poll responses under a-mpdu sessions
-+    mac80211: suppress BSS info change notifications for AP_VLAN
-     
+-    
 -    When passing tx frames to the U-APSD queue for powersave poll responses,
 -    the ath_atx_tid pointer needs to be passed to ath_tx_setup_buffer for
 -    proper sequence number accounting.
-+    Fixes warnings on tx power changes
-     
+-    
 -    This fixes high latency and connection stability issues with ath9k
 -    running as AP and a few kinds of mobile phones as client, when PS-Poll
 -    is heavily used
 -    
 -    Cc: stable@vger.kernel.org
-     Signed-off-by: Felix Fietkau <nbd@openwrt.org>
- 
+-    Signed-off-by: Felix Fietkau <nbd@openwrt.org>
+-
 -commit d5d87a37bbd6066b2c3c5d0bd0fe2a6e2ea45cc5
-+commit ec998e5991781ecdaad0911dc64f1c8d3749c308
- Author: Felix Fietkau <nbd@openwrt.org>
+-Author: Felix Fietkau <nbd@openwrt.org>
 -Date:   Fri Feb 21 11:39:59 2014 +0100
-+Date:   Tue Apr 8 23:42:17 2014 +0200
- 
+-
 -    ath9k: list more reset causes in debugfs
-+    ath9k: fix a scheduling while atomic bug in CSA handling
-     
+-    
 -    Number of MAC hangs and stuck beacons were missing
-+    Commit "ath9k: prepare for multi-interface CSA support" added a call to
-+    ieee80211_iterate_active_interfaces in atomic context (beacon tasklet),
-+    which is crashing.
-+    Use ieee80211_iterate_active_interfaces_atomic instead.
-     
-     Signed-off-by: Felix Fietkau <nbd@openwrt.org>
- 
+-    
+-    Signed-off-by: Felix Fietkau <nbd@openwrt.org>
+-
 -commit d84856012e0f10fe598a5ad3b7b869397a089e07
--Author: Johannes Berg <johannes.berg@intel.com>
++commit 6788105c46babaa6938cbacb72fdf20bec4bb2e3
+ Author: Johannes Berg <johannes.berg@intel.com>
 -Date:   Thu Feb 20 11:19:58 2014 +0100
--
++Date:   Mon May 19 17:53:16 2014 +0200
+ 
 -    mac80211: fix station wakeup powersave race
 -    
 -    Consider the following (relatively unlikely) scenario:
@@ -2404,24 +2519,32 @@ index a1af6c2..892f51e 100644
 -    As a result, no frames will be delivered to the client, even
 -    though it is awake, until it sends another frame to us that
 -    triggers ieee80211_sta_ps_deliver_wakeup() in sta_ps_end().
--    
++    cfg80211: constify more pointers in the cfg80211 API
+     
 -    Since we now take the PS spinlock, we can fix this while at
 -    the same time removing the complexity with the pending skb
 -    queue function. This was broken since my commit 50a9432daeec
 -    ("mac80211: fix powersaving clients races") due to removing
 -    the clearing of WLAN_STA_PS_STA in the RX path.
--    
++    This also propagates through the drivers.
+     
 -    While at it, fix a cleanup path issue when a station is
 -    removed while the driver is still blocking its wakeup.
--    
--    Signed-off-by: Johannes Berg <johannes.berg@intel.com>
--
++    The orinoco driver uses the cfg80211 API structs for internal
++    bookkeeping, and so needs a (void *) cast that removes the
++    const - but that's OK because it allocates those pointers.
+     
+     Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+ 
 -commit 798f2786602cbe93e6b928299614aa36ebf50692
--Author: Johannes Berg <johannes.berg@intel.com>
++commit c3d95010fd881da0fa0a4e88532412f5d0c092f6
+ Author: Johannes Berg <johannes.berg@intel.com>
 -Date:   Mon Feb 17 20:49:03 2014 +0100
--
++Date:   Mon May 19 17:19:31 2014 +0200
+ 
 -    mac80211: insert stations before adding to driver
--    
++    cfg80211: constify MAC addresses in cfg80211 ops
+     
 -    There's a race condition in mac80211 because we add stations
 -    to the internal lists after adding them to the driver, which
 -    means that (for example) the following can happen:
@@ -2443,13 +2566,17 @@ index a1af6c2..892f51e 100644
 -    driver fails to add the station, in that case a bit more is
 -    needed. To not make that overly complex prevent starting BA
 -    sessions in the meantime.
--    
--    Signed-off-by: Johannes Berg <johannes.berg@intel.com>
--
++    This propagates through all the drivers and mac80211.
+     
+     Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+ 
 -commit b9ba6a520cb07ab3aa7aaaf9ce4a0bc7a6bc06fe
 -Author: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
 -Date:   Thu Feb 20 09:22:11 2014 +0200
--
++commit ddf1e6f0f0354c601af7d42e5ace4b51f8b0bffc
++Author: Luciano Coelho <luciano.coelho@intel.com>
++Date:   Thu May 15 20:32:08 2014 +0300
+ 
 -    mac80211: fix AP powersave TX vs. wakeup race
 -    
 -    There is a race between the TX path and the STA wakeup: while
@@ -2457,18 +2584,24 @@ index a1af6c2..892f51e 100644
 -    up, then the frames are transmitted. However, the RX and TX
 -    path are concurrent, so the packet indicating wakeup can be
 -    processed while a packet is being transmitted.
--    
++    mac80211: fix csa_counter_offs argument name in docbook
+     
 -    This can lead to a situation where the buffered frames list
 -    is emptied on the one side, while a frame is being added on
 -    the other side, as the station is still seen as sleeping in
 -    the TX path.
--    
++    The csa_counter_offs was erroneously described as csa_offs in
++    the docbook section.
+     
 -    As a result, the newly added frame will not be send anytime
 -    soon. It might be sent much later (and out of order) when the
 -    station goes to sleep and wakes up the next time.
--    
++    This fixes two warnings when making htmldocs (at least):
+     
 -    Additionally, it can lead to the crash below.
--    
++    Warning(include/net/mac80211.h:3428): No description found for parameter 'csa_counter_offs[IEEE80211_MAX_CSA_COUNTERS_NUM]'
++    Warning(include/net/mac80211.h:3428): Excess struct/union/enum/typedef member 'csa_offs' description in 'ieee80211_mutable_offsets'
+     
 -    Fix all this by synchronising both paths with a new lock.
 -    Both path are not fastpath since they handle PS situations.
 -    
@@ -2523,8 +2656,9 @@ index a1af6c2..892f51e 100644
 -    when the status is not "IGNORE" nor "ALREADY_SET".
 -    
 -    Signed-off-by: Inbal Hacohen <Inbal.Hacohen@intel.com>
--    Signed-off-by: Johannes Berg <johannes.berg@intel.com>
--
++    Signed-off-by: Luciano Coelho <luciano.coelho@intel.com>
+     Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+ 
 -commit 6514c93afede55284e2cb63359aadedb85884c80
 -Author: Jouni Malinen <jouni@qca.qualcomm.com>
 -Date:   Tue Feb 18 20:41:08 2014 +0200
@@ -2540,13 +2674,19 @@ index a1af6c2..892f51e 100644
 -commit a63caf0a357ad5c1f08d6b7827dc76c451445017
 -Author: Stanislaw Gruszka <sgruszka@redhat.com>
 -Date:   Wed Feb 19 13:15:17 2014 +0100
--
++commit 202322d1c04b8e498bd5bb78606fcf3941512b35
++Author: Luciano Coelho <luciano.coelho@intel.com>
++Date:   Thu May 15 20:18:09 2014 +0300
+ 
 -    ath9k: protect tid->sched check
--    
++    cfg80211: add documentation for max_num_csa_counters
+     
 -    We check tid->sched without a lock taken on ath_tx_aggr_sleep(). That
 -    is race condition which can result of doing list_del(&tid->list) twice
 -    (second time with poisoned list node) and cause crash like shown below:
--    
++    Move the comment in the structure to a description of the
++    max_num_csa_counters field in the docbook area.
+     
 -    [424271.637220] BUG: unable to handle kernel paging request at 00100104
 -    [424271.637328] IP: [<f90fc072>] ath_tx_aggr_sleep+0x62/0xe0 [ath9k]
 -    ...
@@ -2569,37 +2709,46 @@ index a1af6c2..892f51e 100644
 -    [424271.641266]  [<f90fa6ee>] ath_rx_tasklet+0x88e/0xf70 [ath9k]
 -    [424271.641358]  [<f80a0f2c>] ? ieee80211_rx+0x1dc/0x7c0 [mac80211]
 -    [424271.641445]  [<f90f82db>] ath9k_tasklet+0xcb/0x130 [ath9k]
--    
++    This fixes a warning when building htmldocs (at least):
+     
 -    Bug report:
 -    https://bugzilla.kernel.org/show_bug.cgi?id=70551
--    
++     Warning(include/net/cfg80211.h:3064): No description found for parameter 'max_num_csa_counters'
+     
 -    Reported-and-tested-by: Max Sydorenko <maxim.stargazer@gmail.com>
 -    Cc: stable@vger.kernel.org
 -    Signed-off-by: Stanislaw Gruszka <sgruszka@redhat.com>
--
++    Signed-off-by: Luciano Coelho <luciano.coelho@intel.com>
++    Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+ 
 -commit 82ed9e3ccc02797df2ffe4b78127c4cd5f799a41
-+commit 93f310a38a1d81a4bc8fcd9bf29628bd721cf2ef
- Author: Felix Fietkau <nbd@openwrt.org>
+-Author: Felix Fietkau <nbd@openwrt.org>
 -Date:   Tue Feb 11 15:54:13 2014 +0100
-+Date:   Sun Apr 6 23:35:28 2014 +0200
++commit 457a33192f64b7637e8fd0ae0e9f32701c908603
++Author: Johannes Berg <johannes.berg@intel.com>
++Date:   Mon May 19 11:24:19 2014 +0200
  
 -    mac80211: send control port protocol frames to the VO queue
-+    ath9k_hw: reduce ANI firstep range for older chips
++    mac80211: minstrel-ht: small clarifications
      
 -    Improves reliability of wifi connections with WPA, since authentication
 -    frames are prioritized over normal traffic and also typically exempt
 -    from aggregation.
-+    Use 0-8 instead of 0-16, which is closer to the old implementation.
-+    Also drop the overwrite of the firstep_low parameter to improve
-+    stability.
++    Antonio and I were looking over this code and some things
++    didn't immediately make sense, so we came up with two small
++    clarifications.
      
 -    Cc: stable@vger.kernel.org
-     Signed-off-by: Felix Fietkau <nbd@openwrt.org>
+-    Signed-off-by: Felix Fietkau <nbd@openwrt.org>
++    Signed-off-by: Johannes Berg <johannes.berg@intel.com>
  
 -commit d4426800f71e972feaa33e04c5801fc730627bdd
 -Author: Stanislaw Gruszka <stf_xl@wp.pl>
 -Date:   Mon Feb 10 22:38:28 2014 +0100
--
++commit 1e35dce952a64a957de97ae1f2bb19301756b936
++Author: Andrei Otcheretianski <andrei.otcheretianski@intel.com>
++Date:   Fri May 9 14:11:50 2014 +0300
+ 
 -    rtl8187: fix regression on MIPS without coherent DMA
 -    
 -    This patch fixes regression caused by commit a16dad77634 "MIPS: Fix
@@ -2626,44 +2775,77 @@ index a1af6c2..892f51e 100644
 -    reproducible regression and seems other possible corruptions do not
 -    happen in practice, since Yeeloong laptop works stable without rtl8187
 -    driver.
--    
++    mac80211: Handle the CSA counters correctly
+     
 -    Bug report:
 -    https://bugzilla.kernel.org/show_bug.cgi?id=54391
--    
++    Make the beacon CSA counters part of ieee80211_mutable_offsets and don't
++    decrement CSA counters when generating a beacon template. This permits the
++    driver to offload the CSA counters handling. Since mac80211 updates the probe
++    responses with the correct counter, the driver should sync the counter's value
++    with mac80211 using ieee80211_csa_update_counter function.
+     
 -    Reported-by: Petr Pisar <petr.pisar@atlas.cz>
 -    Bisected-by: Tom Li <biergaizi2009@gmail.com>
 -    Reported-and-tested-by: Tom Li <biergaizi2009@gmail.com>
 -    Cc: stable@vger.kernel.org
 -    Signed-off-by: Stanislaw Gruszka <stf_xl@wp.pl>
--
++    Signed-off-by: Andrei Otcheretianski <andrei.otcheretianski@intel.com>
++    Signed-off-by: Luciano Coelho <luciano.coelho@intel.com>
++    Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+ 
 -commit e2f141d67ad1e7fe10aaab61811e8a409dfb2442
 -Author: Sujith Manoharan <c_manoha@qca.qualcomm.com>
 -Date:   Fri Feb 7 10:29:55 2014 +0530
--
++commit e7b5c449815d28a2105fde5b42e112f78cc711ac
++Author: Andrei Otcheretianski <andrei.otcheretianski@intel.com>
++Date:   Fri May 9 14:11:49 2014 +0300
+ 
 -    ath9k: Calculate IQ-CAL median
--    
++    mac80211: Provide ieee80211_beacon_get_template API
+     
 -    This patch adds a routine to calculate the median IQ correction
 -    values for AR955x, which is used for outlier detection.
 -    The normal method which is used for all other chips is
 -    bypassed for AR955x.
--    
++    Add a new API ieee80211_beacon_get_template, which doesn't
++    affect DTIM counter and should be used if the device generates beacon
++    frames, and new beacon template is needed. In addition set the offsets
++    to TIM IE for MESH interface.
+     
 -    Signed-off-by: Sujith Manoharan <c_manoha@qca.qualcomm.com>
--
++    Signed-off-by: Andrei Otcheretianski <andrei.otcheretianski@intel.com>
++    Signed-off-by: Luciano Coelho <luciano.coelho@intel.com>
++    Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+ 
 -commit c52a6fce0820c8d0687443ab86058ae03b478c8f
 -Author: Sujith Manoharan <c_manoha@qca.qualcomm.com>
 -Date:   Fri Feb 7 10:29:54 2014 +0530
--
++commit e54eda80273ce8aded058c3c9365dca2342e2e75
++Author: Andrei Otcheretianski <andrei.otcheretianski@intel.com>
++Date:   Fri May 9 14:11:47 2014 +0300
+ 
 -    ath9k: Expand the IQ coefficient array
--    
++    mac80211: Support multiple CSA counters
+     
 -    This will be used for storing data for mutiple
 -    IQ calibration runs, for AR955x.
--    
++    Support up to IEEE80211_MAX_CSA_COUNTERS_NUM csa counters.
++    This is defined to be 2 now, to support both CSA and eCSA
++    counters.
+     
 -    Signed-off-by: Sujith Manoharan <c_manoha@qca.qualcomm.com>
--
++    Signed-off-by: Andrei Otcheretianski <andrei.otcheretianski@intel.com>
++    Signed-off-by: Luciano Coelho <luciano.coelho@intel.com>
++    Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+ 
 -commit 034969ff5c2b6431d10e07c1938f0b916da85cc3
 -Author: Sujith Manoharan <c_manoha@qca.qualcomm.com>
 -Date:   Fri Feb 7 10:29:53 2014 +0530
--
++commit 678e87c3b929dd60d59470e8981eb551cee10319
++Author: Andrei Otcheretianski <andrei.otcheretianski@intel.com>
++Date:   Fri May 9 14:11:46 2014 +0300
+ 
 -    ath9k: Modify IQ calibration for AR955x
 -    
 -    IQ calibration post-processing for AR955x is different
@@ -2679,25 +2861,53 @@ index a1af6c2..892f51e 100644
 -    in subsequent patches) is set to zero.
 -    
 -    Signed-off-by: Sujith Manoharan <c_manoha@qca.qualcomm.com>
--
++    cfg80211: Support multiple CSA counters
++    
++    Change the type of NL80211_ATTR_CSA_C_OFF_BEACON and
++    NL80211_ATTR_CSA_C_OFF_PRESP to be NLA_BINARY which allows
++    userspace to use beacons and probe responses with
++    multiple CSA counters.
++    This isn't breaking the API since userspace can
++    continue to use nla_put_u16 for this attributes, which
++    is equivalent to a single element u16 array.
++    In addition advertise max number of supported CSA counters.
++    This is needed when using CSA and eCSA IEs together.
++    
++    Signed-off-by: Andrei Otcheretianski <andrei.otcheretianski@intel.com>
++    Signed-off-by: Luciano Coelho <luciano.coelho@intel.com>
++    Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+ 
 -commit 9b1ed6454e6f3511f24266be99b4e403f243f6a8
 -Author: Sujith Manoharan <c_manoha@qca.qualcomm.com>
 -Date:   Fri Feb 7 10:29:52 2014 +0530
--
++commit 93f4867a966cc8645659031bbd44a9bb4b78485f
++Author: Andrei Otcheretianski <andrei.otcheretianski@intel.com>
++Date:   Fri May 9 14:11:45 2014 +0300
+ 
 -    ath9k: Fix magnitude/phase calculation
--    
++    mac80211: Update CSA counters in mgmt frames
+     
 -    Incorrect values are programmed in the registers
 -    containing the IQ correction coefficients by the IQ-CAL
 -    post-processing code. Fix this.
--    
++    Track current csa counter value and use it
++    to update mgmt frames at the provided offsets.
+     
 -    Signed-off-by: Sujith Manoharan <c_manoha@qca.qualcomm.com>
--
++    Signed-off-by: Andrei Otcheretianski <andrei.otcheretianski@intel.com>
++    Signed-off-by: Luciano Coelho <luciano.coelho@intel.com>
++    Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+ 
 -commit 36f93484f96f79171dcecb67c5ef0c3de22531a6
 -Author: Sujith Manoharan <c_manoha@qca.qualcomm.com>
 -Date:   Fri Feb 7 10:29:51 2014 +0530
--
++commit 6c8461fcc03ff4d250027e47f53315b5e0ec43aa
++Author: Andrei Otcheretianski <andrei.otcheretianski@intel.com>
++Date:   Fri May 9 14:11:44 2014 +0300
+ 
 -    ath9k: Rename ar9003_hw_tx_iqcal_load_avg_2_passes
--    
++    cfg80211: Add API to update CSA counters in mgmt frames
+     
 -    Use ar9003_hw_tx_iq_cal_outlier_detection instead.
 -    
 -    Signed-off-by: Sujith Manoharan <c_manoha@qca.qualcomm.com>
@@ -2707,26 +2917,43 @@ index a1af6c2..892f51e 100644
 -Date:   Fri Feb 7 10:29:50 2014 +0530
 -
 -    ath9k: Check explicitly for IQ calibration
--    
++    Add NL80211_ATTR_CSA_C_OFFSETS_TX which holds an array
++    of offsets to the CSA counters which should be updated
++    when sending a management frames with NL80211_CMD_FRAME.
+     
 -    In chips like AR955x, the initvals contain the information
 -    whether IQ calibration is to be done in the HW when an
 -    AGC calibration is triggered. Check if IQ-CAL is enabled
 -    in the initvals before flagging 'txiqcal_done' as true.
--    
++    This API should be used by the drivers that wish to keep the
++    CSA counter updated in probe responses, but do not implement
++    probe response offloading and so, do not use
++    ieee80211_proberesp_get function.
+     
 -    Signed-off-by: Sujith Manoharan <c_manoha@qca.qualcomm.com>
--
++    Signed-off-by: Andrei Otcheretianski <andrei.otcheretianski@intel.com>
++    Signed-off-by: Luciano Coelho <luciano.coelho@intel.com>
++    Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+ 
 -commit cb4969634b93c4643a32cc3fbd27d2b288b25771
 -Author: Sujith Manoharan <c_manoha@qca.qualcomm.com>
 -Date:   Fri Feb 7 10:29:49 2014 +0530
--
++commit 7d09fc9f1903b3d5e7d046bdf10467f37a97c4f9
++Author: Luciano Coelho <luciano.coelho@intel.com>
++Date:   Thu May 15 13:05:39 2014 +0300
+ 
 -    ath9k: Fix IQ cal post processing for SoC
--    
++    cfg80211: pass the actual iftype when calling cfg80211_chandef_dfs_required()
+     
 -    Calibration data is not reused for SoC chips, so
 -    call ar9003_hw_tx_iq_cal_post_proc() with the correct
 -    argument. The 'is_reusable' flag is currently used
 -    only for PC-OEM chips, but it makes things clearer to
 -    specify it explicity.
--    
++    There is no need to pass NL80211_IFTYPE_UNSPECIFIED when calling
++    cfg80211_chandef_dfs_required() since we always already have the
++    interface type.  So, pass the actual interface type instead.
+     
 -    Signed-off-by: Sujith Manoharan <c_manoha@qca.qualcomm.com>
 -
 -commit e138e0ef9560c46ce93dbb22a728a57888e94d1c
@@ -2734,7 +2961,10 @@ index a1af6c2..892f51e 100644
 -Date:   Mon Feb 3 13:31:37 2014 +0530
 -
 -    ath9k: Fix TX power calculation
--    
++    Additionally, have cfg80211_chandef_dfs_required() WARN if the passed
++    interface type is NL80211_IFTYPE_UNSPECIFIED, so we can detect
++    problems more easily.
+     
 -    The commit, "ath9k_hw: Fix incorrect Tx control power in AR9003 template"
 -    fixed the incorrect values in the eeprom templates, but if
 -    boards have already been calibrated with incorrect values,
@@ -2743,22 +2973,33 @@ index a1af6c2..892f51e 100644
 -    
 -    Cc: Rajkumar Manoharan <rmanohar@qti.qualcomm.com>
 -    Signed-off-by: Sujith Manoharan <c_manoha@qca.qualcomm.com>
--
++    Tested-by: Janusz Dziedzic <janusz.dziedzic@tieto.com>
++    Reported-by: Eliad Peller <eliad@wizery.com>
++    Signed-off-by: Luciano Coelho <luciano.coelho@intel.com>
++    Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+ 
 -commit b9f268b5b01331c3c82179abca551429450e9417
 -Author: Michal Kazior <michal.kazior@tieto.com>
 -Date:   Wed Jan 29 14:22:27 2014 +0100
--
++commit 2b7443b15f26ecb98281474666383cf2a882fbad
++Author: Janusz Dziedzic <janusz.dziedzic@tieto.com>
++Date:   Wed May 14 13:25:04 2014 +0200
+ 
 -    cfg80211: consider existing DFS interfaces
 -    
 -    It was possible to break interface combinations in
 -    the following way:
--    
++    cfg80211: fix start_radar_detection issue
+     
 -     combo 1: iftype = AP, num_ifaces = 2, num_chans = 2,
 -     combo 2: iftype = AP, num_ifaces = 1, num_chans = 1, radar = HT20
--    
++    After patch:
++    cfg80211/mac80211: refactor cfg80211_chandef_dfs_required()
+     
 -    With the above interface combinations it was
 -    possible to:
--    
++    start_radar_detection always fail with -EINVAL.
+     
 -     step 1. start AP on DFS channel by matching combo 2
 -     step 2. start AP on non-DFS channel by matching combo 1
 -    
@@ -2770,12 +3011,17 @@ index a1af6c2..892f51e 100644
 -    is stored.
 -    
 -    Signed-off-by: Michal Kazior <michal.kazior@tieto.com>
--    Signed-off-by: Johannes Berg <johannes.berg@intel.com>
--
++    Acked-by: Luciano Coelho <luciano.coelho@intel.com>
++    Signed-off-by: Janusz Dziedzic <janusz.dziedzic@tieto.com>
+     Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+ 
 -commit bc9c62f5f511cc395c62dbf4cdd437f23db53b28
 -Author: Antonio Quartulli <antonio@open-mesh.com>
 -Date:   Wed Jan 29 17:53:43 2014 +0100
--
++commit 4f46eb8b28f96aca212a364e0fa847eb5333df67
++Author: Felix Fietkau <nbd@openwrt.org>
++Date:   Mon May 5 11:48:40 2014 +0200
+ 
 -    cfg80211: fix channel configuration in IBSS join
 -    
 -    When receiving an IBSS_JOINED event select the BSS object
@@ -2787,7 +3033,8 @@ index a1af6c2..892f51e 100644
 -    The result is a mismatching channel configuration between
 -    cfg80211 and the driver, that can lead to any sort of
 -    problem.
--    
++    cfg80211: allow restricting supported dfs regions
+     
 -    The issue can be triggered by having an IBSS sitting on
 -    given channel and then asking the driver to create a new
 -    cell using the same BSSID but with a different frequency.
@@ -2795,7 +3042,12 @@ index a1af6c2..892f51e 100644
 -    this ambiguity and retrieve/create the correct BSS object.
 -    All the users of cfg80211_ibss_joined() have been changed
 -    accordingly.
--    
++    At the moment, the ath9k/ath10k DFS module only supports detecting ETSI
++    radar patterns.
++    Add a bitmap in the interface combinations, indicating which DFS regions
++    are supported by the detector. If unset, support for all regions is
++    assumed.
+     
 -    Moreover WARN when cfg80211_ibss_joined() gets a NULL
 -    channel as argument and remove a bogus call of the same
 -    function in ath6kl (it does not make sense to call
@@ -2809,36 +3061,53 @@ index a1af6c2..892f51e 100644
 -    Acked-by: Kalle Valo <kvalo@qca.qualcomm.com>
 -    Signed-off-by: Antonio Quartulli <antonio@open-mesh.com>
 -    [minor code cleanup in ath6kl]
--    Signed-off-by: Johannes Berg <johannes.berg@intel.com>
--
++    Signed-off-by: Felix Fietkau <nbd@openwrt.org>
+     Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+ 
 -commit 7e0c41cb41f215aba2c39b1c237bb4d42ec49a85
--Author: Johannes Berg <johannes.berg@intel.com>
++commit 0277b034768d1800a00829a755fc56b925aa6b95
+ Author: Johannes Berg <johannes.berg@intel.com>
 -Date:   Fri Jan 24 14:41:44 2014 +0100
--
++Date:   Wed Apr 30 14:19:04 2014 +0200
+ 
 -    mac80211: fix bufferable MMPDU RX handling
--    
++    mac80211: handle failed restart/resume better
+     
 -    Action, disassoc and deauth frames are bufferable, and as such don't
 -    have the PM bit in the frame control field reserved which means we
 -    need to react to the bit when receiving in such a frame.
--    
++    When the driver fails during HW restart or resume, the whole
++    stack goes into a very confused state with interfaces being
++    up while the hardware is down etc.
+     
 -    Fix this by introducing a new helper ieee80211_is_bufferable_mmpdu()
 -    and using it for the RX path that currently ignores the PM bit in
 -    any non-data frames for doze->wake transitions, but listens to it in
 -    all frames for wake->doze transitions, both of which are wrong.
 -    
 -    Also use the new helper in the TX path to clean up the code.
--    
--    Signed-off-by: Johannes Berg <johannes.berg@intel.com>
--
++    Address this by shutting down everything; we'll run into a
++    lot of warnings in the process but that's better than having
++    the whole stack get messed up.
+     
++    Reviewed-by: Arik Nemtsov <arik@wizery.com>
+     Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+ 
 -commit fc0df6d2343636e3f48a069330d5b972e3d8659d
 -Author: Janusz Dziedzic <janusz.dziedzic@tieto.com>
 -Date:   Fri Jan 24 14:29:21 2014 +0100
--
++commit 43fd71bc4b83d24981e90ca178f505cf6a6b16dc
++Author: Luciano Coelho <luciano.coelho@intel.com>
++Date:   Wed May 7 20:05:12 2014 +0300
+ 
 -    cfg80211: set preset_chandef after channel switch
--    
++    mac80211: fix sparse warning caused by __ieee80211_channel_switch()
+     
 -    Set preset_chandef in channel switch notification.
 -    In other case we will have old preset_chandef.
--    
++    Commit 59af6928 (mac80211: fix CSA tx queue stopping) introduced a
++    sparse warning:
+     
 -    Signed-off-by: Janusz Dziedzic <janusz.dziedzic@tieto.com>
 -    Signed-off-by: Johannes Berg <johannes.berg@intel.com>
 -
@@ -2847,38 +3116,57 @@ index a1af6c2..892f51e 100644
 -Date:   Fri Jan 24 23:48:29 2014 +0100
 -
 -    mac80211: send ibss probe responses with noack flag
--    
++    net/mac80211/cfg.c:3274:5: warning: symbol '__ieee80211_channel_switch' was not declared. Should it be static?
+     
 -    Responding to probe requests for scanning clients will often create
 -    excessive retries, as it happens quite often that the scanning client
 -    already left the channel. Therefore do it like hostapd and send probe
 -    responses for wildcard SSID only once by using the noack flag.
--    
++    Fix it by declaring the function static.
+     
 -    Signed-off-by: Simon Wunderlich <simon@open-mesh.com>
 -    [fix typo & 'wildcard SSID' in commit log]
--    Signed-off-by: Johannes Berg <johannes.berg@intel.com>
--
++    Signed-off-by: Luciano Coelho <luciano.coelho@intel.com>
+     Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+ 
 -commit 0b865d1e6b9c05052adae9315df7cb195dc60c3b
--Author: Luciano Coelho <luciano.coelho@intel.com>
++commit dd4371e2957db19870bb22ab84e841e1ac6e8997
+ Author: Luciano Coelho <luciano.coelho@intel.com>
 -Date:   Tue Jan 28 17:09:08 2014 +0200
--
++Date:   Wed May 7 19:07:05 2014 +0300
+ 
 -    mac80211: ibss: remove unnecessary call to release channel
--    
++    cfg80211: fix docbook warning
++    
++    When trying to generate documentation, at least xmldocs, we get the
++    following warning:
++    
++    Warning(include/net/cfg80211.h:461): No description found for parameter 'nl80211_iftype'
+     
 -    The ieee80211_vif_use_channel() function calls
 -    ieee80211_vif_release_channel(), so there's no need to call it
 -    explicitly in __ieee80211_sta_join_ibss().
--    
--    Signed-off-by: Luciano Coelho <luciano.coelho@intel.com>
--    Signed-off-by: Johannes Berg <johannes.berg@intel.com>
--
++    Fix it by adding the iftype argument name to the
++    cfg80211_chandef_dfs_required() function declaration.
+     
++    Reported-and-tested-by: Masanari Iida <standby24x7@gmail.com>
+     Signed-off-by: Luciano Coelho <luciano.coelho@intel.com>
+     Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+ 
 -commit e1b6c17e971f0a51ff86c2dac2584c63cd999cd7
--Author: Michal Kazior <michal.kazior@tieto.com>
++commit 56de850ae960f096c784ec07864ca5b71abd16e6
+ Author: Michal Kazior <michal.kazior@tieto.com>
 -Date:   Wed Jan 29 07:56:21 2014 +0100
--
++Date:   Thu May 8 09:10:02 2014 +0200
+ 
 -    mac80211: add missing CSA locking
--    
++    mac80211: disconnect iface if CSA unexpectedly fails
+     
 -    The patch adds a missing sdata lock and adds a few
 -    lockdeps for easier maintenance.
--    
++    It doesn't make much sense to leave a crippled
++    interface running.
+     
 -    Signed-off-by: Michal Kazior <michal.kazior@tieto.com>
 -    Signed-off-by: Johannes Berg <johannes.berg@intel.com>
 -
@@ -2887,48 +3175,76 @@ index a1af6c2..892f51e 100644
 -Date:   Wed Jan 29 07:56:20 2014 +0100
 -
 -    mac80211: fix sdata->radar_required locking
--    
++    As a side effect this will unblock tx queues with
++    CSA reason immediately after failure instead of
++    until after userspace requests interface to stop.
+     
 -    radar_required setting wasn't protected by
 -    local->mtx in some places. This should prevent
 -    from scanning/radar detection/roc colliding.
--    
--    Signed-off-by: Michal Kazior <michal.kazior@tieto.com>
--    Signed-off-by: Johannes Berg <johannes.berg@intel.com>
--
++    This also gives userspace an opportunity to
++    indirectly see CSA failure.
+     
+     Signed-off-by: Michal Kazior <michal.kazior@tieto.com>
++    [small code cleanup]
+     Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+ 
 -commit 5fcd5f1808813a3d9e502fd756e01bee8a79c85d
 -Author: Michal Kazior <michal.kazior@tieto.com>
 -Date:   Wed Jan 29 07:56:19 2014 +0100
--
++commit f5894c4f19e55bb1ea6376031fe9d47d7528be9e
++Author: Loic Poulain <loic.poulain@intel.com>
++Date:   Wed May 7 11:38:11 2014 +0200
+ 
 -    mac80211: move csa_active setting in STA CSA
--    
++    rfkill-gpio: Use gpio cansleep version
+     
 -    The sdata->vif.csa_active could be left set after,
 -    e.g. channel context constraints check fail in STA
 -    mode leaving the interface in a strange state for
 -    a brief period of time until it is disconnected.
 -    This was harmless but ugly.
--    
++    If gpio controller requires waiting for read and write
++    GPIO values, then we have to use the gpio cansleep api.
++    Fix the rfkill_gpio_set_power which calls only the
++    nonsleep version (causing kernel warning).
++    There is no problem to use the cansleep version here
++    because we are not in IRQ handler or similar context
++    (cf rfkill_set_block).
+     
 -    Signed-off-by: Michal Kazior <michal.kazior@tieto.com>
 -    Reviewed-by: Luciano Coelho <luciano.coelho@intel.com>
--    Signed-off-by: Johannes Berg <johannes.berg@intel.com>
--
++    Signed-off-by: Loic Poulain <loic.poulain@intel.com>
+     Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+ 
 -commit e486da4b7eed71821c6b4c1bb9ac62ffd3ab13e9
--Author: Michal Kazior <michal.kazior@tieto.com>
++commit 47fdf5d4f3704d2db9d1c0f647f788edef104fc8
+ Author: Michal Kazior <michal.kazior@tieto.com>
 -Date:   Wed Jan 29 07:56:18 2014 +0100
--
++Date:   Wed Apr 9 15:45:36 2014 +0200
+ 
 -    mac80211: fix possible memory leak on AP CSA failure
--    
++    mac80211: ignore cqm during csa
+     
 -    If CSA for AP interface failed and the interface
 -    was not stopped afterwards another CSA request
 -    would leak sdata->u.ap.next_beacon.
--    
--    Signed-off-by: Michal Kazior <michal.kazior@tieto.com>
++    It is not guaranteed that multi-vif channel
++    switching is tightly synchronized. It makes sense
++    to ignore cqm (missing beacons, et al) while csa
++    is progressing and re-check it after it completes.
+     
+     Signed-off-by: Michal Kazior <michal.kazior@tieto.com>
 -    Reviewed-by: Luciano Coelho <luciano.coelho@intel.com>
--    Signed-off-by: Johannes Berg <johannes.berg@intel.com>
--
+     Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+ 
 -commit 3a77ba08940682bf3d52cf14f980337324af9d4a
 -Author: Johannes Berg <johannes.berg@intel.com>
 -Date:   Sat Feb 1 00:33:29 2014 +0100
--
++commit 1a8ed386e1684b266a15dacf675102ae53361ee5
++Author: Michal Kazior <michal.kazior@tieto.com>
++Date:   Wed Apr 9 15:11:01 2014 +0200
+ 
 -    mac80211: fix fragmentation code, particularly for encryption
 -    
 -    The "new" fragmentation code (since my rewrite almost 5 years ago)
@@ -2938,7 +3254,8 @@ index a1af6c2..892f51e 100644
 -    originally ended, and thus causes the encryption MIC to be written
 -    at that point, rather than where it belongs: immediately after the
 -    data.
--    
++    cfg80211: export interface stopping function
+     
 -    The impact of this is that if software encryption is done, then
 -     a) encryption doesn't work for the first fragment, the connection
 -        becomes unusable as the first fragment will never be properly
@@ -2946,20 +3263,27 @@ index a1af6c2..892f51e 100644
 -        be wrong
 -     b) we leak up to 8 bytes of plaintext (!) of the packet out into
 -        the air
--    
++    This exports a new cfg80211_stop_iface() function.
+     
 -    This is only mitigated by the fact that many devices are capable
 -    of doing encryption in hardware, in which case this can't happen
 -    as the tail pointer is irrelevant in that case. Additionally,
 -    fragmentation is not used very frequently and would normally have
 -    to be configured manually.
--    
++    This is intended for driver internal interface
++    combination management and channel switching.
+     
 -    Fix this by using skb_trim() properly.
--    
++    Due to locking issues (it re-enters driver) the
++    call is asynchronous and uses cfg80211 event
++    list/worker.
+     
 -    Cc: stable@vger.kernel.org
 -    Fixes: 2de8e0d999b8 ("mac80211: rewrite fragmentation")
 -    Reported-by: Jouni Malinen <j@w1.fi>
--    Signed-off-by: Johannes Berg <johannes.berg@intel.com>
--
++    Signed-off-by: Michal Kazior <michal.kazior@tieto.com>
+     Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+ 
 -commit de5f242e0c10e841017e37eb8c38974a642dbca8
 -Author: Sujith Manoharan <c_manoha@qca.qualcomm.com>
 -Date:   Tue Jan 28 06:21:59 2014 +0530
@@ -2992,20 +3316,29 @@ index a1af6c2..892f51e 100644
 -commit a4a634a6937ebdd827fa58e8fcdb8ca49a3769f6
 -Author: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
 -Date:   Mon Jan 27 11:07:42 2014 +0200
--
++commit 573f31d6d0e572ff8186c45a1ecd9273242233e6
++Author: Michal Kazior <michal.kazior@tieto.com>
++Date:   Wed Apr 9 15:11:00 2014 +0200
+ 
 -    mac80211: release the channel in error path in start_ap
--    
++    mac80211: split CSA finalize function
+     
 -    When the driver cannot start the AP or when the assignement
 -    of the beacon goes wrong, we need to unassign the vif.
--    
++    Improves readability and modularity.
+     
 -    Cc: stable@vger.kernel.org
 -    Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
--    Signed-off-by: Johannes Berg <johannes.berg@intel.com>
--
++    Signed-off-by: Michal Kazior <michal.kazior@tieto.com>
+     Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+ 
 -commit dfb6889a75c601aedb7450b7e606668e77da6679
 -Author: Johannes Berg <johannes.berg@intel.com>
 -Date:   Wed Jan 22 11:14:19 2014 +0200
--
++commit 2d104d52e7c7640d68f29f2136dbe3938b7bc9ba
++Author: Michal Kazior <michal.kazior@tieto.com>
++Date:   Wed Apr 9 15:10:59 2014 +0200
+ 
 -    cfg80211: send scan results from work queue
 -    
 -    Due to the previous commit, when a scan finishes, it is in theory
@@ -3027,13 +3360,39 @@ index a1af6c2..892f51e 100644
 -    
 -    As this can't work for wext, so we send the message immediately,
 -    but this shouldn't be an issue since we still return -EBUSY.
--    
--    Signed-off-by: Johannes Berg <johannes.berg@intel.com>
--
++    mac80211: fix CSA tx queue stopping
++    
++    It was possible for tx queues to be stuck stopped
++    if AP CSA finalization failed. In that case
++    neither stop_ap nor do_stop woke the queues up.
++    This means it was impossible to perform tx at all
++    until driver was reloaded or a successful CSA was
++    performed later.
++    
++    It was possible to solve this in a simpler manner
++    however this is more robust and future proof
++    (having multi-vif CSA in mind).
++    
++    New sdata->csa_block_tx is introduced to keep
++    track of which interfaces requested tx to be
++    blocked for CSA. This is required because mac80211
++    stops all tx queues for that purpose. This means
++    queues must be awoken only when last tx-blocking
++    CSA interface is finished.
++    
++    It is still possible to have tx queues stopped
++    after CSA failure but as soon as offending
++    interfaces are stopped from userspace (stop_ap or
++    ifdown) tx queues are woken up properly.
+     
++    Signed-off-by: Michal Kazior <michal.kazior@tieto.com>
+     Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+ 
 -commit 45b7ab41fc08627d9a8428cb413d5d84662a9707
--Author: Johannes Berg <johannes.berg@intel.com>
++commit 6be615d6d42aa7fdab6c4278031d8fa0953e594f
+ Author: Johannes Berg <johannes.berg@intel.com>
 -Date:   Wed Jan 22 11:14:18 2014 +0200
- 
+-
 -    cfg80211: fix scan done race
 -    
 -    When an interface/wdev is removed, any ongoing scan should be
@@ -3060,7 +3419,8 @@ index a1af6c2..892f51e 100644
 -commit ae04fa489ab31b5a10d3cc8399f52761175d4321
 -Author: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
 -Date:   Thu Jan 23 14:28:16 2014 +0200
--
++Date:   Wed Apr 9 21:31:13 2014 +0200
+ 
 -    mac80211: avoid deadlock revealed by lockdep
 -    
 -    sdata->u.ap.request_smps_work can’t be flushed synchronously
@@ -3070,14 +3430,18 @@ index a1af6c2..892f51e 100644
 -    stopped to its default: OFF.
 -    
 -    This solves:
--    
++    mac80211: mark local variable __maybe_unused
+     
 -    ======================================================
 -    [ INFO: possible circular locking dependency detected ]
 -    3.12.0-ipeer+ #2 Tainted: G           O
 -    -------------------------------------------------------
 -    rmmod/2867 is trying to acquire lock:
 -      ((&sdata->u.ap.request_smps_work)){+.+...}, at: [<c105b8d0>] flush_work+0x0/0x90
--    
++    The 'local' variable in __ieee80211_vif_copy_chanctx_to_vlans()
++    is only used/needed when lockdep is compiled in, mark it as such
++    to avoid compile warnings in the other case.
+     
 -    but task is already holding lock:
 -      (&wdev->mtx){+.+.+.}, at: [<f9b32626>] cfg80211_stop_ap+0x26/0x230 [cfg80211]
 -    
@@ -3137,38 +3501,53 @@ index a1af6c2..892f51e 100644
 -    Unfortunately I forgot this during the merge window, but the
 -    patch seems small enough to go in as a fix. The userspace API
 -    bug that was the reason for disabling it has long been fixed.
--    
--    Signed-off-by: Johannes Berg <johannes.berg@intel.com>
--
++    While at it, fix some indentation where it's used.
+     
++    Reviewed-by: Luciano Coelho <luciano.coelho@intel.com>
++    Reviewed-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
+     Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+ 
 -commit 110a1c79acda14edc83b7c8dc5af9c7ddd23eb61
 -Author: Pontus Fuchs <pontus.fuchs@gmail.com>
 -Date:   Thu Jan 16 15:00:40 2014 +0100
--
++commit 43279e584aeb78aa0c853728db047b58156c0753
++Author: Arik Nemtsov <arik@wizery.com>
++Date:   Thu May 1 10:17:28 2014 +0300
+ 
 -    nl80211: Reset split_start when netlink skb is exhausted
 -    
 -    When the netlink skb is exhausted split_start is left set. In the
 -    subsequent retry, with a larger buffer, the dump is continued from the
 -    failing point instead of from the beginning.
--    
++    mac80211: move TDLS code to another file
+     
 -    This was causing my rt28xx based USB dongle to now show up when
 -    running "iw list" with an old iw version without split dump support.
--    
++    With new additions planned, this code is getting too big for cfg.c.
+     
 -    Cc: stable@vger.kernel.org
 -    Fixes: 3713b4e364ef ("nl80211: allow splitting wiphy information in dumps")
 -    Signed-off-by: Pontus Fuchs <pontus.fuchs@gmail.com>
 -    [avoid the entire workaround when state->split is set]
--    Signed-off-by: Johannes Berg <johannes.berg@intel.com>
--
++    Signed-off-by: Arik Nemtsov <arikx.nemtsov@intel.com>
+     Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+ 
 -commit b4c31b45ffc7ef110fa9ecc34d7878fe7c5b9da4
 -Author: Eliad Peller <eliad@wizery.com>
 -Date:   Sun Jan 12 11:06:37 2014 +0200
--
++commit bf9c234b83c77f1ebbcbab73de2a9e4a5d4aafc6
++Author: Arik Nemtsov <arik@wizery.com>
++Date:   Thu May 1 10:17:27 2014 +0300
+ 
 -    mac80211: move roc cookie assignment earlier
--    
++    mac80211: set an external flag for TDLS stations
+     
 -    ieee80211_start_roc_work() might add a new roc
 -    to existing roc, and tell cfg80211 it has already
 -    started.
--    
++    Expose a new tdls flag for the public ieee80211_sta struct.
++    This can be used in some rate control decisions.
+     
 -    However, this might happen before the roc cookie
 -    was set, resulting in REMAIN_ON_CHANNEL (started)
 -    event with null cookie. Consequently, it can make
@@ -3178,44 +3557,59 @@ index a1af6c2..892f51e 100644
 -    
 -    Cc: stable@vger.kernel.org
 -    Signed-off-by: Eliad Peller <eliad@wizery.com>
--    Signed-off-by: Johannes Berg <johannes.berg@intel.com>
--
++    Signed-off-by: Arik Nemtsov <arikx.nemtsov@intel.com>
+     Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+ 
 -commit cfdc9157bfd7bcf88ab4dae08873a9907eba984c
--Author: Johannes Berg <johannes.berg@intel.com>
++commit 910e65141a17f645ab85dae1a497e64ebe63df70
+ Author: Johannes Berg <johannes.berg@intel.com>
 -Date:   Fri Jan 24 14:06:29 2014 +0100
--
++Date:   Tue Apr 29 17:55:26 2014 +0200
+ 
 -    nl80211: send event when AP operation is stopped
--    
++    mac80211: remove BUG_ON usage
+     
 -    There are a few cases, e.g. suspend, where an AP interface is
 -    stopped by the kernel rather than by userspace request, most
 -    commonly when suspending. To let userspace know about this,
 -    send the NL80211_CMD_STOP_AP command as an event every time
 -    an AP interface is stopped. This also happens when userspace
 -    did in fact request the AP stop, but that's not a problem.
--    
++    These BUG_ON statements should never trigger, but in the unlikely
++    event that somebody does manage don't stop everything but simply
++    exit the code path with an error.
+     
 -    For full-MAC drivers this may need to be extended to also
 -    cover cases where the device stopped the AP operation for
 -    some reason, this a bit more complicated because then all
 -    cfg80211 state also needs to be reset; such API is not part
 -    of this patch.
--    
--    Signed-off-by: Johannes Berg <johannes.berg@intel.com>
--
++    Leave the one BUG_ON where changing it would result in a NULL
++    pointer dereference.
+     
+     Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+ 
 -commit d5d567eda7704f190379ca852a8f9a4112e3eee3
--Author: Johannes Berg <johannes.berg@intel.com>
++commit ff36b582a10285530351aab036087b57ddb4ae2b
+ Author: Johannes Berg <johannes.berg@intel.com>
 -Date:   Thu Jan 23 16:20:29 2014 +0100
--
++Date:   Tue Apr 29 17:52:36 2014 +0200
+ 
 -    mac80211: add length check in ieee80211_is_robust_mgmt_frame()
--    
++    cfg80211: remove BUG_ON usage
+     
 -    A few places weren't checking that the frame passed to the
 -    function actually has enough data even though the function
 -    clearly documents it must have a payload byte. Make this
 -    safer by changing the function to take an skb and checking
 -    the length inside. The old version is preserved for now as
 -    the rtl* drivers use it and don't have a correct skb.
--    
--    Signed-off-by: Johannes Berg <johannes.berg@intel.com>
--
++    These really can't trigger unless somebody messes up the code,
++    but don't make debugging it needlessly complicated, WARN and
++    return instead of BUG_ON().
+     
+     Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+ 
 -commit f8f6d212a047fc65c7d3442dfc038f65517236fc
 -Author: Johannes Berg <johannes.berg@intel.com>
 -Date:   Fri Jan 24 10:53:53 2014 +0100
@@ -3293,8 +3687,8 @@ index a1af6c2..892f51e 100644
 -    Cc: Helmut Schaa <helmut.schaa@googlemail.com>
 -    Cc: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
 -    Signed-off-by: Johannes Berg <johannes.berg@intel.com>
----- a/drivers/net/wireless/ath/ath6kl/cfg80211.c
--+++ b/drivers/net/wireless/ath/ath6kl/cfg80211.c
+ --- a/drivers/net/wireless/ath/ath6kl/cfg80211.c
+ +++ b/drivers/net/wireless/ath/ath6kl/cfg80211.c
 -@@ -790,7 +790,7 @@ void ath6kl_cfg80211_connect_event(struc
 - 	if (nw_type & ADHOC_NETWORK) {
 - 		ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "ad-hoc %s selected\n",
@@ -3318,7 +3712,9 @@ index a1af6c2..892f51e 100644
 --		cfg80211_ibss_joined(vif->ndev, bssid, GFP_KERNEL);
 - 		return;
 - 	}
-- 
++@@ -1759,7 +1759,7 @@ static bool is_rate_ht40(s32 rate, u8 *m
++ }
+  
 -@@ -3256,6 +3252,15 @@ static int ath6kl_cfg80211_sscan_start(s
 - 	struct ath6kl_vif *vif = netdev_priv(dev);
 - 	u16 interval;
@@ -3378,7 +3774,10 @@ index a1af6c2..892f51e 100644
 - 
 -@@ -1534,7 +1534,7 @@ EXPORT_SYMBOL(ath9k_hw_check_nav);
 - bool ath9k_hw_check_alive(struct ath_hw *ah)
-- {
++ static int ath6kl_get_station(struct wiphy *wiphy, struct net_device *dev,
++-			      u8 *mac, struct station_info *sinfo)
+++			      const u8 *mac, struct station_info *sinfo)
+  {
 - 	int count = 50;
 --	u32 reg;
 -+	u32 reg, last_val;
@@ -3441,9 +3840,16 @@ index a1af6c2..892f51e 100644
 - 			goto out;
 - 		}
 -@@ -1866,7 +1866,7 @@ static void ath9k_set_coverage_class(str
-- 
++ 	struct ath6kl *ar = ath6kl_priv(dev);
++ 	struct ath6kl_vif *vif = netdev_priv(dev);
++@@ -2974,7 +2974,7 @@ static int ath6kl_stop_ap(struct wiphy *
++ static const u8 bcast_addr[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
+  
 - static bool ath9k_has_tx_pending(struct ath_softc *sc)
-- {
++ static int ath6kl_del_station(struct wiphy *wiphy, struct net_device *dev,
++-			      u8 *mac)
+++			      const u8 *mac)
+  {
 --	int i, npend;
 -+	int i, npend = 0;
 - 
@@ -3508,8 +3914,11 @@ index a1af6c2..892f51e 100644
 ---- a/include/linux/ieee80211.h
 -+++ b/include/linux/ieee80211.h
 -@@ -597,6 +597,20 @@ static inline int ieee80211_is_qos_nullf
-- }
-- 
++ 	struct ath6kl *ar = ath6kl_priv(dev);
++ 	struct ath6kl_vif *vif = netdev_priv(dev);
++@@ -2985,7 +2985,8 @@ static int ath6kl_del_station(struct wip
+  }
+  
 - /**
 -+ * ieee80211_is_bufferable_mmpdu - check if frame is bufferable MMPDU
 -+ * @fc: frame control field in little-endian byteorder
@@ -3529,8 +3938,19 @@ index a1af6c2..892f51e 100644
 -  * @seq_ctrl: frame sequence control bytes in little-endian byteorder
 -  */
 -@@ -2192,10 +2206,10 @@ static inline u8 *ieee80211_get_DA(struc
-- }
-- 
++ static int ath6kl_change_station(struct wiphy *wiphy, struct net_device *dev,
++-				 u8 *mac, struct station_parameters *params)
+++				 const u8 *mac,
+++				 struct station_parameters *params)
++ {
++ 	struct ath6kl *ar = ath6kl_priv(dev);
++ 	struct ath6kl_vif *vif = netdev_priv(dev);
++--- a/drivers/net/wireless/ath/ath6kl/wmi.c
+++++ b/drivers/net/wireless/ath/ath6kl/wmi.c
++@@ -2320,7 +2320,7 @@ int ath6kl_wmi_addkey_cmd(struct wmi *wm
++ 	return ret;
+  }
+  
 - /**
 -- * ieee80211_is_robust_mgmt_frame - check if frame is a robust management frame
 -+ * _ieee80211_is_robust_mgmt_frame - check if frame is a robust management frame
@@ -3538,12 +3958,36 @@ index a1af6c2..892f51e 100644
 -  */
 --static inline bool ieee80211_is_robust_mgmt_frame(struct ieee80211_hdr *hdr)
 -+static inline bool _ieee80211_is_robust_mgmt_frame(struct ieee80211_hdr *hdr)
-- {
++-int ath6kl_wmi_add_krk_cmd(struct wmi *wmi, u8 if_idx, u8 *krk)
+++int ath6kl_wmi_add_krk_cmd(struct wmi *wmi, u8 if_idx, const u8 *krk)
++ {
++ 	struct sk_buff *skb;
++ 	struct wmi_add_krk_cmd *cmd;
++--- a/drivers/net/wireless/ath/ath6kl/wmi.h
+++++ b/drivers/net/wireless/ath/ath6kl/wmi.h
++@@ -2616,7 +2616,7 @@ int ath6kl_wmi_addkey_cmd(struct wmi *wm
++ 			  u8 *key_material,
++ 			  u8 key_op_ctrl, u8 *mac_addr,
++ 			  enum wmi_sync_flag sync_flag);
++-int ath6kl_wmi_add_krk_cmd(struct wmi *wmi, u8 if_idx, u8 *krk);
+++int ath6kl_wmi_add_krk_cmd(struct wmi *wmi, u8 if_idx, const u8 *krk);
++ int ath6kl_wmi_deletekey_cmd(struct wmi *wmi, u8 if_idx, u8 key_index);
++ int ath6kl_wmi_setpmkid_cmd(struct wmi *wmi, u8 if_idx, const u8 *bssid,
++ 			    const u8 *pmkid, bool set);
++--- a/drivers/net/wireless/ath/ath9k/htc.h
+++++ b/drivers/net/wireless/ath/ath9k/htc.h
++@@ -378,7 +378,7 @@ void ath9k_htc_get_et_stats(struct ieee8
++ #define TX_QSTAT_INC(c) do { } while (0)
++ 
++ static inline void ath9k_htc_err_stat_rx(struct ath9k_htc_priv *priv,
++-					 struct ath_htc_rx_status *rxs)
+++					 struct ath_rx_status *rs);
+  {
 - 	if (ieee80211_is_disassoc(hdr->frame_control) ||
 - 	    ieee80211_is_deauth(hdr->frame_control))
 -@@ -2224,6 +2238,17 @@ static inline bool ieee80211_is_robust_m
-- }
-- 
+  }
+  
 - /**
 -+ * ieee80211_is_robust_mgmt_frame - check if skb contains a robust mgmt frame
 -+ * @skb: the skb containing the frame, length will be checked
@@ -3629,7 +4073,10 @@ index a1af6c2..892f51e 100644
 --void cfg80211_ibss_joined(struct net_device *dev, const u8 *bssid, gfp_t gfp);
 -+void cfg80211_ibss_joined(struct net_device *dev, const u8 *bssid,
 -+			  struct ieee80211_channel *channel, gfp_t gfp);
-- 
++--- a/drivers/net/wireless/ath/wil6210/cfg80211.c
+++++ b/drivers/net/wireless/ath/wil6210/cfg80211.c
++@@ -172,7 +172,7 @@ static int wil_cid_fill_sinfo(struct wil
+  
 - /**
 -  * cfg80211_notify_new_candidate - notify cfg80211 of a new mesh peer candidate
 ---- a/include/uapi/linux/nl80211.h
@@ -3660,8 +4107,16 @@ index a1af6c2..892f51e 100644
 - 
 --	ieee80211_tx_skb_tid(sdata, skb, tid);
 -+	ieee80211_tx_skb(sdata, skb);
-- }
-- 
++ static int wil_cfg80211_get_station(struct wiphy *wiphy,
++ 				    struct net_device *ndev,
++-				    u8 *mac, struct station_info *sinfo)
+++				    const u8 *mac, struct station_info *sinfo)
++ {
++ 	struct wil6210_priv *wil = wiphy_to_wil(wiphy);
++ 	int rc;
++@@ -671,7 +671,7 @@ static int wil_cfg80211_stop_ap(struct w
+  }
+  
 - void ieee80211_send_bar(struct ieee80211_vif *vif, u8 *ra, u16 tid, u16 ssn)
 ---- a/net/mac80211/cfg.c
 -+++ b/net/mac80211/cfg.c
@@ -3678,7 +4133,12 @@ index a1af6c2..892f51e 100644
 - 	mutex_unlock(&local->mtx);
 -@@ -1021,8 +1021,10 @@ static int ieee80211_start_ap(struct wip
 - 					IEEE80211_P2P_OPPPS_ENABLE_BIT;
-- 
++ static int wil_cfg80211_del_station(struct wiphy *wiphy,
++-				    struct net_device *dev, u8 *mac)
+++				    struct net_device *dev, const u8 *mac)
++ {
++ 	struct wil6210_priv *wil = wiphy_to_wil(wiphy);
+  
 - 	err = ieee80211_assign_beacon(sdata, &params->beacon);
 --	if (err < 0)
 -+	if (err < 0) {
@@ -3695,19 +4155,59 @@ index a1af6c2..892f51e 100644
 -+		ieee80211_vif_release_channel(sdata);
 - 		return err;
 - 	}
-- 
++--- a/drivers/net/wireless/ath/wil6210/main.c
+++++ b/drivers/net/wireless/ath/wil6210/main.c
++@@ -81,7 +81,7 @@ static void wil_disconnect_cid(struct wi
++ 	memset(&sta->stats, 0, sizeof(sta->stats));
++ }
+  
 -@@ -1053,6 +1056,7 @@ static int ieee80211_change_beacon(struc
 - 	int err;
-- 
++-static void _wil6210_disconnect(struct wil6210_priv *wil, void *bssid)
+++static void _wil6210_disconnect(struct wil6210_priv *wil, const u8 *bssid)
++ {
++ 	int cid = -ENOENT;
++ 	struct net_device *ndev = wil_to_ndev(wil);
++@@ -252,7 +252,7 @@ int wil_priv_init(struct wil6210_priv *w
++ 	return 0;
++ }
+  
 - 	sdata = IEEE80211_DEV_TO_SUB_IF(dev);
 -+	sdata_assert_lock(sdata);
-- 
++-void wil6210_disconnect(struct wil6210_priv *wil, void *bssid)
+++void wil6210_disconnect(struct wil6210_priv *wil, const u8 *bssid)
++ {
++ 	del_timer_sync(&wil->connect_timer);
++ 	_wil6210_disconnect(wil, bssid);
++--- a/drivers/net/wireless/ath/wil6210/wil6210.h
+++++ b/drivers/net/wireless/ath/wil6210/wil6210.h
++@@ -508,7 +508,7 @@ void wil_wdev_free(struct wil6210_priv *
++ int wmi_set_mac_address(struct wil6210_priv *wil, void *addr);
++ int wmi_pcp_start(struct wil6210_priv *wil, int bi, u8 wmi_nettype, u8 chan);
++ int wmi_pcp_stop(struct wil6210_priv *wil);
++-void wil6210_disconnect(struct wil6210_priv *wil, void *bssid);
+++void wil6210_disconnect(struct wil6210_priv *wil, const u8 *bssid);
++ 
++ int wil_rx_init(struct wil6210_priv *wil);
++ void wil_rx_fini(struct wil6210_priv *wil);
++--- a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c
+++++ b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c
++@@ -2236,7 +2236,7 @@ brcmf_cfg80211_config_default_mgmt_key(s
+  
 - 	/* don't allow changing the beacon while CSA is in place - offset
 - 	 * of channel switch counter may change
 -@@ -1080,6 +1084,8 @@ static int ieee80211_stop_ap(struct wiph
 - 	struct probe_resp *old_probe_resp;
 - 	struct cfg80211_chan_def chandef;
-- 
++ static s32
++ brcmf_cfg80211_get_station(struct wiphy *wiphy, struct net_device *ndev,
++-			   u8 *mac, struct station_info *sinfo)
+++			   const u8 *mac, struct station_info *sinfo)
++ {
++ 	struct brcmf_if *ifp = netdev_priv(ndev);
++ 	struct brcmf_cfg80211_profile *profile = &ifp->vif->profile;
++@@ -4014,7 +4014,7 @@ brcmf_cfg80211_change_beacon(struct wiph
+  
 -+	sdata_assert_lock(sdata);
 -+
 - 	old_beacon = sdata_dereference(sdata->u.ap.beacon, sdata);
@@ -3716,7 +4216,16 @@ index a1af6c2..892f51e 100644
 -@@ -1090,8 +1096,6 @@ static int ieee80211_stop_ap(struct wiph
 - 	kfree(sdata->u.ap.next_beacon);
 - 	sdata->u.ap.next_beacon = NULL;
-- 
++ static int
++ brcmf_cfg80211_del_station(struct wiphy *wiphy, struct net_device *ndev,
++-			   u8 *mac)
+++			   const u8 *mac)
++ {
++ 	struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
++ 	struct brcmf_scb_val_le scbval;
++@@ -4242,7 +4242,7 @@ static int brcmf_convert_nl80211_tdls_op
++ }
+  
 --	cancel_work_sync(&sdata->u.ap.request_smps_work);
 --
 - 	/* turn off carrier for this interface and dependent VLANs */
@@ -3743,7 +4252,29 @@ index a1af6c2..892f51e 100644
 -@@ -2638,6 +2646,24 @@ static int ieee80211_start_roc_work(stru
 - 	INIT_DELAYED_WORK(&roc->work, ieee80211_sw_roc_work);
 - 	INIT_LIST_HEAD(&roc->dependents);
-- 
++ static int brcmf_cfg80211_tdls_oper(struct wiphy *wiphy,
++-				    struct net_device *ndev, u8 *peer,
+++				    struct net_device *ndev, const u8 *peer,
++ 				    enum nl80211_tdls_operation oper)
++ {
++ 	struct brcmf_if *ifp;
++--- a/drivers/net/wireless/libertas/cfg.c
+++++ b/drivers/net/wireless/libertas/cfg.c
++@@ -1006,9 +1006,8 @@ struct cmd_key_material {
++ } __packed;
++ 
++ static int lbs_set_key_material(struct lbs_private *priv,
++-				int key_type,
++-				int key_info,
++-				u8 *key, u16 key_len)
+++				int key_type, int key_info,
+++				const u8 *key, u16 key_len)
++ {
++ 	struct cmd_key_material cmd;
++ 	int ret;
++@@ -1610,7 +1609,7 @@ static int lbs_cfg_del_key(struct wiphy 
++  */
+  
 -+	/*
 -+	 * cookie is either the roc cookie (for normal roc)
 -+	 * or the SKB (for mgmt TX)
@@ -3768,7 +4299,24 @@ index a1af6c2..892f51e 100644
 -@@ -2772,24 +2798,6 @@ static int ieee80211_start_roc_work(stru
 - 	if (!queued)
 - 		list_add_tail(&roc->list, &local->roc_list);
-- 
++ static int lbs_cfg_get_station(struct wiphy *wiphy, struct net_device *dev,
++-			      u8 *mac, struct station_info *sinfo)
+++			       const u8 *mac, struct station_info *sinfo)
++ {
++ 	struct lbs_private *priv = wiphy_priv(wiphy);
++ 	s8 signal, noise;
++--- a/drivers/net/wireless/libertas/defs.h
+++++ b/drivers/net/wireless/libertas/defs.h
++@@ -90,7 +90,8 @@ do { if ((lbs_debug & (grp)) == (grp)) \
++ #define lbs_deb_cfg80211(fmt, args...)  LBS_DEB_LL(LBS_DEB_CFG80211, " cfg80211", fmt, ##args)
++ 
++ #ifdef DEBUG
++-static inline void lbs_deb_hex(unsigned int grp, const char *prompt, u8 *buf, int len)
+++static inline void lbs_deb_hex(unsigned int grp, const char *prompt,
+++			       const u8 *buf, int len)
++ {
++ 	int i = 0;
+  
 --	/*
 --	 * cookie is either the roc cookie (for normal roc)
 --	 * or the SKB (for mgmt TX)
@@ -3788,8 +4336,11 @@ index a1af6c2..892f51e 100644
 --	}
 --
 - 	return 0;
-- }
-- 
++--- a/drivers/net/wireless/mwifiex/11n.h
+++++ b/drivers/net/wireless/mwifiex/11n.h
++@@ -200,7 +200,7 @@ static inline int mwifiex_is_sta_11n_ena
+  }
+  
 -@@ -3004,8 +3012,10 @@ void ieee80211_csa_finalize_work(struct 
 - 	if (!ieee80211_sdata_running(sdata))
 - 		goto unlock;
@@ -3811,7 +4362,23 @@ index a1af6c2..892f51e 100644
 -+
 - 		if (err < 0)
 - 			goto unlock;
-- 
++ static inline u8
++-mwifiex_tdls_peer_11n_enabled(struct mwifiex_private *priv, u8 *ra)
+++mwifiex_tdls_peer_11n_enabled(struct mwifiex_private *priv, const u8 *ra)
++ {
++ 	struct mwifiex_sta_node *node = mwifiex_get_sta_entry(priv, ra);
++ 	if (node)
++--- a/drivers/net/wireless/mwifiex/cfg80211.c
+++++ b/drivers/net/wireless/mwifiex/cfg80211.c
++@@ -994,7 +994,7 @@ mwifiex_dump_station_info(struct mwifiex
++  */
++ static int
++ mwifiex_cfg80211_get_station(struct wiphy *wiphy, struct net_device *dev,
++-			     u8 *mac, struct station_info *sinfo)
+++			     const u8 *mac, struct station_info *sinfo)
++ {
++ 	struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
+  
 - 		changed |= err;
 --		kfree(sdata->u.ap.next_beacon);
 --		sdata->u.ap.next_beacon = NULL;
@@ -3822,10 +4389,35 @@ index a1af6c2..892f51e 100644
 -@@ -3066,7 +3076,7 @@ int ieee80211_channel_switch(struct wiph
 - 	struct ieee80211_if_mesh __maybe_unused *ifmsh;
 - 	int err, num_chanctx;
-- 
++@@ -1270,7 +1270,7 @@ static int mwifiex_cfg80211_change_beaco
++  */
++ static int
++ mwifiex_cfg80211_del_station(struct wiphy *wiphy, struct net_device *dev,
++-			     u8 *mac)
+++			     const u8 *mac)
++ {
++ 	struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
++ 	struct mwifiex_sta_node *sta_node;
++@@ -2629,7 +2629,7 @@ static int mwifiex_cfg80211_set_coalesce
++  */
++ static int
++ mwifiex_cfg80211_tdls_mgmt(struct wiphy *wiphy, struct net_device *dev,
++-			   u8 *peer, u8 action_code, u8 dialog_token,
+++			   const u8 *peer, u8 action_code, u8 dialog_token,
++ 			   u16 status_code, u32 peer_capability,
++ 			   const u8 *extra_ies, size_t extra_ies_len)
++ {
++@@ -2701,7 +2701,7 @@ mwifiex_cfg80211_tdls_mgmt(struct wiphy 
+  
 --	lockdep_assert_held(&sdata->wdev.mtx);
 -+	sdata_assert_lock(sdata);
-- 
++ static int
++ mwifiex_cfg80211_tdls_oper(struct wiphy *wiphy, struct net_device *dev,
++-			   u8 *peer, enum nl80211_tdls_operation action)
+++			   const u8 *peer, enum nl80211_tdls_operation action)
++ {
++ 	struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
+  
 - 	if (!list_empty(&local->roc_list) || local->scanning)
 - 		return -EBUSY;
 ---- a/net/mac80211/ht.c
@@ -3836,20 +4428,30 @@ index a1af6c2..892f51e 100644
 - 
 --	ieee80211_tx_skb_tid(sdata, skb, tid);
 -+	ieee80211_tx_skb(sdata, skb);
-- }
-- 
++@@ -2748,9 +2748,8 @@ mwifiex_cfg80211_tdls_oper(struct wiphy 
+  }
+  
 - void ieee80211_process_delba(struct ieee80211_sub_if_data *sdata,
 -@@ -466,7 +466,9 @@ void ieee80211_request_smps_ap_work(stru
 - 			     u.ap.request_smps_work);
-- 
++ static int
++-mwifiex_cfg80211_add_station(struct wiphy *wiphy,
++-			     struct net_device *dev,
++-			     u8 *mac, struct station_parameters *params)
+++mwifiex_cfg80211_add_station(struct wiphy *wiphy, struct net_device *dev,
+++			     const u8 *mac, struct station_parameters *params)
++ {
++ 	struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
+  
 - 	sdata_lock(sdata);
 --	__ieee80211_request_smps_ap(sdata, sdata->u.ap.driver_smps_mode);
 -+	if (sdata_dereference(sdata->u.ap.beacon, sdata))
 -+		__ieee80211_request_smps_ap(sdata,
 -+					    sdata->u.ap.driver_smps_mode);
 - 	sdata_unlock(sdata);
-- }
-- 
++@@ -2765,9 +2764,9 @@ mwifiex_cfg80211_add_station(struct wiph
+  }
+  
 ---- a/net/mac80211/iface.c
 -+++ b/net/mac80211/iface.c
 -@@ -770,12 +770,19 @@ static void ieee80211_do_stop(struct iee
@@ -3873,47 +4475,201 @@ index a1af6c2..892f51e 100644
 -+	default:
 -+		break;
 -+	}
-- 
++ static int
++-mwifiex_cfg80211_change_station(struct wiphy *wiphy,
++-				struct net_device *dev,
++-				u8 *mac, struct station_parameters *params)
+++mwifiex_cfg80211_change_station(struct wiphy *wiphy, struct net_device *dev,
+++				const u8 *mac,
+++				struct station_parameters *params)
++ {
++ 	int ret;
++ 	struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
++--- a/drivers/net/wireless/mwifiex/main.h
+++++ b/drivers/net/wireless/mwifiex/main.h
++@@ -910,8 +910,6 @@ int mwifiex_handle_uap_rx_forward(struct
++ 				  struct sk_buff *skb);
++ int mwifiex_process_sta_event(struct mwifiex_private *);
++ int mwifiex_process_uap_event(struct mwifiex_private *);
++-struct mwifiex_sta_node *
++-mwifiex_get_sta_entry(struct mwifiex_private *priv, u8 *mac);
++ void mwifiex_delete_all_station_list(struct mwifiex_private *priv);
++ void *mwifiex_process_sta_txpd(struct mwifiex_private *, struct sk_buff *skb);
++ void *mwifiex_process_uap_txpd(struct mwifiex_private *, struct sk_buff *skb);
++@@ -1220,26 +1218,26 @@ void mwifiex_dnld_txpwr_table(struct mwi
++ extern const struct ethtool_ops mwifiex_ethtool_ops;
++ 
++ void mwifiex_del_all_sta_list(struct mwifiex_private *priv);
++-void mwifiex_del_sta_entry(struct mwifiex_private *priv, u8 *mac);
+++void mwifiex_del_sta_entry(struct mwifiex_private *priv, const u8 *mac);
++ void
++ mwifiex_set_sta_ht_cap(struct mwifiex_private *priv, const u8 *ies,
++ 		       int ies_len, struct mwifiex_sta_node *node);
++ struct mwifiex_sta_node *
++-mwifiex_add_sta_entry(struct mwifiex_private *priv, u8 *mac);
+++mwifiex_add_sta_entry(struct mwifiex_private *priv, const u8 *mac);
++ struct mwifiex_sta_node *
++-mwifiex_get_sta_entry(struct mwifiex_private *priv, u8 *mac);
++-int mwifiex_send_tdls_data_frame(struct mwifiex_private *priv, u8 *peer,
+++mwifiex_get_sta_entry(struct mwifiex_private *priv, const u8 *mac);
+++int mwifiex_send_tdls_data_frame(struct mwifiex_private *priv, const u8 *peer,
++ 				 u8 action_code, u8 dialog_token,
++ 				 u16 status_code, const u8 *extra_ies,
++ 				 size_t extra_ies_len);
++-int mwifiex_send_tdls_action_frame(struct mwifiex_private *priv,
++-				 u8 *peer, u8 action_code, u8 dialog_token,
++-				 u16 status_code, const u8 *extra_ies,
++-				 size_t extra_ies_len);
+++int mwifiex_send_tdls_action_frame(struct mwifiex_private *priv, const u8 *peer,
+++				   u8 action_code, u8 dialog_token,
+++				   u16 status_code, const u8 *extra_ies,
+++				   size_t extra_ies_len);
++ void mwifiex_process_tdls_action_frame(struct mwifiex_private *priv,
++ 				       u8 *buf, int len);
++-int mwifiex_tdls_oper(struct mwifiex_private *priv, u8 *peer, u8 action);
++-int mwifiex_get_tdls_link_status(struct mwifiex_private *priv, u8 *mac);
+++int mwifiex_tdls_oper(struct mwifiex_private *priv, const u8 *peer, u8 action);
+++int mwifiex_get_tdls_link_status(struct mwifiex_private *priv, const u8 *mac);
++ void mwifiex_disable_all_tdls_links(struct mwifiex_private *priv);
++ bool mwifiex_is_bss_in_11ac_mode(struct mwifiex_private *priv);
++ u8 mwifiex_get_center_freq_index(struct mwifiex_private *priv, u8 band,
++--- a/drivers/net/wireless/mwifiex/tdls.c
+++++ b/drivers/net/wireless/mwifiex/tdls.c
++@@ -25,8 +25,8 @@
++ #define TDLS_RESP_FIX_LEN     8
++ #define TDLS_CONFIRM_FIX_LEN  6
++ 
++-static void
++-mwifiex_restore_tdls_packets(struct mwifiex_private *priv, u8 *mac, u8 status)
+++static void mwifiex_restore_tdls_packets(struct mwifiex_private *priv,
+++					 const u8 *mac, u8 status)
++ {
++ 	struct mwifiex_ra_list_tbl *ra_list;
++ 	struct list_head *tid_list;
++@@ -84,7 +84,8 @@ mwifiex_restore_tdls_packets(struct mwif
++ 	return;
++ }
+  
 - 	/*
 - 	 * Remove all stations associated with this interface.
 -@@ -827,7 +834,9 @@ static void ieee80211_do_stop(struct iee
 - 	cancel_work_sync(&local->dynamic_ps_enable_work);
-- 
++-static void mwifiex_hold_tdls_packets(struct mwifiex_private *priv, u8 *mac)
+++static void mwifiex_hold_tdls_packets(struct mwifiex_private *priv,
+++				      const u8 *mac)
++ {
++ 	struct mwifiex_ra_list_tbl *ra_list;
++ 	struct list_head *ra_list_head;
++@@ -228,7 +229,7 @@ mwifiex_tdls_add_ht_oper(struct mwifiex_
++ }
+  
 - 	cancel_work_sync(&sdata->recalc_smps);
 -+	sdata_lock(sdata);
 - 	sdata->vif.csa_active = false;
 -+	sdata_unlock(sdata);
 - 	cancel_work_sync(&sdata->csa_finalize_work);
-- 
++ static int mwifiex_tdls_add_vht_oper(struct mwifiex_private *priv,
++-				     u8 *mac, struct sk_buff *skb)
+++				     const u8 *mac, struct sk_buff *skb)
++ {
++ 	struct mwifiex_bssdescriptor *bss_desc;
++ 	struct ieee80211_vht_operation *vht_oper;
++@@ -367,8 +368,9 @@ static void mwifiex_tdls_add_qos_capab(s
++ }
+  
 - 	cancel_delayed_work_sync(&sdata->dfs_cac_timer_work);
 ---- a/net/mac80211/rx.c
 -+++ b/net/mac80211/rx.c
 -@@ -599,10 +599,10 @@ static int ieee80211_is_unicast_robust_m
-- {
++ static int mwifiex_prep_tdls_encap_data(struct mwifiex_private *priv,
++-			     u8 *peer, u8 action_code, u8 dialog_token,
++-			     u16 status_code, struct sk_buff *skb)
+++					const u8 *peer, u8 action_code,
+++					u8 dialog_token,
+++					u16 status_code, struct sk_buff *skb)
+  {
 - 	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
-- 
++ 	struct ieee80211_tdls_data *tf;
++ 	int ret;
++@@ -506,7 +508,8 @@ static int mwifiex_prep_tdls_encap_data(
++ }
+  
 --	if (skb->len < 24 || is_multicast_ether_addr(hdr->addr1))
 -+	if (is_multicast_ether_addr(hdr->addr1))
 - 		return 0;
-- 
++ static void
++-mwifiex_tdls_add_link_ie(struct sk_buff *skb, u8 *src_addr, u8 *peer, u8 *bssid)
+++mwifiex_tdls_add_link_ie(struct sk_buff *skb, const u8 *src_addr,
+++			 const u8 *peer, const u8 *bssid)
++ {
++ 	struct ieee80211_tdls_lnkie *lnkid;
+  
 --	return ieee80211_is_robust_mgmt_frame(hdr);
 -+	return ieee80211_is_robust_mgmt_frame(skb);
-- }
-- 
-- 
++@@ -520,8 +523,8 @@ mwifiex_tdls_add_link_ie(struct sk_buff 
++ 	memcpy(lnkid->resp_sta, peer, ETH_ALEN);
+  }
+  
++-int mwifiex_send_tdls_data_frame(struct mwifiex_private *priv,
++-				 u8 *peer, u8 action_code, u8 dialog_token,
+++int mwifiex_send_tdls_data_frame(struct mwifiex_private *priv, const u8 *peer,
+++				 u8 action_code, u8 dialog_token,
++ 				 u16 status_code, const u8 *extra_ies,
++ 				 size_t extra_ies_len)
++ {
++@@ -613,7 +616,8 @@ int mwifiex_send_tdls_data_frame(struct 
++ }
+  
 -@@ -610,10 +610,10 @@ static int ieee80211_is_multicast_robust
-- {
++ static int
++-mwifiex_construct_tdls_action_frame(struct mwifiex_private *priv, u8 *peer,
+++mwifiex_construct_tdls_action_frame(struct mwifiex_private *priv,
+++				    const u8 *peer,
++ 				    u8 action_code, u8 dialog_token,
++ 				    u16 status_code, struct sk_buff *skb)
+  {
 - 	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
-- 
++@@ -691,10 +695,10 @@ mwifiex_construct_tdls_action_frame(stru
++ 	return 0;
++ }
+  
 --	if (skb->len < 24 || !is_multicast_ether_addr(hdr->addr1))
 -+	if (!is_multicast_ether_addr(hdr->addr1))
 - 		return 0;
-- 
++-int mwifiex_send_tdls_action_frame(struct mwifiex_private *priv,
++-				 u8 *peer, u8 action_code, u8 dialog_token,
++-				 u16 status_code, const u8 *extra_ies,
++-				 size_t extra_ies_len)
+++int mwifiex_send_tdls_action_frame(struct mwifiex_private *priv, const u8 *peer,
+++				   u8 action_code, u8 dialog_token,
+++				   u16 status_code, const u8 *extra_ies,
+++				   size_t extra_ies_len)
++ {
++ 	struct sk_buff *skb;
++ 	struct mwifiex_txinfo *tx_info;
++@@ -901,7 +905,7 @@ void mwifiex_process_tdls_action_frame(s
++ }
+  
 --	return ieee80211_is_robust_mgmt_frame(hdr);
 -+	return ieee80211_is_robust_mgmt_frame(skb);
-- }
-- 
-- 
++ static int
++-mwifiex_tdls_process_config_link(struct mwifiex_private *priv, u8 *peer)
+++mwifiex_tdls_process_config_link(struct mwifiex_private *priv, const u8 *peer)
++ {
++ 	struct mwifiex_sta_node *sta_ptr;
++ 	struct mwifiex_ds_tdls_oper tdls_oper;
++@@ -922,7 +926,7 @@ mwifiex_tdls_process_config_link(struct 
+  }
+  
++ static int
++-mwifiex_tdls_process_create_link(struct mwifiex_private *priv, u8 *peer)
+++mwifiex_tdls_process_create_link(struct mwifiex_private *priv, const u8 *peer)
++ {
++ 	struct mwifiex_sta_node *sta_ptr;
++ 	struct mwifiex_ds_tdls_oper tdls_oper;
++@@ -949,7 +953,7 @@ mwifiex_tdls_process_create_link(struct 
++ }
+  
 -@@ -626,7 +626,7 @@ static int ieee80211_get_mmie_keyidx(str
 - 	if (skb->len < 24 + sizeof(*mmie) || !is_multicast_ether_addr(hdr->da))
 - 		return -1;
@@ -3973,7 +4729,15 @@ index a1af6c2..892f51e 100644
 -+			     ieee80211_is_robust_mgmt_frame(rx->skb)))
 - 			return -EACCES;
 - 	}
-- 
++ static int
++-mwifiex_tdls_process_disable_link(struct mwifiex_private *priv, u8 *peer)
+++mwifiex_tdls_process_disable_link(struct mwifiex_private *priv, const u8 *peer)
++ {
++ 	struct mwifiex_sta_node *sta_ptr;
++ 	struct mwifiex_ds_tdls_oper tdls_oper;
++@@ -978,7 +982,7 @@ mwifiex_tdls_process_disable_link(struct
++ }
+  
 ---- a/net/mac80211/tx.c
 -+++ b/net/mac80211/tx.c
 -@@ -452,8 +452,7 @@ static int ieee80211_use_mfp(__le16 fc, 
@@ -4052,17 +4816,36 @@ index a1af6c2..892f51e 100644
 - 		I802_DEBUG_INC(tx->local->tx_handlers_drop_unencrypted);
 -@@ -878,7 +890,7 @@ static int ieee80211_fragment(struct iee
 - 	}
-- 
++ static int
++-mwifiex_tdls_process_enable_link(struct mwifiex_private *priv, u8 *peer)
+++mwifiex_tdls_process_enable_link(struct mwifiex_private *priv, const u8 *peer)
++ {
++ 	struct mwifiex_sta_node *sta_ptr;
++ 	struct ieee80211_mcs_info mcs;
++@@ -1035,7 +1039,7 @@ mwifiex_tdls_process_enable_link(struct 
++ 	return 0;
++ }
+  
 - 	/* adjust first fragment's length */
 --	skb->len = hdrlen + per_fragm;
 -+	skb_trim(skb, hdrlen + per_fragm);
-- 	return 0;
-- }
-- 
++-int mwifiex_tdls_oper(struct mwifiex_private *priv, u8 *peer, u8 action)
+++int mwifiex_tdls_oper(struct mwifiex_private *priv, const u8 *peer, u8 action)
++ {
++ 	switch (action) {
++ 	case MWIFIEX_TDLS_ENABLE_LINK:
++@@ -1050,7 +1054,7 @@ int mwifiex_tdls_oper(struct mwifiex_pri
+  	return 0;
+  }
+  
 -@@ -2900,7 +2912,7 @@ ieee80211_get_buffered_bc(struct ieee802
 - 				cpu_to_le16(IEEE80211_FCTL_MOREDATA);
 - 		}
-- 
++-int mwifiex_get_tdls_link_status(struct mwifiex_private *priv, u8 *mac)
+++int mwifiex_get_tdls_link_status(struct mwifiex_private *priv, const u8 *mac)
++ {
++ 	struct mwifiex_sta_node *sta_ptr;
+  
 --		if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
 -+		if (sdata->vif.type == NL80211_IFTYPE_AP)
 - 			sdata = IEEE80211_DEV_TO_SUB_IF(skb->dev);
@@ -4072,12 +4855,33 @@ index a1af6c2..892f51e 100644
 -+++ b/net/mac80211/wpa.c
 -@@ -499,7 +499,7 @@ ieee80211_crypto_ccmp_decrypt(struct iee
 - 	hdrlen = ieee80211_hdrlen(hdr->frame_control);
-- 
++--- a/drivers/net/wireless/mwifiex/util.c
+++++ b/drivers/net/wireless/mwifiex/util.c
++@@ -259,7 +259,7 @@ int mwifiex_complete_cmd(struct mwifiex_
++  * NULL is returned if station entry is not found in associated STA list.
++  */
++ struct mwifiex_sta_node *
++-mwifiex_get_sta_entry(struct mwifiex_private *priv, u8 *mac)
+++mwifiex_get_sta_entry(struct mwifiex_private *priv, const u8 *mac)
++ {
++ 	struct mwifiex_sta_node *node;
+  
 - 	if (!ieee80211_is_data(hdr->frame_control) &&
 --	    !ieee80211_is_robust_mgmt_frame(hdr))
 -+	    !ieee80211_is_robust_mgmt_frame(skb))
 - 		return RX_CONTINUE;
-- 
++@@ -280,7 +280,7 @@ mwifiex_get_sta_entry(struct mwifiex_pri
++  * If received mac address is NULL, NULL is returned.
++  */
++ struct mwifiex_sta_node *
++-mwifiex_add_sta_entry(struct mwifiex_private *priv, u8 *mac)
+++mwifiex_add_sta_entry(struct mwifiex_private *priv, const u8 *mac)
++ {
++ 	struct mwifiex_sta_node *node;
++ 	unsigned long flags;
++@@ -332,7 +332,7 @@ mwifiex_set_sta_ht_cap(struct mwifiex_pr
++ }
+  
 - 	data_len = skb->len - hdrlen - IEEE80211_CCMP_HDR_LEN -
 ---- a/net/wireless/ap.c
 -+++ b/net/wireless/ap.c
@@ -4091,14 +4895,127 @@ index a1af6c2..892f51e 100644
 - 		rdev_set_qos_map(rdev, dev, NULL);
 -+		nl80211_send_ap_stopped(wdev);
 - 	}
-- 
++ /* This function will delete a station entry from station list */
++-void mwifiex_del_sta_entry(struct mwifiex_private *priv, u8 *mac)
+++void mwifiex_del_sta_entry(struct mwifiex_private *priv, const u8 *mac)
++ {
++ 	struct mwifiex_sta_node *node;
++ 	unsigned long flags;
++--- a/drivers/net/wireless/mwifiex/wmm.c
+++++ b/drivers/net/wireless/mwifiex/wmm.c
++@@ -92,7 +92,7 @@ mwifiex_wmm_ac_debug_print(const struct 
++  * The function also initializes the list with the provided RA.
++  */
++ static struct mwifiex_ra_list_tbl *
++-mwifiex_wmm_allocate_ralist_node(struct mwifiex_adapter *adapter, u8 *ra)
+++mwifiex_wmm_allocate_ralist_node(struct mwifiex_adapter *adapter, const u8 *ra)
++ {
++ 	struct mwifiex_ra_list_tbl *ra_list;
+  
 - 	return err;
 ---- a/net/wireless/core.c
 -+++ b/net/wireless/core.c
 -@@ -203,8 +203,11 @@ void cfg80211_stop_p2p_device(struct cfg
-- 
++@@ -139,8 +139,7 @@ static u8 mwifiex_get_random_ba_threshol
++  * This function allocates and adds a RA list for all TIDs
++  * with the given RA.
++  */
++-void
++-mwifiex_ralist_add(struct mwifiex_private *priv, u8 *ra)
+++void mwifiex_ralist_add(struct mwifiex_private *priv, const u8 *ra)
++ {
++ 	int i;
++ 	struct mwifiex_ra_list_tbl *ra_list;
++@@ -566,7 +565,7 @@ mwifiex_clean_txrx(struct mwifiex_privat
++  */
++ static struct mwifiex_ra_list_tbl *
++ mwifiex_wmm_get_ralist_node(struct mwifiex_private *priv, u8 tid,
++-			    u8 *ra_addr)
+++			    const u8 *ra_addr)
++ {
++ 	struct mwifiex_ra_list_tbl *ra_list;
++ 
++@@ -587,7 +586,8 @@ mwifiex_wmm_get_ralist_node(struct mwifi
++  * retrieved.
++  */
++ struct mwifiex_ra_list_tbl *
++-mwifiex_wmm_get_queue_raptr(struct mwifiex_private *priv, u8 tid, u8 *ra_addr)
+++mwifiex_wmm_get_queue_raptr(struct mwifiex_private *priv, u8 tid,
+++			    const u8 *ra_addr)
++ {
++ 	struct mwifiex_ra_list_tbl *ra_list;
++ 
++--- a/drivers/net/wireless/mwifiex/wmm.h
+++++ b/drivers/net/wireless/mwifiex/wmm.h
++@@ -99,7 +99,7 @@ mwifiex_wmm_is_ra_list_empty(struct list
++ 
++ void mwifiex_wmm_add_buf_txqueue(struct mwifiex_private *priv,
++ 				 struct sk_buff *skb);
++-void mwifiex_ralist_add(struct mwifiex_private *priv, u8 *ra);
+++void mwifiex_ralist_add(struct mwifiex_private *priv, const u8 *ra);
++ void mwifiex_rotate_priolists(struct mwifiex_private *priv,
++ 			      struct mwifiex_ra_list_tbl *ra, int tid);
++ 
++@@ -123,7 +123,8 @@ void mwifiex_wmm_setup_ac_downgrade(stru
++ int mwifiex_ret_wmm_get_status(struct mwifiex_private *priv,
++ 			       const struct host_cmd_ds_command *resp);
++ struct mwifiex_ra_list_tbl *
++-mwifiex_wmm_get_queue_raptr(struct mwifiex_private *priv, u8 tid, u8 *ra_addr);
+++mwifiex_wmm_get_queue_raptr(struct mwifiex_private *priv, u8 tid,
+++			    const u8 *ra_addr);
++ u8 mwifiex_wmm_downgrade_tid(struct mwifiex_private *priv, u32 tid);
++ 
++ #endif /* !_MWIFIEX_WMM_H_ */
++--- a/drivers/net/wireless/orinoco/hw.c
+++++ b/drivers/net/wireless/orinoco/hw.c
++@@ -988,8 +988,8 @@ int __orinoco_hw_setup_enc(struct orinoc
++  * tsc must be NULL or up to 8 bytes
++  */
++ int __orinoco_hw_set_tkip_key(struct orinoco_private *priv, int key_idx,
++-			      int set_tx, u8 *key, u8 *rsc, size_t rsc_len,
++-			      u8 *tsc, size_t tsc_len)
+++			      int set_tx, const u8 *key, const u8 *rsc,
+++			      size_t rsc_len, const u8 *tsc, size_t tsc_len)
++ {
++ 	struct {
++ 		__le16 idx;
++--- a/drivers/net/wireless/orinoco/hw.h
+++++ b/drivers/net/wireless/orinoco/hw.h
++@@ -38,8 +38,8 @@ int __orinoco_hw_set_wap(struct orinoco_
++ int __orinoco_hw_setup_wepkeys(struct orinoco_private *priv);
++ int __orinoco_hw_setup_enc(struct orinoco_private *priv);
++ int __orinoco_hw_set_tkip_key(struct orinoco_private *priv, int key_idx,
++-			      int set_tx, u8 *key, u8 *rsc, size_t rsc_len,
++-			      u8 *tsc, size_t tsc_len);
+++			      int set_tx, const u8 *key, const u8 *rsc,
+++			      size_t rsc_len, const u8 *tsc, size_t tsc_len);
++ int orinoco_clear_tkip_key(struct orinoco_private *priv, int key_idx);
++ int __orinoco_hw_set_multicast_list(struct orinoco_private *priv,
++ 				    struct net_device *dev,
++--- a/drivers/net/wireless/orinoco/wext.c
+++++ b/drivers/net/wireless/orinoco/wext.c
++@@ -52,9 +52,9 @@ static int orinoco_set_key(struct orinoc
++ 	priv->keys[index].seq_len = seq_len;
++ 
++ 	if (key_len)
++-		memcpy(priv->keys[index].key, key, key_len);
+++		memcpy((void *)priv->keys[index].key, key, key_len);
++ 	if (seq_len)
++-		memcpy(priv->keys[index].seq, seq, seq_len);
+++		memcpy((void *)priv->keys[index].seq, seq, seq_len);
++ 
++ 	switch (alg) {
++ 	case ORINOCO_ALG_TKIP:
++--- a/drivers/net/wireless/rndis_wlan.c
+++++ b/drivers/net/wireless/rndis_wlan.c
++@@ -517,7 +517,7 @@ static int rndis_set_default_key(struct 
++ 				 u8 key_index, bool unicast, bool multicast);
+  
 - 	rdev->opencount--;
-- 
++ static int rndis_get_station(struct wiphy *wiphy, struct net_device *dev,
++-					u8 *mac, struct station_info *sinfo);
+++			     const u8 *mac, struct station_info *sinfo);
+  
 --	WARN_ON(rdev->scan_req && rdev->scan_req->wdev == wdev &&
 --		!rdev->scan_req->notified);
 -+	if (rdev->scan_req && rdev->scan_req->wdev == wdev) {
@@ -4106,8 +5023,11 @@ index a1af6c2..892f51e 100644
 -+			rdev->scan_req->aborted = true;
 -+		___cfg80211_scan_done(rdev, false);
 -+	}
-- }
-- 
++ static int rndis_dump_station(struct wiphy *wiphy, struct net_device *dev,
++ 			       int idx, u8 *mac, struct station_info *sinfo);
++@@ -2490,7 +2490,7 @@ static void rndis_fill_station_info(stru
+  }
+  
 - static int cfg80211_rfkill_set_block(void *data, bool blocked)
 -@@ -447,9 +450,6 @@ int wiphy_register(struct wiphy *wiphy)
 - 	int i;
@@ -4126,7 +5046,56 @@ index a1af6c2..892f51e 100644
 --
 --	wdev->beacon_interval = 0;
 - }
-- 
++ static int rndis_get_station(struct wiphy *wiphy, struct net_device *dev,
++-					u8 *mac, struct station_info *sinfo)
+++			     const u8 *mac, struct station_info *sinfo)
++ {
++ 	struct rndis_wlan_private *priv = wiphy_priv(wiphy);
++ 	struct usbnet *usbdev = priv->usbdev;
++--- a/drivers/net/wireless/ti/wlcore/main.c
+++++ b/drivers/net/wireless/ti/wlcore/main.c
++@@ -1416,7 +1416,7 @@ void wl1271_rx_filter_free(struct wl12xx
++ 
++ int wl1271_rx_filter_alloc_field(struct wl12xx_rx_filter *filter,
++ 				 u16 offset, u8 flags,
++-				 u8 *pattern, u8 len)
+++				 const u8 *pattern, u8 len)
++ {
++ 	struct wl12xx_rx_filter_field *field;
++ 
++--- a/drivers/net/wireless/ti/wlcore/wlcore_i.h
+++++ b/drivers/net/wireless/ti/wlcore/wlcore_i.h
++@@ -512,8 +512,8 @@ int wl1271_recalc_rx_streaming(struct wl
++ void wl12xx_queue_recovery_work(struct wl1271 *wl);
++ size_t wl12xx_copy_fwlog(struct wl1271 *wl, u8 *memblock, size_t maxlen);
++ int wl1271_rx_filter_alloc_field(struct wl12xx_rx_filter *filter,
++-					u16 offset, u8 flags,
++-					u8 *pattern, u8 len);
+++				 u16 offset, u8 flags,
+++				 const u8 *pattern, u8 len);
++ void wl1271_rx_filter_free(struct wl12xx_rx_filter *filter);
++ struct wl12xx_rx_filter *wl1271_rx_filter_alloc(void);
++ int wl1271_rx_filter_get_fields_size(struct wl12xx_rx_filter *filter);
++--- a/include/net/cfg80211.h
+++++ b/include/net/cfg80211.h
++@@ -341,8 +341,8 @@ struct vif_params {
++  * @seq_len: length of @seq.
++  */
++ struct key_params {
++-	u8 *key;
++-	u8 *seq;
+++	const u8 *key;
+++	const u8 *seq;
++ 	int key_len;
++ 	int seq_len;
++ 	u32 cipher;
++@@ -458,7 +458,7 @@ bool cfg80211_chandef_usable(struct wiph
++  */
++ int cfg80211_chandef_dfs_required(struct wiphy *wiphy,
++ 				  const struct cfg80211_chan_def *chandef,
++-				  enum nl80211_iftype);
+++				  enum nl80211_iftype iftype);
+  
 - static int cfg80211_netdev_notifier_call(struct notifier_block *nb,
 -@@ -875,8 +873,11 @@ static int cfg80211_netdev_notifier_call
 - 		break;
@@ -4139,9 +5108,68 @@ index a1af6c2..892f51e 100644
 -+				rdev->scan_req->aborted = true;
 -+			___cfg80211_scan_done(rdev, false);
 -+		}
-- 
-- 		if (WARN_ON(rdev->sched_scan_req &&
-- 			    rdev->sched_scan_req->dev == wdev->netdev)) {
++ /**
++  * ieee80211_chandef_rate_flags - returns rate flags for a channel
++@@ -694,8 +694,10 @@ struct cfg80211_ap_settings {
++  *
++  * @chandef: defines the channel to use after the switch
++  * @beacon_csa: beacon data while performing the switch
++- * @counter_offset_beacon: offset for the counter within the beacon (tail)
++- * @counter_offset_presp: offset for the counter within the probe response
+++ * @counter_offsets_beacon: offsets of the counters within the beacon (tail)
+++ * @counter_offsets_presp: offsets of the counters within the probe response
+++ * @n_counter_offsets_beacon: number of csa counters the beacon (tail)
+++ * @n_counter_offsets_presp: number of csa counters in the probe response
++  * @beacon_after: beacon data to be used on the new channel
++  * @radar_required: whether radar detection is required on the new channel
++  * @block_tx: whether transmissions should be blocked while changing
++@@ -704,7 +706,10 @@ struct cfg80211_ap_settings {
++ struct cfg80211_csa_settings {
++ 	struct cfg80211_chan_def chandef;
++ 	struct cfg80211_beacon_data beacon_csa;
++-	u16 counter_offset_beacon, counter_offset_presp;
+++	const u16 *counter_offsets_beacon;
+++	const u16 *counter_offsets_presp;
+++	unsigned int n_counter_offsets_beacon;
+++	unsigned int n_counter_offsets_presp;
++ 	struct cfg80211_beacon_data beacon_after;
++ 	bool radar_required;
++ 	bool block_tx;
++@@ -1164,7 +1169,7 @@ struct bss_parameters {
++ 	int use_cts_prot;
++ 	int use_short_preamble;
++ 	int use_short_slot_time;
++-	u8 *basic_rates;
+++	const u8 *basic_rates;
++ 	u8 basic_rates_len;
++ 	int ap_isolate;
++ 	int ht_opmode;
++@@ -1694,10 +1699,10 @@ struct cfg80211_disassoc_request {
++  * @ht_capa_mask:  The bits of ht_capa which are to be used.
++  */
++ struct cfg80211_ibss_params {
++-	u8 *ssid;
++-	u8 *bssid;
+++	const u8 *ssid;
+++	const u8 *bssid;
++ 	struct cfg80211_chan_def chandef;
++-	u8 *ie;
+++	const u8 *ie;
++ 	u8 ssid_len, ie_len;
++ 	u16 beacon_interval;
++ 	u32 basic_rates;
++@@ -1806,8 +1811,8 @@ struct cfg80211_bitrate_mask {
++  * @pmkid: The PMK material itself.
++  */
++ struct cfg80211_pmksa {
++-	u8 *bssid;
++-	u8 *pmkid;
+++	const u8 *bssid;
+++	const u8 *pmkid;
++ };
+  
+- 		if (WARN_ON(rdev->sched_scan_req &&
+- 			    rdev->sched_scan_req->dev == wdev->netdev)) {
 ---- a/net/wireless/core.h
 -+++ b/net/wireless/core.h
 -@@ -62,6 +62,7 @@ struct cfg80211_registered_device {
@@ -4159,7 +5187,32 @@ index a1af6c2..892f51e 100644
 -+			struct ieee80211_channel *channel;
 - 		} ij;
 - 	};
-- };
++ /**
++@@ -1822,7 +1827,7 @@ struct cfg80211_pmksa {
++  * memory, free @mask only!
++  */
++ struct cfg80211_pkt_pattern {
++-	u8 *mask, *pattern;
+++	const u8 *mask, *pattern;
++ 	int pattern_len;
++ 	int pkt_offset;
++ };
++@@ -1986,6 +1991,8 @@ struct cfg80211_update_ft_ies_params {
++  * @len: buffer length
++  * @no_cck: don't use cck rates for this frame
++  * @dont_wait_for_ack: tells the low level not to wait for an ack
+++ * @n_csa_offsets: length of csa_offsets array
+++ * @csa_offsets: array of all the csa offsets in the frame
++  */
++ struct cfg80211_mgmt_tx_params {
++ 	struct ieee80211_channel *chan;
++@@ -1995,6 +2002,8 @@ struct cfg80211_mgmt_tx_params {
++ 	size_t len;
++ 	bool no_cck;
++ 	bool dont_wait_for_ack;
+++	int n_csa_offsets;
+++	const u16 *csa_offsets;
+  };
 -@@ -257,7 +259,8 @@ int __cfg80211_leave_ibss(struct cfg8021
 - 			  struct net_device *dev, bool nowext);
 - int cfg80211_leave_ibss(struct cfg80211_registered_device *rdev,
@@ -4265,7 +5318,7 @@ index a1af6c2..892f51e 100644
 -@@ -5509,11 +5515,40 @@ static int nl80211_start_sched_scan(stru
 - 	if (n_ssids > wiphy->max_sched_scan_ssids)
 - 		return -EINVAL;
-- 
+  
 --	if (info->attrs[NL80211_ATTR_SCHED_SCAN_MATCH])
 -+	/*
 -+	 * First, count the number of 'real' matchsets. Due to an issue with
@@ -4299,11 +5352,103 @@ index a1af6c2..892f51e 100644
 -+				default_match_rssi = nla_get_s32(rssi);
 -+		}
 -+	}
--+
++ /**
++@@ -2336,28 +2345,29 @@ struct cfg80211_ops {
++ 
++ 
++ 	int	(*add_station)(struct wiphy *wiphy, struct net_device *dev,
++-			       u8 *mac, struct station_parameters *params);
+++			       const u8 *mac,
+++			       struct station_parameters *params);
++ 	int	(*del_station)(struct wiphy *wiphy, struct net_device *dev,
++-			       u8 *mac);
+++			       const u8 *mac);
++ 	int	(*change_station)(struct wiphy *wiphy, struct net_device *dev,
++-				  u8 *mac, struct station_parameters *params);
+++				  const u8 *mac,
+++				  struct station_parameters *params);
++ 	int	(*get_station)(struct wiphy *wiphy, struct net_device *dev,
++-			       u8 *mac, struct station_info *sinfo);
+++			       const u8 *mac, struct station_info *sinfo);
++ 	int	(*dump_station)(struct wiphy *wiphy, struct net_device *dev,
++-			       int idx, u8 *mac, struct station_info *sinfo);
+++				int idx, u8 *mac, struct station_info *sinfo);
++ 
++ 	int	(*add_mpath)(struct wiphy *wiphy, struct net_device *dev,
++-			       u8 *dst, u8 *next_hop);
+++			       const u8 *dst, const u8 *next_hop);
++ 	int	(*del_mpath)(struct wiphy *wiphy, struct net_device *dev,
++-			       u8 *dst);
+++			       const u8 *dst);
++ 	int	(*change_mpath)(struct wiphy *wiphy, struct net_device *dev,
++-				  u8 *dst, u8 *next_hop);
+++				  const u8 *dst, const u8 *next_hop);
++ 	int	(*get_mpath)(struct wiphy *wiphy, struct net_device *dev,
++-			       u8 *dst, u8 *next_hop,
++-			       struct mpath_info *pinfo);
+++			     u8 *dst, u8 *next_hop, struct mpath_info *pinfo);
++ 	int	(*dump_mpath)(struct wiphy *wiphy, struct net_device *dev,
++-			       int idx, u8 *dst, u8 *next_hop,
++-			       struct mpath_info *pinfo);
+++			      int idx, u8 *dst, u8 *next_hop,
+++			      struct mpath_info *pinfo);
++ 	int	(*get_mesh_config)(struct wiphy *wiphy,
++ 				struct net_device *dev,
++ 				struct mesh_config *conf);
++@@ -2487,11 +2497,11 @@ struct cfg80211_ops {
++ 				  struct cfg80211_gtk_rekey_data *data);
++ 
++ 	int	(*tdls_mgmt)(struct wiphy *wiphy, struct net_device *dev,
++-			     u8 *peer, u8 action_code,  u8 dialog_token,
+++			     const u8 *peer, u8 action_code,  u8 dialog_token,
++ 			     u16 status_code, u32 peer_capability,
++ 			     const u8 *buf, size_t len);
++ 	int	(*tdls_oper)(struct wiphy *wiphy, struct net_device *dev,
++-			     u8 *peer, enum nl80211_tdls_operation oper);
+++			     const u8 *peer, enum nl80211_tdls_operation oper);
++ 
++ 	int	(*probe_client)(struct wiphy *wiphy, struct net_device *dev,
++ 				const u8 *peer, u64 *cookie);
++@@ -2638,6 +2648,7 @@ struct ieee80211_iface_limit {
++  *	between infrastructure and AP types must match. This is required
++  *	only in special cases.
++  * @radar_detect_widths: bitmap of channel widths supported for radar detection
+++ * @radar_detect_regions: bitmap of regions supported for radar detection
++  *
++  * With this structure the driver can describe which interface
++  * combinations it supports concurrently.
++@@ -2695,6 +2706,7 @@ struct ieee80211_iface_combination {
++ 	u8 n_limits;
++ 	bool beacon_int_infra_match;
++ 	u8 radar_detect_widths;
+++	u8 radar_detect_regions;
++ };
++ 
++ struct ieee80211_txrx_stypes {
++@@ -2925,6 +2937,11 @@ struct wiphy_vendor_command {
++  *	(including P2P GO) or 0 to indicate no such limit is advertised. The
++  *	driver is allowed to advertise a theoretical limit that it can reach in
++  *	some cases, but may not always reach.
+++ *
+++ * @max_num_csa_counters: Number of supported csa_counters in beacons
+++ *	and probe responses.  This value should be set if the driver
+++ *	wishes to limit the number of csa counters. Default (0) means
+++ *	infinite.
++  */
++ struct wiphy {
++ 	/* assign these fields before you register the wiphy */
++@@ -3045,6 +3062,8 @@ struct wiphy {
++ 
++ 	u16 max_ap_assoc_sta;
++ 
+++	u8 max_num_csa_counters;
+ +
 -+	/* However, if there's no other matchset, add the RSSI one */
 -+	if (!n_match_sets && default_match_rssi != NL80211_SCAN_RSSI_THOLD_OFF)
 -+		n_match_sets = 1;
-- 
++ 	char priv[0] __aligned(NETDEV_ALIGN);
++ };
+  
 - 	if (n_match_sets > wiphy->max_match_sets)
 - 		return -EINVAL;
 -@@ -5634,11 +5669,22 @@ static int nl80211_start_sched_scan(stru
@@ -4352,11 +5497,70 @@ index a1af6c2..892f51e 100644
 --						   NL80211_SCAN_RSSI_THOLD_OFF;
 - 			i++;
 - 		}
--+
++@@ -3273,7 +3292,7 @@ struct wireless_dev {
++ 		struct cfg80211_ibss_params ibss;
++ 		struct cfg80211_connect_params connect;
++ 		struct cfg80211_cached_keys *keys;
++-		u8 *ie;
+++		const u8 *ie;
++ 		size_t ie_len;
++ 		u8 bssid[ETH_ALEN], prev_bssid[ETH_ALEN];
++ 		u8 ssid[IEEE80211_MAX_SSID_LEN];
++@@ -3514,7 +3533,8 @@ int ieee80211_data_to_8023(struct sk_buf
++  * Return: 0 on success, or a negative error code.
++  */
++ int ieee80211_data_from_8023(struct sk_buff *skb, const u8 *addr,
++-			     enum nl80211_iftype iftype, u8 *bssid, bool qos);
+++			     enum nl80211_iftype iftype, const u8 *bssid,
+++			     bool qos);
++ 
++ /**
++  * ieee80211_amsdu_to_8023s - decode an IEEE 802.11n A-MSDU frame
++@@ -4315,7 +4335,7 @@ void cfg80211_roamed_bss(struct net_devi
++  * and not try to connect to any AP any more.
++  */
++ void cfg80211_disconnected(struct net_device *dev, u16 reason,
++-			   u8 *ie, size_t ie_len, gfp_t gfp);
+++			   const u8 *ie, size_t ie_len, gfp_t gfp);
++ 
++ /**
++  * cfg80211_ready_on_channel - notification of remain_on_channel start
++@@ -4771,6 +4791,35 @@ int cfg80211_iter_combinations(struct wi
++ 					    void *data),
++ 			       void *data);
++ 
+++/*
+++ * cfg80211_stop_iface - trigger interface disconnection
+++ *
+++ * @wiphy: the wiphy
+++ * @wdev: wireless device
+++ * @gfp: context flags
+++ *
+++ * Trigger interface to be stopped as if AP was stopped, IBSS/mesh left, STA
+++ * disconnected.
+++ *
+++ * Note: This doesn't need any locks and is asynchronous.
+++ */
+++void cfg80211_stop_iface(struct wiphy *wiphy, struct wireless_dev *wdev,
+++			 gfp_t gfp);
+ +
 -+		/* there was no other matchset, so the RSSI one is alone */
 -+		if (i == 0)
 -+			request->match_sets[0].rssi_thold = default_match_rssi;
--+
+++/**
+++ * cfg80211_shutdown_all_interfaces - shut down all interfaces for a wiphy
+++ * @wiphy: the wiphy to shut down
+++ *
+++ * This function shuts down all interfaces belonging to this wiphy by
+++ * calling dev_close() (and treating non-netdev interfaces as needed).
+++ * It shouldn't really be used unless there are some fatal device errors
+++ * that really can't be recovered in any other way.
+++ *
+++ * Callers must hold the RTNL and be able to deal with callbacks into
+++ * the driver while the function is running.
+++ */
+++void cfg80211_shutdown_all_interfaces(struct wiphy *wiphy);
+ +
 -+		request->min_rssi_thold = INT_MAX;
 -+		for (i = 0; i < n_match_sets; i++)
 -+			request->min_rssi_thold =
@@ -4368,7 +5572,42 @@ index a1af6c2..892f51e 100644
 - 
 - 	if (info->attrs[NL80211_ATTR_IE]) {
 -@@ -5751,7 +5810,7 @@ static int nl80211_start_radar_detection
-- 
++ /* Logging, debugging and troubleshooting/diagnostic helpers. */
++ 
++ /* wiphy_printk helpers, similar to dev_printk */
++--- a/include/net/mac80211.h
+++++ b/include/net/mac80211.h
++@@ -1113,7 +1113,9 @@ enum ieee80211_vif_flags {
++  * @addr: address of this interface
++  * @p2p: indicates whether this AP or STA interface is a p2p
++  *	interface, i.e. a GO or p2p-sta respectively
++- * @csa_active: marks whether a channel switch is going on
+++ * @csa_active: marks whether a channel switch is going on. Internally it is
+++ *	write-protected by sdata_lock and local->mtx so holding either is fine
+++ *	for read access.
++  * @driver_flags: flags/capabilities the driver has for this interface,
++  *	these need to be set (or cleared) when the interface is added
++  *	or, if supported by the driver, the interface type is changed
++@@ -1374,6 +1376,7 @@ struct ieee80211_sta_rates {
++  *	the station moves to associated state.
++  * @smps_mode: current SMPS mode (off, static or dynamic)
++  * @rates: rate control selection table
+++ * @tdls: indicates whether the STA is a TDLS peer
++  */
++ struct ieee80211_sta {
++ 	u32 supp_rates[IEEE80211_NUM_BANDS];
++@@ -1388,6 +1391,7 @@ struct ieee80211_sta {
++ 	enum ieee80211_sta_rx_bandwidth bandwidth;
++ 	enum ieee80211_smps_mode smps_mode;
++ 	struct ieee80211_sta_rates __rcu *rates;
+++	bool tdls;
++ 
++ 	/* must be last */
++ 	u8 drv_priv[0] __aligned(sizeof(void *));
++@@ -3407,6 +3411,47 @@ void ieee80211_tx_status_irqsafe(struct 
++  */
++ void ieee80211_report_low_ack(struct ieee80211_sta *sta, u32 num_packets);
+  
 - 	err = rdev->ops->start_radar_detection(&rdev->wiphy, dev, &chandef);
 - 	if (!err) {
 --		wdev->channel = chandef.chan;
@@ -4402,8 +5641,73 @@ index a1af6c2..892f51e 100644
 - 				sband,
 -@@ -10054,40 +10116,31 @@ void nl80211_send_scan_start(struct cfg8
 - 				NL80211_MCGRP_SCAN, GFP_KERNEL);
-- }
-- 
+++#define IEEE80211_MAX_CSA_COUNTERS_NUM 2
+++
+++/**
+++ * struct ieee80211_mutable_offsets - mutable beacon offsets
+++ * @tim_offset: position of TIM element
+++ * @tim_length: size of TIM element
+++ * @csa_counter_offs: array of IEEE80211_MAX_CSA_COUNTERS_NUM offsets
+++ *	to CSA counters.  This array can contain zero values which
+++ *	should be ignored.
+++ */
+++struct ieee80211_mutable_offsets {
+++	u16 tim_offset;
+++	u16 tim_length;
+++
+++	u16 csa_counter_offs[IEEE80211_MAX_CSA_COUNTERS_NUM];
+++};
+++
+++/**
+++ * ieee80211_beacon_get_template - beacon template generation function
+++ * @hw: pointer obtained from ieee80211_alloc_hw().
+++ * @vif: &struct ieee80211_vif pointer from the add_interface callback.
+++ * @offs: &struct ieee80211_mutable_offsets pointer to struct that will
+++ *	receive the offsets that may be updated by the driver.
+++ *
+++ * If the driver implements beaconing modes, it must use this function to
+++ * obtain the beacon template.
+++ *
+++ * This function should be used if the beacon frames are generated by the
+++ * device, and then the driver must use the returned beacon as the template
+++ * The driver or the device are responsible to update the DTIM and, when
+++ * applicable, the CSA count.
+++ *
+++ * The driver is responsible for freeing the returned skb.
+++ *
+++ * Return: The beacon template. %NULL on error.
+++ */
+++struct sk_buff *
+++ieee80211_beacon_get_template(struct ieee80211_hw *hw,
+++			      struct ieee80211_vif *vif,
+++			      struct ieee80211_mutable_offsets *offs);
+++
++ /**
++  * ieee80211_beacon_get_tim - beacon generation function
++  * @hw: pointer obtained from ieee80211_alloc_hw().
++@@ -3418,16 +3463,12 @@ void ieee80211_report_low_ack(struct iee
++  *	Set to 0 if invalid (in non-AP modes).
++  *
++  * If the driver implements beaconing modes, it must use this function to
++- * obtain the beacon frame/template.
+++ * obtain the beacon frame.
++  *
++  * If the beacon frames are generated by the host system (i.e., not in
++  * hardware/firmware), the driver uses this function to get each beacon
++- * frame from mac80211 -- it is responsible for calling this function
++- * before the beacon is needed (e.g. based on hardware interrupt).
++- *
++- * If the beacon frames are generated by the device, then the driver
++- * must use the returned beacon as the template and change the TIM IE
++- * according to the current DTIM parameters/TIM bitmap.
+++ * frame from mac80211 -- it is responsible for calling this function exactly
+++ * once before the beacon is needed (e.g. based on hardware interrupt).
++  *
++  * The driver is responsible for freeing the returned skb.
++  *
++@@ -3453,6 +3494,20 @@ static inline struct sk_buff *ieee80211_
+  }
+  
 --void nl80211_send_scan_done(struct cfg80211_registered_device *rdev,
 --			    struct wireless_dev *wdev)
 -+struct sk_buff *nl80211_build_scan_msg(struct cfg80211_registered_device *rdev,
@@ -4415,7 +5719,65 @@ index a1af6c2..892f51e 100644
 - 	if (!msg)
 --		return;
 -+		return NULL;
-- 
++ /**
+++ * ieee80211_csa_update_counter - request mac80211 to decrement the csa counter
+++ * @vif: &struct ieee80211_vif pointer from the add_interface callback.
+++ *
+++ * The csa counter should be updated after each beacon transmission.
+++ * This function is called implicitly when
+++ * ieee80211_beacon_get/ieee80211_beacon_get_tim are called, however if the
+++ * beacon frames are generated by the device, the driver should call this
+++ * function after each beacon transmission to sync mac80211's csa counters.
+++ *
+++ * Return: new csa counter value
+++ */
+++u8 ieee80211_csa_update_counter(struct ieee80211_vif *vif);
+++
+++/**
++  * ieee80211_csa_finish - notify mac80211 about channel switch
++  * @vif: &struct ieee80211_vif pointer from the add_interface callback.
++  *
++--- a/include/uapi/linux/nl80211.h
+++++ b/include/uapi/linux/nl80211.h
++@@ -503,6 +503,9 @@
++  *	TX status event pertaining to the TX request.
++  *	%NL80211_ATTR_TX_NO_CCK_RATE is used to decide whether to send the
++  *	management frames at CCK rate or not in 2GHz band.
+++ *	%NL80211_ATTR_CSA_C_OFFSETS_TX is an array of offsets to CSA
+++ *	counters which will be updated to the current value. This attribute
+++ *	is used during CSA period.
++  * @NL80211_CMD_FRAME_WAIT_CANCEL: When an off-channel TX was requested, this
++  *	command may be used with the corresponding cookie to cancel the wait
++  *	time if it is known that it is no longer necessary.
++@@ -1525,10 +1528,10 @@ enum nl80211_commands {
++  *	operation).
++  * @NL80211_ATTR_CSA_IES: Nested set of attributes containing the IE information
++  *	for the time while performing a channel switch.
++- * @NL80211_ATTR_CSA_C_OFF_BEACON: Offset of the channel switch counter
++- *	field in the beacons tail (%NL80211_ATTR_BEACON_TAIL).
++- * @NL80211_ATTR_CSA_C_OFF_PRESP: Offset of the channel switch counter
++- *	field in the probe response (%NL80211_ATTR_PROBE_RESP).
+++ * @NL80211_ATTR_CSA_C_OFF_BEACON: An array of offsets (u16) to the channel
+++ *	switch counters in the beacons tail (%NL80211_ATTR_BEACON_TAIL).
+++ * @NL80211_ATTR_CSA_C_OFF_PRESP: An array of offsets (u16) to the channel
+++ *	switch counters in the probe response (%NL80211_ATTR_PROBE_RESP).
++  *
++  * @NL80211_ATTR_RXMGMT_FLAGS: flags for nl80211_send_mgmt(), u32.
++  *	As specified in the &enum nl80211_rxmgmt_flags.
++@@ -1576,6 +1579,11 @@ enum nl80211_commands {
++  *	advertise values that cannot always be met. In such cases, an attempt
++  *	to add a new station entry with @NL80211_CMD_NEW_STATION may fail.
++  *
+++ * @NL80211_ATTR_CSA_C_OFFSETS_TX: An array of csa counter offsets (u16) which
+++ *	should be updated when the frame is transmitted.
+++ * @NL80211_ATTR_MAX_CSA_COUNTERS: U8 attribute used to advertise the maximum
+++ *	supported number of csa counters.
+++ *
++  * @NL80211_ATTR_TDLS_PEER_CAPABILITY: flags for TDLS peer capabilities, u32.
++  *	As specified in the &enum nl80211_tdls_peer_capability.
++  *
++@@ -1920,6 +1928,9 @@ enum nl80211_attrs {
+  
 - 	if (nl80211_send_scan_msg(msg, rdev, wdev, 0, 0, 0,
 --				  NL80211_CMD_NEW_SCAN_RESULTS) < 0) {
 -+				  aborted ? NL80211_CMD_SCAN_ABORTED :
@@ -4424,17 +5786,59 @@ index a1af6c2..892f51e 100644
 --		return;
 -+		return NULL;
 - 	}
-- 
++ 	NL80211_ATTR_IFACE_SOCKET_OWNER,
+  
 --	genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
 --				NL80211_MCGRP_SCAN, GFP_KERNEL);
 -+	return msg;
-- }
-- 
+++	NL80211_ATTR_CSA_C_OFFSETS_TX,
+++	NL80211_ATTR_MAX_CSA_COUNTERS,
+++
++ 	/* add attributes here, update the policy in nl80211.c */
++ 
++ 	__NL80211_ATTR_AFTER_LAST,
++@@ -3688,6 +3699,8 @@ enum nl80211_iface_limit_attrs {
++  *	different channels may be used within this group.
++  * @NL80211_IFACE_COMB_RADAR_DETECT_WIDTHS: u32 attribute containing the bitmap
++  *	of supported channel widths for radar detection.
+++ * @NL80211_IFACE_COMB_RADAR_DETECT_REGIONS: u32 attribute containing the bitmap
+++ *	of supported regulatory regions for radar detection.
++  * @NUM_NL80211_IFACE_COMB: number of attributes
++  * @MAX_NL80211_IFACE_COMB: highest attribute number
++  *
++@@ -3721,6 +3734,7 @@ enum nl80211_if_combination_attrs {
++ 	NL80211_IFACE_COMB_STA_AP_BI_MATCH,
++ 	NL80211_IFACE_COMB_NUM_CHANNELS,
++ 	NL80211_IFACE_COMB_RADAR_DETECT_WIDTHS,
+++	NL80211_IFACE_COMB_RADAR_DETECT_REGIONS,
++ 
++ 	/* keep last */
++ 	NUM_NL80211_IFACE_COMB,
++--- a/net/mac80211/Makefile
+++++ b/net/mac80211/Makefile
++@@ -25,7 +25,8 @@ mac80211-y := \
++ 	wme.o \
++ 	event.o \
++ 	chan.o \
++-	trace.o mlme.o
+++	trace.o mlme.o \
+++	tdls.o
++ 
++ mac80211-$(CPTCFG_MAC80211_LEDS) += led.o
++ mac80211-$(CPTCFG_MAC80211_DEBUGFS) += \
++--- a/net/mac80211/cfg.c
+++++ b/net/mac80211/cfg.c
++@@ -777,7 +777,7 @@ static void ieee80211_get_et_strings(str
+  }
+  
 --void nl80211_send_scan_aborted(struct cfg80211_registered_device *rdev,
 --			       struct wireless_dev *wdev)
 -+void nl80211_send_scan_result(struct cfg80211_registered_device *rdev,
 -+			      struct sk_buff *msg)
-- {
++ static int ieee80211_dump_station(struct wiphy *wiphy, struct net_device *dev,
++-				 int idx, u8 *mac, struct station_info *sinfo)
+++				  int idx, u8 *mac, struct station_info *sinfo)
+  {
 --	struct sk_buff *msg;
 --
 --	msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
@@ -4449,11 +5853,14 @@ index a1af6c2..892f51e 100644
 --
 - 	genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
 - 				NL80211_MCGRP_SCAN, GFP_KERNEL);
-- }
++ 	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
++ 	struct ieee80211_local *local = sdata->local;
++@@ -807,7 +807,7 @@ static int ieee80211_dump_survey(struct 
+  }
 -@@ -11158,7 +11211,8 @@ void cfg80211_ch_switch_notify(struct ne
 - 		    wdev->iftype != NL80211_IFTYPE_MESH_POINT))
 - 		return;
-- 
+  
 --	wdev->channel = chandef->chan;
 -+	wdev->chandef = *chandef;
 -+	wdev->preset_chandef = *chandef;
@@ -4461,38 +5868,63 @@ index a1af6c2..892f51e 100644
 - }
 - EXPORT_SYMBOL(cfg80211_ch_switch_notify);
 -@@ -11673,6 +11727,35 @@ void cfg80211_crit_proto_stopped(struct 
-- }
++ static int ieee80211_get_station(struct wiphy *wiphy, struct net_device *dev,
++-				 u8 *mac, struct station_info *sinfo)
+++				 const u8 *mac, struct station_info *sinfo)
++ {
++ 	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
++ 	struct ieee80211_local *local = sdata->local;
++@@ -1084,6 +1084,31 @@ static int ieee80211_change_beacon(struc
++ 	return 0;
+  }
 - EXPORT_SYMBOL(cfg80211_crit_proto_stopped);
-- 
+  
 -+void nl80211_send_ap_stopped(struct wireless_dev *wdev)
--+{
+++bool ieee80211_csa_needs_block_tx(struct ieee80211_local *local)
+ +{
 -+	struct wiphy *wiphy = wdev->wiphy;
 -+	struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
 -+	struct sk_buff *msg;
 -+	void *hdr;
--+
+++	struct ieee80211_sub_if_data *sdata;
+ +
 -+	msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
 -+	if (!msg)
 -+		return;
--+
+++	lockdep_assert_held(&local->mtx);
+++
+++	rcu_read_lock();
+++	list_for_each_entry_rcu(sdata, &local->interfaces, list) {
+++		if (!ieee80211_sdata_running(sdata))
+++			continue;
+ +
 -+	hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_STOP_AP);
 -+	if (!hdr)
 -+		goto out;
--+
+++		if (!sdata->vif.csa_active)
+++			continue;
+ +
 -+	if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
 -+	    nla_put_u32(msg, NL80211_ATTR_IFINDEX, wdev->netdev->ifindex) ||
 -+	    nla_put_u64(msg, NL80211_ATTR_WDEV, wdev_id(wdev)))
 -+		goto out;
--+
+++		if (!sdata->csa_block_tx)
+++			continue;
+ +
 -+	genlmsg_end(msg, hdr);
--+
+++		rcu_read_unlock();
+++		return true;
+++	}
+++	rcu_read_unlock();
+ +
 -+	genlmsg_multicast_netns(&nl80211_fam, wiphy_net(wiphy), msg, 0,
 -+				NL80211_MCGRP_MLME, GFP_KERNEL);
 -+	return;
 -+ out:
 -+	nlmsg_free(msg);
--+}
--+
+++	return false;
+ +}
+ +
 - /* initialisation/exit functions */
 - 
 - int nl80211_init(void)
@@ -4531,7 +5963,8 @@ index a1af6c2..892f51e 100644
 --void ___cfg80211_scan_done(struct cfg80211_registered_device *rdev)
 -+void ___cfg80211_scan_done(struct cfg80211_registered_device *rdev,
 -+			   bool send_message)
-- {
++ static int ieee80211_stop_ap(struct wiphy *wiphy, struct net_device *dev)
+  {
 - 	struct cfg80211_scan_request *request;
 - 	struct wireless_dev *wdev;
 -+	struct sk_buff *msg;
@@ -4540,18 +5973,34 @@ index a1af6c2..892f51e 100644
 - #endif
 - 
 - 	ASSERT_RTNL();
-- 
++ 	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
++@@ -1101,7 +1126,14 @@ static int ieee80211_stop_ap(struct wiph
++ 	old_probe_resp = sdata_dereference(sdata->u.ap.probe_resp, sdata);
+  
 --	request = rdev->scan_req;
 -+	if (rdev->scan_msg) {
 -+		nl80211_send_scan_result(rdev, rdev->scan_msg);
 -+		rdev->scan_msg = NULL;
 -+		return;
 -+	}
-- 
++ 	/* abort any running channel switch */
+++	mutex_lock(&local->mtx);
++ 	sdata->vif.csa_active = false;
+++	if (!ieee80211_csa_needs_block_tx(local))
+++		ieee80211_wake_queues_by_reason(&local->hw,
+++					IEEE80211_MAX_QUEUE_MAP,
+++					IEEE80211_QUEUE_STOP_REASON_CSA);
+++	mutex_unlock(&local->mtx);
+++
++ 	kfree(sdata->u.ap.next_beacon);
++ 	sdata->u.ap.next_beacon = NULL;
+  
 -+	request = rdev->scan_req;
 - 	if (!request)
 - 		return;
-- 
++@@ -1425,7 +1457,8 @@ static int sta_apply_parameters(struct i
++ }
+  
 -@@ -186,18 +193,16 @@ void ___cfg80211_scan_done(struct cfg802
 - 	if (wdev->netdev)
 - 		cfg80211_sme_scan_done(wdev->netdev);
@@ -4572,15 +6021,31 @@ index a1af6c2..892f51e 100644
 -+		spin_lock_bh(&rdev->bss_lock);
 -+		__cfg80211_bss_expire(rdev, request->scan_start);
 -+		spin_unlock_bh(&rdev->bss_lock);
-- 	}
-- 
++ static int ieee80211_add_station(struct wiphy *wiphy, struct net_device *dev,
++-				 u8 *mac, struct station_parameters *params)
+++				 const u8 *mac,
+++				 struct station_parameters *params)
++ {
++ 	struct ieee80211_local *local = wiphy_priv(wiphy);
++ 	struct sta_info *sta;
++@@ -1459,6 +1492,8 @@ static int ieee80211_add_station(struct 
++ 	if (!(params->sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER))) {
++ 		sta_info_pre_move_state(sta, IEEE80211_STA_AUTH);
++ 		sta_info_pre_move_state(sta, IEEE80211_STA_ASSOC);
+++	} else {
+++		sta->sta.tdls = true;
+  	}
+  
 -+	msg = nl80211_build_scan_msg(rdev, wdev, request->aborted);
 -+
 - #ifdef CPTCFG_CFG80211_WEXT
 - 	if (wdev->netdev && !request->aborted) {
 - 		memset(&wrqu, 0, sizeof(wrqu));
 -@@ -211,6 +216,11 @@ void ___cfg80211_scan_done(struct cfg802
-- 
++ 	err = sta_apply_parameters(local, sta, params);
++@@ -1492,7 +1527,7 @@ static int ieee80211_add_station(struct 
++ }
+  
 - 	rdev->scan_req = NULL;
 - 	kfree(request);
 -+
@@ -4588,22 +6053,49 @@ index a1af6c2..892f51e 100644
 -+		rdev->scan_msg = msg;
 -+	else
 -+		nl80211_send_scan_result(rdev, msg);
-- }
-- 
++ static int ieee80211_del_station(struct wiphy *wiphy, struct net_device *dev,
++-				 u8 *mac)
+++				 const u8 *mac)
++ {
++ 	struct ieee80211_sub_if_data *sdata;
++ 
++@@ -1506,7 +1541,7 @@ static int ieee80211_del_station(struct 
+  }
+  
 - void __cfg80211_scan_done(struct work_struct *wk)
 -@@ -221,7 +231,7 @@ void __cfg80211_scan_done(struct work_st
 - 			    scan_done_wk);
-- 
++ static int ieee80211_change_station(struct wiphy *wiphy,
++-				    struct net_device *dev, u8 *mac,
+++				    struct net_device *dev, const u8 *mac,
++ 				    struct station_parameters *params)
++ {
++ 	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
++@@ -1631,7 +1666,7 @@ out_err:
+  
 - 	rtnl_lock();
 --	___cfg80211_scan_done(rdev);
 -+	___cfg80211_scan_done(rdev, true);
 - 	rtnl_unlock();
-- }
-- 
++ #ifdef CPTCFG_MAC80211_MESH
++ static int ieee80211_add_mpath(struct wiphy *wiphy, struct net_device *dev,
++-				 u8 *dst, u8 *next_hop)
+++			       const u8 *dst, const u8 *next_hop)
++ {
++ 	struct ieee80211_sub_if_data *sdata;
++ 	struct mesh_path *mpath;
++@@ -1659,7 +1694,7 @@ static int ieee80211_add_mpath(struct wi
+  }
+  
 -@@ -1079,7 +1089,7 @@ int cfg80211_wext_siwscan(struct net_dev
 - 	if (IS_ERR(rdev))
 - 		return PTR_ERR(rdev);
-- 
++ static int ieee80211_del_mpath(struct wiphy *wiphy, struct net_device *dev,
++-			       u8 *dst)
+++			       const u8 *dst)
++ {
++ 	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+  
 --	if (rdev->scan_req) {
 -+	if (rdev->scan_req || rdev->scan_msg) {
 - 		err = -EBUSY;
@@ -4612,39 +6104,167 @@ index a1af6c2..892f51e 100644
 -@@ -1481,7 +1491,7 @@ int cfg80211_wext_giwscan(struct net_dev
 - 	if (IS_ERR(rdev))
 - 		return PTR_ERR(rdev);
-- 
++@@ -1670,9 +1705,8 @@ static int ieee80211_del_mpath(struct wi
++ 	return 0;
++ }
++ 
++-static int ieee80211_change_mpath(struct wiphy *wiphy,
++-				    struct net_device *dev,
++-				    u8 *dst, u8 *next_hop)
+++static int ieee80211_change_mpath(struct wiphy *wiphy, struct net_device *dev,
+++				  const u8 *dst, const u8 *next_hop)
++ {
++ 	struct ieee80211_sub_if_data *sdata;
++ 	struct mesh_path *mpath;
++@@ -1764,8 +1798,8 @@ static int ieee80211_get_mpath(struct wi
++ }
+  
 --	if (rdev->scan_req)
 -+	if (rdev->scan_req || rdev->scan_msg)
 - 		return -EAGAIN;
-- 
++ static int ieee80211_dump_mpath(struct wiphy *wiphy, struct net_device *dev,
++-				 int idx, u8 *dst, u8 *next_hop,
++-				 struct mpath_info *pinfo)
+++				int idx, u8 *dst, u8 *next_hop,
+++				struct mpath_info *pinfo)
++ {
++ 	struct ieee80211_sub_if_data *sdata;
++ 	struct mesh_path *mpath;
++@@ -3019,26 +3053,11 @@ void ieee80211_csa_finish(struct ieee802
++ }
++ EXPORT_SYMBOL(ieee80211_csa_finish);
+  
 - 	res = ieee80211_scan_results(rdev, info, extra, data->length);
 ---- a/net/wireless/sme.c
 -+++ b/net/wireless/sme.c
 -@@ -67,7 +67,7 @@ static int cfg80211_conn_scan(struct wir
 - 	ASSERT_RDEV_LOCK(rdev);
 - 	ASSERT_WDEV_LOCK(wdev);
-- 
++-static void ieee80211_csa_finalize(struct ieee80211_sub_if_data *sdata)
+++static int ieee80211_set_after_csa_beacon(struct ieee80211_sub_if_data *sdata,
+++					  u32 *changed)
++ {
++-	struct ieee80211_local *local = sdata->local;
++-	int err, changed = 0;
++-
++-	sdata_assert_lock(sdata);
++-
++-	mutex_lock(&local->mtx);
++-	sdata->radar_required = sdata->csa_radar_required;
++-	err = ieee80211_vif_change_channel(sdata, &changed);
++-	mutex_unlock(&local->mtx);
++-	if (WARN_ON(err < 0))
++-		return;
++-
++-	if (!local->use_chanctx) {
++-		local->_oper_chandef = sdata->csa_chandef;
++-		ieee80211_hw_config(local, 0);
++-	}
+++	int err;
+  
 --	if (rdev->scan_req)
 -+	if (rdev->scan_req || rdev->scan_msg)
 - 		return -EBUSY;
-- 
++-	sdata->vif.csa_active = false;
++ 	switch (sdata->vif.type) {
++ 	case NL80211_IFTYPE_AP:
++ 		err = ieee80211_assign_beacon(sdata, sdata->u.ap.next_beacon);
++@@ -3046,35 +3065,75 @@ static void ieee80211_csa_finalize(struc
++ 		sdata->u.ap.next_beacon = NULL;
+  
 - 	if (wdev->conn->params.channel)
 ---- a/net/mac80211/mlme.c
 -+++ b/net/mac80211/mlme.c
 -@@ -1001,7 +1001,6 @@ ieee80211_sta_process_chanswitch(struct 
-- 	}
-- 
++ 		if (err < 0)
++-			return;
++-		changed |= err;
+++			return err;
+++		*changed |= err;
++ 		break;
++ 	case NL80211_IFTYPE_ADHOC:
++ 		err = ieee80211_ibss_finish_csa(sdata);
++ 		if (err < 0)
++-			return;
++-		changed |= err;
+++			return err;
+++		*changed |= err;
++ 		break;
++ #ifdef CPTCFG_MAC80211_MESH
++ 	case NL80211_IFTYPE_MESH_POINT:
++ 		err = ieee80211_mesh_finish_csa(sdata);
++ 		if (err < 0)
++-			return;
++-		changed |= err;
+++			return err;
+++		*changed |= err;
++ 		break;
++ #endif
++ 	default:
++ 		WARN_ON(1);
++-		return;
+++		return -EINVAL;
+  	}
+  
 - 	ifmgd->flags |= IEEE80211_STA_CSA_RECEIVED;
 --	sdata->vif.csa_active = true;
-- 
+++
+++	return 0;
+++}
+++
+++static int __ieee80211_csa_finalize(struct ieee80211_sub_if_data *sdata)
+++{
+++	struct ieee80211_local *local = sdata->local;
+++	u32 changed = 0;
+++	int err;
+++
+++	sdata_assert_lock(sdata);
+++	lockdep_assert_held(&local->mtx);
+++
+++	sdata->radar_required = sdata->csa_radar_required;
+++	err = ieee80211_vif_change_channel(sdata, &changed);
+++	if (err < 0)
+++		return err;
+++
+++	if (!local->use_chanctx) {
+++		local->_oper_chandef = sdata->csa_chandef;
+++		ieee80211_hw_config(local, 0);
+++	}
+++
+++	sdata->vif.csa_active = false;
+++
+++	err = ieee80211_set_after_csa_beacon(sdata, &changed);
+++	if (err)
+++		return err;
+++
++ 	ieee80211_bss_info_change_notify(sdata, changed);
+++	cfg80211_ch_switch_notify(sdata->dev, &sdata->csa_chandef);
+  
 - 	mutex_lock(&local->chanctx_mtx);
 - 	if (local->use_chanctx) {
 -@@ -1039,6 +1038,7 @@ ieee80211_sta_process_chanswitch(struct 
 - 	mutex_unlock(&local->chanctx_mtx);
-- 
++-	ieee80211_wake_queues_by_reason(&sdata->local->hw,
+++	if (!ieee80211_csa_needs_block_tx(local))
+++		ieee80211_wake_queues_by_reason(&local->hw,
++ 					IEEE80211_MAX_QUEUE_MAP,
++ 					IEEE80211_QUEUE_STOP_REASON_CSA);
+  
 - 	sdata->csa_chandef = csa_ie.chandef;
 -+	sdata->vif.csa_active = true;
-- 
++-	cfg80211_ch_switch_notify(sdata->dev, &sdata->csa_chandef);
+++	return 0;
+++}
+++
+++static void ieee80211_csa_finalize(struct ieee80211_sub_if_data *sdata)
+++{
+++	if (__ieee80211_csa_finalize(sdata)) {
+++		sdata_info(sdata, "failed to finalize CSA, disconnecting\n");
+++		cfg80211_stop_iface(sdata->local->hw.wiphy, &sdata->wdev,
+++				    GFP_KERNEL);
+++	}
++ }
+  
 - 	if (csa_ie.mode)
 - 		ieee80211_stop_queues_by_reason(&local->hw,
 ---- a/net/mac80211/chan.c
@@ -4652,9 +6272,17 @@ index a1af6c2..892f51e 100644
 -@@ -196,6 +196,8 @@ static bool ieee80211_is_radar_required(
 - {
 - 	struct ieee80211_sub_if_data *sdata;
-- 
++ void ieee80211_csa_finalize_work(struct work_struct *work)
++@@ -3082,8 +3141,11 @@ void ieee80211_csa_finalize_work(struct 
++ 	struct ieee80211_sub_if_data *sdata =
++ 		container_of(work, struct ieee80211_sub_if_data,
++ 			     csa_finalize_work);
+++	struct ieee80211_local *local = sdata->local;
+  
 -+	lockdep_assert_held(&local->mtx);
--+
++ 	sdata_lock(sdata);
+++	mutex_lock(&local->mtx);
+ +
 - 	rcu_read_lock();
 - 	list_for_each_entry_rcu(sdata, &local->interfaces, list) {
 - 		if (sdata->radar_required) {
@@ -4674,7 +6302,12 @@ index a1af6c2..892f51e 100644
 - 	}
 -+	sdata->radar_required = radar_required;
 - 	mutex_unlock(&local->mtx);
-- 
++ 	/* AP might have been stopped while waiting for the lock. */
++ 	if (!sdata->vif.csa_active)
++ 		goto unlock;
++@@ -3094,6 +3156,7 @@ void ieee80211_csa_finalize_work(struct 
++ 	ieee80211_csa_finalize(sdata);
+  
 - 	memcpy(ifibss->bssid, bssid, ETH_ALEN);
 -@@ -318,7 +318,6 @@ static void __ieee80211_sta_join_ibss(st
 - 	rcu_assign_pointer(ifibss->presp, presp);
@@ -4690,15 +6323,29 @@ index a1af6c2..892f51e 100644
 - 	netif_carrier_on(sdata->dev);
 --	cfg80211_ibss_joined(sdata->dev, ifibss->bssid, GFP_KERNEL);
 -+	cfg80211_ibss_joined(sdata->dev, ifibss->bssid, chan, GFP_KERNEL);
-- }
-- 
++ unlock:
+++	mutex_unlock(&local->mtx);
++ 	sdata_unlock(sdata);
+  }
+  
 - static void ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
 -@@ -802,6 +801,8 @@ ieee80211_ibss_process_chanswitch(struct
 - 	int err;
 - 	u32 sta_flags;
-- 
++@@ -3129,9 +3192,25 @@ static int ieee80211_set_csa_beacon(stru
++ 		if (params->count <= 1)
++ 			break;
+  
 -+	sdata_assert_lock(sdata);
--+
++-		sdata->csa_counter_offset_beacon =
++-			params->counter_offset_beacon;
++-		sdata->csa_counter_offset_presp = params->counter_offset_presp;
+++		if ((params->n_counter_offsets_beacon >
+++		     IEEE80211_MAX_CSA_COUNTERS_NUM) ||
+++		    (params->n_counter_offsets_presp >
+++		     IEEE80211_MAX_CSA_COUNTERS_NUM))
+++			return -EINVAL;
+ +
 - 	sta_flags = IEEE80211_STA_DISABLE_VHT;
 - 	switch (ifibss->chandef.width) {
 - 	case NL80211_CHAN_WIDTH_5:
@@ -4706,20 +6353,46 @@ index a1af6c2..892f51e 100644
 - 	memcpy(((struct ieee80211_mgmt *) skb->data)->da, mgmt->sa, ETH_ALEN);
 - 	ibss_dbg(sdata, "Sending ProbeResp to %pM\n", mgmt->sa);
 - 	IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT;
--+
+++		/* make sure we don't have garbage in other counters */
+++		memset(sdata->csa_counter_offset_beacon, 0,
+++		       sizeof(sdata->csa_counter_offset_beacon));
+++		memset(sdata->csa_counter_offset_presp, 0,
+++		       sizeof(sdata->csa_counter_offset_presp));
+ +
 -+	/* avoid excessive retries for probe request to wildcard SSIDs */
 -+	if (pos[1] == 0)
 -+		IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_CTL_NO_ACK;
--+
+++		memcpy(sdata->csa_counter_offset_beacon,
+++		       params->counter_offsets_beacon,
+++		       params->n_counter_offsets_beacon * sizeof(u16));
+++		memcpy(sdata->csa_counter_offset_presp,
+++		       params->counter_offsets_presp,
+++		       params->n_counter_offsets_presp * sizeof(u16));
+ +
 - 	ieee80211_tx_skb(sdata, skb);
-- }
-- 
++ 		err = ieee80211_assign_beacon(sdata, &params->beacon_csa);
++ 		if (err < 0) {
++ 			kfree(sdata->u.ap.next_beacon);
++@@ -3220,8 +3299,9 @@ static int ieee80211_set_csa_beacon(stru
++ 	return 0;
+  }
+  
 ---- a/net/mac80211/mesh.c
 -+++ b/net/mac80211/mesh.c
 -@@ -872,6 +872,8 @@ ieee80211_mesh_process_chnswitch(struct 
 - 	if (!ifmsh->mesh_id)
 - 		return false;
-- 
++-int ieee80211_channel_switch(struct wiphy *wiphy, struct net_device *dev,
++-			     struct cfg80211_csa_settings *params)
+++static int
+++__ieee80211_channel_switch(struct wiphy *wiphy, struct net_device *dev,
+++			   struct cfg80211_csa_settings *params)
++ {
++ 	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
++ 	struct ieee80211_local *local = sdata->local;
++@@ -3230,6 +3310,7 @@ int ieee80211_channel_switch(struct wiph
++ 	int err, num_chanctx, changed = 0;
+  
 -+	sdata_assert_lock(sdata);
 -+
 - 	sta_flags = IEEE80211_STA_DISABLE_VHT;
@@ -4752,11 +6425,17 @@ index a1af6c2..892f51e 100644
 -@@ -1766,7 +1766,8 @@ static void lbs_join_post(struct lbs_pri
 - 	memcpy(priv->wdev->ssid, params->ssid, params->ssid_len);
 - 	priv->wdev->ssid_len = params->ssid_len;
-- 
++ 	sdata_assert_lock(sdata);
+++	lockdep_assert_held(&local->mtx);
+  
 --	cfg80211_ibss_joined(priv->dev, bssid, GFP_KERNEL);
 -+	cfg80211_ibss_joined(priv->dev, bssid, params->chandef.chan,
 -+			     GFP_KERNEL);
-- 
++ 	if (!list_empty(&local->roc_list) || local->scanning)
++ 		return -EBUSY;
++@@ -3272,15 +3353,16 @@ int ieee80211_channel_switch(struct wiph
++ 		return err;
+  
 - 	/* TODO: consider doing this at MACREG_INT_CODE_LINK_SENSED time */
 - 	priv->connect_status = LBS_CONNECTED;
 ---- a/drivers/net/wireless/mwifiex/cfg80211.c
@@ -4781,105 +6460,510 @@ index a1af6c2..892f51e 100644
 -+		cfg80211_ibss_joined(usbdev->net, bssid,
 -+				     get_current_channel(usbdev, NULL),
 -+				     GFP_KERNEL);
-- 
-- 	kfree(info);
-+--- a/drivers/net/wireless/ath/ath9k/ar5008_phy.c
-++++ b/drivers/net/wireless/ath/ath9k/ar5008_phy.c
-+@@ -1004,11 +1004,9 @@ static bool ar5008_hw_ani_control_new(st
-+ 	case ATH9K_ANI_FIRSTEP_LEVEL:{
-+ 		u32 level = param;
++ 	sdata->csa_radar_required = params->radar_required;
++-
++-	if (params->block_tx)
++-		ieee80211_stop_queues_by_reason(&local->hw,
++-				IEEE80211_MAX_QUEUE_MAP,
++-				IEEE80211_QUEUE_STOP_REASON_CSA);
++-
++ 	sdata->csa_chandef = params->chandef;
+++	sdata->csa_block_tx = params->block_tx;
+++	sdata->csa_current_counter = params->count;
++ 	sdata->vif.csa_active = true;
++ 
+++	if (sdata->csa_block_tx)
+++		ieee80211_stop_queues_by_reason(&local->hw,
+++					IEEE80211_MAX_QUEUE_MAP,
+++					IEEE80211_QUEUE_STOP_REASON_CSA);
+++
++ 	if (changed) {
++ 		ieee80211_bss_info_change_notify(sdata, changed);
++ 		drv_channel_switch_beacon(sdata, &params->chandef);
++@@ -3292,6 +3374,20 @@ int ieee80211_channel_switch(struct wiph
++ 	return 0;
++ }
   
----- a/net/wireless/ibss.c
--+++ b/net/wireless/ibss.c
+- 	kfree(info);
+++int ieee80211_channel_switch(struct wiphy *wiphy, struct net_device *dev,
+++			     struct cfg80211_csa_settings *params)
+++{
+++	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+++	struct ieee80211_local *local = sdata->local;
+++	int err;
+++
+++	mutex_lock(&local->mtx);
+++	err = __ieee80211_channel_switch(wiphy, dev, params);
+++	mutex_unlock(&local->mtx);
+++
+++	return err;
+++}
+++
++ static int ieee80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev,
++ 			     struct cfg80211_mgmt_tx_params *params,
++ 			     u64 *cookie)
++@@ -3304,6 +3400,7 @@ static int ieee80211_mgmt_tx(struct wiph
++ 	bool need_offchan = false;
++ 	u32 flags;
++ 	int ret;
+++	u8 *data;
+  
+---- a/net/wireless/ibss.c
+-+++ b/net/wireless/ibss.c
 -@@ -14,7 +14,8 @@
 - #include "rdev-ops.h"
-+-		value = level * 2;
-++		value = level;
-+ 		REG_RMW_FIELD(ah, AR_PHY_FIND_SIG,
-+ 			      AR_PHY_FIND_SIG_FIRSTEP, value);
-+-		REG_RMW_FIELD(ah, AR_PHY_FIND_SIG_LOW,
-+-			      AR_PHY_FIND_SIG_FIRSTEP_LOW, value);
-  
-+ 		if (level != aniState->firstepLevel) {
-+ 			ath_dbg(common, ANI,
-+--- a/drivers/net/wireless/ath/ath9k/beacon.c
-++++ b/drivers/net/wireless/ath/ath9k/beacon.c
-+@@ -312,10 +312,9 @@ static void ath9k_csa_update_vif(void *d
++ 	if (params->dont_wait_for_ack)
++ 		flags = IEEE80211_TX_CTL_NO_ACK;
++@@ -3397,7 +3494,20 @@ static int ieee80211_mgmt_tx(struct wiph
++ 	}
++ 	skb_reserve(skb, local->hw.extra_tx_headroom);
+  
++-	memcpy(skb_put(skb, params->len), params->buf, params->len);
+++	data = skb_put(skb, params->len);
+++	memcpy(data, params->buf, params->len);
+++
+++	/* Update CSA counters */
+++	if (sdata->vif.csa_active &&
+++	    (sdata->vif.type == NL80211_IFTYPE_AP ||
+++	     sdata->vif.type == NL80211_IFTYPE_ADHOC) &&
+++	    params->n_csa_offsets) {
+++		int i;
+++		u8 c = sdata->csa_current_counter;
+++
+++		for (i = 0; i < params->n_csa_offsets; i++)
+++			data[params->csa_offsets[i]] = c;
+++	}
   
 --void __cfg80211_ibss_joined(struct net_device *dev, const u8 *bssid)
 -+void __cfg80211_ibss_joined(struct net_device *dev, const u8 *bssid,
 -+			    struct ieee80211_channel *channel)
-+ void ath9k_csa_update(struct ath_softc *sc)
-  {
+- {
 - 	struct wireless_dev *wdev = dev->ieee80211_ptr;
 - 	struct cfg80211_bss *bss;
 -@@ -28,8 +29,7 @@ void __cfg80211_ibss_joined(struct net_d
 - 	if (!wdev->ssid_len)
 - 		return;
-- 
++ 	IEEE80211_SKB_CB(skb)->flags = flags;
+  
 --	bss = cfg80211_get_bss(wdev->wiphy, NULL, bssid,
 --			       wdev->ssid, wdev->ssid_len,
 -+	bss = cfg80211_get_bss(wdev->wiphy, channel, bssid, NULL, 0,
 - 			       WLAN_CAPABILITY_IBSS, WLAN_CAPABILITY_IBSS);
-- 
++@@ -3506,320 +3616,6 @@ static int ieee80211_set_rekey_data(stru
++ 	return 0;
++ }
+  
 - 	if (WARN_ON(!bss))
 -@@ -54,21 +54,26 @@ void __cfg80211_ibss_joined(struct net_d
 - #endif
-- }
-- 
++-static void ieee80211_tdls_add_ext_capab(struct sk_buff *skb)
++-{
++-	u8 *pos = (void *)skb_put(skb, 7);
++-
++-	*pos++ = WLAN_EID_EXT_CAPABILITY;
++-	*pos++ = 5; /* len */
++-	*pos++ = 0x0;
++-	*pos++ = 0x0;
++-	*pos++ = 0x0;
++-	*pos++ = 0x0;
++-	*pos++ = WLAN_EXT_CAPA5_TDLS_ENABLED;
++-}
++-
++-static u16 ieee80211_get_tdls_sta_capab(struct ieee80211_sub_if_data *sdata)
++-{
++-	struct ieee80211_local *local = sdata->local;
++-	u16 capab;
++-
++-	capab = 0;
++-	if (ieee80211_get_sdata_band(sdata) != IEEE80211_BAND_2GHZ)
++-		return capab;
++-
++-	if (!(local->hw.flags & IEEE80211_HW_2GHZ_SHORT_SLOT_INCAPABLE))
++-		capab |= WLAN_CAPABILITY_SHORT_SLOT_TIME;
++-	if (!(local->hw.flags & IEEE80211_HW_2GHZ_SHORT_PREAMBLE_INCAPABLE))
++-		capab |= WLAN_CAPABILITY_SHORT_PREAMBLE;
++-
++-	return capab;
++-}
++-
++-static void ieee80211_tdls_add_link_ie(struct sk_buff *skb, u8 *src_addr,
++-				       u8 *peer, u8 *bssid)
++-{
++-	struct ieee80211_tdls_lnkie *lnkid;
++-
++-	lnkid = (void *)skb_put(skb, sizeof(struct ieee80211_tdls_lnkie));
++-
++-	lnkid->ie_type = WLAN_EID_LINK_ID;
++-	lnkid->ie_len = sizeof(struct ieee80211_tdls_lnkie) - 2;
++-
++-	memcpy(lnkid->bssid, bssid, ETH_ALEN);
++-	memcpy(lnkid->init_sta, src_addr, ETH_ALEN);
++-	memcpy(lnkid->resp_sta, peer, ETH_ALEN);
++-}
++-
++-static int
++-ieee80211_prep_tdls_encap_data(struct wiphy *wiphy, struct net_device *dev,
++-			       u8 *peer, u8 action_code, u8 dialog_token,
++-			       u16 status_code, struct sk_buff *skb)
++-{
++-	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
++-	enum ieee80211_band band = ieee80211_get_sdata_band(sdata);
++-	struct ieee80211_tdls_data *tf;
++-
++-	tf = (void *)skb_put(skb, offsetof(struct ieee80211_tdls_data, u));
++-
++-	memcpy(tf->da, peer, ETH_ALEN);
++-	memcpy(tf->sa, sdata->vif.addr, ETH_ALEN);
++-	tf->ether_type = cpu_to_be16(ETH_P_TDLS);
++-	tf->payload_type = WLAN_TDLS_SNAP_RFTYPE;
++-
++-	switch (action_code) {
++-	case WLAN_TDLS_SETUP_REQUEST:
++-		tf->category = WLAN_CATEGORY_TDLS;
++-		tf->action_code = WLAN_TDLS_SETUP_REQUEST;
++-
++-		skb_put(skb, sizeof(tf->u.setup_req));
++-		tf->u.setup_req.dialog_token = dialog_token;
++-		tf->u.setup_req.capability =
++-			cpu_to_le16(ieee80211_get_tdls_sta_capab(sdata));
++-
++-		ieee80211_add_srates_ie(sdata, skb, false, band);
++-		ieee80211_add_ext_srates_ie(sdata, skb, false, band);
++-		ieee80211_tdls_add_ext_capab(skb);
++-		break;
++-	case WLAN_TDLS_SETUP_RESPONSE:
++-		tf->category = WLAN_CATEGORY_TDLS;
++-		tf->action_code = WLAN_TDLS_SETUP_RESPONSE;
++-
++-		skb_put(skb, sizeof(tf->u.setup_resp));
++-		tf->u.setup_resp.status_code = cpu_to_le16(status_code);
++-		tf->u.setup_resp.dialog_token = dialog_token;
++-		tf->u.setup_resp.capability =
++-			cpu_to_le16(ieee80211_get_tdls_sta_capab(sdata));
++-
++-		ieee80211_add_srates_ie(sdata, skb, false, band);
++-		ieee80211_add_ext_srates_ie(sdata, skb, false, band);
++-		ieee80211_tdls_add_ext_capab(skb);
++-		break;
++-	case WLAN_TDLS_SETUP_CONFIRM:
++-		tf->category = WLAN_CATEGORY_TDLS;
++-		tf->action_code = WLAN_TDLS_SETUP_CONFIRM;
++-
++-		skb_put(skb, sizeof(tf->u.setup_cfm));
++-		tf->u.setup_cfm.status_code = cpu_to_le16(status_code);
++-		tf->u.setup_cfm.dialog_token = dialog_token;
++-		break;
++-	case WLAN_TDLS_TEARDOWN:
++-		tf->category = WLAN_CATEGORY_TDLS;
++-		tf->action_code = WLAN_TDLS_TEARDOWN;
++-
++-		skb_put(skb, sizeof(tf->u.teardown));
++-		tf->u.teardown.reason_code = cpu_to_le16(status_code);
++-		break;
++-	case WLAN_TDLS_DISCOVERY_REQUEST:
++-		tf->category = WLAN_CATEGORY_TDLS;
++-		tf->action_code = WLAN_TDLS_DISCOVERY_REQUEST;
++-
++-		skb_put(skb, sizeof(tf->u.discover_req));
++-		tf->u.discover_req.dialog_token = dialog_token;
++-		break;
++-	default:
++-		return -EINVAL;
++-	}
++-
++-	return 0;
++-}
++-
++-static int
++-ieee80211_prep_tdls_direct(struct wiphy *wiphy, struct net_device *dev,
++-			   u8 *peer, u8 action_code, u8 dialog_token,
++-			   u16 status_code, struct sk_buff *skb)
++-{
++-	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
++-	enum ieee80211_band band = ieee80211_get_sdata_band(sdata);
++-	struct ieee80211_mgmt *mgmt;
++-
++-	mgmt = (void *)skb_put(skb, 24);
++-	memset(mgmt, 0, 24);
++-	memcpy(mgmt->da, peer, ETH_ALEN);
++-	memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN);
++-	memcpy(mgmt->bssid, sdata->u.mgd.bssid, ETH_ALEN);
++-
++-	mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
++-					  IEEE80211_STYPE_ACTION);
++-
++-	switch (action_code) {
++-	case WLAN_PUB_ACTION_TDLS_DISCOVER_RES:
++-		skb_put(skb, 1 + sizeof(mgmt->u.action.u.tdls_discover_resp));
++-		mgmt->u.action.category = WLAN_CATEGORY_PUBLIC;
++-		mgmt->u.action.u.tdls_discover_resp.action_code =
++-			WLAN_PUB_ACTION_TDLS_DISCOVER_RES;
++-		mgmt->u.action.u.tdls_discover_resp.dialog_token =
++-			dialog_token;
++-		mgmt->u.action.u.tdls_discover_resp.capability =
++-			cpu_to_le16(ieee80211_get_tdls_sta_capab(sdata));
++-
++-		ieee80211_add_srates_ie(sdata, skb, false, band);
++-		ieee80211_add_ext_srates_ie(sdata, skb, false, band);
++-		ieee80211_tdls_add_ext_capab(skb);
++-		break;
++-	default:
++-		return -EINVAL;
++-	}
++-
++-	return 0;
++-}
++-
++-static int ieee80211_tdls_mgmt(struct wiphy *wiphy, struct net_device *dev,
++-			       u8 *peer, u8 action_code, u8 dialog_token,
++-			       u16 status_code, u32 peer_capability,
++-			       const u8 *extra_ies, size_t extra_ies_len)
++-{
++-	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
++-	struct ieee80211_local *local = sdata->local;
++-	struct sk_buff *skb = NULL;
++-	bool send_direct;
++-	int ret;
++-
++-	if (!(wiphy->flags & WIPHY_FLAG_SUPPORTS_TDLS))
++-		return -ENOTSUPP;
++-
++-	/* make sure we are in managed mode, and associated */
++-	if (sdata->vif.type != NL80211_IFTYPE_STATION ||
++-	    !sdata->u.mgd.associated)
++-		return -EINVAL;
++-
++-	tdls_dbg(sdata, "TDLS mgmt action %d peer %pM\n",
++-		 action_code, peer);
++-
++-	skb = dev_alloc_skb(local->hw.extra_tx_headroom +
++-			    max(sizeof(struct ieee80211_mgmt),
++-				sizeof(struct ieee80211_tdls_data)) +
++-			    50 + /* supported rates */
++-			    7 + /* ext capab */
++-			    extra_ies_len +
++-			    sizeof(struct ieee80211_tdls_lnkie));
++-	if (!skb)
++-		return -ENOMEM;
++-
++-	skb_reserve(skb, local->hw.extra_tx_headroom);
++-
++-	switch (action_code) {
++-	case WLAN_TDLS_SETUP_REQUEST:
++-	case WLAN_TDLS_SETUP_RESPONSE:
++-	case WLAN_TDLS_SETUP_CONFIRM:
++-	case WLAN_TDLS_TEARDOWN:
++-	case WLAN_TDLS_DISCOVERY_REQUEST:
++-		ret = ieee80211_prep_tdls_encap_data(wiphy, dev, peer,
++-						     action_code, dialog_token,
++-						     status_code, skb);
++-		send_direct = false;
++-		break;
++-	case WLAN_PUB_ACTION_TDLS_DISCOVER_RES:
++-		ret = ieee80211_prep_tdls_direct(wiphy, dev, peer, action_code,
++-						 dialog_token, status_code,
++-						 skb);
++-		send_direct = true;
++-		break;
++-	default:
++-		ret = -ENOTSUPP;
++-		break;
++-	}
++-
++-	if (ret < 0)
++-		goto fail;
++-
++-	if (extra_ies_len)
++-		memcpy(skb_put(skb, extra_ies_len), extra_ies, extra_ies_len);
++-
++-	/* the TDLS link IE is always added last */
++-	switch (action_code) {
++-	case WLAN_TDLS_SETUP_REQUEST:
++-	case WLAN_TDLS_SETUP_CONFIRM:
++-	case WLAN_TDLS_TEARDOWN:
++-	case WLAN_TDLS_DISCOVERY_REQUEST:
++-		/* we are the initiator */
++-		ieee80211_tdls_add_link_ie(skb, sdata->vif.addr, peer,
++-					   sdata->u.mgd.bssid);
++-		break;
++-	case WLAN_TDLS_SETUP_RESPONSE:
++-	case WLAN_PUB_ACTION_TDLS_DISCOVER_RES:
++-		/* we are the responder */
++-		ieee80211_tdls_add_link_ie(skb, peer, sdata->vif.addr,
++-					   sdata->u.mgd.bssid);
++-		break;
++-	default:
++-		ret = -ENOTSUPP;
++-		goto fail;
++-	}
++-
++-	if (send_direct) {
++-		ieee80211_tx_skb(sdata, skb);
++-		return 0;
++-	}
++-
++-	/*
++-	 * According to 802.11z: Setup req/resp are sent in AC_BK, otherwise
++-	 * we should default to AC_VI.
++-	 */
++-	switch (action_code) {
++-	case WLAN_TDLS_SETUP_REQUEST:
++-	case WLAN_TDLS_SETUP_RESPONSE:
++-		skb_set_queue_mapping(skb, IEEE80211_AC_BK);
++-		skb->priority = 2;
++-		break;
++-	default:
++-		skb_set_queue_mapping(skb, IEEE80211_AC_VI);
++-		skb->priority = 5;
++-		break;
++-	}
++-
++-	/* disable bottom halves when entering the Tx path */
++-	local_bh_disable();
++-	ret = ieee80211_subif_start_xmit(skb, dev);
++-	local_bh_enable();
++-
++-	return ret;
++-
++-fail:
++-	dev_kfree_skb(skb);
++-	return ret;
++-}
++-
++-static int ieee80211_tdls_oper(struct wiphy *wiphy, struct net_device *dev,
++-			       u8 *peer, enum nl80211_tdls_operation oper)
++-{
++-	struct sta_info *sta;
++-	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
++-
++-	if (!(wiphy->flags & WIPHY_FLAG_SUPPORTS_TDLS))
++-		return -ENOTSUPP;
++-
++-	if (sdata->vif.type != NL80211_IFTYPE_STATION)
++-		return -EINVAL;
++-
++-	tdls_dbg(sdata, "TDLS oper %d peer %pM\n", oper, peer);
++-
++-	switch (oper) {
++-	case NL80211_TDLS_ENABLE_LINK:
++-		rcu_read_lock();
++-		sta = sta_info_get(sdata, peer);
++-		if (!sta) {
++-			rcu_read_unlock();
++-			return -ENOLINK;
++-		}
++-
++-		set_sta_flag(sta, WLAN_STA_TDLS_PEER_AUTH);
++-		rcu_read_unlock();
++-		break;
++-	case NL80211_TDLS_DISABLE_LINK:
++-		return sta_info_destroy_addr(sdata, peer);
++-	case NL80211_TDLS_TEARDOWN:
++-	case NL80211_TDLS_SETUP:
++-	case NL80211_TDLS_DISCOVERY_REQ:
++-		/* We don't support in-driver setup/teardown/discovery */
++-		return -ENOTSUPP;
++-	default:
++-		return -ENOTSUPP;
++-	}
++-
++-	return 0;
++-}
++-
++ static int ieee80211_probe_client(struct wiphy *wiphy, struct net_device *dev,
++ 				  const u8 *peer, u64 *cookie)
++ {
++--- a/net/mac80211/chan.c
+++++ b/net/mac80211/chan.c
++@@ -855,7 +855,7 @@ static void
++ __ieee80211_vif_copy_chanctx_to_vlans(struct ieee80211_sub_if_data *sdata,
++ 				      bool clear)
++ {
++-	struct ieee80211_local *local = sdata->local;
+++	struct ieee80211_local *local __maybe_unused = sdata->local;
++ 	struct ieee80211_sub_if_data *vlan;
++ 	struct ieee80211_chanctx_conf *conf;
++ 
++@@ -871,7 +871,7 @@ __ieee80211_vif_copy_chanctx_to_vlans(st
++ 	 * to a channel context that has already been freed.
++ 	 */
++ 	conf = rcu_dereference_protected(sdata->vif.chanctx_conf,
++-				lockdep_is_held(&local->chanctx_mtx));
+++					 lockdep_is_held(&local->chanctx_mtx));
++ 	WARN_ON(!conf);
++ 
++ 	if (clear)
++--- a/net/mac80211/driver-ops.h
+++++ b/net/mac80211/driver-ops.h
++@@ -5,11 +5,11 @@
++ #include "ieee80211_i.h"
++ #include "trace.h"
++ 
++-static inline void check_sdata_in_driver(struct ieee80211_sub_if_data *sdata)
+++static inline bool check_sdata_in_driver(struct ieee80211_sub_if_data *sdata)
++ {
++-	WARN(!(sdata->flags & IEEE80211_SDATA_IN_DRIVER),
++-	     "%s:  Failed check-sdata-in-driver check, flags: 0x%x\n",
++-	     sdata->dev ? sdata->dev->name : sdata->name, sdata->flags);
+++	return !WARN(!(sdata->flags & IEEE80211_SDATA_IN_DRIVER),
+++		     "%s:  Failed check-sdata-in-driver check, flags: 0x%x\n",
+++		     sdata->dev ? sdata->dev->name : sdata->name, sdata->flags);
+  }
+  
 --void cfg80211_ibss_joined(struct net_device *dev, const u8 *bssid, gfp_t gfp)
 -+void cfg80211_ibss_joined(struct net_device *dev, const u8 *bssid,
 -+			  struct ieee80211_channel *channel, gfp_t gfp)
-+-	ieee80211_iterate_active_interfaces(sc->hw,
-+-					    IEEE80211_IFACE_ITER_NORMAL,
-+-					    ath9k_csa_update_vif,
-+-					    sc);
-++	ieee80211_iterate_active_interfaces_atomic(sc->hw,
-++						   IEEE80211_IFACE_ITER_NORMAL,
-++						   ath9k_csa_update_vif, sc);
-+ }
++ static inline struct ieee80211_sub_if_data *
++@@ -168,7 +168,8 @@ static inline int drv_change_interface(s
 + 
-+ void ath9k_beacon_tasklet(unsigned long data)
-+--- a/net/mac80211/main.c
-++++ b/net/mac80211/main.c
-+@@ -152,6 +152,8 @@ static u32 ieee80211_hw_conf_chan(struct
-+ 	list_for_each_entry_rcu(sdata, &local->interfaces, list) {
-+ 		if (!rcu_access_pointer(sdata->vif.chanctx_conf))
-+ 			continue;
-++		if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
-++			continue;
-+ 		power = min(power, sdata->vif.bss_conf.txpower);
-+ 	}
-+ 	rcu_read_unlock();
-+@@ -203,7 +205,7 @@ void ieee80211_bss_info_change_notify(st
++ 	might_sleep();
++ 
++-	check_sdata_in_driver(sdata);
+++	if (!check_sdata_in_driver(sdata))
+++		return -EIO;
++ 
++ 	trace_drv_change_interface(local, sdata, type, p2p);
++ 	ret = local->ops->change_interface(&local->hw, &sdata->vif, type, p2p);
++@@ -181,7 +182,8 @@ static inline void drv_remove_interface(
   {
 - 	struct wireless_dev *wdev = dev->ieee80211_ptr;
 - 	struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
 - 	struct cfg80211_event *ev;
 - 	unsigned long flags;
-- 
++ 	might_sleep();
+  
 --	trace_cfg80211_ibss_joined(dev, bssid);
 -+	trace_cfg80211_ibss_joined(dev, bssid, channel);
 -+
 -+	if (WARN_ON(!channel))
--+		return;
-+ 	struct ieee80211_local *local = sdata->local;
++-	check_sdata_in_driver(sdata);
+++	if (!check_sdata_in_driver(sdata))
+ +		return;
   
 - 	ev = kzalloc(sizeof(*ev), gfp);
 - 	if (!ev)
-+-	if (!changed)
-++	if (!changed || sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
++ 	trace_drv_remove_interface(local, sdata);
++ 	local->ops->remove_interface(&local->hw, &sdata->vif);
++@@ -219,7 +221,8 @@ static inline void drv_bss_info_changed(
++ 			 sdata->vif.type == NL80211_IFTYPE_MONITOR))
   		return;
   
 - 	ev->type = EVENT_IBSS_JOINED;
 --	memcpy(ev->cr.bssid, bssid, ETH_ALEN);
 -+	memcpy(ev->ij.bssid, bssid, ETH_ALEN);
 -+	ev->ij.channel = channel;
-- 
++-	check_sdata_in_driver(sdata);
+++	if (!check_sdata_in_driver(sdata))
+++		return;
+  
 - 	spin_lock_irqsave(&wdev->event_lock, flags);
 - 	list_add_tail(&ev->list, &wdev->event_list);
 -@@ -117,6 +122,7 @@ int __cfg80211_join_ibss(struct cfg80211
-- 
++ 	trace_drv_bss_info_changed(local, sdata, info, changed);
++ 	if (local->ops->bss_info_changed)
++@@ -278,7 +281,8 @@ static inline int drv_set_key(struct iee
++ 	might_sleep();
+  
 - 	wdev->ibss_fixed = params->channel_fixed;
 - 	wdev->ibss_dfs_possible = params->userspace_handles_dfs;
 -+	wdev->chandef = params->chandef;
@@ -4887,7 +6971,11 @@ index a1af6c2..892f51e 100644
 - 	wdev->wext.ibss.chandef = params->chandef;
 - #endif
 -@@ -200,6 +206,7 @@ static void __cfg80211_clear_ibss(struct
-- 
++ 	sdata = get_bss_sdata(sdata);
++-	check_sdata_in_driver(sdata);
+++	if (!check_sdata_in_driver(sdata))
+++		return -EIO;
+  
 - 	wdev->current_bss = NULL;
 - 	wdev->ssid_len = 0;
 -+	memset(&wdev->chandef, 0, sizeof(wdev->chandef));
@@ -4899,7 +6987,11 @@ index a1af6c2..892f51e 100644
 -@@ -2278,11 +2278,6 @@ DECLARE_EVENT_CLASS(cfg80211_rx_evt,
 - 	TP_printk(NETDEV_PR_FMT ", " MAC_PR_FMT, NETDEV_PR_ARG, MAC_PR_ARG(addr))
 - );
-- 
++ 	trace_drv_set_key(local, cmd, sdata, sta, key);
++ 	ret = local->ops->set_key(&local->hw, cmd, &sdata->vif, sta, key);
++@@ -298,7 +302,8 @@ static inline void drv_update_tkip_key(s
++ 		ista = &sta->sta;
+  
 --DEFINE_EVENT(cfg80211_rx_evt, cfg80211_ibss_joined,
 --	TP_PROTO(struct net_device *netdev, const u8 *addr),
 --	TP_ARGS(netdev, addr)
@@ -4911,7 +7003,11 @@ index a1af6c2..892f51e 100644
 -@@ -2293,6 +2288,24 @@ DEFINE_EVENT(cfg80211_rx_evt, cfg80211_r
 - 	TP_ARGS(netdev, addr)
 - );
-- 
++ 	sdata = get_bss_sdata(sdata);
++-	check_sdata_in_driver(sdata);
+++	if (!check_sdata_in_driver(sdata))
+++		return;
+  
 -+TRACE_EVENT(cfg80211_ibss_joined,
 -+	TP_PROTO(struct net_device *netdev, const u8 *bssid,
 -+		 struct ieee80211_channel *channel),
@@ -4929,7 +7025,216 @@ index a1af6c2..892f51e 100644
 -+	TP_printk(NETDEV_PR_FMT ", bssid: " MAC_PR_FMT ", " CHAN_PR_FMT,
 -+		  NETDEV_PR_ARG, MAC_PR_ARG(bssid), CHAN_PR_ARG)
 -+);
--+
++ 	trace_drv_update_tkip_key(local, sdata, conf, ista, iv32);
++ 	if (local->ops->update_tkip_key)
++@@ -315,7 +320,8 @@ static inline int drv_hw_scan(struct iee
++ 
++ 	might_sleep();
++ 
++-	check_sdata_in_driver(sdata);
+++	if (!check_sdata_in_driver(sdata))
+++		return -EIO;
++ 
++ 	trace_drv_hw_scan(local, sdata);
++ 	ret = local->ops->hw_scan(&local->hw, &sdata->vif, req);
++@@ -328,7 +334,8 @@ static inline void drv_cancel_hw_scan(st
++ {
++ 	might_sleep();
++ 
++-	check_sdata_in_driver(sdata);
+++	if (!check_sdata_in_driver(sdata))
+++		return;
++ 
++ 	trace_drv_cancel_hw_scan(local, sdata);
++ 	local->ops->cancel_hw_scan(&local->hw, &sdata->vif);
++@@ -345,7 +352,8 @@ drv_sched_scan_start(struct ieee80211_lo
++ 
++ 	might_sleep();
++ 
++-	check_sdata_in_driver(sdata);
+++	if (!check_sdata_in_driver(sdata))
+++		return -EIO;
++ 
++ 	trace_drv_sched_scan_start(local, sdata);
++ 	ret = local->ops->sched_scan_start(&local->hw, &sdata->vif,
++@@ -361,7 +369,8 @@ static inline int drv_sched_scan_stop(st
++ 
++ 	might_sleep();
++ 
++-	check_sdata_in_driver(sdata);
+++	if (!check_sdata_in_driver(sdata))
+++		return -EIO;
++ 
++ 	trace_drv_sched_scan_stop(local, sdata);
++ 	ret = local->ops->sched_scan_stop(&local->hw, &sdata->vif);
++@@ -462,7 +471,8 @@ static inline void drv_sta_notify(struct
++ 				  struct ieee80211_sta *sta)
++ {
++ 	sdata = get_bss_sdata(sdata);
++-	check_sdata_in_driver(sdata);
+++	if (!check_sdata_in_driver(sdata))
+++		return;
++ 
++ 	trace_drv_sta_notify(local, sdata, cmd, sta);
++ 	if (local->ops->sta_notify)
++@@ -479,7 +489,8 @@ static inline int drv_sta_add(struct iee
++ 	might_sleep();
++ 
++ 	sdata = get_bss_sdata(sdata);
++-	check_sdata_in_driver(sdata);
+++	if (!check_sdata_in_driver(sdata))
+++		return -EIO;
++ 
++ 	trace_drv_sta_add(local, sdata, sta);
++ 	if (local->ops->sta_add)
++@@ -497,7 +508,8 @@ static inline void drv_sta_remove(struct
++ 	might_sleep();
++ 
++ 	sdata = get_bss_sdata(sdata);
++-	check_sdata_in_driver(sdata);
+++	if (!check_sdata_in_driver(sdata))
+++		return;
++ 
++ 	trace_drv_sta_remove(local, sdata, sta);
++ 	if (local->ops->sta_remove)
++@@ -515,7 +527,8 @@ static inline void drv_sta_add_debugfs(s
++ 	might_sleep();
++ 
++ 	sdata = get_bss_sdata(sdata);
++-	check_sdata_in_driver(sdata);
+++	if (!check_sdata_in_driver(sdata))
+++		return;
++ 
++ 	if (local->ops->sta_add_debugfs)
++ 		local->ops->sta_add_debugfs(&local->hw, &sdata->vif,
++@@ -545,7 +558,8 @@ static inline void drv_sta_pre_rcu_remov
++ 	might_sleep();
++ 
++ 	sdata = get_bss_sdata(sdata);
++-	check_sdata_in_driver(sdata);
+++	if (!check_sdata_in_driver(sdata))
+++		return;
++ 
++ 	trace_drv_sta_pre_rcu_remove(local, sdata, &sta->sta);
++ 	if (local->ops->sta_pre_rcu_remove)
++@@ -566,7 +580,8 @@ int drv_sta_state(struct ieee80211_local
++ 	might_sleep();
++ 
++ 	sdata = get_bss_sdata(sdata);
++-	check_sdata_in_driver(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) {
++@@ -590,7 +605,8 @@ static inline void drv_sta_rc_update(str
++ 				     struct ieee80211_sta *sta, u32 changed)
++ {
++ 	sdata = get_bss_sdata(sdata);
++-	check_sdata_in_driver(sdata);
+++	if (!check_sdata_in_driver(sdata))
+++		return;
++ 
++ 	WARN_ON(changed & IEEE80211_RC_SUPP_RATES_CHANGED &&
++ 		(sdata->vif.type != NL80211_IFTYPE_ADHOC &&
++@@ -612,7 +628,8 @@ static inline int drv_conf_tx(struct iee
++ 
++ 	might_sleep();
++ 
++-	check_sdata_in_driver(sdata);
+++	if (!check_sdata_in_driver(sdata))
+++		return -EIO;
++ 
++ 	trace_drv_conf_tx(local, sdata, ac, params);
++ 	if (local->ops->conf_tx)
++@@ -629,7 +646,8 @@ static inline u64 drv_get_tsf(struct iee
++ 
++ 	might_sleep();
++ 
++-	check_sdata_in_driver(sdata);
+++	if (!check_sdata_in_driver(sdata))
+++		return ret;
++ 
++ 	trace_drv_get_tsf(local, sdata);
++ 	if (local->ops->get_tsf)
++@@ -644,7 +662,8 @@ static inline void drv_set_tsf(struct ie
++ {
++ 	might_sleep();
++ 
++-	check_sdata_in_driver(sdata);
+++	if (!check_sdata_in_driver(sdata))
+++		return;
++ 
++ 	trace_drv_set_tsf(local, sdata, tsf);
++ 	if (local->ops->set_tsf)
++@@ -657,7 +676,8 @@ static inline void drv_reset_tsf(struct 
++ {
++ 	might_sleep();
++ 
++-	check_sdata_in_driver(sdata);
+++	if (!check_sdata_in_driver(sdata))
+++		return;
++ 
++ 	trace_drv_reset_tsf(local, sdata);
++ 	if (local->ops->reset_tsf)
++@@ -689,7 +709,8 @@ static inline int drv_ampdu_action(struc
++ 	might_sleep();
++ 
++ 	sdata = get_bss_sdata(sdata);
++-	check_sdata_in_driver(sdata);
+++	if (!check_sdata_in_driver(sdata))
+++		return -EIO;
++ 
++ 	trace_drv_ampdu_action(local, sdata, action, sta, tid, ssn, buf_size);
++ 
++@@ -733,8 +754,8 @@ static inline void drv_flush(struct ieee
++ 
++ 	might_sleep();
++ 
++-	if (sdata)
++-		check_sdata_in_driver(sdata);
+++	if (sdata && !check_sdata_in_driver(sdata))
+++		return;
++ 
++ 	trace_drv_flush(local, queues, drop);
++ 	if (local->ops->flush)
++@@ -854,7 +875,8 @@ static inline int drv_set_bitrate_mask(s
++ 
++ 	might_sleep();
++ 
++-	check_sdata_in_driver(sdata);
+++	if (!check_sdata_in_driver(sdata))
+++		return -EIO;
++ 
++ 	trace_drv_set_bitrate_mask(local, sdata, mask);
++ 	if (local->ops->set_bitrate_mask)
++@@ -869,7 +891,8 @@ static inline void drv_set_rekey_data(st
++ 				      struct ieee80211_sub_if_data *sdata,
++ 				      struct cfg80211_gtk_rekey_data *data)
++ {
++-	check_sdata_in_driver(sdata);
+++	if (!check_sdata_in_driver(sdata))
+++		return;
++ 
++ 	trace_drv_set_rekey_data(local, sdata, data);
++ 	if (local->ops->set_rekey_data)
++@@ -937,7 +960,8 @@ static inline void drv_mgd_prepare_tx(st
++ {
++ 	might_sleep();
++ 
++-	check_sdata_in_driver(sdata);
+++	if (!check_sdata_in_driver(sdata))
+++		return;
++ 	WARN_ON_ONCE(sdata->vif.type != NL80211_IFTYPE_STATION);
++ 
++ 	trace_drv_mgd_prepare_tx(local, sdata);
++@@ -964,6 +988,9 @@ static inline int drv_add_chanctx(struct
++ static inline void drv_remove_chanctx(struct ieee80211_local *local,
++ 				      struct ieee80211_chanctx *ctx)
++ {
+++	if (WARN_ON(!ctx->driver_present))
+++		return;
+ +
 - TRACE_EVENT(cfg80211_probe_status,
 - 	TP_PROTO(struct net_device *netdev, const u8 *addr, u64 cookie,
 - 		 bool acked),
@@ -4952,13 +7257,7 @@ index a1af6c2..892f51e 100644
 --		cfg80211_get_chan_state(wdev_iter, &ch, &chmode);
 -+		cfg80211_get_chan_state(wdev_iter, &ch, &chmode, &radar_detect);
 - 		wdev_unlock(wdev_iter);
-+ 	drv_bss_info_changed(local, sdata, &sdata->vif.bss_conf, changed);
-+--- a/drivers/net/wireless/ath/ath9k/ani.c
-++++ b/drivers/net/wireless/ath/ath9k/ani.c
-+@@ -155,6 +155,9 @@ static void ath9k_hw_set_ofdm_nil(struct
-+ 		ATH9K_ANI_RSSI_THR_LOW,
-+ 		ATH9K_ANI_RSSI_THR_HIGH);
-  
+- 
 - 		switch (chmode) {
 ---- a/net/wireless/chan.c
 -+++ b/net/wireless/chan.c
@@ -4969,7 +7268,11 @@ index a1af6c2..892f51e 100644
 --		        enum cfg80211_chan_mode *chanmode)
 -+		        enum cfg80211_chan_mode *chanmode,
 -+		        u8 *radar_detect)
-- {
++ 	trace_drv_remove_chanctx(local, ctx);
++ 	if (local->ops->remove_chanctx)
++ 		local->ops->remove_chanctx(&local->hw, &ctx->conf);
++@@ -989,7 +1016,8 @@ static inline int drv_assign_vif_chanctx
+  {
 - 	*chan = NULL;
 - 	*chanmode = CHAN_MODE_UNDEFINED;
 -@@ -660,6 +661,11 @@ cfg80211_get_chan_state(struct wireless_
@@ -5007,9 +7310,7 @@ index a1af6c2..892f51e 100644
 --			*chan = wdev->channel;
 -+			*chan = wdev->chandef.chan;
 - 			*chanmode = CHAN_MODE_SHARED;
-++	if (AR_SREV_9100(ah) && immunityLevel < ATH9K_ANI_OFDM_DEF_LEVEL)
-++		immunityLevel = ATH9K_ANI_OFDM_DEF_LEVEL;
- +
+-+
 -+			if (cfg80211_chandef_dfs_required(wdev->wiphy,
 -+							  &wdev->chandef))
 -+				*radar_detect |= BIT(wdev->chandef.width);
@@ -5024,8 +7325,85 @@ index a1af6c2..892f51e 100644
 - 		wdev->mesh_id_len = setup->mesh_id_len;
 --		wdev->channel = setup->chandef.chan;
 -+		wdev->chandef = setup->chandef;
-- 	}
-- 
++ 	int ret = 0;
++ 
++-	check_sdata_in_driver(sdata);
+++	if (!check_sdata_in_driver(sdata))
+++		return -EIO;
++ 
++ 	trace_drv_assign_vif_chanctx(local, sdata, ctx);
++ 	if (local->ops->assign_vif_chanctx) {
++@@ -1007,7 +1035,8 @@ static inline void drv_unassign_vif_chan
++ 					    struct ieee80211_sub_if_data *sdata,
++ 					    struct ieee80211_chanctx *ctx)
++ {
++-	check_sdata_in_driver(sdata);
+++	if (!check_sdata_in_driver(sdata))
+++		return;
++ 
++ 	trace_drv_unassign_vif_chanctx(local, sdata, ctx);
++ 	if (local->ops->unassign_vif_chanctx) {
++@@ -1024,7 +1053,8 @@ static inline int drv_start_ap(struct ie
++ {
++ 	int ret = 0;
++ 
++-	check_sdata_in_driver(sdata);
+++	if (!check_sdata_in_driver(sdata))
+++		return -EIO;
++ 
++ 	trace_drv_start_ap(local, sdata, &sdata->vif.bss_conf);
++ 	if (local->ops->start_ap)
++@@ -1036,7 +1066,8 @@ static inline int drv_start_ap(struct ie
++ static inline void drv_stop_ap(struct ieee80211_local *local,
++ 			       struct ieee80211_sub_if_data *sdata)
++ {
++-	check_sdata_in_driver(sdata);
+++	if (!check_sdata_in_driver(sdata))
+++		return;
++ 
++ 	trace_drv_stop_ap(local, sdata);
++ 	if (local->ops->stop_ap)
++@@ -1059,7 +1090,8 @@ drv_set_default_unicast_key(struct ieee8
++ 			    struct ieee80211_sub_if_data *sdata,
++ 			    int key_idx)
++ {
++-	check_sdata_in_driver(sdata);
+++	if (!check_sdata_in_driver(sdata))
+++		return;
++ 
++ 	WARN_ON_ONCE(key_idx < -1 || key_idx > 3);
++ 
++@@ -1101,7 +1133,8 @@ static inline int drv_join_ibss(struct i
++ 	int ret = 0;
++ 
++ 	might_sleep();
++-	check_sdata_in_driver(sdata);
+++	if (!check_sdata_in_driver(sdata))
+++		return -EIO;
++ 
++ 	trace_drv_join_ibss(local, sdata, &sdata->vif.bss_conf);
++ 	if (local->ops->join_ibss)
++@@ -1114,7 +1147,8 @@ static inline void drv_leave_ibss(struct
++ 				  struct ieee80211_sub_if_data *sdata)
++ {
++ 	might_sleep();
++-	check_sdata_in_driver(sdata);
+++	if (!check_sdata_in_driver(sdata))
+++		return;
++ 
++ 	trace_drv_leave_ibss(local, sdata);
++ 	if (local->ops->leave_ibss)
++--- a/net/mac80211/ibss.c
+++++ b/net/mac80211/ibss.c
++@@ -143,7 +143,7 @@ ieee80211_ibss_build_presp(struct ieee80
++ 		*pos++ = csa_settings->block_tx ? 1 : 0;
++ 		*pos++ = ieee80211_frequency_to_channel(
++ 				csa_settings->chandef.chan->center_freq);
++-		sdata->csa_counter_offset_beacon = (pos - presp->head);
+++		sdata->csa_counter_offset_beacon[0] = (pos - presp->head);
++ 		*pos++ = csa_settings->count;
+  	}
+  
 - 	return err;
 -@@ -244,7 +244,7 @@ int cfg80211_set_mesh_channel(struct cfg
 - 		err = rdev_libertas_set_mesh_channel(rdev, wdev->netdev,
@@ -5033,8 +7411,138 @@ index a1af6c2..892f51e 100644
 - 		if (!err)
 --			wdev->channel = chandef->chan;
 -+			wdev->chandef = *chandef;
-+ 	if (!scan)
-+ 		aniState->ofdmNoiseImmunityLevel = immunityLevel;
++--- a/net/mac80211/ieee80211_i.h
+++++ b/net/mac80211/ieee80211_i.h
++@@ -754,9 +754,10 @@ struct ieee80211_sub_if_data {
++ 	struct mac80211_qos_map __rcu *qos_map;
++ 
++ 	struct work_struct csa_finalize_work;
++-	int csa_counter_offset_beacon;
++-	int csa_counter_offset_presp;
+++	u16 csa_counter_offset_beacon[IEEE80211_MAX_CSA_COUNTERS_NUM];
+++	u16 csa_counter_offset_presp[IEEE80211_MAX_CSA_COUNTERS_NUM];
++ 	bool csa_radar_required;
+++	bool csa_block_tx; /* write-protected by sdata_lock and local->mtx */
++ 	struct cfg80211_chan_def csa_chandef;
++ 
++ 	struct list_head assigned_chanctx_list; /* protected by chanctx_mtx */
++@@ -766,6 +767,7 @@ struct ieee80211_sub_if_data {
++ 	struct ieee80211_chanctx *reserved_chanctx;
++ 	struct cfg80211_chan_def reserved_chandef;
++ 	bool reserved_radar_required;
+++	u8 csa_current_counter;
++ 
++ 	/* used to reconfigure hardware SM PS */
++ 	struct work_struct recalc_smps;
++@@ -1462,6 +1464,7 @@ __ieee80211_request_sched_scan_start(str
++ int ieee80211_request_sched_scan_start(struct ieee80211_sub_if_data *sdata,
++ 				       struct cfg80211_sched_scan_request *req);
++ int ieee80211_request_sched_scan_stop(struct ieee80211_sub_if_data *sdata);
+++void ieee80211_sched_scan_end(struct ieee80211_local *local);
++ void ieee80211_sched_scan_stopped_work(struct work_struct *work);
++ 
++ /* off-channel helpers */
++@@ -1476,6 +1479,7 @@ void ieee80211_sw_roc_work(struct work_s
++ void ieee80211_handle_roc_started(struct ieee80211_roc_work *roc);
++ 
++ /* channel switch handling */
+++bool ieee80211_csa_needs_block_tx(struct ieee80211_local *local);
++ void ieee80211_csa_finalize_work(struct work_struct *work);
++ int ieee80211_channel_switch(struct wiphy *wiphy, struct net_device *dev,
++ 			     struct cfg80211_csa_settings *params);
++@@ -1837,6 +1841,15 @@ int ieee80211_check_combinations(struct 
++ 				 u8 radar_detect);
++ int ieee80211_max_num_channels(struct ieee80211_local *local);
++ 
+++/* TDLS */
+++int ieee80211_tdls_mgmt(struct wiphy *wiphy, struct net_device *dev,
+++			const u8 *peer, u8 action_code, u8 dialog_token,
+++			u16 status_code, u32 peer_capability,
+++			const u8 *extra_ies, size_t extra_ies_len);
+++int ieee80211_tdls_oper(struct wiphy *wiphy, struct net_device *dev,
+++			const u8 *peer, enum nl80211_tdls_operation oper);
+++
+++
++ #ifdef CPTCFG_MAC80211_NOINLINE
++ #define debug_noinline noinline
++ #else
++--- a/net/mac80211/iface.c
+++++ b/net/mac80211/iface.c
++@@ -838,8 +838,15 @@ static void ieee80211_do_stop(struct iee
++ 
++ 	cancel_work_sync(&sdata->recalc_smps);
++ 	sdata_lock(sdata);
+++	mutex_lock(&local->mtx);
++ 	sdata->vif.csa_active = false;
+++	if (!ieee80211_csa_needs_block_tx(local))
+++		ieee80211_wake_queues_by_reason(&local->hw,
+++					IEEE80211_MAX_QUEUE_MAP,
+++					IEEE80211_QUEUE_STOP_REASON_CSA);
+++	mutex_unlock(&local->mtx);
++ 	sdata_unlock(sdata);
+++
++ 	cancel_work_sync(&sdata->csa_finalize_work);
++ 
++ 	cancel_delayed_work_sync(&sdata->dfs_cac_timer_work);
++--- a/net/mac80211/key.c
+++++ b/net/mac80211/key.c
++@@ -325,7 +325,8 @@ ieee80211_key_alloc(u32 cipher, int idx,
++ 	struct ieee80211_key *key;
++ 	int i, j, err;
++ 
++-	BUG_ON(idx < 0 || idx >= NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS);
+++	if (WARN_ON(idx < 0 || idx >= NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS))
+++		return ERR_PTR(-EINVAL);
++ 
++ 	key = kzalloc(sizeof(struct ieee80211_key) + key_len, GFP_KERNEL);
++ 	if (!key)
++@@ -481,8 +482,8 @@ int ieee80211_key_link(struct ieee80211_
++ 	int idx, ret;
++ 	bool pairwise;
++ 
++-	BUG_ON(!sdata);
++-	BUG_ON(!key);
+++	if (WARN_ON(!sdata || !key))
+++		return -EINVAL;
++ 
++ 	pairwise = key->conf.flags & IEEE80211_KEY_FLAG_PAIRWISE;
++ 	idx = key->conf.keyidx;
++--- a/net/mac80211/main.c
+++++ b/net/mac80211/main.c
++@@ -956,6 +956,8 @@ int ieee80211_register_hw(struct ieee802
++ 	if (local->hw.wiphy->flags & WIPHY_FLAG_SUPPORTS_TDLS)
++ 		local->hw.wiphy->flags |= WIPHY_FLAG_TDLS_EXTERNAL_SETUP;
++ 
+++	local->hw.wiphy->max_num_csa_counters = IEEE80211_MAX_CSA_COUNTERS_NUM;
+++
++ 	result = wiphy_register(local->hw.wiphy);
++ 	if (result < 0)
++ 		goto fail_wiphy_register;
++--- a/net/mac80211/mesh.c
+++++ b/net/mac80211/mesh.c
++@@ -679,7 +679,7 @@ ieee80211_mesh_build_beacon(struct ieee8
++ 		*pos++ = 0x0;
++ 		*pos++ = ieee80211_frequency_to_channel(
++ 				csa->settings.chandef.chan->center_freq);
++-		sdata->csa_counter_offset_beacon = hdr_len + 6;
+++		sdata->csa_counter_offset_beacon[0] = hdr_len + 6;
++ 		*pos++ = csa->settings.count;
++ 		*pos++ = WLAN_EID_CHAN_SWITCH_PARAM;
++ 		*pos++ = 6;
++--- a/net/mac80211/mesh_pathtbl.c
+++++ b/net/mac80211/mesh_pathtbl.c
++@@ -287,8 +287,10 @@ static void mesh_path_move_to_queue(stru
++ 	struct sk_buff_head failq;
++ 	unsigned long flags;
++ 
++-	BUG_ON(gate_mpath == from_mpath);
++-	BUG_ON(!gate_mpath->next_hop);
+++	if (WARN_ON(gate_mpath == from_mpath))
+++		return;
+++	if (WARN_ON(!gate_mpath->next_hop))
+++		return;
++ 
++ 	__skb_queue_head_init(&failq);
   
 - 		return err;
 - 	}
@@ -5046,20 +7554,31 @@ index a1af6c2..892f51e 100644
 -+		memset(&wdev->chandef, 0, sizeof(wdev->chandef));
 - 		rdev_set_qos_map(rdev, dev, NULL);
 - 	}
-- 
++--- a/net/mac80211/mesh_sync.c
+++++ b/net/mac80211/mesh_sync.c
++@@ -171,7 +171,7 @@ static void mesh_sync_offset_adjust_tbtt
++ 	u8 cap;
+  
 ---- a/net/wireless/mlme.c
 -+++ b/net/wireless/mlme.c
 -@@ -772,7 +772,7 @@ void cfg80211_cac_event(struct net_devic
 - 	if (WARN_ON(!wdev->cac_started))
 - 		return;
-+@@ -235,6 +238,9 @@ static void ath9k_hw_set_cck_nil(struct 
-+ 		BEACON_RSSI(ah), ATH9K_ANI_RSSI_THR_LOW,
-+ 		ATH9K_ANI_RSSI_THR_HIGH);
++ 	WARN_ON(ifmsh->mesh_sp_id != IEEE80211_SYNC_METHOD_NEIGHBOR_OFFSET);
++-	BUG_ON(!rcu_read_lock_held());
+++	WARN_ON(!rcu_read_lock_held());
++ 	cap = beacon->meshconf->meshconf_cap;
   
 --	if (WARN_ON(!wdev->channel))
 -+	if (WARN_ON(!wdev->chandef.chan))
 - 		return;
-- 
++ 	spin_lock_bh(&ifmsh->sync_offset_lock);
++--- a/net/mac80211/mlme.c
+++++ b/net/mac80211/mlme.c
++@@ -975,16 +975,23 @@ static void ieee80211_chswitch_work(stru
++ 	/* XXX: shouldn't really modify cfg80211-owned data! */
++ 	ifmgd->associated->channel = sdata->csa_chandef.chan;
+  
 - 	switch (event) {
 ---- a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c
 -+++ b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c
@@ -5067,15 +7586,34 @@ index a1af6c2..892f51e 100644
 - 			break;
 - 		}
 - 	}
-++	if (AR_SREV_9100(ah) && immunityLevel < ATH9K_ANI_CCK_DEF_LEVEL)
-++		immunityLevel = ATH9K_ANI_CCK_DEF_LEVEL;
+++	ieee80211_bss_info_change_notify(sdata, changed);
  +
 -+	if (is2GHz && !twiceMaxEdgePower)
 -+		twiceMaxEdgePower = 60;
--+
+++	mutex_lock(&local->mtx);
+++	sdata->vif.csa_active = false;
++ 	/* XXX: wait for a beacon first? */
++-	ieee80211_wake_queues_by_reason(&local->hw,
+++	if (!ieee80211_csa_needs_block_tx(local))
+++		ieee80211_wake_queues_by_reason(&local->hw,
++ 					IEEE80211_MAX_QUEUE_MAP,
++ 					IEEE80211_QUEUE_STOP_REASON_CSA);
+++	mutex_unlock(&local->mtx);
++ 
++-	ieee80211_bss_info_change_notify(sdata, changed);
++-
++- out:
++-	sdata->vif.csa_active = false;
++ 	ifmgd->flags &= ~IEEE80211_STA_CSA_RECEIVED;
+++
+++	ieee80211_sta_reset_beacon_monitor(sdata);
+++	ieee80211_sta_reset_conn_monitor(sdata);
+ +
 - 	return twiceMaxEdgePower;
-- }
-- 
+++out:
++ 	sdata_unlock(sdata);
+  }
+  
 ---- a/drivers/net/wireless/ath/ath9k/ar9003_calib.c
 -+++ b/drivers/net/wireless/ath/ath9k/ar9003_calib.c
 -@@ -23,10 +23,11 @@
@@ -5090,41 +7628,100 @@ index a1af6c2..892f51e 100644
 -+	int mag_coeff[AR9300_MAX_CHAINS][MAX_MEASUREMENT][MAXIQCAL];
 -+	int phs_coeff[AR9300_MAX_CHAINS][MAX_MEASUREMENT][MAXIQCAL];
 - 	int iqc_coeff[2];
-+ 	if (ah->opmode == NL80211_IFTYPE_STATION &&
-+ 	    BEACON_RSSI(ah) <= ATH9K_ANI_RSSI_THR_LOW &&
-+ 	    immunityLevel > ATH9K_ANI_CCK_MAX_LEVEL_LOW_RSSI)
-+--- a/drivers/net/wireless/ath/ath9k/ath9k.h
-++++ b/drivers/net/wireless/ath/ath9k/ath9k.h
-+@@ -251,7 +251,6 @@ struct ath_atx_tid {
-+ 
-+ 	s8 bar_index;
-+ 	bool sched;
-+-	bool paused;
-+ 	bool active;
-  };
+- };
++@@ -1100,12 +1107,16 @@ ieee80211_sta_process_chanswitch(struct 
++ 	mutex_unlock(&local->chanctx_mtx);
++ 
++ 	sdata->csa_chandef = csa_ie.chandef;
+++
+++	mutex_lock(&local->mtx);
++ 	sdata->vif.csa_active = true;
+++	sdata->csa_block_tx = csa_ie.mode;
++ 
++-	if (csa_ie.mode)
+++	if (sdata->csa_block_tx)
++ 		ieee80211_stop_queues_by_reason(&local->hw,
++-				IEEE80211_MAX_QUEUE_MAP,
++-				IEEE80211_QUEUE_STOP_REASON_CSA);
+++					IEEE80211_MAX_QUEUE_MAP,
+++					IEEE80211_QUEUE_STOP_REASON_CSA);
+++	mutex_unlock(&local->mtx);
++ 
++ 	if (local->ops->channel_switch) {
++ 		/* use driver's channel switch callback */
++@@ -1817,6 +1828,12 @@ static void ieee80211_set_disassoc(struc
++ 	ifmgd->flags = 0;
++ 	mutex_lock(&local->mtx);
++ 	ieee80211_vif_release_channel(sdata);
+++
+++	sdata->vif.csa_active = false;
+++	if (!ieee80211_csa_needs_block_tx(local))
+++		ieee80211_wake_queues_by_reason(&local->hw,
+++					IEEE80211_MAX_QUEUE_MAP,
+++					IEEE80211_QUEUE_STOP_REASON_CSA);
++ 	mutex_unlock(&local->mtx);
   
 -@@ -800,7 +801,7 @@ static bool ar9003_hw_calc_iq_corr(struc
 - 	if (q_q_coff > 63)
 - 		q_q_coff = 63;
-- 
++ 	sdata->encrypt_headroom = IEEE80211_ENCRYPT_HEADROOM;
++@@ -2045,6 +2062,7 @@ EXPORT_SYMBOL(ieee80211_ap_probereq_get)
+  
 --	iqc_coeff[0] = (q_q_coff * 128) + q_i_coff;
 -+	iqc_coeff[0] = (q_q_coff * 128) + (0x7f & q_i_coff);
-- 
++ static void __ieee80211_disconnect(struct ieee80211_sub_if_data *sdata)
++ {
+++	struct ieee80211_local *local = sdata->local;
++ 	struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
++ 	u8 frame_buf[IEEE80211_DEAUTH_FRAME_LEN];
+  
 - 	ath_dbg(common, CALIBRATE, "tx chain %d: iq corr coeff=%x\n",
 - 		chain_idx, iqc_coeff[0]);
 -@@ -831,7 +832,7 @@ static bool ar9003_hw_calc_iq_corr(struc
 - 	if (q_q_coff > 63)
 - 		q_q_coff = 63;
-- 
++@@ -2058,10 +2076,14 @@ static void __ieee80211_disconnect(struc
++ 			       WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY,
++ 			       true, frame_buf);
++ 	ifmgd->flags &= ~IEEE80211_STA_CSA_RECEIVED;
+++
+++	mutex_lock(&local->mtx);
++ 	sdata->vif.csa_active = false;
++-	ieee80211_wake_queues_by_reason(&sdata->local->hw,
+++	if (!ieee80211_csa_needs_block_tx(local))
+++		ieee80211_wake_queues_by_reason(&local->hw,
++ 					IEEE80211_MAX_QUEUE_MAP,
++ 					IEEE80211_QUEUE_STOP_REASON_CSA);
+++	mutex_unlock(&local->mtx);
++ 
++ 	cfg80211_tx_mlme_mgmt(sdata->dev, frame_buf,
++ 			      IEEE80211_DEAUTH_FRAME_LEN);
++@@ -3546,6 +3568,9 @@ static void ieee80211_sta_bcn_mon_timer(
++ 	if (local->quiescing)
++ 		return;
+  
 --	iqc_coeff[1] = (q_q_coff * 128) + q_i_coff;
 -+	iqc_coeff[1] = (q_q_coff * 128) + (0x7f & q_i_coff);
-- 
+++	if (sdata->vif.csa_active)
+++		return;
+++
++ 	sdata->u.mgd.connection_loss = false;
++ 	ieee80211_queue_work(&sdata->local->hw,
++ 			     &sdata->u.mgd.beacon_connection_loss_work);
++@@ -3561,6 +3586,9 @@ static void ieee80211_sta_conn_mon_timer
++ 	if (local->quiescing)
++ 		return;
+  
 - 	ath_dbg(common, CALIBRATE, "rx chain %d: iq corr coeff=%x\n",
 - 		chain_idx, iqc_coeff[1]);
 -@@ -839,7 +840,8 @@ static bool ar9003_hw_calc_iq_corr(struc
 - 	return true;
-- }
-- 
+++	if (sdata->vif.csa_active)
+++		return;
+++
++ 	ieee80211_queue_work(&local->hw, &ifmgd->monitor_work);
+  }
+  
 --static void ar9003_hw_detect_outlier(int *mp_coeff, int nmeasurement,
 -+static void ar9003_hw_detect_outlier(int mp_coeff[][MAXIQCAL],
 -+				     int nmeasurement,
@@ -5147,7 +7744,11 @@ index a1af6c2..892f51e 100644
 - 			min_idx = i;
 - 		}
 - 	}
-- 
++--- a/net/mac80211/rc80211_minstrel_ht.c
+++++ b/net/mac80211/rc80211_minstrel_ht.c
++@@ -22,7 +22,7 @@
++ #define MCS_NBITS (AVG_PKT_SIZE << 3)
+  
 - 	/* find average (exclude max abs value) */
 - 	for (i = 0; i < nmeasurement; i++) {
 --		if ((abs(mp_coeff[i]) < abs(mp_max)) ||
@@ -5175,17 +7776,37 @@ index a1af6c2..892f51e 100644
 --		mp_coeff[outlier_idx] = mp_avg;
 -+		mp_coeff[outlier_idx][0] = mp_avg;
 - 	}
-- }
-- 
++ /* Number of symbols for a packet with (bps) bits per symbol */
++-#define MCS_NSYMS(bps) ((MCS_NBITS + (bps) - 1) / (bps))
+++#define MCS_NSYMS(bps) DIV_ROUND_UP(MCS_NBITS, (bps))
++ 
++ /* Transmission time (nanoseconds) for a packet containing (syms) symbols */
++ #define MCS_SYMBOL_TIME(sgi, syms)					\
++@@ -226,8 +226,9 @@ minstrel_ht_calc_tp(struct minstrel_ht_s
++ 		nsecs = 1000 * mi->overhead / MINSTREL_TRUNC(mi->avg_ampdu_len);
++ 
++ 	nsecs += minstrel_mcs_groups[group].duration[rate];
++-	tp = 1000000 * ((prob * 1000) / nsecs);
++ 
+++	/* prob is scaled - see MINSTREL_FRAC above */
+++	tp = 1000000 * ((prob * 1000) / nsecs);
++ 	mr->cur_tp = MINSTREL_TRUNC(tp);
+  }
+  
 --static void ar9003_hw_tx_iqcal_load_avg_2_passes(struct ath_hw *ah,
 --						 struct coeff *coeff,
 --						 bool is_reusable)
 -+static void ar9003_hw_tx_iq_cal_outlier_detection(struct ath_hw *ah,
 -+						  struct coeff *coeff,
 -+						  bool is_reusable)
-+--- a/drivers/net/wireless/ath/ath9k/xmit.c
-++++ b/drivers/net/wireless/ath/ath9k/xmit.c
-+@@ -107,9 +107,6 @@ static void ath_tx_queue_tid(struct ath_
++--- a/net/mac80211/scan.c
+++++ b/net/mac80211/scan.c
++@@ -1076,12 +1076,8 @@ void ieee80211_sched_scan_results(struct
++ }
++ EXPORT_SYMBOL(ieee80211_sched_scan_results);
++ 
++-void ieee80211_sched_scan_stopped_work(struct work_struct *work)
+++void ieee80211_sched_scan_end(struct ieee80211_local *local)
   {
 - 	int i, im, nmeasurement;
 -+	int magnitude, phase;
@@ -5195,15 +7816,15 @@ index a1af6c2..892f51e 100644
 -@@ -920,21 +923,30 @@ static void ar9003_hw_tx_iqcal_load_avg_
 - 		if (nmeasurement > MAX_MEASUREMENT)
 - 			nmeasurement = MAX_MEASUREMENT;
-+ 	struct ath_atx_ac *ac = tid->ac;
-  
+- 
 --		/* detect outlier only if nmeasurement > 1 */
 --		if (nmeasurement > 1) {
 --			/* Detect magnitude outlier */
 --			ar9003_hw_detect_outlier(coeff->mag_coeff[i],
 --					nmeasurement, MAX_MAG_DELTA);
-+-	if (tid->paused)
-+-		return;
++-	struct ieee80211_local *local =
++-		container_of(work, struct ieee80211_local,
++-			     sched_scan_stopped_work);
  -
 --			/* Detect phase outlier */
 --			ar9003_hw_detect_outlier(coeff->phs_coeff[i],
@@ -5234,22 +7855,23 @@ index a1af6c2..892f51e 100644
 --				((coeff->phs_coeff[i][im] & 0x7f) << 7);
 -+			coeff->iqc_coeff[0] =
 -+				(phase & 0x7f) | ((magnitude & 0x7f) << 7);
-+ 	if (tid->sched)
-+ 		return;
++ 	mutex_lock(&local->mtx);
   
 - 			if ((im % 2) == 0)
 - 				REG_RMW_FIELD(ah, tx_corr_coeff[im][i],
 -@@ -991,7 +1003,63 @@ static bool ar9003_hw_tx_iq_cal_run(stru
 - 	return true;
-- }
-+@@ -1407,7 +1404,6 @@ int ath_tx_aggr_start(struct ath_softc *
-+ 	ath_tx_tid_change_state(sc, txtid);
++ 	if (!rcu_access_pointer(local->sched_scan_sdata)) {
++@@ -1099,6 +1095,15 @@ void ieee80211_sched_scan_stopped_work(s
++ 	cfg80211_sched_scan_stopped(local->hw.wiphy);
+  }
   
 --static void ar9003_hw_tx_iq_cal_post_proc(struct ath_hw *ah, bool is_reusable)
 -+static void __ar955x_tx_iq_cal_sort(struct ath_hw *ah,
 -+				    struct coeff *coeff,
 -+				    int i, int nmeasurement)
--+{
+++void ieee80211_sched_scan_stopped_work(struct work_struct *work)
+ +{
 -+	struct ath_common *common = ath9k_hw_common(ah);
 -+	int im, ix, iy, temp;
 -+
@@ -5280,30 +7902,367 @@ index a1af6c2..892f51e 100644
 -+			i, im,
 -+			coeff->mag_coeff[i][im][0],
 -+			coeff->phs_coeff[i][im][0]);
--+	}
--+}
--+
+++	struct ieee80211_local *local =
+++		container_of(work, struct ieee80211_local,
+++			     sched_scan_stopped_work);
+++
+++	ieee80211_sched_scan_end(local);
+++}
+++
++ void ieee80211_sched_scan_stopped(struct ieee80211_hw *hw)
++ {
++ 	struct ieee80211_local *local = hw_to_local(hw);
++--- /dev/null
+++++ b/net/mac80211/tdls.c
++@@ -0,0 +1,325 @@
+++/*
+++ * mac80211 TDLS handling code
+++ *
+++ * Copyright 2006-2010	Johannes Berg <johannes@sipsolutions.net>
+++ * Copyright 2014, Intel Corporation
+++ *
+++ * This file is GPLv2 as found in COPYING.
+++ */
+++
+++#include <linux/ieee80211.h>
+++#include "ieee80211_i.h"
+++
+++static void ieee80211_tdls_add_ext_capab(struct sk_buff *skb)
+++{
+++	u8 *pos = (void *)skb_put(skb, 7);
+++
+++	*pos++ = WLAN_EID_EXT_CAPABILITY;
+++	*pos++ = 5; /* len */
+++	*pos++ = 0x0;
+++	*pos++ = 0x0;
+++	*pos++ = 0x0;
+++	*pos++ = 0x0;
+++	*pos++ = WLAN_EXT_CAPA5_TDLS_ENABLED;
+++}
+++
+++static u16 ieee80211_get_tdls_sta_capab(struct ieee80211_sub_if_data *sdata)
+++{
+++	struct ieee80211_local *local = sdata->local;
+++	u16 capab;
+++
+++	capab = 0;
+++	if (ieee80211_get_sdata_band(sdata) != IEEE80211_BAND_2GHZ)
+++		return capab;
+++
+++	if (!(local->hw.flags & IEEE80211_HW_2GHZ_SHORT_SLOT_INCAPABLE))
+++		capab |= WLAN_CAPABILITY_SHORT_SLOT_TIME;
+++	if (!(local->hw.flags & IEEE80211_HW_2GHZ_SHORT_PREAMBLE_INCAPABLE))
+++		capab |= WLAN_CAPABILITY_SHORT_PREAMBLE;
+++
+++	return capab;
+++}
+++
+++static void ieee80211_tdls_add_link_ie(struct sk_buff *skb, const u8 *src_addr,
+++				       const u8 *peer, const u8 *bssid)
+++{
+++	struct ieee80211_tdls_lnkie *lnkid;
+++
+++	lnkid = (void *)skb_put(skb, sizeof(struct ieee80211_tdls_lnkie));
+++
+++	lnkid->ie_type = WLAN_EID_LINK_ID;
+++	lnkid->ie_len = sizeof(struct ieee80211_tdls_lnkie) - 2;
+++
+++	memcpy(lnkid->bssid, bssid, ETH_ALEN);
+++	memcpy(lnkid->init_sta, src_addr, ETH_ALEN);
+++	memcpy(lnkid->resp_sta, peer, ETH_ALEN);
+++}
+++
+++static int
+++ieee80211_prep_tdls_encap_data(struct wiphy *wiphy, struct net_device *dev,
+++			       const u8 *peer, u8 action_code, u8 dialog_token,
+++			       u16 status_code, struct sk_buff *skb)
+++{
+++	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+++	enum ieee80211_band band = ieee80211_get_sdata_band(sdata);
+++	struct ieee80211_tdls_data *tf;
+++
+++	tf = (void *)skb_put(skb, offsetof(struct ieee80211_tdls_data, u));
+++
+++	memcpy(tf->da, peer, ETH_ALEN);
+++	memcpy(tf->sa, sdata->vif.addr, ETH_ALEN);
+++	tf->ether_type = cpu_to_be16(ETH_P_TDLS);
+++	tf->payload_type = WLAN_TDLS_SNAP_RFTYPE;
+++
+++	switch (action_code) {
+++	case WLAN_TDLS_SETUP_REQUEST:
+++		tf->category = WLAN_CATEGORY_TDLS;
+++		tf->action_code = WLAN_TDLS_SETUP_REQUEST;
+++
+++		skb_put(skb, sizeof(tf->u.setup_req));
+++		tf->u.setup_req.dialog_token = dialog_token;
+++		tf->u.setup_req.capability =
+++			cpu_to_le16(ieee80211_get_tdls_sta_capab(sdata));
+++
+++		ieee80211_add_srates_ie(sdata, skb, false, band);
+++		ieee80211_add_ext_srates_ie(sdata, skb, false, band);
+++		ieee80211_tdls_add_ext_capab(skb);
+++		break;
+++	case WLAN_TDLS_SETUP_RESPONSE:
+++		tf->category = WLAN_CATEGORY_TDLS;
+++		tf->action_code = WLAN_TDLS_SETUP_RESPONSE;
+++
+++		skb_put(skb, sizeof(tf->u.setup_resp));
+++		tf->u.setup_resp.status_code = cpu_to_le16(status_code);
+++		tf->u.setup_resp.dialog_token = dialog_token;
+++		tf->u.setup_resp.capability =
+++			cpu_to_le16(ieee80211_get_tdls_sta_capab(sdata));
+++
+++		ieee80211_add_srates_ie(sdata, skb, false, band);
+++		ieee80211_add_ext_srates_ie(sdata, skb, false, band);
+++		ieee80211_tdls_add_ext_capab(skb);
+++		break;
+++	case WLAN_TDLS_SETUP_CONFIRM:
+++		tf->category = WLAN_CATEGORY_TDLS;
+++		tf->action_code = WLAN_TDLS_SETUP_CONFIRM;
+++
+++		skb_put(skb, sizeof(tf->u.setup_cfm));
+++		tf->u.setup_cfm.status_code = cpu_to_le16(status_code);
+++		tf->u.setup_cfm.dialog_token = dialog_token;
+++		break;
+++	case WLAN_TDLS_TEARDOWN:
+++		tf->category = WLAN_CATEGORY_TDLS;
+++		tf->action_code = WLAN_TDLS_TEARDOWN;
+++
+++		skb_put(skb, sizeof(tf->u.teardown));
+++		tf->u.teardown.reason_code = cpu_to_le16(status_code);
+++		break;
+++	case WLAN_TDLS_DISCOVERY_REQUEST:
+++		tf->category = WLAN_CATEGORY_TDLS;
+++		tf->action_code = WLAN_TDLS_DISCOVERY_REQUEST;
+++
+++		skb_put(skb, sizeof(tf->u.discover_req));
+++		tf->u.discover_req.dialog_token = dialog_token;
+++		break;
+++	default:
+++		return -EINVAL;
+++	}
+++
+++	return 0;
+++}
+++
+++static int
+++ieee80211_prep_tdls_direct(struct wiphy *wiphy, struct net_device *dev,
+++			   const u8 *peer, u8 action_code, u8 dialog_token,
+++			   u16 status_code, struct sk_buff *skb)
+++{
+++	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+++	enum ieee80211_band band = ieee80211_get_sdata_band(sdata);
+++	struct ieee80211_mgmt *mgmt;
+++
+++	mgmt = (void *)skb_put(skb, 24);
+++	memset(mgmt, 0, 24);
+++	memcpy(mgmt->da, peer, ETH_ALEN);
+++	memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN);
+++	memcpy(mgmt->bssid, sdata->u.mgd.bssid, ETH_ALEN);
+++
+++	mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
+++					  IEEE80211_STYPE_ACTION);
+++
+++	switch (action_code) {
+++	case WLAN_PUB_ACTION_TDLS_DISCOVER_RES:
+++		skb_put(skb, 1 + sizeof(mgmt->u.action.u.tdls_discover_resp));
+++		mgmt->u.action.category = WLAN_CATEGORY_PUBLIC;
+++		mgmt->u.action.u.tdls_discover_resp.action_code =
+++			WLAN_PUB_ACTION_TDLS_DISCOVER_RES;
+++		mgmt->u.action.u.tdls_discover_resp.dialog_token =
+++			dialog_token;
+++		mgmt->u.action.u.tdls_discover_resp.capability =
+++			cpu_to_le16(ieee80211_get_tdls_sta_capab(sdata));
+++
+++		ieee80211_add_srates_ie(sdata, skb, false, band);
+++		ieee80211_add_ext_srates_ie(sdata, skb, false, band);
+++		ieee80211_tdls_add_ext_capab(skb);
+++		break;
+++	default:
+++		return -EINVAL;
+ +	}
+++
+++	return 0;
+ +}
+ +
 -+static bool ar955x_tx_iq_cal_median(struct ath_hw *ah,
 -+				    struct coeff *coeff,
 -+				    int iqcal_idx,
 -+				    int nmeasurement)
--+{
+++int ieee80211_tdls_mgmt(struct wiphy *wiphy, struct net_device *dev,
+++			const u8 *peer, u8 action_code, u8 dialog_token,
+++			u16 status_code, u32 peer_capability,
+++			const u8 *extra_ies, size_t extra_ies_len)
+ +{
 -+	int i;
--+
+++	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+++	struct ieee80211_local *local = sdata->local;
+++	struct sk_buff *skb = NULL;
+++	bool send_direct;
+++	int ret;
+++
+++	if (!(wiphy->flags & WIPHY_FLAG_SUPPORTS_TDLS))
+++		return -ENOTSUPP;
+++
+++	/* make sure we are in managed mode, and associated */
+++	if (sdata->vif.type != NL80211_IFTYPE_STATION ||
+++	    !sdata->u.mgd.associated)
+++		return -EINVAL;
+++
+++	tdls_dbg(sdata, "TDLS mgmt action %d peer %pM\n",
+++		 action_code, peer);
+++
+++	skb = dev_alloc_skb(local->hw.extra_tx_headroom +
+++			    max(sizeof(struct ieee80211_mgmt),
+++				sizeof(struct ieee80211_tdls_data)) +
+++			    50 + /* supported rates */
+++			    7 + /* ext capab */
+++			    extra_ies_len +
+++			    sizeof(struct ieee80211_tdls_lnkie));
+++	if (!skb)
+++		return -ENOMEM;
+++
+++	skb_reserve(skb, local->hw.extra_tx_headroom);
+++
+++	switch (action_code) {
+++	case WLAN_TDLS_SETUP_REQUEST:
+++	case WLAN_TDLS_SETUP_RESPONSE:
+++	case WLAN_TDLS_SETUP_CONFIRM:
+++	case WLAN_TDLS_TEARDOWN:
+++	case WLAN_TDLS_DISCOVERY_REQUEST:
+++		ret = ieee80211_prep_tdls_encap_data(wiphy, dev, peer,
+++						     action_code, dialog_token,
+++						     status_code, skb);
+++		send_direct = false;
+++		break;
+++	case WLAN_PUB_ACTION_TDLS_DISCOVER_RES:
+++		ret = ieee80211_prep_tdls_direct(wiphy, dev, peer, action_code,
+++						 dialog_token, status_code,
+++						 skb);
+++		send_direct = true;
+++		break;
+++	default:
+++		ret = -ENOTSUPP;
+++		break;
+++	}
+++
+++	if (ret < 0)
+++		goto fail;
+++
+++	if (extra_ies_len)
+++		memcpy(skb_put(skb, extra_ies_len), extra_ies, extra_ies_len);
+++
+++	/* the TDLS link IE is always added last */
+++	switch (action_code) {
+++	case WLAN_TDLS_SETUP_REQUEST:
+++	case WLAN_TDLS_SETUP_CONFIRM:
+++	case WLAN_TDLS_TEARDOWN:
+++	case WLAN_TDLS_DISCOVERY_REQUEST:
+++		/* we are the initiator */
+++		ieee80211_tdls_add_link_ie(skb, sdata->vif.addr, peer,
+++					   sdata->u.mgd.bssid);
+++		break;
+++	case WLAN_TDLS_SETUP_RESPONSE:
+++	case WLAN_PUB_ACTION_TDLS_DISCOVER_RES:
+++		/* we are the responder */
+++		ieee80211_tdls_add_link_ie(skb, peer, sdata->vif.addr,
+++					   sdata->u.mgd.bssid);
+++		break;
+++	default:
+++		ret = -ENOTSUPP;
+++		goto fail;
+++	}
+ +
 -+	if ((iqcal_idx + 1) != MAXIQCAL)
 -+		return false;
--+
+++	if (send_direct) {
+++		ieee80211_tx_skb(sdata, skb);
+++		return 0;
+++	}
+ +
 -+	for (i = 0; i < AR9300_MAX_CHAINS; i++) {
 -+		__ar955x_tx_iq_cal_sort(ah, coeff, i, nmeasurement);
--+	}
--+
+++	/*
+++	 * According to 802.11z: Setup req/resp are sent in AC_BK, otherwise
+++	 * we should default to AC_VI.
+++	 */
+++	switch (action_code) {
+++	case WLAN_TDLS_SETUP_REQUEST:
+++	case WLAN_TDLS_SETUP_RESPONSE:
+++		skb_set_queue_mapping(skb, IEEE80211_AC_BK);
+++		skb->priority = 2;
+++		break;
+++	default:
+++		skb_set_queue_mapping(skb, IEEE80211_AC_VI);
+++		skb->priority = 5;
+++		break;
+ +	}
+ +
 -+	return true;
--+}
--+
+++	/* disable bottom halves when entering the Tx path */
+++	local_bh_disable();
+++	ret = ieee80211_subif_start_xmit(skb, dev);
+++	local_bh_enable();
+++
+++	return ret;
+++
+++fail:
+++	dev_kfree_skb(skb);
+++	return ret;
+ +}
+ +
 -+static void ar9003_hw_tx_iq_cal_post_proc(struct ath_hw *ah,
 -+					  int iqcal_idx,
 -+					  bool is_reusable)
-- {
+++int ieee80211_tdls_oper(struct wiphy *wiphy, struct net_device *dev,
+++			const u8 *peer, enum nl80211_tdls_operation oper)
+++{
+++	struct sta_info *sta;
+++	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+++
+++	if (!(wiphy->flags & WIPHY_FLAG_SUPPORTS_TDLS))
+++		return -ENOTSUPP;
+++
+++	if (sdata->vif.type != NL80211_IFTYPE_STATION)
+++		return -EINVAL;
+++
+++	tdls_dbg(sdata, "TDLS oper %d peer %pM\n", oper, peer);
+++
+++	switch (oper) {
+++	case NL80211_TDLS_ENABLE_LINK:
+++		rcu_read_lock();
+++		sta = sta_info_get(sdata, peer);
+++		if (!sta) {
+++			rcu_read_unlock();
+++			return -ENOLINK;
+++		}
+++
+++		set_sta_flag(sta, WLAN_STA_TDLS_PEER_AUTH);
+++		rcu_read_unlock();
+++		break;
+++	case NL80211_TDLS_DISABLE_LINK:
+++		return sta_info_destroy_addr(sdata, peer);
+++	case NL80211_TDLS_TEARDOWN:
+++	case NL80211_TDLS_SETUP:
+++	case NL80211_TDLS_DISCOVERY_REQ:
+++		/* We don't support in-driver setup/teardown/discovery */
+++		return -ENOTSUPP;
+++	default:
+++		return -ENOTSUPP;
+++	}
+++
+++	return 0;
+++}
++--- a/net/mac80211/tx.c
+++++ b/net/mac80211/tx.c
++@@ -2330,7 +2330,8 @@ void ieee80211_tx_pending(unsigned long 
++ /* functions for drivers to get certain frames */
++ 
++ static void __ieee80211_beacon_add_tim(struct ieee80211_sub_if_data *sdata,
++-				       struct ps_data *ps, struct sk_buff *skb)
+++				       struct ps_data *ps, struct sk_buff *skb,
+++				       bool is_template)
+  {
 - 	struct ath_common *common = ath9k_hw_common(ah);
 - 	const u32 txiqcal_status[AR9300_MAX_CHAINS] = {
 -@@ -1004,10 +1072,11 @@ static void ar9003_hw_tx_iq_cal_post_pro
@@ -5317,17 +8276,29 @@ index a1af6c2..892f51e 100644
 --	int nmeasurement;
 -+	int nmeasurement = 0;
 -+	bool outlier_detect = true;
-+ 	txtid->active = true;
-+-	txtid->paused = true;
-+ 	*ssn = txtid->seq_start = txtid->seq_next;
-+ 	txtid->bar_index = -1;
-  
+- 
 - 	for (i = 0; i < AR9300_MAX_CHAINS; i++) {
 - 		if (!(ah->txchainmask & (1 << i)))
 -@@ -1065,17 +1134,23 @@ static void ar9003_hw_tx_iq_cal_post_pro
 - 				goto tx_iqcal_fail;
 - 			}
-+@@ -1427,7 +1423,6 @@ void ath_tx_aggr_stop(struct ath_softc *
++ 	u8 *pos, *tim;
++ 	int aid0 = 0;
++@@ -2343,11 +2344,12 @@ static void __ieee80211_beacon_add_tim(s
++ 		 * checking byte-for-byte */
++ 		have_bits = !bitmap_empty((unsigned long *)ps->tim,
++ 					  IEEE80211_MAX_AID+1);
++-
++-	if (ps->dtim_count == 0)
++-		ps->dtim_count = sdata->vif.bss_conf.dtim_period - 1;
++-	else
++-		ps->dtim_count--;
+++	if (!is_template) {
+++		if (ps->dtim_count == 0)
+++			ps->dtim_count = sdata->vif.bss_conf.dtim_period - 1;
+++		else
+++			ps->dtim_count--;
+++	}
   
 --			coeff.mag_coeff[i][im] = coeff.iqc_coeff[0] & 0x7f;
 --			coeff.phs_coeff[i][im] =
@@ -5335,16 +8306,7 @@ index a1af6c2..892f51e 100644
 -+				coeff.iqc_coeff[0] & 0x7f;
 -+			coeff.mag_coeff[i][im][iqcal_idx] =
 - 				(coeff.iqc_coeff[0] >> 7) & 0x7f;
-+ 	ath_txq_lock(sc, txq);
-+ 	txtid->active = false;
-+-	txtid->paused = false;
-+ 	ath_tx_flush_tid(sc, txtid);
-+ 	ath_tx_tid_change_state(sc, txtid);
-+ 	ath_txq_unlock_complete(sc, txq);
-+@@ -1487,7 +1482,7 @@ void ath_tx_aggr_wakeup(struct ath_softc
-+ 		ath_txq_lock(sc, txq);
-+ 		ac->clear_ps_filter = true;
-  
+- 
 --			if (coeff.mag_coeff[i][im] > 63)
 --				coeff.mag_coeff[i][im] -= 128;
 --			if (coeff.phs_coeff[i][im] > 63)
@@ -5353,39 +8315,325 @@ index a1af6c2..892f51e 100644
 -+				coeff.mag_coeff[i][im][iqcal_idx] -= 128;
 -+			if (coeff.phs_coeff[i][im][iqcal_idx] > 63)
 -+				coeff.phs_coeff[i][im][iqcal_idx] -= 128;
-+-		if (!tid->paused && ath_tid_has_buffered(tid)) {
-++		if (ath_tid_has_buffered(tid)) {
-+ 			ath_tx_queue_tid(txq, tid);
-+ 			ath_txq_schedule(sc, txq);
++ 	tim = pos = (u8 *) skb_put(skb, 6);
++ 	*pos++ = WLAN_EID_TIM;
++@@ -2393,7 +2395,8 @@ static void __ieee80211_beacon_add_tim(s
++ }
++ 
++ static int ieee80211_beacon_add_tim(struct ieee80211_sub_if_data *sdata,
++-				    struct ps_data *ps, struct sk_buff *skb)
+++				    struct ps_data *ps, struct sk_buff *skb,
+++				    bool is_template)
++ {
++ 	struct ieee80211_local *local = sdata->local;
++ 
++@@ -2405,24 +2408,24 @@ static int ieee80211_beacon_add_tim(stru
++ 	 * of the tim bitmap in mac80211 and the driver.
++ 	 */
++ 	if (local->tim_in_locked_section) {
++-		__ieee80211_beacon_add_tim(sdata, ps, skb);
+++		__ieee80211_beacon_add_tim(sdata, ps, skb, is_template);
++ 	} else {
++ 		spin_lock_bh(&local->tim_lock);
++-		__ieee80211_beacon_add_tim(sdata, ps, skb);
+++		__ieee80211_beacon_add_tim(sdata, ps, skb, is_template);
++ 		spin_unlock_bh(&local->tim_lock);
++ 	}
++ 
++ 	return 0;
++ }
++ 
++-static void ieee80211_update_csa(struct ieee80211_sub_if_data *sdata,
++-				 struct beacon_data *beacon)
+++static void ieee80211_set_csa(struct ieee80211_sub_if_data *sdata,
+++			      struct beacon_data *beacon)
++ {
++ 	struct probe_resp *resp;
++-	int counter_offset_beacon = sdata->csa_counter_offset_beacon;
++-	int counter_offset_presp = sdata->csa_counter_offset_presp;
++ 	u8 *beacon_data;
++ 	size_t beacon_data_len;
+++	int i;
+++	u8 count = sdata->csa_current_counter;
++ 
++ 	switch (sdata->vif.type) {
++ 	case NL80211_IFTYPE_AP:
++@@ -2440,40 +2443,57 @@ static void ieee80211_update_csa(struct 
++ 	default:
++ 		return;
++ 	}
++-	if (WARN_ON(counter_offset_beacon >= beacon_data_len))
++-		return;
++ 
++-	/* Warn if the driver did not check for/react to csa
++-	 * completeness.  A beacon with CSA counter set to 0 should
++-	 * never occur, because a counter of 1 means switch just
++-	 * before the next beacon.
++-	 */
++-	if (WARN_ON(beacon_data[counter_offset_beacon] == 1))
++-		return;
+++	for (i = 0; i < IEEE80211_MAX_CSA_COUNTERS_NUM; ++i) {
+++		u16 counter_offset_beacon =
+++			sdata->csa_counter_offset_beacon[i];
+++		u16 counter_offset_presp = sdata->csa_counter_offset_presp[i];
+++
+++		if (counter_offset_beacon) {
+++			if (WARN_ON(counter_offset_beacon >= beacon_data_len))
+++				return;
++ 
++-	beacon_data[counter_offset_beacon]--;
+++			beacon_data[counter_offset_beacon] = count;
+++		}
++ 
++-	if (sdata->vif.type == NL80211_IFTYPE_AP && counter_offset_presp) {
++-		rcu_read_lock();
++-		resp = rcu_dereference(sdata->u.ap.probe_resp);
+++		if (sdata->vif.type == NL80211_IFTYPE_AP &&
+++		    counter_offset_presp) {
+++			rcu_read_lock();
+++			resp = rcu_dereference(sdata->u.ap.probe_resp);
++ 
++-		/* if nl80211 accepted the offset, this should not happen. */
++-		if (WARN_ON(!resp)) {
+++			/* If nl80211 accepted the offset, this should
+++			 * not happen.
+++			 */
+++			if (WARN_ON(!resp)) {
+++				rcu_read_unlock();
+++				return;
+++			}
+++			resp->data[counter_offset_presp] = count;
++ 			rcu_read_unlock();
++-			return;
   		}
-- 	}
++-		resp->data[counter_offset_presp]--;
++-		rcu_read_unlock();
+  	}
 --	ar9003_hw_tx_iqcal_load_avg_2_passes(ah, &coeff, is_reusable);
--+
++ }
++ 
+++u8 ieee80211_csa_update_counter(struct ieee80211_vif *vif)
+++{
+++	struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
+++
+++	sdata->csa_current_counter--;
+++
+++	/* the counter should never reach 0 */
+++	WARN_ON(!sdata->csa_current_counter);
+ +
 -+	if (AR_SREV_9550(ah))
 -+		outlier_detect = ar955x_tx_iq_cal_median(ah, &coeff,
 -+							 iqcal_idx, nmeasurement);
 -+	if (outlier_detect)
 -+		ar9003_hw_tx_iq_cal_outlier_detection(ah, &coeff, is_reusable);
-- 
+++	return sdata->csa_current_counter;
+++}
+++EXPORT_SYMBOL(ieee80211_csa_update_counter);
+++
++ bool ieee80211_csa_is_complete(struct ieee80211_vif *vif)
++ {
++ 	struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
++ 	struct beacon_data *beacon = NULL;
++ 	u8 *beacon_data;
++ 	size_t beacon_data_len;
++-	int counter_beacon = sdata->csa_counter_offset_beacon;
+++	int counter_beacon = sdata->csa_counter_offset_beacon[0];
++ 	int ret = false;
+  
 - 	return;
-- 
++ 	if (!ieee80211_sdata_running(sdata))
++@@ -2523,9 +2543,11 @@ bool ieee80211_csa_is_complete(struct ie
++ }
++ EXPORT_SYMBOL(ieee80211_csa_is_complete);
++ 
++-struct sk_buff *ieee80211_beacon_get_tim(struct ieee80211_hw *hw,
++-					 struct ieee80211_vif *vif,
++-					 u16 *tim_offset, u16 *tim_length)
+++static struct sk_buff *
+++__ieee80211_beacon_get(struct ieee80211_hw *hw,
+++		       struct ieee80211_vif *vif,
+++		       struct ieee80211_mutable_offsets *offs,
+++		       bool is_template)
++ {
++ 	struct ieee80211_local *local = hw_to_local(hw);
++ 	struct sk_buff *skb = NULL;
++@@ -2534,6 +2556,7 @@ struct sk_buff *ieee80211_beacon_get_tim
++ 	enum ieee80211_band band;
++ 	struct ieee80211_tx_rate_control txrc;
++ 	struct ieee80211_chanctx_conf *chanctx_conf;
+++	int csa_off_base = 0;
++ 
++ 	rcu_read_lock();
++ 
++@@ -2543,18 +2566,20 @@ struct sk_buff *ieee80211_beacon_get_tim
++ 	if (!ieee80211_sdata_running(sdata) || !chanctx_conf)
++ 		goto out;
++ 
++-	if (tim_offset)
++-		*tim_offset = 0;
++-	if (tim_length)
++-		*tim_length = 0;
+++	if (offs)
+++		memset(offs, 0, sizeof(*offs));
++ 
++ 	if (sdata->vif.type == NL80211_IFTYPE_AP) {
++ 		struct ieee80211_if_ap *ap = &sdata->u.ap;
++ 		struct beacon_data *beacon = rcu_dereference(ap->beacon);
++ 
++ 		if (beacon) {
++-			if (sdata->vif.csa_active)
++-				ieee80211_update_csa(sdata, beacon);
+++			if (sdata->vif.csa_active) {
+++				if (!is_template)
+++					ieee80211_csa_update_counter(vif);
+++
+++				ieee80211_set_csa(sdata, beacon);
+++			}
++ 
++ 			/*
++ 			 * headroom, head length,
++@@ -2571,12 +2596,16 @@ struct sk_buff *ieee80211_beacon_get_tim
++ 			memcpy(skb_put(skb, beacon->head_len), beacon->head,
++ 			       beacon->head_len);
++ 
++-			ieee80211_beacon_add_tim(sdata, &ap->ps, skb);
+++			ieee80211_beacon_add_tim(sdata, &ap->ps, skb,
+++						 is_template);
+++
+++			if (offs) {
+++				offs->tim_offset = beacon->head_len;
+++				offs->tim_length = skb->len - beacon->head_len;
++ 
++-			if (tim_offset)
++-				*tim_offset = beacon->head_len;
++-			if (tim_length)
++-				*tim_length = skb->len - beacon->head_len;
+++				/* for AP the csa offsets are from tail */
+++				csa_off_base = skb->len;
+++			}
++ 
++ 			if (beacon->tail)
++ 				memcpy(skb_put(skb, beacon->tail_len),
++@@ -2591,9 +2620,12 @@ struct sk_buff *ieee80211_beacon_get_tim
++ 		if (!presp)
++ 			goto out;
++ 
++-		if (sdata->vif.csa_active)
++-			ieee80211_update_csa(sdata, presp);
+++		if (sdata->vif.csa_active) {
+++			if (!is_template)
+++				ieee80211_csa_update_counter(vif);
++ 
+++			ieee80211_set_csa(sdata, presp);
+++		}
++ 
++ 		skb = dev_alloc_skb(local->tx_headroom + presp->head_len +
++ 				    local->hw.extra_beacon_tailroom);
++@@ -2613,8 +2645,17 @@ struct sk_buff *ieee80211_beacon_get_tim
++ 		if (!bcn)
++ 			goto out;
++ 
++-		if (sdata->vif.csa_active)
++-			ieee80211_update_csa(sdata, bcn);
+++		if (sdata->vif.csa_active) {
+++			if (!is_template)
+++				/* TODO: For mesh csa_counter is in TU, so
+++				 * decrementing it by one isn't correct, but
+++				 * for now we leave it consistent with overall
+++				 * mac80211's behavior.
+++				 */
+++				ieee80211_csa_update_counter(vif);
+++
+++			ieee80211_set_csa(sdata, bcn);
+++		}
+  
 -@@ -1409,7 +1484,7 @@ skip_tx_iqcal:
-- 	}
-- 
++ 		if (ifmsh->sync_ops)
++ 			ifmsh->sync_ops->adjust_tbtt(sdata, bcn);
++@@ -2628,13 +2669,33 @@ struct sk_buff *ieee80211_beacon_get_tim
++ 			goto out;
++ 		skb_reserve(skb, local->tx_headroom);
++ 		memcpy(skb_put(skb, bcn->head_len), bcn->head, bcn->head_len);
++-		ieee80211_beacon_add_tim(sdata, &ifmsh->ps, skb);
+++		ieee80211_beacon_add_tim(sdata, &ifmsh->ps, skb, is_template);
+++
+++		if (offs) {
+++			offs->tim_offset = bcn->head_len;
+++			offs->tim_length = skb->len - bcn->head_len;
+++		}
+++
++ 		memcpy(skb_put(skb, bcn->tail_len), bcn->tail, bcn->tail_len);
++ 	} else {
++ 		WARN_ON(1);
++ 		goto out;
+  	}
+  
 - 	if (txiqcal_done)
 --		ar9003_hw_tx_iq_cal_post_proc(ah, is_reusable);
 -+		ar9003_hw_tx_iq_cal_post_proc(ah, 0, is_reusable);
 - 	else if (caldata && test_bit(TXIQCAL_DONE, &caldata->cal_flags))
 - 		ar9003_hw_tx_iq_cal_reload(ah);
-+@@ -1510,7 +1505,6 @@ void ath_tx_aggr_resume(struct ath_softc
-+ 	ath_txq_lock(sc, txq);
+++	/* CSA offsets */
+++	if (offs) {
+++		int i;
+++
+++		for (i = 0; i < IEEE80211_MAX_CSA_COUNTERS_NUM; i++) {
+++			u16 csa_off = sdata->csa_counter_offset_beacon[i];
+++
+++			if (!csa_off)
+++				continue;
+++
+++			offs->csa_counter_offs[i] = csa_off_base + csa_off;
+++		}
+++	}
+++
++ 	band = chanctx_conf->def.chan->band;
++ 
++ 	info = IEEE80211_SKB_CB(skb);
++@@ -2665,6 +2726,32 @@ struct sk_buff *ieee80211_beacon_get_tim
++  out:
++ 	rcu_read_unlock();
++ 	return skb;
+++
+++}
+++
+++struct sk_buff *
+++ieee80211_beacon_get_template(struct ieee80211_hw *hw,
+++			      struct ieee80211_vif *vif,
+++			      struct ieee80211_mutable_offsets *offs)
+++{
+++	return __ieee80211_beacon_get(hw, vif, offs, true);
+++}
+++EXPORT_SYMBOL(ieee80211_beacon_get_template);
+++
+++struct sk_buff *ieee80211_beacon_get_tim(struct ieee80211_hw *hw,
+++					 struct ieee80211_vif *vif,
+++					 u16 *tim_offset, u16 *tim_length)
+++{
+++	struct ieee80211_mutable_offsets offs = {};
+++	struct sk_buff *bcn = __ieee80211_beacon_get(hw, vif, &offs, false);
+++
+++	if (tim_offset)
+++		*tim_offset = offs.tim_offset;
+++
+++	if (tim_length)
+++		*tim_length = offs.tim_length;
+++
+++	return bcn;
++ }
++ EXPORT_SYMBOL(ieee80211_beacon_get_tim);
   
 -@@ -1455,14 +1530,38 @@ skip_tx_iqcal:
 - 	return true;
-- }
-- 
++--- a/net/mac80211/util.c
+++++ b/net/mac80211/util.c
++@@ -1457,6 +1457,44 @@ void ieee80211_stop_device(struct ieee80
++ 	drv_stop(local);
+  }
+  
 -+static bool do_ar9003_agc_cal(struct ath_hw *ah)
--+{
+++static void ieee80211_handle_reconfig_failure(struct ieee80211_local *local)
+ +{
 -+	struct ath_common *common = ath9k_hw_common(ah);
 -+	bool status;
 -+
@@ -5403,13 +8651,48 @@ index a1af6c2..892f51e 100644
 -+			AH_WAIT_TIMEOUT / 1000);
 -+		return false;
 -+	}
--+
+++	struct ieee80211_sub_if_data *sdata;
+++	struct ieee80211_chanctx *ctx;
+++
+++	/*
+++	 * We get here if during resume the device can't be restarted properly.
+++	 * We might also get here if this happens during HW reset, which is a
+++	 * slightly different situation and we need to drop all connections in
+++	 * the latter case.
+++	 *
+++	 * Ask cfg80211 to turn off all interfaces, this will result in more
+++	 * warnings but at least we'll then get into a clean stopped state.
+++	 */
+++
+++	local->resuming = false;
+++	local->suspended = false;
+++	local->started = false;
+++
+++	/* scheduled scan clearly can't be running any more, but tell
+++	 * cfg80211 and clear local state
+++	 */
+++	ieee80211_sched_scan_end(local);
+ +
 -+	return true;
--+}
--+
+++	list_for_each_entry(sdata, &local->interfaces, list)
+++		sdata->flags &= ~IEEE80211_SDATA_IN_DRIVER;
+++
+++	/* Mark channel contexts as not being in the driver any more to avoid
+++	 * removing them from the driver during the shutdown process...
+++	 */
+++	mutex_lock(&local->chanctx_mtx);
+++	list_for_each_entry(ctx, &local->chanctx_list, list)
+++		ctx->driver_present = false;
+++	mutex_unlock(&local->chanctx_mtx);
+++
+++	cfg80211_shutdown_all_interfaces(local->hw.wiphy);
+ +}
+ +
 - static bool ar9003_hw_init_cal_soc(struct ath_hw *ah,
 - 				   struct ath9k_channel *chan)
-- {
++ static void ieee80211_assign_chanctx(struct ieee80211_local *local,
++ 				     struct ieee80211_sub_if_data *sdata)
+  {
 - 	struct ath_common *common = ath9k_hw_common(ah);
 - 	struct ath9k_hw_cal_data *caldata = ah->caldata;
 - 	bool txiqcal_done = false;
@@ -5417,14 +8700,13 @@ index a1af6c2..892f51e 100644
 -+	bool status = true;
 - 	bool run_agc_cal = false, sep_iq_cal = false;
 -+	int i = 0;
-+ 	tid->baw_size = IEEE80211_MIN_AMPDU_BUF << sta->ht_cap.ampdu_factor;
-+-	tid->paused = false;
-  
+- 
 - 	/* Use chip chainmask only for calibration */
 - 	ar9003_hw_set_chain_masks(ah, ah->caps.rx_chainmask, ah->caps.tx_chainmask);
 -@@ -1485,7 +1584,12 @@ static bool ar9003_hw_init_cal_soc(struc
 - 	 * AGC calibration. Specifically, AR9550 in SoC chips.
-- 	 */
++@@ -1520,9 +1558,11 @@ int ieee80211_reconfig(struct ieee80211_
+  	 */
 - 	if (ah->enabled_cals & TX_IQ_ON_AGC_CAL) {
 --		txiqcal_done = true;
 -+		if (REG_READ_FIELD(ah, AR_PHY_TX_IQCAL_CONTROL_0,
@@ -5439,11 +8721,7 @@ index a1af6c2..892f51e 100644
 -@@ -1512,27 +1616,37 @@ skip_tx_iqcal:
 - 		if (AR_SREV_9330_11(ah))
 - 			ar9003_hw_manual_peak_cal(ah, 0, IS_CHAN_2GHZ(chan));
-+ 	if (ath_tid_has_buffered(tid)) {
-+ 		ath_tx_queue_tid(txq, tid);
-+@@ -1544,8 +1538,6 @@ void ath9k_release_buffered_frames(struc
-+ 			continue;
-  
+- 
 --		/* Calibrate the AGC */
 --		REG_WRITE(ah, AR_PHY_AGC_CONTROL,
 --			  REG_READ(ah, AR_PHY_AGC_CONTROL) |
@@ -5466,10 +8744,7 @@ index a1af6c2..892f51e 100644
 -+			status = do_ar9003_agc_cal(ah);
 -+			if (!status)
 -+				return false;
-+ 		tid = ATH_AN_2_TID(an, i);
-+-		if (tid->paused)
-+-			continue;
-  
+- 
 --	if (!status) {
 --		ath_dbg(common, CALIBRATE,
 --			"offset calibration failed to complete in %d ms; noisy environment?\n",
@@ -5491,32 +8766,74 @@ index a1af6c2..892f51e 100644
 -+				}
 -+			}
 -+		}
-- 	}
-+ 		ath_txq_lock(sc, tid->ac->txq);
-+ 		while (nframes > 0) {
-+@@ -1844,9 +1836,6 @@ void ath_txq_schedule(struct ath_softc *
-+ 			list_del(&tid->list);
-+ 			tid->sched = false;
++ 	res = drv_start(local);
++ 	if (res) {
++-		WARN(local->suspended, "Hardware became unavailable "
++-		     "upon resume. This could be a software issue "
++-		     "prior to suspend or a hardware issue.\n");
+++		if (local->suspended)
+++			WARN(1, "Hardware became unavailable upon resume. This could be a software issue prior to suspend or a hardware issue.\n");
+++		else
+++			WARN(1, "Hardware became unavailable during restart.\n");
+++		ieee80211_handle_reconfig_failure(local);
++ 		return res;
+  	}
   
 --	if (txiqcal_done)
 --		ar9003_hw_tx_iq_cal_post_proc(ah, is_reusable);
-+-			if (tid->paused)
-+-				continue;
- -
+--
 - 	/* Revert chainmask to runtime parameters */
 - 	ar9003_hw_set_chain_masks(ah, ah->rxchainmask, ah->txchainmask);
-- 
++--- a/net/wireless/ap.c
+++++ b/net/wireless/ap.c
++@@ -6,8 +6,8 @@
++ #include "rdev-ops.h"
+  
 ---- a/drivers/net/wireless/rtl818x/rtl8187/rtl8187.h
 -+++ b/drivers/net/wireless/rtl818x/rtl8187/rtl8187.h
 -@@ -15,6 +15,8 @@
 - #ifndef RTL8187_H
 - #define RTL8187_H
-- 
+  
 -+#include <linux/cache.h>
 -+
 - #include "rtl818x.h"
 - #include "leds.h"
-- 
++-static int __cfg80211_stop_ap(struct cfg80211_registered_device *rdev,
++-			      struct net_device *dev, bool notify)
+++int __cfg80211_stop_ap(struct cfg80211_registered_device *rdev,
+++		       struct net_device *dev, bool notify)
++ {
++ 	struct wireless_dev *wdev = dev->ieee80211_ptr;
++ 	int err;
++--- a/net/wireless/chan.c
+++++ b/net/wireless/chan.c
++@@ -370,8 +370,8 @@ int cfg80211_chandef_dfs_required(struct
++ 	case NL80211_IFTYPE_AP_VLAN:
++ 	case NL80211_IFTYPE_WDS:
++ 	case NL80211_IFTYPE_P2P_DEVICE:
++-	case NL80211_IFTYPE_UNSPECIFIED:
++ 		break;
+++	case NL80211_IFTYPE_UNSPECIFIED:
++ 	case NUM_NL80211_IFTYPES:
++ 		WARN_ON(1);
++ 	}
++@@ -796,8 +796,7 @@ bool cfg80211_reg_can_beacon(struct wiph
++ 	    !cfg80211_go_permissive_chan(rdev, chandef->chan))
++ 		prohibited_flags |= IEEE80211_CHAN_NO_IR;
++ 
++-	if (cfg80211_chandef_dfs_required(wiphy, chandef,
++-					  NL80211_IFTYPE_UNSPECIFIED) > 0 &&
+++	if (cfg80211_chandef_dfs_required(wiphy, chandef, iftype) > 0 &&
++ 	    cfg80211_chandef_dfs_available(wiphy, chandef)) {
++ 		/* We can skip IEEE80211_CHAN_NO_IR if chandef dfs available */
++ 		prohibited_flags = IEEE80211_CHAN_DISABLED;
++--- a/net/wireless/core.c
+++++ b/net/wireless/core.c
++@@ -210,15 +210,12 @@ void cfg80211_stop_p2p_device(struct cfg
++ 	}
++ }
+  
 -@@ -139,7 +141,10 @@ struct rtl8187_priv {
 - 	u8 aifsn[4];
 - 	u8 rfkill_mask;
@@ -5543,13 +8860,36 @@ index a1af6c2..892f51e 100644
 -+++ b/net/mac80211/wme.c
 -@@ -154,6 +154,11 @@ u16 ieee80211_select_queue(struct ieee80
 - 		return IEEE80211_AC_BE;
-- 	}
-- 
++-static int cfg80211_rfkill_set_block(void *data, bool blocked)
+++void cfg80211_shutdown_all_interfaces(struct wiphy *wiphy)
++ {
++-	struct cfg80211_registered_device *rdev = data;
+++	struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
++ 	struct wireless_dev *wdev;
++ 
++-	if (!blocked)
++-		return 0;
++-
++-	rtnl_lock();
+++	ASSERT_RTNL();
++ 
++ 	list_for_each_entry(wdev, &rdev->wdev_list, list) {
++ 		if (wdev->netdev) {
++@@ -234,7 +231,18 @@ static int cfg80211_rfkill_set_block(voi
++ 			break;
++ 		}
+  	}
+++}
+++EXPORT_SYMBOL_GPL(cfg80211_shutdown_all_interfaces);
+  
 -+	if (skb->protocol == sdata->control_port_protocol) {
 -+		skb->priority = 7;
 -+		return ieee80211_downgrade_queue(sdata, skb);
 -+	}
--+
+++static int cfg80211_rfkill_set_block(void *data, bool blocked)
+++{
+++	struct cfg80211_registered_device *rdev = data;
+ +
 - 	/* use the data classifier to determine what 802.1d tag the
 - 	 * data frame has */
 - 	rcu_read_lock();
@@ -5558,61 +8898,77 @@ index a1af6c2..892f51e 100644
 -@@ -1444,14 +1444,16 @@ void ath_tx_aggr_sleep(struct ieee80211_
 - 	for (tidno = 0, tid = &an->tid[tidno];
 - 	     tidno < IEEE80211_NUM_TIDS; tidno++, tid++) {
-+ 			if (ath_tx_sched_aggr(sc, txq, tid, &stop))
-+ 				sent = true;
-+ 
-+@@ -2698,7 +2687,6 @@ void ath_tx_node_init(struct ath_softc *
-+ 		tid->baw_size  = WME_MAX_BA;
-+ 		tid->baw_head  = tid->baw_tail = 0;
-+ 		tid->sched     = false;
-+-		tid->paused    = false;
-+ 		tid->active	   = false;
-+ 		__skb_queue_head_init(&tid->buf_q);
-+ 		__skb_queue_head_init(&tid->retry_q);
-+--- a/drivers/net/wireless/ath/ath9k/recv.c
-++++ b/drivers/net/wireless/ath/ath9k/recv.c
-+@@ -975,6 +975,7 @@ int ath_rx_tasklet(struct ath_softc *sc,
-+ 	u64 tsf = 0;
-+ 	unsigned long flags;
-+ 	dma_addr_t new_buf_addr;
-++	unsigned int budget = 512;
-  
+- 
 --		if (!tid->sched)
-+ 	if (edma)
-+ 		dma_type = DMA_BIDIRECTIONAL;
-+@@ -1113,15 +1114,17 @@ requeue_drop_frag:
-+ 		}
-+ requeue:
-+ 		list_add_tail(&bf->list, &sc->rx.rxbuf);
-+-		if (flush)
- -			continue;
+--			continue;
 --
 - 		ac = tid->ac;
 - 		txq = ac->txq;
-- 
+++	if (!blocked)
+++		return 0;
+++
+++	rtnl_lock();
+++	cfg80211_shutdown_all_interfaces(&rdev->wiphy);
++ 	rtnl_unlock();
+  
 - 		ath_txq_lock(sc, txq);
-- 
++ 	return 0;
++@@ -401,6 +409,8 @@ struct wiphy *wiphy_new(const struct cfg
++ 	rdev->wiphy.rts_threshold = (u32) -1;
++ 	rdev->wiphy.coverage_class = 0;
+  
 -+		if (!tid->sched) {
 -+			ath_txq_unlock(sc, txq);
 -+			continue;
 -+		}
--+
+++	rdev->wiphy.max_num_csa_counters = 1;
+ +
 - 		buffered = ath_tid_has_buffered(tid);
++ 	return &rdev->wiphy;
++ }
++ EXPORT_SYMBOL(wiphy_new);
++@@ -697,7 +707,7 @@ void wiphy_unregister(struct wiphy *wiph
++ 	rtnl_lock();
++ 	rdev->wiphy.registered = false;
   
 - 		tid->sched = false;
 -@@ -1696,7 +1698,7 @@ int ath_cabq_update(struct ath_softc *sc
-- 
++-	BUG_ON(!list_empty(&rdev->wdev_list));
+++	WARN_ON(!list_empty(&rdev->wdev_list));
+  
 - 	ath9k_hw_get_txq_props(sc->sc_ah, qnum, &qi);
-- 
++ 	/*
++ 	 * First remove the hardware from everywhere, this makes
++@@ -799,23 +809,23 @@ void cfg80211_update_iface_num(struct cf
++ 		rdev->num_running_monitor_ifaces += num;
++ }
+  
 --	qi.tqi_readyTime = (cur_conf->beacon_interval *
 -+	qi.tqi_readyTime = (TU_TO_USEC(cur_conf->beacon_interval) *
 - 			    ATH_CABQ_READY_TIME) / 100;
 - 	ath_txq_update(sc, qnum, &qi);
-- 
++-void cfg80211_leave(struct cfg80211_registered_device *rdev,
++-		    struct wireless_dev *wdev)
+++void __cfg80211_leave(struct cfg80211_registered_device *rdev,
+++		      struct wireless_dev *wdev)
++ {
++ 	struct net_device *dev = wdev->netdev;
+  
 -@@ -2061,7 +2063,7 @@ static struct ath_buf *ath_tx_setup_buff
-- 
++ 	ASSERT_RTNL();
+++	ASSERT_WDEV_LOCK(wdev);
+  
 - 	ATH_TXBUF_RESET(bf);
-- 
++ 	switch (wdev->iftype) {
++ 	case NL80211_IFTYPE_ADHOC:
++-		cfg80211_leave_ibss(rdev, dev, true);
+++		__cfg80211_leave_ibss(rdev, dev, true);
++ 		break;
++ 	case NL80211_IFTYPE_P2P_CLIENT:
++ 	case NL80211_IFTYPE_STATION:
++ 		if (rdev->sched_scan_req && dev == rdev->sched_scan_req->dev)
++ 			__cfg80211_stop_sched_scan(rdev, false);
+  
 --	if (tid) {
 -+	if (tid && ieee80211_is_data_present(hdr->frame_control)) {
 - 		fragno = le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_FRAG;
@@ -5620,19 +8976,32 @@ index a1af6c2..892f51e 100644
 - 		hdr->seq_ctrl = cpu_to_le16(tid->seq_next << IEEE80211_SEQ_SEQ_SHIFT);
 -@@ -2184,14 +2186,15 @@ int ath_tx_start(struct ieee80211_hw *hw
 - 		txq->stopped = true;
-- 	}
++-		wdev_lock(wdev);
++ #ifdef CPTCFG_CFG80211_WEXT
++ 		kfree(wdev->wext.ie);
++ 		wdev->wext.ie = NULL;
++@@ -824,20 +834,49 @@ void cfg80211_leave(struct cfg80211_regi
++ #endif
++ 		cfg80211_disconnect(rdev, dev,
++ 				    WLAN_REASON_DEAUTH_LEAVING, true);
++-		wdev_unlock(wdev);
++ 		break;
++ 	case NL80211_IFTYPE_MESH_POINT:
++-		cfg80211_leave_mesh(rdev, dev);
+++		__cfg80211_leave_mesh(rdev, dev);
++ 		break;
++ 	case NL80211_IFTYPE_AP:
++ 	case NL80211_IFTYPE_P2P_GO:
++-		cfg80211_stop_ap(rdev, dev, true);
+++		__cfg80211_stop_ap(rdev, dev, true);
++ 		break;
++ 	default:
++ 		break;
+  	}
 - 
 -+	if (txctl->an && ieee80211_is_data_present(hdr->frame_control))
 -+		tid = ath_get_skb_tid(sc, txctl->an, skb);
-+ 		if (edma) {
-+ 			ath_rx_edma_buf_link(sc, qtype);
-+ 		} else {
-+ 			ath_rx_buf_relink(sc, bf);
-+-			ath9k_hw_rxena(ah);
-++			if (!flush)
-++				ath9k_hw_rxena(ah);
-+ 		}
- +
+-+
 - 	if (info->flags & IEEE80211_TX_CTL_PS_RESPONSE) {
 - 		ath_txq_unlock(sc, txq);
 - 		txq = sc->tx.uapsdq;
@@ -5642,34 +9011,10 @@ index a1af6c2..892f51e 100644
 --		tid = ath_get_skb_tid(sc, txctl->an, skb);
 --
 - 		WARN_ON(tid->ac->txq != txctl->txq);
-++		if (!budget--)
-++			break;
-+ 	} while (1);
-+ 
-+ 	if (!(ah->imask & ATH9K_INT_RXEOL)) {
-+--- a/drivers/net/wireless/ath/ath9k/ahb.c
-++++ b/drivers/net/wireless/ath/ath9k/ahb.c
-+@@ -86,7 +86,6 @@ static int ath_ahb_probe(struct platform
-+ 	int irq;
-+ 	int ret = 0;
-+ 	struct ath_hw *ah;
-+-	struct ath_common *common;
-+ 	char hw_name[64];
-+ 
-+ 	if (!dev_get_platdata(&pdev->dev)) {
-+@@ -146,9 +145,6 @@ static int ath_ahb_probe(struct platform
-+ 	wiphy_info(hw->wiphy, "%s mem=0x%lx, irq=%d\n",
-+ 		   hw_name, (unsigned long)mem, irq);
-+ 
-+-	common = ath9k_hw_common(sc->sc_ah);
-+-	/* Will be cleared in ath9k_start() */
-+-	set_bit(ATH_OP_INVALID, &common->op_flags);
-+ 	return 0;
-  
+- 
 - 		if (info->flags & IEEE80211_TX_CTL_CLEAR_PS_FILT)
-+  err_irq:
- --- a/drivers/net/wireless/ath/ath9k/init.c
- +++ b/drivers/net/wireless/ath/ath9k/init.c
+---- a/drivers/net/wireless/ath/ath9k/init.c
+-+++ b/drivers/net/wireless/ath/ath9k/init.c
 -@@ -943,6 +943,7 @@ static void ath9k_set_hw_capab(struct at
 - 	hw->wiphy->flags |= WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL;
 - 	hw->wiphy->flags |= WIPHY_FLAG_SUPPORTS_5_10_MHZ;
@@ -5701,8 +9046,8 @@ index a1af6c2..892f51e 100644
 -+++ b/net/mac80211/sta_info.c
 -@@ -91,7 +91,7 @@ static int sta_info_hash_del(struct ieee
 - 	return -ENOENT;
-- }
-- 
+  }
+  
 --static void cleanup_single_sta(struct sta_info *sta)
 -+static void __cleanup_single_sta(struct sta_info *sta)
 - {
@@ -5730,13 +9075,25 @@ index a1af6c2..892f51e 100644
 - 		ieee80211_purge_tx_queue(&local->hw, &tid_tx->pending);
 - 		kfree(tid_tx);
 - 	}
--+}
+++void cfg80211_leave(struct cfg80211_registered_device *rdev,
+++		    struct wireless_dev *wdev)
+++{
+++	wdev_lock(wdev);
+++	__cfg80211_leave(rdev, wdev);
+++	wdev_unlock(wdev);
+ +}
 - 
 -+static void cleanup_single_sta(struct sta_info *sta)
--+{
+++
+++void cfg80211_stop_iface(struct wiphy *wiphy, struct wireless_dev *wdev,
+++			 gfp_t gfp)
+ +{
 -+	struct ieee80211_sub_if_data *sdata = sta->sdata;
 -+	struct ieee80211_local *local = sdata->local;
--+
+++	struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
+++	struct cfg80211_event *ev;
+++	unsigned long flags;
+ +
 -+	__cleanup_single_sta(sta);
 - 	sta_info_free(local, sta);
 - }
@@ -5764,12 +9121,64 @@ index a1af6c2..892f51e 100644
 - 
 -+	/* simplify things and don't accept BA sessions yet */
 -+	set_sta_flag(sta, WLAN_STA_BLOCK_BA);
--+
+++	trace_cfg80211_stop_iface(wiphy, wdev);
+++
+++	ev = kzalloc(sizeof(*ev), gfp);
+++	if (!ev)
+++		return;
+ +
 - 	/* make the station visible */
 - 	sta_info_hash_add(local, sta);
-- 
+++	ev->type = EVENT_STOPPED;
+++
+++	spin_lock_irqsave(&wdev->event_lock, flags);
+++	list_add_tail(&ev->list, &wdev->event_list);
+++	spin_unlock_irqrestore(&wdev->event_lock, flags);
+++	queue_work(cfg80211_wq, &rdev->event_work);
+++}
+++EXPORT_SYMBOL(cfg80211_stop_iface);
+++
++ static int cfg80211_netdev_notifier_call(struct notifier_block *nb,
++ 					 unsigned long state, void *ptr)
++ {
++--- a/net/wireless/core.h
+++++ b/net/wireless/core.h
++@@ -185,6 +185,7 @@ enum cfg80211_event_type {
++ 	EVENT_ROAMED,
++ 	EVENT_DISCONNECTED,
++ 	EVENT_IBSS_JOINED,
+++	EVENT_STOPPED,
++ };
+  
 - 	list_add_rcu(&sta->list, &local->sta_list);
-- 
++ struct cfg80211_event {
++@@ -281,6 +282,8 @@ int cfg80211_join_mesh(struct cfg80211_r
++ 		       struct net_device *dev,
++ 		       struct mesh_setup *setup,
++ 		       const struct mesh_config *conf);
+++int __cfg80211_leave_mesh(struct cfg80211_registered_device *rdev,
+++			  struct net_device *dev);
++ int cfg80211_leave_mesh(struct cfg80211_registered_device *rdev,
++ 			struct net_device *dev);
++ int cfg80211_set_mesh_channel(struct cfg80211_registered_device *rdev,
++@@ -288,6 +291,8 @@ int cfg80211_set_mesh_channel(struct cfg
++ 			      struct cfg80211_chan_def *chandef);
++ 
++ /* AP */
+++int __cfg80211_stop_ap(struct cfg80211_registered_device *rdev,
+++		       struct net_device *dev, bool notify);
++ int cfg80211_stop_ap(struct cfg80211_registered_device *rdev,
++ 		     struct net_device *dev, bool notify);
++ 
++@@ -441,6 +446,8 @@ int cfg80211_validate_beacon_int(struct 
++ void cfg80211_update_iface_num(struct cfg80211_registered_device *rdev,
++ 			       enum nl80211_iftype iftype, int num);
++ 
+++void __cfg80211_leave(struct cfg80211_registered_device *rdev,
+++		      struct wireless_dev *wdev);
++ void cfg80211_leave(struct cfg80211_registered_device *rdev,
++ 		    struct wireless_dev *wdev);
+  
 -+	/* notify driver */
 -+	err = sta_info_insert_drv_state(local, sdata, sta);
 -+	if (err)
@@ -5778,13 +9187,26 @@ index a1af6c2..892f51e 100644
 - 	set_sta_flag(sta, WLAN_STA_INSERTED);
 -+	/* accept BA sessions now */
 -+	clear_sta_flag(sta, WLAN_STA_BLOCK_BA);
-- 
++--- a/net/wireless/ibss.c
+++++ b/net/wireless/ibss.c
++@@ -420,8 +420,8 @@ int cfg80211_ibss_wext_siwessid(struct n
++ 	if (len > 0 && ssid[len - 1] == '\0')
++ 		len--;
+  
 - 	ieee80211_recalc_min_chandef(sdata);
 - 	ieee80211_sta_debugfs_add(sta);
 -@@ -522,6 +537,12 @@ static int sta_info_insert_finish(struct
 - 		mesh_accept_plinks_update(sdata);
-- 
-- 	return 0;
+++	memcpy(wdev->ssid, ssid, len);
++ 	wdev->wext.ibss.ssid = wdev->ssid;
++-	memcpy(wdev->wext.ibss.ssid, ssid, len);
++ 	wdev->wext.ibss.ssid_len = len;
+  
++ 	wdev_lock(wdev);
++--- a/net/wireless/mesh.c
+++++ b/net/wireless/mesh.c
++@@ -238,8 +238,8 @@ int cfg80211_set_mesh_channel(struct cfg
+  	return 0;
 -+ out_remove:
 -+	sta_info_hash_del(local, sta);
 -+	list_del_rcu(&sta->list);
@@ -5795,13 +9217,17 @@ index a1af6c2..892f51e 100644
 - 	mutex_unlock(&local->sta_mtx);
 - 	rcu_read_lock();
 -@@ -1071,10 +1092,14 @@ struct ieee80211_sta *ieee80211_find_sta
-- }
+  }
 - EXPORT_SYMBOL(ieee80211_find_sta);
-- 
+  
 --static void clear_sta_ps_flags(void *_sta)
 -+/* powersave support code */
 -+void ieee80211_sta_ps_deliver_wakeup(struct sta_info *sta)
-- {
++-static int __cfg80211_leave_mesh(struct cfg80211_registered_device *rdev,
++-				 struct net_device *dev)
+++int __cfg80211_leave_mesh(struct cfg80211_registered_device *rdev,
+++			  struct net_device *dev)
+  {
 --	struct sta_info *sta = _sta;
 - 	struct ieee80211_sub_if_data *sdata = sta->sdata;
 -+	struct ieee80211_local *local = sdata->local;
@@ -5809,12 +9235,63 @@ index a1af6c2..892f51e 100644
 -+	int filtered = 0, buffered = 0, ac;
 -+	unsigned long flags;
 - 	struct ps_data *ps;
-- 
++ 	struct wireless_dev *wdev = dev->ieee80211_ptr;
++ 	int err;
++--- a/net/wireless/nl80211.c
+++++ b/net/wireless/nl80211.c
++@@ -371,8 +371,8 @@ static const struct nla_policy nl80211_p
++ 	[NL80211_ATTR_CH_SWITCH_COUNT] = { .type = NLA_U32 },
++ 	[NL80211_ATTR_CH_SWITCH_BLOCK_TX] = { .type = NLA_FLAG },
++ 	[NL80211_ATTR_CSA_IES] = { .type = NLA_NESTED },
++-	[NL80211_ATTR_CSA_C_OFF_BEACON] = { .type = NLA_U16 },
++-	[NL80211_ATTR_CSA_C_OFF_PRESP] = { .type = NLA_U16 },
+++	[NL80211_ATTR_CSA_C_OFF_BEACON] = { .type = NLA_BINARY },
+++	[NL80211_ATTR_CSA_C_OFF_PRESP] = { .type = NLA_BINARY },
++ 	[NL80211_ATTR_STA_SUPPORTED_CHANNELS] = { .type = NLA_BINARY },
++ 	[NL80211_ATTR_STA_SUPPORTED_OPER_CLASSES] = { .type = NLA_BINARY },
++ 	[NL80211_ATTR_HANDLE_DFS] = { .type = NLA_FLAG },
++@@ -386,6 +386,7 @@ static const struct nla_policy nl80211_p
++ 	[NL80211_ATTR_WIPHY_FREQ_HINT] = { .type = NLA_U32 },
++ 	[NL80211_ATTR_TDLS_PEER_CAPABILITY] = { .type = NLA_U32 },
++ 	[NL80211_ATTR_IFACE_SOCKET_OWNER] = { .type = NLA_FLAG },
+++	[NL80211_ATTR_CSA_C_OFFSETS_TX] = { .type = NLA_BINARY },
++ };
+  
 - 	if (sdata->vif.type == NL80211_IFTYPE_AP ||
 -@@ -1085,20 +1110,6 @@ static void clear_sta_ps_flags(void *_st
 - 	else
 - 		return;
-- 
++ /* policy for the key attributes */
++@@ -970,8 +971,10 @@ static int nl80211_put_iface_combination
++ 				c->max_interfaces))
++ 			goto nla_put_failure;
++ 		if (large &&
++-		    nla_put_u32(msg, NL80211_IFACE_COMB_RADAR_DETECT_WIDTHS,
++-				c->radar_detect_widths))
+++		    (nla_put_u32(msg, NL80211_IFACE_COMB_RADAR_DETECT_WIDTHS,
+++				c->radar_detect_widths) ||
+++		     nla_put_u32(msg, NL80211_IFACE_COMB_RADAR_DETECT_REGIONS,
+++				c->radar_detect_regions)))
++ 			goto nla_put_failure;
++ 
++ 		nla_nest_end(msg, nl_combi);
++@@ -1667,6 +1670,13 @@ static int nl80211_send_wiphy(struct cfg
++ 			}
++ 			nla_nest_end(msg, nested);
++ 		}
+++		state->split_start++;
+++		break;
+++	case 12:
+++		if (rdev->wiphy.flags & WIPHY_FLAG_HAS_CHANNEL_SWITCH &&
+++		    nla_put_u8(msg, NL80211_ATTR_MAX_CSA_COUNTERS,
+++			       rdev->wiphy.max_num_csa_counters))
+++			goto nla_put_failure;
++ 
++ 		/* done */
++ 		state->split_start = 0;
++@@ -5825,7 +5835,7 @@ static int nl80211_start_radar_detection
++ 		return -EBUSY;
+  
 --	clear_sta_flag(sta, WLAN_STA_PS_DRIVER);
 --	if (test_and_clear_sta_flag(sta, WLAN_STA_PS_STA))
 --		atomic_dec(&ps->num_sta_ps);
@@ -5830,25 +9307,26 @@ index a1af6c2..892f51e 100644
 --	unsigned long flags;
 --
 - 	clear_sta_flag(sta, WLAN_STA_SP);
-- 
++ 	err = cfg80211_chandef_dfs_required(wdev->wiphy, &chandef,
++-					    NL80211_IFTYPE_UNSPECIFIED);
+++					    wdev->iftype);
++ 	if (err < 0)
++ 		return err;
+  
 - 	BUILD_BUG_ON(BITS_TO_LONGS(IEEE80211_NUM_TIDS) > 1);
 -@@ -1109,6 +1120,8 @@ void ieee80211_sta_ps_deliver_wakeup(str
-- 
++@@ -5866,6 +5876,7 @@ static int nl80211_channel_switch(struct
++ 	u8 radar_detect_width = 0;
++ 	int err;
++ 	bool need_new_beacon = false;
+++	int len, i;
+  
 - 	skb_queue_head_init(&pending);
-+@@ -670,6 +670,7 @@ static const struct ieee80211_iface_comb
-+ 		.num_different_channels = 1,
-+ 		.beacon_int_infra_match = true,
-+ 	},
-++#ifdef CONFIG_ATH9K_DFS_CERTIFIED
-+ 	{
-+ 		.limits = if_dfs_limits,
-+ 		.n_limits = ARRAY_SIZE(if_dfs_limits),
-+@@ -679,6 +680,7 @@ static const struct ieee80211_iface_comb
-+ 		.radar_detect_widths =	BIT(NL80211_CHAN_WIDTH_20_NOHT) |
-+ 					BIT(NL80211_CHAN_WIDTH_20),
-+ 	}
-++#endif
-+ };
++ 	if (!rdev->ops->channel_switch ||
++ 	    !(rdev->wiphy.flags & WIPHY_FLAG_HAS_CHANNEL_SWITCH))
++@@ -5924,26 +5935,55 @@ static int nl80211_channel_switch(struct
++ 	if (!csa_attrs[NL80211_ATTR_CSA_C_OFF_BEACON])
++ 		return -EINVAL;
   
 -+	/* sync with ieee80211_tx_h_unicast_ps_buf */
 -+	spin_lock(&sta->ps_lock);
@@ -5858,19 +9336,19 @@ index a1af6c2..892f51e 100644
 -@@ -1127,7 +1140,12 @@ void ieee80211_sta_ps_deliver_wakeup(str
 - 		buffered += tmp - count;
 - 	}
-+ static void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw)
-+@@ -781,6 +783,9 @@ int ath9k_init_device(u16 devid, struct 
-+ 	common = ath9k_hw_common(ah);
-+ 	ath9k_set_hw_capab(sc, hw);
++-	params.counter_offset_beacon =
++-		nla_get_u16(csa_attrs[NL80211_ATTR_CSA_C_OFF_BEACON]);
++-	if (params.counter_offset_beacon >= params.beacon_csa.tail_len)
+++	len = nla_len(csa_attrs[NL80211_ATTR_CSA_C_OFF_BEACON]);
+++	if (!len || (len % sizeof(u16)))
++ 		return -EINVAL;
   
 --	ieee80211_add_pending_skbs_fn(local, &pending, clear_sta_ps_flags, sta);
 -+	ieee80211_add_pending_skbs(local, &pending);
 -+	clear_sta_flag(sta, WLAN_STA_PS_DRIVER);
 -+	clear_sta_flag(sta, WLAN_STA_PS_STA);
 -+	spin_unlock(&sta->ps_lock);
-++	/* Will be cleared in ath9k_start() */
-++	set_bit(ATH_OP_INVALID, &common->op_flags);
- +
+-+
 -+	atomic_dec(&ps->num_sta_ps);
 - 
 - 	/* This station just woke up and isn't aware of our SMPS state */
@@ -5888,7 +9366,15 @@ index a1af6c2..892f51e 100644
 -@@ -356,10 +357,8 @@ struct sta_info {
 - 	/* use the accessors defined below */
 - 	unsigned long _flags;
-- 
++-	/* sanity check - counters should be the same */
++-	if (params.beacon_csa.tail[params.counter_offset_beacon] !=
++-	    params.count)
+++	params.n_counter_offsets_beacon = len / sizeof(u16);
+++	if (rdev->wiphy.max_num_csa_counters &&
+++	    (params.n_counter_offsets_beacon >
+++	     rdev->wiphy.max_num_csa_counters))
++ 		return -EINVAL;
+  
 --	/*
 --	 * STA powersave frame queues, no more than the internal
 --	 * locking required.
@@ -5903,41 +9389,66 @@ index a1af6c2..892f51e 100644
 -@@ -435,9 +435,8 @@ void ieee80211_add_pending_skb(struct ie
 - 	spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags);
 - }
-- 
+++	params.counter_offsets_beacon =
+++		nla_data(csa_attrs[NL80211_ATTR_CSA_C_OFF_BEACON]);
+++
+++	/* sanity checks - counters should fit and be the same */
+++	for (i = 0; i < params.n_counter_offsets_beacon; i++) {
+++		u16 offset = params.counter_offsets_beacon[i];
+++
+++		if (offset >= params.beacon_csa.tail_len)
+++			return -EINVAL;
+++
+++		if (params.beacon_csa.tail[offset] != params.count)
+++			return -EINVAL;
+++	}
+++
++ 	if (csa_attrs[NL80211_ATTR_CSA_C_OFF_PRESP]) {
++-		params.counter_offset_presp =
++-			nla_get_u16(csa_attrs[NL80211_ATTR_CSA_C_OFF_PRESP]);
++-		if (params.counter_offset_presp >=
++-		    params.beacon_csa.probe_resp_len)
+++		len = nla_len(csa_attrs[NL80211_ATTR_CSA_C_OFF_PRESP]);
+++		if (!len || (len % sizeof(u16)))
++ 			return -EINVAL;
+  
 --void ieee80211_add_pending_skbs_fn(struct ieee80211_local *local,
 --				   struct sk_buff_head *skbs,
 --				   void (*fn)(void *data), void *data)
 -+void ieee80211_add_pending_skbs(struct ieee80211_local *local,
 -+				struct sk_buff_head *skbs)
-+ 	/* Initialize regulatory */
-+ 	error = ath_regd_init(&common->regulatory, sc->hw->wiphy,
-+ 			      ath9k_reg_notifier);
-+--- a/drivers/net/wireless/ath/ath9k/pci.c
-++++ b/drivers/net/wireless/ath/ath9k/pci.c
-+@@ -784,7 +784,6 @@ static int ath_pci_probe(struct pci_dev 
-  {
+- {
 - 	struct ieee80211_hw *hw = &local->hw;
 - 	struct sk_buff *skb;
 -@@ -461,9 +460,6 @@ void ieee80211_add_pending_skbs_fn(struc
 - 		__skb_queue_tail(&local->pending[queue], skb);
-- 	}
-- 
++-		if (params.beacon_csa.probe_resp[params.counter_offset_presp] !=
++-		    params.count)
+++		params.n_counter_offsets_presp = len / sizeof(u16);
+++		if (rdev->wiphy.max_num_csa_counters &&
+++		    (params.n_counter_offsets_beacon >
+++		     rdev->wiphy.max_num_csa_counters))
++ 			return -EINVAL;
+++
+++		params.counter_offsets_presp =
+++			nla_data(csa_attrs[NL80211_ATTR_CSA_C_OFF_PRESP]);
+++
+++		/* sanity checks - counters should fit and be the same */
+++		for (i = 0; i < params.n_counter_offsets_presp; i++) {
+++			u16 offset = params.counter_offsets_presp[i];
+++
+++			if (offset >= params.beacon_csa.probe_resp_len)
+++				return -EINVAL;
+++
+++			if (params.beacon_csa.probe_resp[offset] !=
+++			    params.count)
+++				return -EINVAL;
+++		}
+  	}
+  
 --	if (fn)
 --		fn(data);
-+ 	struct ath_softc *sc;
-+ 	struct ieee80211_hw *hw;
-+-	struct ath_common *common;
-+ 	u8 csz;
-+ 	u32 val;
-+ 	int ret = 0;
-+@@ -877,10 +876,6 @@ static int ath_pci_probe(struct pci_dev 
-+ 	wiphy_info(hw->wiphy, "%s mem=0x%lx, irq=%d\n",
-+ 		   hw_name, (unsigned long)sc->mem, pdev->irq);
-+ 
-+-	/* Will be cleared in ath9k_start() */
-+-	common = ath9k_hw_common(sc->sc_ah);
-+-	set_bit(ATH_OP_INVALID, &common->op_flags);
- -
+--
 - 	for (i = 0; i < hw->queues; i++)
 - 		__ieee80211_wake_queue(hw, i,
 - 			IEEE80211_QUEUE_STOP_REASON_SKB_ADD);
@@ -5992,7 +9503,11 @@ index a1af6c2..892f51e 100644
 -+	if (common->disable_ani)
 - 		goto exit;
 --	}
-- 
++ skip_beacons:
++@@ -7793,6 +7833,27 @@ static int nl80211_tx_mgmt(struct sk_buf
++ 	if (!chandef.chan && params.offchan)
++ 		return -EINVAL;
+  
 --	len += scnprintf(buf + len, size - len, "%15s: %s\n",
 --			 "ANI", "ENABLED");
 --	len += scnprintf(buf + len, size - len, "%15s: %u\n",
@@ -6083,16 +9598,47 @@ index a1af6c2..892f51e 100644
 -+			 */
 -+			rs->rs_datalen = 0;
 -+			rs->rs_more = true;
--+		}
-- 	}
-- 
+++	params.buf = nla_data(info->attrs[NL80211_ATTR_FRAME]);
+++	params.len = nla_len(info->attrs[NL80211_ATTR_FRAME]);
+++
+++	if (info->attrs[NL80211_ATTR_CSA_C_OFFSETS_TX]) {
+++		int len = nla_len(info->attrs[NL80211_ATTR_CSA_C_OFFSETS_TX]);
+++		int i;
+++
+++		if (len % sizeof(u16))
+++			return -EINVAL;
+++
+++		params.n_csa_offsets = len / sizeof(u16);
+++		params.csa_offsets =
+++			nla_data(info->attrs[NL80211_ATTR_CSA_C_OFFSETS_TX]);
+++
+++		/* check that all the offsets fit the frame */
+++		for (i = 0; i < params.n_csa_offsets; i++) {
+++			if (params.csa_offsets[i] >= params.len)
+++				return -EINVAL;
+ +		}
+++	}
+++
++ 	if (!params.dont_wait_for_ack) {
++ 		msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
++ 		if (!msg)
++@@ -7807,8 +7868,6 @@ static int nl80211_tx_mgmt(struct sk_buf
++ 		}
+  	}
+  
 - 	list_del(&bf->list);
 -@@ -985,32 +992,32 @@ static int ath9k_rx_skb_preprocess(struc
 - 	struct ath_common *common = ath9k_hw_common(ah);
 - 	struct ieee80211_hdr *hdr;
 - 	bool discard_current = sc->rx.discard_next;
 --	int ret = 0;
-- 
++-	params.buf = nla_data(info->attrs[NL80211_ATTR_FRAME]);
++-	params.len = nla_len(info->attrs[NL80211_ATTR_FRAME]);
++ 	params.chan = chandef.chan;
++ 	err = cfg80211_mlme_mgmt_tx(rdev, wdev, &params, &cookie);
++ 	if (err)
++@@ -8507,6 +8566,8 @@ static int nl80211_set_wowlan(struct sk_
+  
 - 	/*
 - 	 * Discard corrupt descriptors which are marked in
 - 	 * ath_get_next_rx_buf().
@@ -6101,7 +9647,10 @@ index a1af6c2..892f51e 100644
 - 	if (discard_current)
 --		return -EINVAL;
 -+		goto corrupt;
--+
++ 		nla_for_each_nested(pat, tb[NL80211_WOWLAN_TRIG_PKT_PATTERN],
++ 				    rem) {
+++			u8 *mask_pat;
+ +
 -+	sc->rx.discard_next = false;
 - 
 - 	/*
@@ -6112,7 +9661,38 @@ index a1af6c2..892f51e 100644
 --		return -EINVAL;
 -+		goto corrupt;
 - 	}
-- 
++ 			nla_parse(pat_tb, MAX_NL80211_PKTPAT, nla_data(pat),
++ 				  nla_len(pat), NULL);
++ 			err = -EINVAL;
++@@ -8530,19 +8591,18 @@ static int nl80211_set_wowlan(struct sk_
++ 				goto error;
++ 			new_triggers.patterns[i].pkt_offset = pkt_offset;
++ 
++-			new_triggers.patterns[i].mask =
++-				kmalloc(mask_len + pat_len, GFP_KERNEL);
++-			if (!new_triggers.patterns[i].mask) {
+++			mask_pat = kmalloc(mask_len + pat_len, GFP_KERNEL);
+++			if (!mask_pat) {
++ 				err = -ENOMEM;
++ 				goto error;
++ 			}
++-			new_triggers.patterns[i].pattern =
++-				new_triggers.patterns[i].mask + mask_len;
++-			memcpy(new_triggers.patterns[i].mask,
++-			       nla_data(pat_tb[NL80211_PKTPAT_MASK]),
+++			new_triggers.patterns[i].mask = mask_pat;
+++			memcpy(mask_pat, nla_data(pat_tb[NL80211_PKTPAT_MASK]),
++ 			       mask_len);
+++			mask_pat += mask_len;
+++			new_triggers.patterns[i].pattern = mask_pat;
++ 			new_triggers.patterns[i].pattern_len = pat_len;
++-			memcpy(new_triggers.patterns[i].pattern,
+++			memcpy(mask_pat,
++ 			       nla_data(pat_tb[NL80211_PKTPAT_PATTERN]),
++ 			       pat_len);
++ 			i++;
++@@ -8735,6 +8795,8 @@ static int nl80211_parse_coalesce_rule(s
+  
 --        /*
 --         * rs_status follows rs_datalen so if rs_datalen is too large
 --         * we can take a hint that hardware corrupted it, so ignore
@@ -6127,8 +9707,42 @@ index a1af6c2..892f51e 100644
 - 		RX_STAT_INC(rx_len_err);
 --		return -EINVAL;
 -+		goto corrupt;
-- 	}
-- 
++ 	nla_for_each_nested(pat, tb[NL80211_ATTR_COALESCE_RULE_PKT_PATTERN],
++ 			    rem) {
+++		u8 *mask_pat;
+++
++ 		nla_parse(pat_tb, MAX_NL80211_PKTPAT, nla_data(pat),
++ 			  nla_len(pat), NULL);
++ 		if (!pat_tb[NL80211_PKTPAT_MASK] ||
++@@ -8756,17 +8818,19 @@ static int nl80211_parse_coalesce_rule(s
++ 			return -EINVAL;
++ 		new_rule->patterns[i].pkt_offset = pkt_offset;
++ 
++-		new_rule->patterns[i].mask =
++-			kmalloc(mask_len + pat_len, GFP_KERNEL);
++-		if (!new_rule->patterns[i].mask)
+++		mask_pat = kmalloc(mask_len + pat_len, GFP_KERNEL);
+++		if (!mask_pat)
++ 			return -ENOMEM;
++-		new_rule->patterns[i].pattern =
++-			new_rule->patterns[i].mask + mask_len;
++-		memcpy(new_rule->patterns[i].mask,
++-		       nla_data(pat_tb[NL80211_PKTPAT_MASK]), mask_len);
+++
+++		new_rule->patterns[i].mask = mask_pat;
+++		memcpy(mask_pat, nla_data(pat_tb[NL80211_PKTPAT_MASK]),
+++		       mask_len);
+++
+++		mask_pat += mask_len;
+++		new_rule->patterns[i].pattern = mask_pat;
++ 		new_rule->patterns[i].pattern_len = pat_len;
++-		memcpy(new_rule->patterns[i].pattern,
++-		       nla_data(pat_tb[NL80211_PKTPAT_PATTERN]), pat_len);
+++		memcpy(mask_pat, nla_data(pat_tb[NL80211_PKTPAT_PATTERN]),
+++		       pat_len);
++ 		i++;
+  	}
+  
 - 	/* Only use status info from the last fragment */
 -@@ -1024,10 +1031,8 @@ static int ath9k_rx_skb_preprocess(struc
 - 	 * This is different from the other corrupt descriptor
@@ -6146,106 +9760,35 @@ index a1af6c2..892f51e 100644
 -@@ -1043,18 +1048,15 @@ static int ath9k_rx_skb_preprocess(struc
 - 		if (ath_process_fft(sc, hdr, rx_stats, rx_status->mactime))
 - 			RX_STAT_INC(rx_spectral);
-+ 	return 0;
-  
+- 
 --		ret = -EINVAL;
 --		goto exit;
 -+		return -EINVAL;
-+ err_init:
-+--- a/drivers/net/wireless/ath/ath9k/ar9003_2p2_initvals.h
-++++ b/drivers/net/wireless/ath/ath9k/ar9003_2p2_initvals.h
-+@@ -410,7 +410,7 @@ static const u32 ar9300_2p2_baseband_cor
-+ 	{0x00009e30, 0x06336f77},
-+ 	{0x00009e34, 0x6af6532f},
-+ 	{0x00009e38, 0x0cc80c00},
-+-	{0x00009e40, 0x0d261820},
-++	{0x00009e40, 0x0d261800},
-+ 	{0x00009e4c, 0x00001004},
-+ 	{0x00009e50, 0x00ff03f1},
-+ 	{0x00009e54, 0x00000000},
-+--- a/drivers/net/wireless/ath/ath9k/ar9330_1p1_initvals.h
-++++ b/drivers/net/wireless/ath/ath9k/ar9330_1p1_initvals.h
-+@@ -592,7 +592,7 @@ static const u32 ar9331_1p1_baseband_cor
-+ 	{0x00009e30, 0x06336f77},
-+ 	{0x00009e34, 0x6af6532f},
-+ 	{0x00009e38, 0x0cc80c00},
-+-	{0x00009e40, 0x0d261820},
-++	{0x00009e40, 0x0d261800},
-+ 	{0x00009e4c, 0x00001004},
-+ 	{0x00009e50, 0x00ff03f1},
-+ 	{0x00009fc0, 0x803e4788},
-+--- a/drivers/net/wireless/ath/ath9k/ar9330_1p2_initvals.h
-++++ b/drivers/net/wireless/ath/ath9k/ar9330_1p2_initvals.h
-+@@ -231,7 +231,7 @@ static const u32 ar9331_1p2_baseband_cor
-+ 	{0x00009e30, 0x06336f77},
-+ 	{0x00009e34, 0x6af6532f},
-+ 	{0x00009e38, 0x0cc80c00},
-+-	{0x00009e40, 0x0d261820},
-++	{0x00009e40, 0x0d261800},
-+ 	{0x00009e4c, 0x00001004},
-+ 	{0x00009e50, 0x00ff03f1},
-+ 	{0x00009fc0, 0x803e4788},
-+--- a/drivers/net/wireless/ath/ath9k/ar9340_initvals.h
-++++ b/drivers/net/wireless/ath/ath9k/ar9340_initvals.h
-+@@ -318,7 +318,7 @@ static const u32 ar9340_1p0_baseband_cor
-+ 	{0x00009e30, 0x06336f77},
-+ 	{0x00009e34, 0x6af6532f},
-+ 	{0x00009e38, 0x0cc80c00},
-+-	{0x00009e40, 0x0d261820},
-++	{0x00009e40, 0x0d261800},
-+ 	{0x00009e4c, 0x00001004},
-+ 	{0x00009e50, 0x00ff03f1},
-+ 	{0x00009e54, 0x00000000},
-+@@ -348,9 +348,9 @@ static const u32 ar9340_1p0_baseband_cor
-+ 	{0x0000a370, 0x00000000},
-+ 	{0x0000a390, 0x00000001},
-+ 	{0x0000a394, 0x00000444},
-+-	{0x0000a398, 0x00000000},
-+-	{0x0000a39c, 0x210d0401},
-+-	{0x0000a3a0, 0xab9a7144},
-++	{0x0000a398, 0x001f0e0f},
-++	{0x0000a39c, 0x0075393f},
-++	{0x0000a3a0, 0xb79f6427},
-+ 	{0x0000a3a4, 0x00000000},
-+ 	{0x0000a3a8, 0xaaaaaaaa},
-+ 	{0x0000a3ac, 0x3c466478},
-+--- a/drivers/net/wireless/ath/ath9k/ar9580_1p0_initvals.h
-++++ b/drivers/net/wireless/ath/ath9k/ar9580_1p0_initvals.h
-+@@ -90,7 +90,7 @@ static const u32 ar9580_1p0_baseband_cor
-+ 	{0x00009e30, 0x06336f77},
-+ 	{0x00009e34, 0x6af6532f},
-+ 	{0x00009e38, 0x0cc80c00},
-+-	{0x00009e40, 0x0d261820},
-++	{0x00009e40, 0x0d261800},
-+ 	{0x00009e4c, 0x00001004},
-+ 	{0x00009e50, 0x00ff03f1},
-+ 	{0x00009e54, 0x00000000},
-+--- a/drivers/net/wireless/ath/ath9k/ar953x_initvals.h
-++++ b/drivers/net/wireless/ath/ath9k/ar953x_initvals.h
-+@@ -257,9 +257,9 @@ static const u32 qca953x_1p0_baseband_co
-+ 	{0x0000a370, 0x00000000},
-+ 	{0x0000a390, 0x00000001},
-+ 	{0x0000a394, 0x00000444},
-+-	{0x0000a398, 0x1f020503},
-+-	{0x0000a39c, 0x29180c03},
-+-	{0x0000a3a0, 0x9a8b6844},
-++	{0x0000a398, 0x001f0e0f},
-++	{0x0000a39c, 0x0075393f},
-++	{0x0000a3a0, 0xb79f6427},
-+ 	{0x0000a3a4, 0x000000ff},
-+ 	{0x0000a3a8, 0x6a6a6a6a},
-+ 	{0x0000a3ac, 0x6a6a6a6a},
-+--- a/drivers/net/wireless/ath/ath5k/phy.c
-++++ b/drivers/net/wireless/ath/ath5k/phy.c
-+@@ -3709,8 +3709,8 @@ ath5k_hw_txpower(struct ath5k_hw *ah, st
-+ 			AR5K_REG_MS(AR5K_TUNE_MAX_TXPOWER, AR5K_TPC_CHIRP),
-+ 			AR5K_TPC);
-+ 	} else {
-+-		ath5k_hw_reg_write(ah, AR5K_PHY_TXPOWER_RATE_MAX |
-+-			AR5K_TUNE_MAX_TXPOWER, AR5K_PHY_TXPOWER_RATE_MAX);
-++		ath5k_hw_reg_write(ah, AR5K_TUNE_MAX_TXPOWER,
-++			AR5K_PHY_TXPOWER_RATE_MAX);
-  	}
+- 	}
++--- a/net/wireless/sme.c
+++++ b/net/wireless/sme.c
++@@ -149,7 +149,8 @@ static int cfg80211_conn_do_work(struct 
++ 	case CFG80211_CONN_SCAN_AGAIN:
++ 		return cfg80211_conn_scan(wdev);
++ 	case CFG80211_CONN_AUTHENTICATE_NEXT:
++-		BUG_ON(!rdev->ops->auth);
+++		if (WARN_ON(!rdev->ops->auth))
+++			return -EOPNOTSUPP;
++ 		wdev->conn->state = CFG80211_CONN_AUTHENTICATING;
++ 		return cfg80211_mlme_auth(rdev, wdev->netdev,
++ 					  params->channel, params->auth_type,
++@@ -161,7 +162,8 @@ static int cfg80211_conn_do_work(struct 
++ 	case CFG80211_CONN_AUTH_FAILED:
++ 		return -ENOTCONN;
++ 	case CFG80211_CONN_ASSOCIATE_NEXT:
++-		BUG_ON(!rdev->ops->assoc);
+++		if (WARN_ON(!rdev->ops->assoc))
+++			return -EOPNOTSUPP;
++ 		wdev->conn->state = CFG80211_CONN_ASSOCIATING;
++ 		if (wdev->conn->prev_bssid_valid)
++ 			req.prev_bssid = wdev->conn->prev_bssid;
++@@ -877,7 +879,7 @@ void __cfg80211_disconnected(struct net_
++ }
   
 - 	/*
 - 	 * everything but the rate is checked here, the rate check is done
@@ -6257,7 +9800,56 @@ index a1af6c2..892f51e 100644
 --	}
 -+	if (!ath9k_rx_accept(common, hdr, rx_status, rx_stats, decrypt_error))
 -+		return -EINVAL;
-- 
++ void cfg80211_disconnected(struct net_device *dev, u16 reason,
++-			   u8 *ie, size_t ie_len, gfp_t gfp)
+++			   const u8 *ie, size_t ie_len, gfp_t gfp)
++ {
++ 	struct wireless_dev *wdev = dev->ieee80211_ptr;
++ 	struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
++--- a/net/wireless/trace.h
+++++ b/net/wireless/trace.h
++@@ -1876,29 +1876,33 @@ TRACE_EVENT(rdev_channel_switch,
++ 		WIPHY_ENTRY
++ 		NETDEV_ENTRY
++ 		CHAN_DEF_ENTRY
++-		__field(u16, counter_offset_beacon)
++-		__field(u16, counter_offset_presp)
++ 		__field(bool, radar_required)
++ 		__field(bool, block_tx)
++ 		__field(u8, count)
+++		__dynamic_array(u16, bcn_ofs, params->n_counter_offsets_beacon)
+++		__dynamic_array(u16, pres_ofs, params->n_counter_offsets_presp)
++ 	),
++ 	TP_fast_assign(
++ 		WIPHY_ASSIGN;
++ 		NETDEV_ASSIGN;
++ 		CHAN_DEF_ASSIGN(&params->chandef);
++-		__entry->counter_offset_beacon = params->counter_offset_beacon;
++-		__entry->counter_offset_presp = params->counter_offset_presp;
++ 		__entry->radar_required = params->radar_required;
++ 		__entry->block_tx = params->block_tx;
++ 		__entry->count = params->count;
+++		memcpy(__get_dynamic_array(bcn_ofs),
+++		       params->counter_offsets_beacon,
+++		       params->n_counter_offsets_beacon * sizeof(u16));
+++
+++		/* probe response offsets are optional */
+++		if (params->n_counter_offsets_presp)
+++			memcpy(__get_dynamic_array(pres_ofs),
+++			       params->counter_offsets_presp,
+++			       params->n_counter_offsets_presp * sizeof(u16));
++ 	),
++ 	TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", " CHAN_DEF_PR_FMT
++-		  ", block_tx: %d, count: %u, radar_required: %d"
++-		  ", counter offsets (beacon/presp): %u/%u",
+++		  ", block_tx: %d, count: %u, radar_required: %d",
++ 		  WIPHY_PR_ARG, NETDEV_PR_ARG, CHAN_DEF_PR_ARG,
++-		  __entry->block_tx, __entry->count, __entry->radar_required,
++-		  __entry->counter_offset_beacon,
++-		  __entry->counter_offset_presp)
+++		  __entry->block_tx, __entry->count, __entry->radar_required)
++ );
+  
 - 	if (ath_is_mybeacon(common, hdr)) {
 - 		RX_STAT_INC(rx_beacons);
 -@@ -1064,15 +1066,11 @@ static int ath9k_rx_skb_preprocess(struc
@@ -6270,30 +9862,127 @@ index a1af6c2..892f51e 100644
 --	}
 -+	if (WARN_ON(!ah->curchan))
 -+		return -EINVAL;
-- 
++ TRACE_EVENT(rdev_set_qos_map,
++@@ -2636,6 +2640,21 @@ TRACE_EVENT(cfg80211_ft_event,
++ 		  WIPHY_PR_ARG, NETDEV_PR_ARG, MAC_PR_ARG(target_ap))
++ );
+  
 --	if (ath9k_process_rate(common, hw, rx_stats, rx_status)) {
 --		ret =-EINVAL;
 --		goto exit;
 --	}
 -+	if (ath9k_process_rate(common, hw, rx_stats, rx_status))
 -+		return -EINVAL;
-- 
+++TRACE_EVENT(cfg80211_stop_iface,
+++	TP_PROTO(struct wiphy *wiphy, struct wireless_dev *wdev),
+++	TP_ARGS(wiphy, wdev),
+++	TP_STRUCT__entry(
+++		WIPHY_ENTRY
+++		WDEV_ENTRY
+++	),
+++	TP_fast_assign(
+++		WIPHY_ASSIGN;
+++		WDEV_ASSIGN;
+++	),
+++	TP_printk(WIPHY_PR_FMT ", " WDEV_PR_FMT,
+++		  WIPHY_PR_ARG, WDEV_PR_ARG)
+++);
+++
++ #endif /* !__RDEV_OPS_TRACE || TRACE_HEADER_MULTI_READ */
+  
 - 	ath9k_process_rssi(common, hw, rx_stats, rx_status);
-- 
++ #undef TRACE_INCLUDE_PATH
++--- a/net/wireless/util.c
+++++ b/net/wireless/util.c
++@@ -476,7 +476,8 @@ int ieee80211_data_to_8023(struct sk_buf
++ EXPORT_SYMBOL(ieee80211_data_to_8023);
+  
 -@@ -1087,9 +1085,11 @@ static int ath9k_rx_skb_preprocess(struc
 - 		sc->rx.num_pkts++;
 - #endif
-- 
++ int ieee80211_data_from_8023(struct sk_buff *skb, const u8 *addr,
++-			     enum nl80211_iftype iftype, u8 *bssid, bool qos)
+++			     enum nl80211_iftype iftype,
+++			     const u8 *bssid, bool qos)
++ {
++ 	struct ieee80211_hdr hdr;
++ 	u16 hdrlen, ethertype;
++@@ -839,6 +840,9 @@ void cfg80211_process_wdev_events(struct
++ 			__cfg80211_ibss_joined(wdev->netdev, ev->ij.bssid,
++ 					       ev->ij.channel);
++ 			break;
+++		case EVENT_STOPPED:
+++			__cfg80211_leave(wiphy_to_rdev(wdev->wiphy), wdev);
+++			break;
++ 		}
++ 		wdev_unlock(wdev);
+  
 --exit:
 --	sc->rx.discard_next = false;
 --	return ret;
 -+	return 0;
--+
++@@ -1271,10 +1275,20 @@ int cfg80211_iter_combinations(struct wi
++ 					    void *data),
++ 			       void *data)
++ {
+++	const struct ieee80211_regdomain *regdom;
+++	enum nl80211_dfs_regions region = 0;
++ 	int i, j, iftype;
++ 	int num_interfaces = 0;
++ 	u32 used_iftypes = 0;
++ 
+++	if (radar_detect) {
+++		rcu_read_lock();
+++		regdom = rcu_dereference(cfg80211_regdomain);
+++		if (regdom)
+++			region = regdom->dfs_region;
+++		rcu_read_unlock();
+++	}
+ +
 -+corrupt:
 -+	sc->rx.discard_next = rx_stats->rs_more;
 -+	return -EINVAL;
-- }
-- 
++ 	for (iftype = 0; iftype < NUM_NL80211_IFTYPES; iftype++) {
++ 		num_interfaces += iftype_num[iftype];
++ 		if (iftype_num[iftype] > 0 &&
++@@ -1315,6 +1329,10 @@ int cfg80211_iter_combinations(struct wi
++ 		if (radar_detect != (c->radar_detect_widths & radar_detect))
++ 			goto cont;
++ 
+++		if (radar_detect && c->radar_detect_regions &&
+++		    !(c->radar_detect_regions & BIT(region)))
+++			goto cont;
+++
++ 		/* Finally check that all iftypes that we're currently
++ 		 * using are actually part of this combination. If they
++ 		 * aren't then we can't use this combination and have
++--- a/drivers/net/wireless/ath/ath9k/recv.c
+++++ b/drivers/net/wireless/ath/ath9k/recv.c
++@@ -34,7 +34,8 @@ static inline bool ath9k_check_auto_slee
++  * buffer (or rx fifo). This can incorrectly acknowledge packets
++  * to a sender if last desc is self-linked.
++  */
++-static void ath_rx_buf_link(struct ath_softc *sc, struct ath_rxbuf *bf)
+++static void ath_rx_buf_link(struct ath_softc *sc, struct ath_rxbuf *bf,
+++			    bool flush)
++ {
++ 	struct ath_hw *ah = sc->sc_ah;
++ 	struct ath_common *common = ath9k_hw_common(ah);
++@@ -59,18 +60,19 @@ static void ath_rx_buf_link(struct ath_s
++ 			     common->rx_bufsize,
++ 			     0);
++ 
++-	if (sc->rx.rxlink == NULL)
++-		ath9k_hw_putrxbuf(ah, bf->bf_daddr);
++-	else
+++	if (sc->rx.rxlink)
++ 		*sc->rx.rxlink = bf->bf_daddr;
+++	else if (!flush)
+++		ath9k_hw_putrxbuf(ah, bf->bf_daddr);
++ 
++ 	sc->rx.rxlink = &ds->ds_link;
+  }
+  
 - static void ath9k_rx_skb_postprocess(struct ath_common *common,
 ---- a/drivers/net/wireless/ath/ath9k/ani.c
 -+++ b/drivers/net/wireless/ath/ath9k/ani.c
@@ -6329,7 +10018,14 @@ index a1af6c2..892f51e 100644
 -+
 -+	if (!AR_SREV_9300_20_OR_LATER(ah))
 -+		return;
-- 
++-static void ath_rx_buf_relink(struct ath_softc *sc, struct ath_rxbuf *bf)
+++static void ath_rx_buf_relink(struct ath_softc *sc, struct ath_rxbuf *bf,
+++			      bool flush)
++ {
++ 	if (sc->rx.buf_hold)
++-		ath_rx_buf_link(sc, sc->rx.buf_hold);
+++		ath_rx_buf_link(sc, sc->rx.buf_hold, flush);
+  
 - 	if (aniState->ofdmNoiseImmunityLevel >= ATH9K_ANI_OFDM_DEF_LEVEL) {
 - 		ah->config.ofdm_trig_high = ATH9K_ANI_OFDM_TRIG_HIGH;
 -@@ -308,17 +318,6 @@ void ath9k_ani_reset(struct ath_hw *ah, 
@@ -6369,7 +10065,16 @@ index a1af6c2..892f51e 100644
 -+		ah->config.cck_trig_high = ATH9K_ANI_CCK_TRIG_HIGH_OLD;
 -+		ah->config.cck_trig_low = ATH9K_ANI_CCK_TRIG_LOW_OLD;
 -+	}
-- 
++ 	sc->rx.buf_hold = bf;
++ }
++@@ -442,7 +444,7 @@ int ath_startrecv(struct ath_softc *sc)
++ 	sc->rx.buf_hold = NULL;
++ 	sc->rx.rxlink = NULL;
++ 	list_for_each_entry_safe(bf, tbf, &sc->rx.rxbuf, list) {
++-		ath_rx_buf_link(sc, bf);
+++		ath_rx_buf_link(sc, bf, false);
++ 	}
+  
 - 	ani->spurImmunityLevel = ATH9K_ANI_SPUR_IMMUNE_LVL;
 - 	ani->firstepLevel = ATH9K_ANI_FIRSTEP_LVL;
 ---- a/drivers/net/wireless/ath/ath9k/ani.h
@@ -6523,16 +10228,33 @@ index a1af6c2..892f51e 100644
 - 				aniState->iniDef.cycpwrThr1Ext);
 - 			if (level > aniState->spurImmunityLevel)
 - 				ah->stats.ast_ani_spurup++;
-+ 	return 0;
++ 	/* We could have deleted elements so the list may be empty now */
++@@ -1118,12 +1120,12 @@ requeue_drop_frag:
++ requeue:
++ 		list_add_tail(&bf->list, &sc->rx.rxbuf);
++ 
++-		if (edma) {
++-			ath_rx_edma_buf_link(sc, qtype);
++-		} else {
++-			ath_rx_buf_relink(sc, bf);
+++		if (!edma) {
+++			ath_rx_buf_relink(sc, bf, flush);
++ 			if (!flush)
++ 				ath9k_hw_rxena(ah);
+++		} else if (!flush) {
+++			ath_rx_edma_buf_link(sc, qtype);
++ 		}
++ 
++ 		if (!budget--)
 diff --git a/package/mac80211/patches/310-ap_scan.patch b/package/mac80211/patches/310-ap_scan.patch
-index 389a003..87f165a 100644
+index 389a003..a12e7e5 100644
 --- a/package/mac80211/patches/310-ap_scan.patch
 +++ b/package/mac80211/patches/310-ap_scan.patch
 @@ -1,6 +1,6 @@
  --- a/net/mac80211/cfg.c
  +++ b/net/mac80211/cfg.c
 -@@ -2148,7 +2148,7 @@ static int ieee80211_scan(struct wiphy *
-+@@ -2154,7 +2154,7 @@ static int ieee80211_scan(struct wiphy *
++@@ -2197,7 +2197,7 @@ static int ieee80211_scan(struct wiphy *
   		 * the  frames sent while scanning on other channel will be
   		 * lost)
   		 */
@@ -6549,21 +10271,8 @@ index 0dba7ac..4cc77af 100644
   #endif /* CPTCFG_ATH_DEBUG */
   
   /** Returns string describing opmode, or NULL if unknown mode. */
-diff --git a/package/mac80211/patches/402-ath9k-fix-invalid-mac-address-handling.patch b/package/mac80211/patches/402-ath9k-fix-invalid-mac-address-handling.patch
-index 63ab0db..acaa317 100644
---- a/package/mac80211/patches/402-ath9k-fix-invalid-mac-address-handling.patch
-+++ b/package/mac80211/patches/402-ath9k-fix-invalid-mac-address-handling.patch
-@@ -8,7 +8,7 @@
-  #include <asm/unaligned.h>
-  
-  #include "hw.h"
--@@ -449,8 +450,16 @@ static int ath9k_hw_init_macaddr(struct 
-+@@ -448,8 +449,16 @@ static int ath9k_hw_init_macaddr(struct 
-  		common->macaddr[2 * i] = eeval >> 8;
-  		common->macaddr[2 * i + 1] = eeval & 0xff;
-  	}
 diff --git a/package/mac80211/patches/403-ath_regd_optional.patch b/package/mac80211/patches/403-ath_regd_optional.patch
-index 07c54cc..4a9b7e4 100644
+index 07c54cc..808e729 100644
 --- a/package/mac80211/patches/403-ath_regd_optional.patch
 +++ b/package/mac80211/patches/403-ath_regd_optional.patch
 @@ -58,7 +58,7 @@
@@ -6571,19 +10280,19 @@ index 07c54cc..4a9b7e4 100644
  --- a/.local-symbols
  +++ b/.local-symbols
 -@@ -119,6 +119,7 @@ RTL8187_LEDS=
-+@@ -120,6 +120,7 @@ RTL8187_LEDS=
++@@ -116,6 +116,7 @@ RTL8187_LEDS=
   ATH_COMMON=
   ATH_CARDS=
   ATH_DEBUG=
 diff --git a/package/mac80211/patches/405-regd_no_assoc_hints.patch b/package/mac80211/patches/405-regd_no_assoc_hints.patch
-index 6ad4fda..4fa611f 100644
+index 6ad4fda..ef60f9e 100644
 --- a/package/mac80211/patches/405-regd_no_assoc_hints.patch
 +++ b/package/mac80211/patches/405-regd_no_assoc_hints.patch
 @@ -1,6 +1,6 @@
  --- a/net/wireless/reg.c
  +++ b/net/wireless/reg.c
 -@@ -1878,6 +1878,8 @@ void regulatory_hint_country_ie(struct w
-+@@ -2000,6 +2000,8 @@ void regulatory_hint_country_ie(struct w
++@@ -2079,6 +2079,8 @@ void regulatory_hint_country_ie(struct w
   	enum environment_cap env = ENVIRON_ANY;
   	struct regulatory_request *request = NULL, *lr;
   
@@ -6592,22 +10301,26 @@ index 6ad4fda..4fa611f 100644
   	if (country_ie_len & 0x01)
   		return;
 -@@ -2072,6 +2074,7 @@ static void restore_regulatory_settings(
-+@@ -2194,6 +2196,7 @@ static void restore_regulatory_settings(
++@@ -2275,6 +2277,7 @@ static void restore_regulatory_settings(
   
   void regulatory_hint_disconnect(void)
   {
 diff --git a/package/mac80211/patches/410-ath9k_allow_adhoc_and_ap.patch b/package/mac80211/patches/410-ath9k_allow_adhoc_and_ap.patch
-index 1f71e0b..909a5f1 100644
+index 1f71e0b..ce752f1 100644
 --- a/package/mac80211/patches/410-ath9k_allow_adhoc_and_ap.patch
 +++ b/package/mac80211/patches/410-ath9k_allow_adhoc_and_ap.patch
-@@ -1,6 +1,6 @@
+@@ -1,8 +1,8 @@
  --- a/drivers/net/wireless/ath/ath9k/init.c
  +++ b/drivers/net/wireless/ath/ath9k/init.c
 -@@ -866,6 +866,7 @@ static const struct ieee80211_iface_limi
-+@@ -652,6 +652,7 @@ static const struct ieee80211_iface_limi
-  #endif
-  				 BIT(NL80211_IFTYPE_AP) |
+- #endif
+- 				 BIT(NL80211_IFTYPE_AP) |
++@@ -655,6 +655,7 @@ static const struct ieee80211_iface_limi
++ 				 BIT(NL80211_IFTYPE_AP) },
++ 	{ .max = 1,	.types = BIT(NL80211_IFTYPE_P2P_CLIENT) |
   				 BIT(NL80211_IFTYPE_P2P_GO) },
+ +	{ .max = 1,	.types = BIT(NL80211_IFTYPE_ADHOC) },
+  };
 diff --git a/package/mac80211/patches/411-ath5k_allow_adhoc_and_ap.patch b/package/mac80211/patches/411-ath5k_allow_adhoc_and_ap.patch
 index 3487ab2..1f06994 100644
 --- a/package/mac80211/patches/411-ath5k_allow_adhoc_and_ap.patch
@@ -6640,14 +10353,14 @@ index 3487ab2..1f06994 100644
   #endif
   				 BIT(NL80211_IFTYPE_AP) },
 diff --git a/package/mac80211/patches/500-ath9k_eeprom_debugfs.patch b/package/mac80211/patches/500-ath9k_eeprom_debugfs.patch
-index 664cf45..36e0151 100644
+index 664cf45..65821fe 100644
 --- a/package/mac80211/patches/500-ath9k_eeprom_debugfs.patch
 +++ b/package/mac80211/patches/500-ath9k_eeprom_debugfs.patch
 @@ -1,6 +1,6 @@
  --- a/drivers/net/wireless/ath/ath9k/debug.c
  +++ b/drivers/net/wireless/ath/ath9k/debug.c
 -@@ -1481,6 +1481,53 @@ void ath9k_deinit_debug(struct ath_softc
-+@@ -1485,6 +1485,53 @@ void ath9k_deinit_debug(struct ath_softc
++@@ -1289,6 +1289,53 @@ void ath9k_deinit_debug(struct ath_softc
   	ath9k_spectral_deinit_debug(sc);
   }
   
@@ -6656,7 +10369,7 @@ index 664cf45..36e0151 100644
   {
   	struct ath_common *common = ath9k_hw_common(ah);
 -@@ -1500,6 +1547,8 @@ int ath9k_init_debug(struct ath_hw *ah)
-+@@ -1504,6 +1551,8 @@ int ath9k_init_debug(struct ath_hw *ah)
++@@ -1308,6 +1355,8 @@ int ath9k_init_debug(struct ath_hw *ah)
   	ath9k_tx99_init_debug(sc);
   	ath9k_spectral_init_debug(sc);
   
@@ -6674,7 +10387,7 @@ index 96e7c6d..169eb9a 100644
   		ah->get_mac_revision = pdata->get_mac_revision;
   		ah->external_reset = pdata->external_reset;
 diff --git a/package/mac80211/patches/502-ath9k_ahb_init.patch b/package/mac80211/patches/502-ath9k_ahb_init.patch
-index 4edc63b..de61a9e 100644
+index 4edc63b..0c8e813 100644
 --- a/package/mac80211/patches/502-ath9k_ahb_init.patch
 +++ b/package/mac80211/patches/502-ath9k_ahb_init.patch
 @@ -1,15 +1,15 @@
@@ -6683,7 +10396,7 @@ index 4edc63b..de61a9e 100644
 -@@ -1112,23 +1112,23 @@ static int __init ath9k_init(void)
 - 		goto err_out;
 - 	}
-+@@ -897,23 +897,23 @@ static int __init ath9k_init(void)
++@@ -904,23 +904,23 @@ static int __init ath9k_init(void)
 + {
 + 	int error;
   
@@ -6707,18 +10420,6 @@ index 4edc63b..de61a9e 100644
 +  err_out:
 + 	return error;
 + }
-diff --git a/package/mac80211/patches/510-ath9k_intr_mitigation_tweak.patch b/package/mac80211/patches/510-ath9k_intr_mitigation_tweak.patch
-index d7478ff..c818933 100644
---- a/package/mac80211/patches/510-ath9k_intr_mitigation_tweak.patch
-+++ b/package/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
--@@ -359,13 +359,8 @@ static void ath9k_hw_init_config(struct 
-+@@ -358,13 +358,8 @@ static void ath9k_hw_init_config(struct 
-  
-  	ah->config.rx_intr_mitigation = true;
-  
 diff --git a/package/mac80211/patches/511-ath9k_reduce_rxbuf.patch b/package/mac80211/patches/511-ath9k_reduce_rxbuf.patch
 index ef0b9a1..e457267 100644
 --- a/package/mac80211/patches/511-ath9k_reduce_rxbuf.patch
@@ -6732,14 +10433,14 @@ index ef0b9a1..e457267 100644
   	} while (0)
   
 diff --git a/package/mac80211/patches/512-ath9k_channelbw_debugfs.patch b/package/mac80211/patches/512-ath9k_channelbw_debugfs.patch
-index 8f3cc03..665d8aa 100644
+index 8f3cc03..c0e173f 100644
 --- a/package/mac80211/patches/512-ath9k_channelbw_debugfs.patch
 +++ b/package/mac80211/patches/512-ath9k_channelbw_debugfs.patch
 @@ -1,6 +1,6 @@
  --- a/drivers/net/wireless/ath/ath9k/debug.c
  +++ b/drivers/net/wireless/ath/ath9k/debug.c
 -@@ -1528,6 +1528,52 @@ static const struct file_operations fops
-+@@ -1532,6 +1532,52 @@ static const struct file_operations fops
++@@ -1336,6 +1336,52 @@ static const struct file_operations fops
   	.owner = THIS_MODULE
   };
   
@@ -6757,7 +10458,7 @@ index 8f3cc03..665d8aa 100644
   {
   	struct ath_common *common = ath9k_hw_common(ah);
 -@@ -1549,6 +1595,8 @@ int ath9k_init_debug(struct ath_hw *ah)
-+@@ -1553,6 +1599,8 @@ int ath9k_init_debug(struct ath_hw *ah)
++@@ -1357,6 +1403,8 @@ int ath9k_init_debug(struct ath_hw *ah)
   
   	debugfs_create_file("eeprom", S_IRUSR, sc->debug.debugfs_phy, sc,
   			    &fops_eeprom);
@@ -6800,27 +10501,15 @@ index 8f3cc03..665d8aa 100644
   					    struct cfg80211_chan_def *chandef)
   {
   	struct ieee80211_channel *curchan = chandef->chan;
-diff --git a/package/mac80211/patches/513-ath9k_add_pci_ids.patch b/package/mac80211/patches/513-ath9k_add_pci_ids.patch
-index db4e6a1..540198f 100644
---- a/package/mac80211/patches/513-ath9k_add_pci_ids.patch
-+++ b/package/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
--@@ -614,6 +614,7 @@ int ath9k_hw_init(struct ath_hw *ah)
-+@@ -613,6 +613,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/mac80211/patches/520-mac80211_cur_txpower.patch b/package/mac80211/patches/520-mac80211_cur_txpower.patch
-index 6df95bc..cb3f852 100644
+index 6df95bc..b79a3c4 100644
 --- a/package/mac80211/patches/520-mac80211_cur_txpower.patch
 +++ b/package/mac80211/patches/520-mac80211_cur_txpower.patch
 @@ -1,6 +1,6 @@
  --- a/include/net/mac80211.h
  +++ b/include/net/mac80211.h
 -@@ -1711,6 +1711,7 @@ struct ieee80211_hw {
-+@@ -1703,6 +1703,7 @@ struct ieee80211_hw {
++@@ -1718,6 +1718,7 @@ struct ieee80211_hw {
   	u8 max_tx_aggregation_subframes;
   	u8 offchannel_tx_hw_queue;
   	u8 radiotap_mcs_details;
@@ -6829,7 +10518,7 @@ index 6df95bc..cb3f852 100644
  --- a/net/mac80211/cfg.c
  +++ b/net/mac80211/cfg.c
 -@@ -2329,7 +2329,9 @@ static int ieee80211_get_tx_power(struct
-+@@ -2335,7 +2335,9 @@ static int ieee80211_get_tx_power(struct
++@@ -2378,7 +2378,9 @@ static int ieee80211_get_tx_power(struct
   	struct ieee80211_local *local = wiphy_priv(wiphy);
   	struct ieee80211_sub_if_data *sdata = IEEE80211_WDEV_TO_SUB_IF(wdev);
   
@@ -6838,32 +10527,40 @@ index 6df95bc..cb3f852 100644
  --- a/net/mac80211/main.c
  +++ b/net/mac80211/main.c
 -@@ -158,6 +158,7 @@ static u32 ieee80211_hw_conf_chan(struct
-+@@ -160,6 +160,7 @@ static u32 ieee80211_hw_conf_chan(struct
++@@ -156,6 +156,7 @@ static u32 ieee80211_hw_conf_chan(struct
   
   	if (local->hw.conf.power_level != power) {
   		changed |= IEEE80211_CONF_CHANGE_POWER;
 diff --git a/package/mac80211/patches/521-ath9k_cur_txpower.patch b/package/mac80211/patches/521-ath9k_cur_txpower.patch
-index 0d6c360..24bc062 100644
+index 0d6c360..3564323 100644
 --- a/package/mac80211/patches/521-ath9k_cur_txpower.patch
 +++ b/package/mac80211/patches/521-ath9k_cur_txpower.patch
+@@ -1,6 +1,6 @@
+ --- a/drivers/net/wireless/ath/ath9k/main.c
+ +++ b/drivers/net/wireless/ath/ath9k/main.c
+-@@ -308,8 +308,12 @@ static int ath_reset_internal(struct ath
++@@ -310,8 +310,12 @@ static int ath_reset_internal(struct ath
+  	    (sc->hw->conf.flags & IEEE80211_CONF_OFFCHANNEL))
+  		ath9k_mci_set_txpower(sc, true, false);
+  
 @@ -14,7 +14,7 @@
   
   out:
   	spin_unlock_bh(&sc->sc_pcu_lock);
 -@@ -1371,6 +1375,7 @@ static int ath9k_config(struct ieee80211
-+@@ -1370,6 +1374,7 @@ static int ath9k_config(struct ieee80211
++@@ -1404,6 +1408,7 @@ static int ath9k_config(struct ieee80211
   		sc->config.txpowlimit = 2 * conf->power_level;
   		ath9k_cmn_update_txpow(ah, sc->curtxpow,
   				       sc->config.txpowlimit, &sc->curtxpow);
 diff --git a/package/mac80211/patches/522-mac80211_configure_antenna_gain.patch b/package/mac80211/patches/522-mac80211_configure_antenna_gain.patch
-index 308ee6e..611f763 100644
+index 308ee6e..6ad04ac 100644
 --- a/package/mac80211/patches/522-mac80211_configure_antenna_gain.patch
 +++ b/package/mac80211/patches/522-mac80211_configure_antenna_gain.patch
 @@ -1,6 +1,6 @@
  --- a/include/net/cfg80211.h
  +++ b/include/net/cfg80211.h
 -@@ -2156,6 +2156,7 @@ struct cfg80211_qos_map {
-+@@ -2167,6 +2167,7 @@ struct cfg80211_qos_map {
++@@ -2188,6 +2188,7 @@ struct cfg80211_qos_map {
    *	(as advertised by the nl80211 feature flag.)
    * @get_tx_power: store the current TX power into the dbm variable;
    *	return 0 if successful
@@ -6872,7 +10569,7 @@ index 308ee6e..611f763 100644
    * @set_wds_peer: set the WDS peer for a WDS interface
    *
 -@@ -2380,6 +2381,7 @@ struct cfg80211_ops {
-+@@ -2396,6 +2397,7 @@ struct cfg80211_ops {
++@@ -2422,6 +2423,7 @@ struct cfg80211_ops {
   				enum nl80211_tx_power_setting type, int mbm);
   	int	(*get_tx_power)(struct wiphy *wiphy, struct wireless_dev *wdev,
   				int *dbm);
@@ -6901,9 +10598,9 @@ index 308ee6e..611f763 100644
 -@@ -1555,6 +1555,9 @@ enum nl80211_commands {
 -  *	data is in the format defined for the payload of the QoS Map Set element
 -  *	in IEEE Std 802.11-2012, 8.4.2.97.
-+@@ -1579,6 +1579,9 @@ enum nl80211_commands {
-+  * @NL80211_ATTR_TDLS_PEER_CAPABILITY: flags for TDLS peer capabilities, u32.
-+  *	As specified in the &enum nl80211_tdls_peer_capability.
++@@ -1591,6 +1591,9 @@ enum nl80211_commands {
++  *	creation then the new interface will be owned by the netlink socket
++  *	that created it and will be destroyed when the socket is closed
    *
  + * @NL80211_ATTR_WIPHY_ANTENNA_GAIN: Configured antenna gain. Used to reduce
  + *	transmit power to stay within regulatory limits. u32, dBi.
@@ -6912,10 +10609,11 @@ index 308ee6e..611f763 100644
    * @__NL80211_ATTR_AFTER_LAST: internal use
    */
 -@@ -1883,6 +1886,8 @@ enum nl80211_attrs {
-+@@ -1914,6 +1917,8 @@ enum nl80211_attrs {
-  
+- 
 - 	NL80211_ATTR_QOS_MAP,
-+ 	NL80211_ATTR_TDLS_PEER_CAPABILITY,
++@@ -1931,6 +1934,8 @@ enum nl80211_attrs {
++ 	NL80211_ATTR_CSA_C_OFFSETS_TX,
++ 	NL80211_ATTR_MAX_CSA_COUNTERS,
   
  +	NL80211_ATTR_WIPHY_ANTENNA_GAIN,
  +
@@ -6924,7 +10622,7 @@ index 308ee6e..611f763 100644
  --- a/net/mac80211/cfg.c
  +++ b/net/mac80211/cfg.c
 -@@ -2339,6 +2339,19 @@ static int ieee80211_get_tx_power(struct
-+@@ -2345,6 +2345,19 @@ static int ieee80211_get_tx_power(struct
++@@ -2388,6 +2388,19 @@ static int ieee80211_get_tx_power(struct
   	return 0;
   }
   
@@ -6933,7 +10631,7 @@ index 308ee6e..611f763 100644
   				  const u8 *addr)
   {
 -@@ -3924,6 +3937,7 @@ struct cfg80211_ops mac80211_config_ops 
-+@@ -4000,6 +4013,7 @@ const struct cfg80211_ops mac80211_confi
++@@ -3820,6 +3833,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,
@@ -6942,11 +10640,17 @@ index 308ee6e..611f763 100644
  --- a/net/mac80211/ieee80211_i.h
  +++ b/net/mac80211/ieee80211_i.h
 -@@ -1221,6 +1221,7 @@ struct ieee80211_local {
-+@@ -1225,6 +1225,7 @@ struct ieee80211_local {
++@@ -1233,6 +1233,7 @@ struct ieee80211_local {
   	int dynamic_ps_forced_timeout;
   
   	int user_power_level; /* in dBm, for all interfaces */
-@@ -102,34 +102,24 @@
+@@ -97,39 +97,29 @@
+  
+ --- a/net/mac80211/main.c
+ +++ b/net/mac80211/main.c
+-@@ -101,7 +101,7 @@ static u32 ieee80211_hw_conf_chan(struct
++@@ -97,7 +97,7 @@ static u32 ieee80211_hw_conf_chan(struct
+  	struct ieee80211_sub_if_data *sdata;
   	struct cfg80211_chan_def chandef = {};
   	u32 changed = 0;
  -	int power;
@@ -6956,7 +10660,7 @@ index 308ee6e..611f763 100644
   
   	offchannel_flag = local->hw.conf.flags & IEEE80211_CONF_OFFCHANNEL;
 -@@ -156,8 +156,21 @@ static u32 ieee80211_hw_conf_chan(struct
-+@@ -158,6 +158,12 @@ static u32 ieee80211_hw_conf_chan(struct
++@@ -154,6 +154,12 @@ static u32 ieee80211_hw_conf_chan(struct
   	}
   	rcu_read_unlock();
   
@@ -6982,7 +10686,7 @@ index 308ee6e..611f763 100644
 - 		local->hw.conf.power_level = power;
 - 	}
 -@@ -584,6 +597,7 @@ struct ieee80211_hw *ieee80211_alloc_hw(
-+@@ -586,6 +592,7 @@ struct ieee80211_hw *ieee80211_alloc_hw(
++@@ -584,6 +590,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;
@@ -6994,17 +10698,17 @@ index 308ee6e..611f763 100644
 - 	[NL80211_ATTR_VENDOR_DATA] = { .type = NLA_BINARY },
 - 	[NL80211_ATTR_QOS_MAP] = { .type = NLA_BINARY,
 - 				   .len = IEEE80211_QOS_MAP_LEN_MAX },
-+@@ -385,6 +385,7 @@ static const struct nla_policy nl80211_p
-+ 	[NL80211_ATTR_MAC_HINT] = { .len = ETH_ALEN },
-+ 	[NL80211_ATTR_WIPHY_FREQ_HINT] = { .type = NLA_U32 },
++@@ -387,6 +387,7 @@ static const struct nla_policy nl80211_p
 + 	[NL80211_ATTR_TDLS_PEER_CAPABILITY] = { .type = NLA_U32 },
++ 	[NL80211_ATTR_IFACE_SOCKET_OWNER] = { .type = NLA_FLAG },
++ 	[NL80211_ATTR_CSA_C_OFFSETS_TX] = { .type = NLA_BINARY },
  +	[NL80211_ATTR_WIPHY_ANTENNA_GAIN] = { .type = NLA_U32 },
   };
   
   /* policy for the key attributes */
 -@@ -2105,6 +2106,22 @@ static int nl80211_set_wiphy(struct sk_b
 - 			goto bad_res;
-+@@ -2116,6 +2117,20 @@ static int nl80211_set_wiphy(struct sk_b
++@@ -2162,6 +2163,20 @@ static int nl80211_set_wiphy(struct sk_b
 + 			return result;
   	}
   
@@ -7029,7 +10733,7 @@ index 308ee6e..611f763 100644
  +
   	if (info->attrs[NL80211_ATTR_WIPHY_ANTENNA_TX] &&
 diff --git a/package/mac80211/patches/523-ath9k_use_configured_antenna_gain.patch b/package/mac80211/patches/523-ath9k_use_configured_antenna_gain.patch
-index 30aa9ee..b84a991 100644
+index 30aa9ee..aaefa2f 100644
 --- a/package/mac80211/patches/523-ath9k_use_configured_antenna_gain.patch
 +++ b/package/mac80211/patches/523-ath9k_use_configured_antenna_gain.patch
 @@ -1,6 +1,6 @@
@@ -7040,42 +10744,25 @@ index 30aa9ee..b84a991 100644
   	u16 max_power_level;
   	u16 current_rd;
   	int16_t power_limit;
-@@ -10,7 +10,7 @@
-  
- --- a/drivers/net/wireless/ath/ath9k/hw.c
- +++ b/drivers/net/wireless/ath/ath9k/hw.c
--@@ -2721,7 +2721,7 @@ void ath9k_hw_apply_txpower(struct ath_h
-+@@ -2720,7 +2720,7 @@ void ath9k_hw_apply_txpower(struct ath_h
-  	channel = chan->chan;
-  	chan_pwr = min_t(int, channel->max_power * 2, MAX_RATE_POWER);
-  	new_pwr = min_t(int, chan_pwr, reg->power_limit);
 @@ -21,7 +21,7 @@
   	if (ant_gain > max_gain)
  --- a/drivers/net/wireless/ath/ath9k/main.c
  +++ b/drivers/net/wireless/ath/ath9k/main.c
 -@@ -1371,7 +1371,10 @@ static int ath9k_config(struct ieee80211
-+@@ -1370,7 +1370,10 @@ static int ath9k_config(struct ieee80211
++@@ -1404,7 +1404,10 @@ static int ath9k_config(struct ieee80211
   	}
   
   	if (changed & IEEE80211_CONF_CHANGE_POWER) {
 diff --git a/package/mac80211/patches/530-ath9k_extra_leds.patch b/package/mac80211/patches/530-ath9k_extra_leds.patch
-index 59f78d9..c78a3e5 100644
+index 59f78d9..4cf0700 100644
 --- a/package/mac80211/patches/530-ath9k_extra_leds.patch
 +++ b/package/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
--@@ -563,6 +563,9 @@ static inline int ath9k_dump_btcoex(stru
-+@@ -554,6 +554,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)
   {
 -@@ -710,6 +713,13 @@ enum sc_op_flags {
-+@@ -692,6 +695,13 @@ void ath_ant_comb_scan(struct ath_softc 
++@@ -701,6 +704,13 @@ void ath_ant_comb_scan(struct ath_softc 
   #define PS_BEACON_SYNC            BIT(4)
   #define PS_WAIT_FOR_ANI           BIT(5)
   
@@ -7085,7 +10772,7 @@ index 59f78d9..c78a3e5 100644
   	struct device *dev;
 -@@ -751,9 +761,8 @@ struct ath_softc {
 - 	struct ieee80211_supported_band sbands[IEEE80211_NUM_BANDS];
-+@@ -731,9 +741,8 @@ struct ath_softc {
++@@ -743,9 +753,8 @@ struct ath_softc {
 + 	struct ath_beacon beacon;
   
   #ifdef CPTCFG_MAC80211_LEDS
@@ -7095,7 +10782,7 @@ index 59f78d9..c78a3e5 100644
  --- a/drivers/net/wireless/ath/ath9k/init.c
  +++ b/drivers/net/wireless/ath/ath9k/init.c
 -@@ -1018,7 +1018,7 @@ int ath9k_init_device(u16 devid, struct 
-+@@ -811,7 +811,7 @@ int ath9k_init_device(u16 devid, struct 
++@@ -815,7 +815,7 @@ int ath9k_init_device(u16 devid, struct 
   
   #ifdef CPTCFG_MAC80211_LEDS
   	/* must be initialized before ieee80211_register_hw */
@@ -7104,7 +10791,7 @@ index 59f78d9..c78a3e5 100644
  --- a/drivers/net/wireless/ath/ath9k/debug.c
  +++ b/drivers/net/wireless/ath/ath9k/debug.c
 -@@ -1573,6 +1573,61 @@ static const struct file_operations fops
-+@@ -1577,6 +1577,61 @@ static const struct file_operations fops
++@@ -1381,6 +1381,61 @@ static const struct file_operations fops
   	.llseek = default_llseek,
   };
   
@@ -7113,19 +10800,36 @@ index 59f78d9..c78a3e5 100644
   int ath9k_init_debug(struct ath_hw *ah)
   {
 -@@ -1597,6 +1652,10 @@ int ath9k_init_debug(struct ath_hw *ah)
-+@@ -1601,6 +1656,10 @@ int ath9k_init_debug(struct ath_hw *ah)
++@@ -1405,6 +1460,10 @@ int ath9k_init_debug(struct ath_hw *ah)
   			    &fops_eeprom);
   	debugfs_create_file("chanbw", S_IRUSR | S_IWUSR, sc->debug.debugfs_phy,
   			    sc, &fops_chanbw);
+diff --git a/package/mac80211/patches/531-ath9k_extra_platform_leds.patch b/package/mac80211/patches/531-ath9k_extra_platform_leds.patch
+index 6c9832c..718a3d0 100644
+--- a/package/mac80211/patches/531-ath9k_extra_platform_leds.patch
++++ b/package/mac80211/patches/531-ath9k_extra_platform_leds.patch
+@@ -1,9 +1,9 @@
+ --- a/include/linux/ath9k_platform.h
+ +++ b/include/linux/ath9k_platform.h
+-@@ -37,6 +37,9 @@ struct ath9k_platform_data {
+- 
+- 	int (*get_mac_revision)(void);
++@@ -39,6 +39,9 @@ struct ath9k_platform_data {
+  	int (*external_reset)(void);
++ 
++ 	bool use_eeprom;
+ +
+ +	int num_leds;
+ +	const struct gpio_led *leds;
 diff --git a/package/mac80211/patches/542-ath9k_debugfs_diag.patch b/package/mac80211/patches/542-ath9k_debugfs_diag.patch
-index e1b6ff1..44aa905 100644
+index e1b6ff1..764e5e2 100644
 --- a/package/mac80211/patches/542-ath9k_debugfs_diag.patch
 +++ b/package/mac80211/patches/542-ath9k_debugfs_diag.patch
 @@ -1,6 +1,6 @@
  --- a/drivers/net/wireless/ath/ath9k/debug.c
  +++ b/drivers/net/wireless/ath/ath9k/debug.c
 -@@ -1629,6 +1629,50 @@ static const struct file_operations fops
-+@@ -1633,6 +1633,50 @@ static const struct file_operations fops
++@@ -1437,6 +1437,50 @@ static const struct file_operations fops
   #endif
   
   
@@ -7134,50 +10838,23 @@ index e1b6ff1..44aa905 100644
   {
   	struct ath_common *common = ath9k_hw_common(ah);
 -@@ -1656,6 +1700,8 @@ int ath9k_init_debug(struct ath_hw *ah)
-+@@ -1660,6 +1704,8 @@ int ath9k_init_debug(struct ath_hw *ah)
++@@ -1464,6 +1508,8 @@ int ath9k_init_debug(struct ath_hw *ah)
   	debugfs_create_file("gpio_led", S_IWUSR,
   			   sc->debug.debugfs_phy, sc, &fops_gpio_led);
   #endif
-@@ -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
--@@ -1735,6 +1735,20 @@ fail:
-+@@ -1734,6 +1734,20 @@ fail:
-  	return -EINVAL;
-  }
-  
-@@ -115,7 +115,7 @@
-  int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,
-  		   struct ath9k_hw_cal_data *caldata, bool fastcc)
-  {
--@@ -1940,6 +1954,7 @@ int ath9k_hw_reset(struct ath_hw *ah, st
-+@@ -1939,6 +1953,7 @@ int ath9k_hw_reset(struct ath_hw *ah, st
-  		ar9003_hw_disable_phy_restart(ah);
-  
-  	ath9k_hw_apply_gpio_override(ah);
 @@ -125,7 +125,7 @@
   		REG_SET_BIT(ah, AR_BTCOEX_WL_LNADIV, AR_BTCOEX_WL_LNADIV_FORCE_ON);
  --- a/drivers/net/wireless/ath/ath9k/main.c
  +++ b/drivers/net/wireless/ath/ath9k/main.c
 -@@ -602,6 +602,11 @@ irqreturn_t ath_isr(int irq, void *dev)
-+@@ -603,6 +603,11 @@ irqreturn_t ath_isr(int irq, void *dev)
++@@ -605,6 +605,11 @@ irqreturn_t ath_isr(int irq, void *dev)
   	ath9k_debug_sync_cause(sc, sync_cause);
   	status &= ah->imask;	/* discard unasked-for bits */
   
 diff --git a/package/mac80211/patches/543-ath9k-allow-to-disable-bands-via-platform-data.patch b/package/mac80211/patches/543-ath9k-allow-to-disable-bands-via-platform-data.patch
-index d26a5af..e2e18c9 100644
+index d26a5af..0501582 100644
 --- a/package/mac80211/patches/543-ath9k-allow-to-disable-bands-via-platform-data.patch
 +++ b/package/mac80211/patches/543-ath9k-allow-to-disable-bands-via-platform-data.patch
-@@ -11,7 +11,7 @@
-  	int (*external_reset)(void);
- --- a/drivers/net/wireless/ath/ath9k/hw.c
- +++ b/drivers/net/wireless/ath/ath9k/hw.c
--@@ -2328,17 +2328,25 @@ int ath9k_hw_fill_cap_info(struct ath_hw
-+@@ -2327,17 +2327,25 @@ int ath9k_hw_fill_cap_info(struct ath_hw
-  	}
-  
-  	eeval = ah->eep_ops->get_eeprom(ah, EEP_OP_MODE);
 @@ -58,7 +58,7 @@
   };
  --- a/drivers/net/wireless/ath/ath9k/init.c
@@ -7188,7 +10865,7 @@ index d26a5af..e2e18c9 100644
   		ah->get_mac_revision = pdata->get_mac_revision;
   		ah->external_reset = pdata->external_reset;
 diff --git a/package/mac80211/patches/550-ath9k_entropy_from_adc.patch b/package/mac80211/patches/550-ath9k_entropy_from_adc.patch
-index b59c362..439a574 100644
+index b59c362..7210a02 100644
 --- a/package/mac80211/patches/550-ath9k_entropy_from_adc.patch
 +++ b/package/mac80211/patches/550-ath9k_entropy_from_adc.patch
 @@ -55,7 +55,7 @@
@@ -7196,7 +10873,7 @@ index b59c362..439a574 100644
  --- a/drivers/net/wireless/ath/ath9k/init.c
  +++ b/drivers/net/wireless/ath/ath9k/init.c
 -@@ -846,7 +846,8 @@ static void ath9k_init_txpower_limits(st
-+@@ -643,7 +643,8 @@ static void ath9k_init_txpower_limits(st
++@@ -646,7 +646,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);
   
@@ -7207,7 +10884,7 @@ index b59c362..439a574 100644
 - void ath9k_reload_chainmask_settings(struct ath_softc *sc)
 -@@ -980,6 +981,18 @@ static void ath9k_set_hw_capab(struct at
 + static const struct ieee80211_iface_limit if_limits[] = {
-+@@ -770,6 +771,18 @@ static void ath9k_set_hw_capab(struct at
++@@ -774,6 +775,18 @@ static void ath9k_set_hw_capab(struct at
   	SET_IEEE80211_PERM_ADDR(hw, common->macaddr);
   }
   
@@ -7216,7 +10893,7 @@ index b59c362..439a574 100644
   		    const struct ath_bus_ops *bus_ops)
   {
 -@@ -1025,6 +1038,8 @@ int ath9k_init_device(u16 devid, struct 
-+@@ -818,6 +831,8 @@ int ath9k_init_device(u16 devid, struct 
++@@ -822,6 +835,8 @@ int ath9k_init_device(u16 devid, struct 
   		ARRAY_SIZE(ath9k_tpt_blink));
   #endif
   
@@ -7229,306 +10906,468 @@ index b59c362..439a574 100644
   	unsigned int timestamp = jiffies_to_msecs(jiffies);
   	u32 cal_interval, short_cal_interval, long_cal_interval;
   	unsigned long flags;
+diff --git a/package/mac80211/patches/551-ath9k-ar933x-usb-hang-workaround.patch b/package/mac80211/patches/551-ath9k-ar933x-usb-hang-workaround.patch
+new file mode 100644
+index 0000000..10280d9
+--- /dev/null
++++ b/package/mac80211/patches/551-ath9k-ar933x-usb-hang-workaround.patch
+@@ -0,0 +1,79 @@
++--- a/drivers/net/wireless/ath/ath9k/hw.c
+++++ b/drivers/net/wireless/ath/ath9k/hw.c
++@@ -215,6 +215,19 @@ void ath9k_hw_get_channel_centers(struct
++ 		centers->synth_center + (extoff * HT40_CHANNEL_CENTER_SHIFT);
++ }
++ 
+++static inline void ath9k_hw_disable_pll_lock_detect(struct ath_hw *ah)
+++{
+++	/* On AR9330 and AR9340 devices, some PHY registers must be
+++	 * tuned to gain better stability/performance. These registers
+++	 * might be changed while doing wlan reset so the registers must
+++	 * be reprogrammed after each reset.
+++	 */
+++	REG_CLR_BIT(ah, AR_PHY_USB_CTRL1, BIT(20));
+++	REG_RMW(ah, AR_PHY_USB_CTRL2,
+++		(1 << 21) | (0xf << 22),
+++		(1 << 21) | (0x3 << 22));
+++}
+++
++ /******************/
++ /* Chip Revisions */
++ /******************/
++@@ -1337,6 +1350,9 @@ static bool ath9k_hw_set_reset(struct at
++ 	if (AR_SREV_9100(ah))
++ 		udelay(50);
++ 
+++	if (AR_SREV_9330(ah) || AR_SREV_9340(ah))
+++		ath9k_hw_disable_pll_lock_detect(ah);
+++
++ 	return true;
++ }
++ 
++@@ -1436,6 +1452,9 @@ static bool ath9k_hw_chip_reset(struct a
++ 		ar9003_hw_internal_regulator_apply(ah);
++ 	ath9k_hw_init_pll(ah, chan);
++ 
+++	if (AR_SREV_9330(ah) || AR_SREV_9340(ah))
+++		ath9k_hw_disable_pll_lock_detect(ah);
+++
++ 	return true;
++ }
++ 
++@@ -1730,8 +1749,14 @@ static int ath9k_hw_do_fastcc(struct ath
++ 	if (AR_SREV_9271(ah))
++ 		ar9002_hw_load_ani_reg(ah, chan);
++ 
+++	if (AR_SREV_9330(ah) || AR_SREV_9340(ah))
+++		ath9k_hw_disable_pll_lock_detect(ah);
+++
++ 	return 0;
++ fail:
+++	if (AR_SREV_9330(ah) || AR_SREV_9340(ah))
+++		ath9k_hw_disable_pll_lock_detect(ah);
+++
++ 	return -EINVAL;
++ }
++ 
++@@ -1959,6 +1984,9 @@ int ath9k_hw_reset(struct ath_hw *ah, st
++ 	if (AR_SREV_9565(ah) && common->bt_ant_diversity)
++ 		REG_SET_BIT(ah, AR_BTCOEX_WL_LNADIV, AR_BTCOEX_WL_LNADIV_FORCE_ON);
++ 
+++	if (AR_SREV_9330(ah) || AR_SREV_9340(ah))
+++		ath9k_hw_disable_pll_lock_detect(ah);
+++
++ 	return 0;
++ }
++ EXPORT_SYMBOL(ath9k_hw_reset);
++--- a/drivers/net/wireless/ath/ath9k/phy.h
+++++ b/drivers/net/wireless/ath/ath9k/phy.h
++@@ -48,6 +48,9 @@
++ #define AR_PHY_PLL_CONTROL 0x16180
++ #define AR_PHY_PLL_MODE 0x16184
++ 
+++#define AR_PHY_USB_CTRL1	0x16c84
+++#define AR_PHY_USB_CTRL2	0x16c88
+++
++ enum ath9k_ant_div_comb_lna_conf {
++ 	ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2,
++ 	ATH_ANT_DIV_COMB_LNA2,
 diff --git a/package/mac80211/patches/551-ath9k_p2p_ifcomb.patch b/package/mac80211/patches/551-ath9k_p2p_ifcomb.patch
-index ffffe0c..579a633 100644
+deleted file mode 100644
+index ffffe0c..0000000
 --- a/package/mac80211/patches/551-ath9k_p2p_ifcomb.patch
-+++ b/package/mac80211/patches/551-ath9k_p2p_ifcomb.patch
-@@ -12,7 +12,7 @@ Signed-off-by: Felix Fietkau <nbd@openwrt.org>
- 
- --- a/drivers/net/wireless/ath/ath9k/init.c
- +++ b/drivers/net/wireless/ath/ath9k/init.c
++++ /dev/null
+@@ -1,33 +0,0 @@
+-From c997a1da25fe7c717ed099888b8eb35d4e139e70 Mon Sep 17 00:00:00 2001
+-From: Felix Fietkau <nbd@openwrt.org>
+-Date: Sun, 8 Dec 2013 08:52:52 +0100
+-Subject: [PATCH] ath9k: support only one P2P interface
+-
+-Preparation for adding P2P powersave and multi-channel support.
+-
+-Signed-off-by: Felix Fietkau <nbd@openwrt.org>
+----
+- drivers/net/wireless/ath/ath9k/init.c | 4 ++--
+-  1 file changed, 2 insertions(+), 2 deletions(-)
+-
+---- a/drivers/net/wireless/ath/ath9k/init.c
+-+++ b/drivers/net/wireless/ath/ath9k/init.c
 -@@ -863,15 +863,15 @@ void ath9k_reload_chainmask_settings(str
-+@@ -649,15 +649,15 @@ static void ath9k_init_txpower_limits(st
-  
-  static const struct ieee80211_iface_limit if_limits[] = {
-  	{ .max = 2048,	.types = BIT(NL80211_IFTYPE_STATION) |
+- 
+- static const struct ieee80211_iface_limit if_limits[] = {
+- 	{ .max = 2048,	.types = BIT(NL80211_IFTYPE_STATION) |
+--				 BIT(NL80211_IFTYPE_P2P_CLIENT) |
+- 				 BIT(NL80211_IFTYPE_WDS) },
+- 	{ .max = 8,	.types =
+- #ifdef CPTCFG_MAC80211_MESH
+- 				 BIT(NL80211_IFTYPE_MESH_POINT) |
+- #endif
+--				 BIT(NL80211_IFTYPE_AP) |
+--				 BIT(NL80211_IFTYPE_P2P_GO) },
+-+				 BIT(NL80211_IFTYPE_AP) },
+- 	{ .max = 1,	.types = BIT(NL80211_IFTYPE_ADHOC) },
+-+	{ .max = 1,	.types = BIT(NL80211_IFTYPE_P2P_CLIENT) |
+-+				 BIT(NL80211_IFTYPE_P2P_GO) },
+- };
+- 
+- static const struct ieee80211_iface_limit if_dfs_limits[] = {
 diff --git a/package/mac80211/patches/552-ath9k_p2p_ps_support.patch b/package/mac80211/patches/552-ath9k_p2p_ps_support.patch
-index 4a61db3..8cf9e61 100644
+deleted file mode 100644
+index 4a61db3..0000000
 --- a/package/mac80211/patches/552-ath9k_p2p_ps_support.patch
-+++ b/package/mac80211/patches/552-ath9k_p2p_ps_support.patch
-@@ -27,7 +27,7 @@ Signed-off-by: Felix Fietkau <nbd@openwrt.org>
-  	return true;
-  }
-  
++++ /dev/null
+@@ -1,247 +0,0 @@
+-From 6744d0a7ea037c7d65e13ca906da93009b241d00 Mon Sep 17 00:00:00 2001
+-From: Felix Fietkau <nbd@openwrt.org>
+-Date: Tue, 11 Feb 2014 11:16:24 +0100
+-Subject: [PATCH] ath9k: implement p2p client powersave support
+-
+-Use generic TSF timers to trigger powersave state changes based
+-information from the P2P NoA attribute.
+-Opportunistic Powersave is not handled, because the driver does not
+-support powersave at the moment.
+-
+-Signed-off-by: Felix Fietkau <nbd@openwrt.org>
+----
+- drivers/net/wireless/ath/ath9k/ath9k.h |  12 ++++
+- drivers/net/wireless/ath/ath9k/init.c  |   6 ++
+- drivers/net/wireless/ath/ath9k/main.c  | 104 +++++++++++++++++++++++++++++++++
+- drivers/net/wireless/ath/ath9k/recv.c  |   3 +
+- 4 files changed, 125 insertions(+)
+-
+---- a/drivers/net/wireless/ath/ath9k/main.c
+-+++ b/drivers/net/wireless/ath/ath9k/main.c
+-@@ -261,6 +261,8 @@ static bool ath_complete_reset(struct at
+- 	sc->gtt_cnt = 0;
+- 	ieee80211_wake_queues(sc->hw);
+- 
+-+	ath9k_p2p_ps_timer(sc);
+-+
+- 	return true;
+- }
+- 
 -@@ -1126,6 +1128,8 @@ static int ath9k_add_interface(struct ie
-+@@ -1128,6 +1130,8 @@ static int ath9k_add_interface(struct ie
-  	if (ath9k_uses_beacons(vif->type))
-  		ath9k_beacon_assign_slot(sc, vif);
-  
-@@ -36,7 +36,7 @@ Signed-off-by: Felix Fietkau <nbd@openwrt.org>
-  	an->sc = sc;
-  	an->sta = NULL;
-  	an->vif = vif;
+- 	if (ath9k_uses_beacons(vif->type))
+- 		ath9k_beacon_assign_slot(sc, vif);
+- 
+-+	avp->vif = vif;
+-+
+- 	an->sc = sc;
+- 	an->sta = NULL;
+- 	an->vif = vif;
 -@@ -1170,6 +1174,29 @@ static int ath9k_change_interface(struct
-+@@ -1172,6 +1176,29 @@ static int ath9k_change_interface(struct
-  	return 0;
-  }
-  
-@@ -66,7 +66,7 @@ Signed-off-by: Felix Fietkau <nbd@openwrt.org>
-  static void ath9k_remove_interface(struct ieee80211_hw *hw,
-  				   struct ieee80211_vif *vif)
-  {
+- 	return 0;
+- }
+- 
+-+static void
+-+ath9k_update_p2p_ps_timer(struct ath_softc *sc, struct ath_vif *avp)
+-+{
+-+	struct ath_hw *ah = sc->sc_ah;
+-+	s32 tsf, target_tsf;
+-+
+-+	if (!avp || !avp->noa.has_next_tsf)
+-+		return;
+-+
+-+	ath9k_hw_gen_timer_stop(ah, sc->p2p_ps_timer);
+-+
+-+	tsf = ath9k_hw_gettsf32(sc->sc_ah);
+-+
+-+	target_tsf = avp->noa.next_tsf;
+-+	if (!avp->noa.absent)
+-+		target_tsf -= ATH_P2P_PS_STOP_TIME;
+-+
+-+	if (target_tsf - tsf < ATH_P2P_PS_STOP_TIME)
+-+		target_tsf = tsf + ATH_P2P_PS_STOP_TIME;
+-+
+-+	ath9k_hw_gen_timer_start(ah, sc->p2p_ps_timer, (u32) target_tsf, 1000000);
+-+}
+-+
+- static void ath9k_remove_interface(struct ieee80211_hw *hw,
+- 				   struct ieee80211_vif *vif)
+- {
 -@@ -1181,6 +1208,13 @@ static void ath9k_remove_interface(struc
-+@@ -1183,6 +1210,13 @@ static void ath9k_remove_interface(struc
-  
-  	mutex_lock(&sc->mutex);
-  
-@@ -80,7 +80,7 @@ Signed-off-by: Felix Fietkau <nbd@openwrt.org>
-  	sc->nvifs--;
-  	sc->tx99_vif = NULL;
-  
+- 
+- 	mutex_lock(&sc->mutex);
+- 
+-+	spin_lock_bh(&sc->sc_pcu_lock);
+-+	if (avp == sc->p2p_ps_vif) {
+-+		sc->p2p_ps_vif = NULL;
+-+		ath9k_update_p2p_ps_timer(sc, NULL);
+-+	}
+-+	spin_unlock_bh(&sc->sc_pcu_lock);
+-+
+- 	sc->nvifs--;
+- 	sc->tx99_vif = NULL;
+- 
 -@@ -1649,6 +1683,70 @@ static void ath9k_bss_assoc_iter(void *d
-+@@ -1649,6 +1683,72 @@ static void ath9k_bss_assoc_iter(void *d
-  		ath9k_set_assoc_state(sc, vif);
-  }
-  
-@@ -130,6 +130,7 @@ Signed-off-by: Felix Fietkau <nbd@openwrt.org>
- +void ath9k_update_p2p_ps(struct ath_softc *sc, struct ieee80211_vif *vif)
- +{
- +	struct ath_vif *avp = (void *)vif->drv_priv;
-++	unsigned long flags;
- +	u32 tsf;
- +
- +	if (!sc->p2p_ps_timer)
-@@ -140,18 +141,19 @@ Signed-off-by: Felix Fietkau <nbd@openwrt.org>
- +
- +	sc->p2p_ps_vif = avp;
- +
+- 		ath9k_set_assoc_state(sc, vif);
+- }
+- 
+-+void ath9k_p2p_ps_timer(void *priv)
+-+{
+-+	struct ath_softc *sc = priv;
+-+	struct ath_vif *avp = sc->p2p_ps_vif;
+-+	struct ieee80211_vif *vif;
+-+	struct ieee80211_sta *sta;
+-+	struct ath_node *an;
+-+	u32 tsf;
+-+
+-+	if (!avp)
+-+		return;
+-+
+-+	tsf = ath9k_hw_gettsf32(sc->sc_ah);
+-+	if (!avp->noa.absent)
+-+		tsf += ATH_P2P_PS_STOP_TIME;
+-+
+-+	if (!avp->noa.has_next_tsf ||
+-+	    avp->noa.next_tsf - tsf > BIT(31))
+-+		ieee80211_update_p2p_noa(&avp->noa, tsf);
+-+
+-+	ath9k_update_p2p_ps_timer(sc, avp);
+-+
+-+	rcu_read_lock();
+-+
+-+	vif = avp->vif;
+-+	sta = ieee80211_find_sta(vif, vif->bss_conf.bssid);
+-+	if (!sta)
+-+		goto out;
+-+
+-+	an = (void *) sta->drv_priv;
+-+	if (an->sleeping == !!avp->noa.absent)
+-+		goto out;
+-+
+-+	an->sleeping = avp->noa.absent;
+-+	if (an->sleeping)
+-+		ath_tx_aggr_sleep(sta, sc, an);
+-+	else
+-+		ath_tx_aggr_wakeup(sc, an);
+-+
+-+out:
+-+	rcu_read_unlock();
+-+}
+-+
+-+void ath9k_update_p2p_ps(struct ath_softc *sc, struct ieee80211_vif *vif)
+-+{
+-+	struct ath_vif *avp = (void *)vif->drv_priv;
+-+	u32 tsf;
+-+
+-+	if (!sc->p2p_ps_timer)
+-+		return;
+-+
+-+	if (vif->type != NL80211_IFTYPE_STATION || !vif->p2p)
+-+		return;
+-+
+-+	sc->p2p_ps_vif = avp;
+-+
 -+	if (sc->ps_flags & PS_BEACON_SYNC)
 -+		return;
 -+
 -+	tsf = ath9k_hw_gettsf32(sc->sc_ah);
 -+	ieee80211_parse_p2p_noa(&vif->bss_conf.p2p_noa_attr, &avp->noa, tsf);
 -+	ath9k_update_p2p_ps_timer(sc, avp);
-++	spin_lock_irqsave(&sc->sc_pm_lock, flags);
-++	if (!(sc->ps_flags & PS_BEACON_SYNC)) {
-++		tsf = ath9k_hw_gettsf32(sc->sc_ah);
-++		ieee80211_parse_p2p_noa(&vif->bss_conf.p2p_noa_attr, &avp->noa, tsf);
-++		ath9k_update_p2p_ps_timer(sc, avp);
-++	}
-++	spin_unlock_irqrestore(&sc->sc_pm_lock, flags);
- +}
- +
-  static void ath9k_bss_info_changed(struct ieee80211_hw *hw,
-  				   struct ieee80211_vif *vif,
-  				   struct ieee80211_bss_conf *bss_conf,
+-+}
+-+
+- static void ath9k_bss_info_changed(struct ieee80211_hw *hw,
+- 				   struct ieee80211_vif *vif,
+- 				   struct ieee80211_bss_conf *bss_conf,
 -@@ -1723,6 +1821,12 @@ static void ath9k_bss_info_changed(struc
-+@@ -1723,6 +1823,12 @@ static void ath9k_bss_info_changed(struc
-  		}
-  	}
-  
-@@ -166,7 +168,7 @@ Signed-off-by: Felix Fietkau <nbd@openwrt.org>
-  
- --- a/drivers/net/wireless/ath/ath9k/ath9k.h
- +++ b/drivers/net/wireless/ath/ath9k/ath9k.h
+- 		}
+- 	}
+- 
+-+	if (changed & BSS_CHANGED_P2P_PS) {
+-+		spin_lock_bh(&sc->sc_pcu_lock);
+-+		ath9k_update_p2p_ps(sc, vif);
+-+		spin_unlock_bh(&sc->sc_pcu_lock);
+-+	}
+-+
+- 	if (changed & CHECK_ANI)
+- 		ath_check_ani(sc);
+- 
+---- a/drivers/net/wireless/ath/ath9k/ath9k.h
+-+++ b/drivers/net/wireless/ath/ath9k/ath9k.h
 -@@ -115,6 +115,9 @@ int ath_descdma_setup(struct ath_softc *
-+@@ -114,6 +114,9 @@ int ath_descdma_setup(struct ath_softc *
-  #define ATH_TXFIFO_DEPTH           8
-  #define ATH_TX_ERROR               0x01
-  
-@@ -176,7 +178,7 @@ Signed-off-by: Felix Fietkau <nbd@openwrt.org>
-  #define IEEE80211_SEQ_SEQ_SHIFT    4
-  #define IEEE80211_SEQ_MAX          4096
-  #define IEEE80211_WEP_IVLEN        3
+- #define ATH_TXFIFO_DEPTH           8
+- #define ATH_TX_ERROR               0x01
+- 
+-+/* Stop tx traffic 1ms before the GO goes away */
+-+#define ATH_P2P_PS_STOP_TIME       1000
+-+
+- #define IEEE80211_SEQ_SEQ_SHIFT    4
+- #define IEEE80211_SEQ_MAX          4096
+- #define IEEE80211_WEP_IVLEN        3
 -@@ -363,11 +366,15 @@ void ath9k_release_buffered_frames(struc
-+@@ -366,11 +369,15 @@ void ath9k_release_buffered_frames(struc
-  /********/
-  
-  struct ath_vif {
-@@ -192,7 +194,7 @@ Signed-off-by: Felix Fietkau <nbd@openwrt.org>
-  };
-  
-  struct ath9k_vif_iter_data {
+- /********/
+- 
+- struct ath_vif {
+-+	struct ieee80211_vif *vif;
+- 	struct ath_node mcast_node;
+- 	int av_bslot;
+- 	bool primary_sta_vif;
+- 	__le64 tsf_adjust; /* TSF adjustment for staggered beacons */
+- 	struct ath_buf *av_bcbuf;
+-+
+-+	/* P2P Client */
+-+	struct ieee80211_noa_data noa;
+- };
+- 
+- struct ath9k_vif_iter_data {
 -@@ -472,6 +479,8 @@ int ath_update_survey_stats(struct ath_s
-+@@ -463,6 +470,8 @@ int ath_update_survey_stats(struct ath_s
-  void ath_update_survey_nf(struct ath_softc *sc, int channel);
-  void ath9k_queue_reset(struct ath_softc *sc, enum ath_reset_type type);
-  void ath_ps_full_sleep(unsigned long data);
-@@ -201,19 +203,19 @@ Signed-off-by: Felix Fietkau <nbd@openwrt.org>
-  
-  /**********/
-  /* BTCOEX */
+- void ath_update_survey_nf(struct ath_softc *sc, int channel);
+- void ath9k_queue_reset(struct ath_softc *sc, enum ath_reset_type type);
+- void ath_ps_full_sleep(unsigned long data);
+-+void ath9k_p2p_ps_timer(void *priv);
+-+void ath9k_update_p2p_ps(struct ath_softc *sc, struct ieee80211_vif *vif);
+- 
+- /**********/
+- /* BTCOEX */
 -@@ -741,6 +750,9 @@ struct ath_softc {
-+@@ -723,6 +732,9 @@ struct ath_softc {
-  	struct completion paprd_complete;
-  	wait_queue_head_t tx_wait;
-  
- +	struct ath_gen_timer *p2p_ps_timer;
- +	struct ath_vif *p2p_ps_vif;
- +
+- 	struct completion paprd_complete;
+- 	wait_queue_head_t tx_wait;
+- 
+-+	struct ath_gen_timer *p2p_ps_timer;
+-+	struct ath_vif *p2p_ps_vif;
+-+
 - 	unsigned long sc_flags;
-  	unsigned long driver_data;
-  
-+ 	u8 gtt_cnt;
- --- a/drivers/net/wireless/ath/ath9k/init.c
- +++ b/drivers/net/wireless/ath/ath9k/init.c
+- 	unsigned long driver_data;
+- 
+---- a/drivers/net/wireless/ath/ath9k/init.c
+-+++ b/drivers/net/wireless/ath/ath9k/init.c
 -@@ -797,6 +797,9 @@ static int ath9k_init_softc(u16 devid, s
-+@@ -593,6 +593,9 @@ static int ath9k_init_softc(u16 devid, s
-  	if (ret)
-  		goto err_btcoex;
-  
-@@ -223,7 +225,7 @@ Signed-off-by: Felix Fietkau <nbd@openwrt.org>
-  	ath9k_cmn_init_crypto(sc->sc_ah);
-  	ath9k_init_misc(sc);
-  	ath_fill_led_pin(sc);
+- 	if (ret)
+- 		goto err_btcoex;
+- 
+-+	sc->p2p_ps_timer = ath_gen_timer_alloc(sc->sc_ah, ath9k_p2p_ps_timer,
+-+		NULL, sc, AR_FIRST_NDP_TIMER);
+-+
+- 	ath9k_cmn_init_crypto(sc->sc_ah);
+- 	ath9k_init_misc(sc);
+- 	ath_fill_led_pin(sc);
 -@@ -1082,6 +1085,9 @@ static void ath9k_deinit_softc(struct at
-+@@ -875,6 +878,9 @@ static void ath9k_deinit_softc(struct at
-  {
-  	int i = 0;
-  
+- {
+- 	int i = 0;
+- 
+-+	if (sc->p2p_ps_timer)
+-+		ath_gen_timer_free(sc->sc_ah, sc->p2p_ps_timer);
+-+
+- 	ath9k_deinit_btcoex(sc);
+- 
+- 	for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++)
+---- a/drivers/net/wireless/ath/ath9k/recv.c
+-+++ b/drivers/net/wireless/ath/ath9k/recv.c
+-@@ -539,6 +539,9 @@ static void ath_rx_ps_beacon(struct ath_
+- 		ath_dbg(common, PS,
+- 			"Reconfigure beacon timers based on synchronized timestamp\n");
+- 		ath9k_set_beacon(sc);
+-+
+-+		if (sc->p2p_ps_vif)
+-+			ath9k_update_p2p_ps(sc, sc->p2p_ps_vif->vif);
+- 	}
+- 
+- 	if (ath_beacon_dtim_pending_cab(skb)) {
 diff --git a/package/mac80211/patches/566-ath9k-ar933x-usb-hang-workaround.patch b/package/mac80211/patches/566-ath9k-ar933x-usb-hang-workaround.patch
-index af94c9e..eddbc6c 100644
+deleted file mode 100644
+index af94c9e..0000000
 --- a/package/mac80211/patches/566-ath9k-ar933x-usb-hang-workaround.patch
-+++ b/package/mac80211/patches/566-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
++++ /dev/null
+@@ -1,79 +0,0 @@
+---- a/drivers/net/wireless/ath/ath9k/hw.c
+-+++ b/drivers/net/wireless/ath/ath9k/hw.c
 -@@ -217,6 +217,19 @@ void ath9k_hw_get_channel_centers(struct
-+@@ -216,6 +216,19 @@ void ath9k_hw_get_channel_centers(struct
-  		centers->synth_center + (extoff * HT40_CHANNEL_CENTER_SHIFT);
-  }
-  
-@@ -20,7 +20,7 @@
-  /******************/
-  /* Chip Revisions */
-  /******************/
+- 		centers->synth_center + (extoff * HT40_CHANNEL_CENTER_SHIFT);
+- }
+- 
+-+static inline void ath9k_hw_disable_pll_lock_detect(struct ath_hw *ah)
+-+{
+-+	/* On AR9330 and AR9340 devices, some PHY registers must be
+-+	 * tuned to gain better stability/performance. These registers
+-+	 * might be changed while doing wlan reset so the registers must
+-+	 * be reprogrammed after each reset.
+-+	 */
+-+	REG_CLR_BIT(ah, AR_PHY_USB_CTRL1, BIT(20));
+-+	REG_RMW(ah, AR_PHY_USB_CTRL2,
+-+		(1 << 21) | (0xf << 22),
+-+		(1 << 21) | (0x3 << 22));
+-+}
+-+
+- /******************/
+- /* Chip Revisions */
+- /******************/
 -@@ -1337,6 +1350,9 @@ static bool ath9k_hw_set_reset(struct at
-+@@ -1336,6 +1349,9 @@ static bool ath9k_hw_set_reset(struct at
-  	if (AR_SREV_9100(ah))
-  		udelay(50);
-  
-@@ -30,7 +30,7 @@
-  	return true;
-  }
-  
+- 	if (AR_SREV_9100(ah))
+- 		udelay(50);
+- 
+-+	if (AR_SREV_9330(ah) || AR_SREV_9340(ah))
+-+		ath9k_hw_disable_pll_lock_detect(ah);
+-+
+- 	return true;
+- }
+- 
 -@@ -1436,6 +1452,9 @@ static bool ath9k_hw_chip_reset(struct a
-+@@ -1435,6 +1451,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;
-  }
-  
+- 		ar9003_hw_internal_regulator_apply(ah);
+- 	ath9k_hw_init_pll(ah, chan);
+- 
+-+	if (AR_SREV_9330(ah) || AR_SREV_9340(ah))
+-+		ath9k_hw_disable_pll_lock_detect(ah);
+-+
+- 	return true;
+- }
+- 
 -@@ -1730,8 +1749,14 @@ static int ath9k_hw_do_fastcc(struct ath
-+@@ -1729,8 +1748,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;
-  }
-  
+- 	if (AR_SREV_9271(ah))
+- 		ar9002_hw_load_ani_reg(ah, chan);
+- 
+-+	if (AR_SREV_9330(ah) || AR_SREV_9340(ah))
+-+		ath9k_hw_disable_pll_lock_detect(ah);
+-+
+- 	return 0;
+- fail:
+-+	if (AR_SREV_9330(ah) || AR_SREV_9340(ah))
+-+		ath9k_hw_disable_pll_lock_detect(ah);
+-+
+- 	return -EINVAL;
+- }
+- 
 -@@ -1959,6 +1984,9 @@ int ath9k_hw_reset(struct ath_hw *ah, st
-+@@ -1958,6 +1983,9 @@ int ath9k_hw_reset(struct ath_hw *ah, st
-  	if (AR_SREV_9565(ah) && common->bt_ant_diversity)
-  		REG_SET_BIT(ah, AR_BTCOEX_WL_LNADIV, AR_BTCOEX_WL_LNADIV_FORCE_ON);
-  
-diff --git a/package/mac80211/patches/567-ath9k_ar953x_read_mac_rev.patch b/package/mac80211/patches/567-ath9k_ar953x_read_mac_rev.patch
-new file mode 100644
-index 0000000..31778a4
---- /dev/null
-+++ b/package/mac80211/patches/567-ath9k_ar953x_read_mac_rev.patch
-@@ -0,0 +1,11 @@
-+--- a/drivers/net/wireless/ath/ath9k/hw.c
-++++ b/drivers/net/wireless/ath/ath9k/hw.c
-+@@ -260,6 +260,8 @@ static void ath9k_hw_read_revisions(stru
-+ 		return;
-+ 	case AR9300_DEVID_AR953X:
-+ 		ah->hw_version.macVersion = AR_SREV_VERSION_9531;
-++		if (ah->get_mac_revision)
-++			ah->hw_version.macRev = ah->get_mac_revision();
-+ 		return;
-+ 	}
-+ 
-diff --git a/package/mac80211/patches/570-restrict_dfs_regions.patch b/package/mac80211/patches/570-restrict_dfs_regions.patch
-new file mode 100644
-index 0000000..10157dc
---- /dev/null
-+++ b/package/mac80211/patches/570-restrict_dfs_regions.patch
-@@ -0,0 +1,82 @@
-+--- a/drivers/net/wireless/ath/ath10k/mac.c
-++++ b/drivers/net/wireless/ath/ath10k/mac.c
-+@@ -4321,6 +4321,7 @@ static const struct ieee80211_iface_comb
-+ 					BIT(NL80211_CHAN_WIDTH_20) |
-+ 					BIT(NL80211_CHAN_WIDTH_40) |
-+ 					BIT(NL80211_CHAN_WIDTH_80),
-++		.radar_detect_regions = BIT(NL80211_DFS_ETSI),
-+ #endif
-+ 	},
-+ };
-+--- a/drivers/net/wireless/ath/ath9k/init.c
-++++ b/drivers/net/wireless/ath/ath9k/init.c
-+@@ -688,6 +688,7 @@ static const struct ieee80211_iface_comb
-+ 		.beacon_int_infra_match = true,
-+ 		.radar_detect_widths =	BIT(NL80211_CHAN_WIDTH_20_NOHT) |
-+ 					BIT(NL80211_CHAN_WIDTH_20),
-++		.radar_detect_regions = BIT(NL80211_DFS_ETSI),
-+ 	}
-+ #endif
-+ };
-+--- a/include/net/cfg80211.h
-++++ b/include/net/cfg80211.h
-+@@ -2620,6 +2620,7 @@ struct ieee80211_iface_limit {
-+  *	between infrastructure and AP types must match. This is required
-+  *	only in special cases.
-+  * @radar_detect_widths: bitmap of channel widths supported for radar detection
-++ * @radar_detect_regions: bitmap of regions supported for radar detection
-+  *
-+  * With this structure the driver can describe which interface
-+  * combinations it supports concurrently.
-+@@ -2677,6 +2678,7 @@ struct ieee80211_iface_combination {
-+ 	u8 n_limits;
-+ 	bool beacon_int_infra_match;
-+ 	u8 radar_detect_widths;
-++	u8 radar_detect_regions;
-+ };
-+ 
-+ struct ieee80211_txrx_stypes {
-+--- a/net/wireless/util.c
-++++ b/net/wireless/util.c
-+@@ -1259,6 +1259,7 @@ int cfg80211_can_use_iftype_chan(struct 
-+ 				 enum cfg80211_chan_mode chanmode,
-+ 				 u8 radar_detect)
-+ {
-++	const struct ieee80211_regdomain *regdom;
-+ 	struct wireless_dev *wdev_iter;
-+ 	u32 used_iftypes = BIT(iftype);
-+ 	int num[NUM_NL80211_IFTYPES];
-+@@ -1267,6 +1268,7 @@ int cfg80211_can_use_iftype_chan(struct 
-+ 	struct ieee80211_channel *ch;
-+ 	enum cfg80211_chan_mode chmode;
-+ 	int num_different_channels = 0;
-++	enum nl80211_dfs_regions region = 0;
-+ 	int total = 1;
-+ 	int i, j;
-+ 
-+@@ -1285,6 +1287,14 @@ int cfg80211_can_use_iftype_chan(struct 
-+ 		return 0;
-+ 	}
-+ 
-++	if (radar_detect) {
-++		rcu_read_lock();
-++		regdom = rcu_dereference(cfg80211_regdomain);
-++		if (regdom)
-++			region = regdom->dfs_region;
-++		rcu_read_unlock();
-++	}
-++
-+ 	memset(num, 0, sizeof(num));
-+ 	memset(used_channels, 0, sizeof(used_channels));
-+ 
-+@@ -1392,6 +1402,10 @@ int cfg80211_can_use_iftype_chan(struct 
-+ 		if (radar_detect && !(c->radar_detect_widths & radar_detect))
-+ 			goto cont;
-+ 
-++		if (radar_detect && c->radar_detect_regions &&
-++		    !(c->radar_detect_regions & BIT(region)))
-++			goto cont;
-++
-+ 		/*
-+ 		 * Finally check that all iftypes that we're currently
-+ 		 * using are actually part of this combination. If they
+- 	if (AR_SREV_9565(ah) && common->bt_ant_diversity)
+- 		REG_SET_BIT(ah, AR_BTCOEX_WL_LNADIV, AR_BTCOEX_WL_LNADIV_FORCE_ON);
+- 
+-+	if (AR_SREV_9330(ah) || AR_SREV_9340(ah))
+-+		ath9k_hw_disable_pll_lock_detect(ah);
+-+
+- 	return 0;
+- }
+- EXPORT_SYMBOL(ath9k_hw_reset);
+---- a/drivers/net/wireless/ath/ath9k/phy.h
+-+++ b/drivers/net/wireless/ath/ath9k/phy.h
+-@@ -48,6 +48,9 @@
+- #define AR_PHY_PLL_CONTROL 0x16180
+- #define AR_PHY_PLL_MODE 0x16184
+- 
+-+#define AR_PHY_USB_CTRL1	0x16c84
+-+#define AR_PHY_USB_CTRL2	0x16c88
+-+
+- enum ath9k_ant_div_comb_lna_conf {
+- 	ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2,
+- 	ATH_ANT_DIV_COMB_LNA2,
 diff --git a/package/mac80211/patches/600-0001-rt2x00-rt2800lib-move-rt2800_drv_data-declaration-in.patch b/package/mac80211/patches/600-0001-rt2x00-rt2800lib-move-rt2800_drv_data-declaration-in.patch
 new file mode 100644
 index 0000000..d344957
@@ -7599,7 +11438,7 @@ index 0000000..d344957
 + 			      const unsigned int offset, u32 *value);
 diff --git a/package/mac80211/patches/600-0002-rt2x00-rt2800lib-introduce-RT2800_HAS_HIGH_SHARED_ME.patch b/package/mac80211/patches/600-0002-rt2x00-rt2800lib-introduce-RT2800_HAS_HIGH_SHARED_ME.patch
 new file mode 100644
-index 0000000..3b11b15
+index 0000000..98c9203
 --- /dev/null
 +++ b/package/mac80211/patches/600-0002-rt2x00-rt2800lib-introduce-RT2800_HAS_HIGH_SHARED_ME.patch
 @@ -0,0 +1,80 @@
@@ -7629,7 +11468,7 @@ index 0000000..3b11b15
 +
 +--- a/drivers/net/wireless/rt2x00/rt2800lib.c
 ++++ b/drivers/net/wireless/rt2x00/rt2800lib.c
-+@@ -7712,6 +7712,7 @@ static int rt2800_probe_rt(struct rt2x00
++@@ -7711,6 +7711,7 @@ static int rt2800_probe_rt(struct rt2x00
 + 
 + int rt2800_probe_hw(struct rt2x00_dev *rt2x00dev)
 + {
@@ -7637,7 +11476,7 @@ index 0000000..3b11b15
 + 	int retval;
 + 	u32 reg;
 + 
-+@@ -7719,6 +7720,9 @@ int rt2800_probe_hw(struct rt2x00_dev *r
++@@ -7718,6 +7719,9 @@ int rt2800_probe_hw(struct rt2x00_dev *r
 + 	if (retval)
 + 		return retval;
 + 
@@ -7685,7 +11524,7 @@ index 0000000..3b11b15
 + 					u32 *value)
 diff --git a/package/mac80211/patches/600-0003-rt2x00-rt2800-serialize-shared-memory-access.patch b/package/mac80211/patches/600-0003-rt2x00-rt2800-serialize-shared-memory-access.patch
 new file mode 100644
-index 0000000..879b4cc
+index 0000000..97e213f
 --- /dev/null
 +++ b/package/mac80211/patches/600-0003-rt2x00-rt2800-serialize-shared-memory-access.patch
 @@ -0,0 +1,531 @@
@@ -7770,8 +11609,8 @@ index 0000000..879b4cc
 ++	rt2800_shared_mem_unlock(rt2x00dev);
 + 
 + 	/*
-+ 	 * Enable beaconing again.
-+@@ -1027,6 +1039,8 @@ static inline void rt2800_clear_beacon_r
++ 	 * Restore beaconing state.
++@@ -1026,6 +1038,8 @@ static inline void rt2800_clear_beacon_r
 + 
 + 	beacon_base = rt2800_hw_beacon_base(rt2x00dev, index);
 + 
@@ -7780,7 +11619,7 @@ index 0000000..879b4cc
 + 	/*
 + 	 * For the Beacon base registers we only need to clear
 + 	 * the whole TXWI which (when set to 0) will invalidate
-+@@ -1034,6 +1048,8 @@ static inline void rt2800_clear_beacon_r
++@@ -1033,6 +1047,8 @@ static inline void rt2800_clear_beacon_r
 + 	 */
 + 	for (i = 0; i < txwi_desc_size; i += sizeof(__le32))
 + 		rt2800_register_write(rt2x00dev, beacon_base + i, 0);
@@ -7789,7 +11628,7 @@ index 0000000..879b4cc
 + }
 + 
 + void rt2800_clear_beacon(struct queue_entry *entry)
-+@@ -1217,7 +1233,9 @@ static void rt2800_delete_wcid_attr(stru
++@@ -1216,7 +1232,9 @@ static void rt2800_delete_wcid_attr(stru
 + {
 + 	u32 offset;
 + 	offset = MAC_WCID_ATTR_ENTRY(wcid);
@@ -7799,7 +11638,7 @@ index 0000000..879b4cc
 + }
 + 
 + static void rt2800_config_wcid_attr_bssidx(struct rt2x00_dev *rt2x00dev,
-+@@ -1230,11 +1248,13 @@ static void rt2800_config_wcid_attr_bssi
++@@ -1229,11 +1247,13 @@ static void rt2800_config_wcid_attr_bssi
 + 	 * The BSS Idx numbers is split in a main value of 3 bits,
 + 	 * and a extended field for adding one additional bit to the value.
 + 	 */
@@ -7813,7 +11652,7 @@ index 0000000..879b4cc
 + }
 + 
 + static void rt2800_config_wcid_attr_cipher(struct rt2x00_dev *rt2x00dev,
-+@@ -1247,6 +1267,7 @@ static void rt2800_config_wcid_attr_ciph
++@@ -1246,6 +1266,7 @@ static void rt2800_config_wcid_attr_ciph
 + 
 + 	offset = MAC_WCID_ATTR_ENTRY(key->hw_key_idx);
 + 
@@ -7821,7 +11660,7 @@ index 0000000..879b4cc
 + 	if (crypto->cmd == SET_KEY) {
 + 		rt2800_register_read(rt2x00dev, offset, &reg);
 + 		rt2x00_set_field32(&reg, MAC_WCID_ATTRIBUTE_KEYTAB,
-+@@ -1271,6 +1292,7 @@ static void rt2800_config_wcid_attr_ciph
++@@ -1270,6 +1291,7 @@ static void rt2800_config_wcid_attr_ciph
 + 		rt2x00_set_field32(&reg, MAC_WCID_ATTRIBUTE_RX_WIUDF, 0);
 + 		rt2800_register_write(rt2x00dev, offset, reg);
 + 	}
@@ -7829,7 +11668,7 @@ index 0000000..879b4cc
 + 
 + 	offset = MAC_IVEIV_ENTRY(key->hw_key_idx);
 + 
-+@@ -1280,8 +1302,11 @@ static void rt2800_config_wcid_attr_ciph
++@@ -1279,8 +1301,11 @@ static void rt2800_config_wcid_attr_ciph
 + 	    (crypto->cipher == CIPHER_AES))
 + 		iveiv_entry.iv[3] |= 0x20;
 + 	iveiv_entry.iv[3] |= key->keyidx << 6;
@@ -7841,7 +11680,7 @@ index 0000000..879b4cc
 + }
 + 
 + int rt2800_config_shared_key(struct rt2x00_dev *rt2x00dev,
-+@@ -1304,8 +1329,11 @@ int rt2800_config_shared_key(struct rt2x
++@@ -1303,8 +1328,11 @@ int rt2800_config_shared_key(struct rt2x
 + 		       sizeof(key_entry.rx_mic));
 + 
 + 		offset = SHARED_KEY_ENTRY(key->hw_key_idx);
@@ -7853,7 +11692,7 @@ index 0000000..879b4cc
 + 	}
 + 
 + 	/*
-+@@ -1320,10 +1348,12 @@ int rt2800_config_shared_key(struct rt2x
++@@ -1319,10 +1347,12 @@ int rt2800_config_shared_key(struct rt2x
 + 
 + 	offset = SHARED_KEY_MODE_ENTRY(key->hw_key_idx / 8);
 + 
@@ -7866,7 +11705,7 @@ index 0000000..879b4cc
 + 
 + 	/*
 + 	 * Update WCID information
-+@@ -1393,8 +1423,11 @@ int rt2800_config_pairwise_key(struct rt
++@@ -1392,8 +1422,11 @@ int rt2800_config_pairwise_key(struct rt
 + 		       sizeof(key_entry.rx_mic));
 + 
 + 		offset = PAIRWISE_KEY_ENTRY(key->hw_key_idx);
@@ -7878,7 +11717,7 @@ index 0000000..879b4cc
 + 	}
 + 
 + 	/*
-+@@ -4876,14 +4909,19 @@ static int rt2800_init_registers(struct
++@@ -4875,14 +4908,19 @@ static int rt2800_init_registers(struct 
 + 	/*
 + 	 * ASIC will keep garbage value after boot, clear encryption keys.
 + 	 */
@@ -7898,7 +11737,7 @@ index 0000000..879b4cc
 + 	}
 + 
 + 	/*
-+@@ -5009,8 +5047,10 @@ static int rt2800_wait_bbp_ready(struct
++@@ -5008,8 +5046,10 @@ static int rt2800_wait_bbp_ready(struct 
 + 	 * BBP was enabled after firmware was loaded,
 + 	 * but we need to reactivate it now.
 + 	 */
@@ -7909,7 +11748,7 @@ index 0000000..879b4cc
 + 	msleep(1);
 + 
 + 	for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
-+@@ -6706,11 +6746,19 @@ int rt2800_enable_radio(struct rt2x00_de
++@@ -6705,11 +6745,19 @@ int rt2800_enable_radio(struct rt2x00_de
 + 	/*
 + 	 * Send signal during boot time to initialize firmware.
 + 	 */
@@ -7930,7 +11769,7 @@ index 0000000..879b4cc
 + 	msleep(1);
 + 
 + 	/*
-+@@ -7716,6 +7764,8 @@ int rt2800_probe_hw(struct rt2x00_dev *r
++@@ -7715,6 +7763,8 @@ int rt2800_probe_hw(struct rt2x00_dev *r
 + 	int retval;
 + 	u32 reg;
 + 
@@ -7939,7 +11778,7 @@ index 0000000..879b4cc
 + 	retval = rt2800_probe_rt(rt2x00dev);
 + 	if (retval)
 + 		return retval;
-+@@ -7795,8 +7845,11 @@ void rt2800_get_tkip_seq(struct ieee8021
++@@ -7794,8 +7844,11 @@ void rt2800_get_tkip_seq(struct ieee8021
 + 	u32 offset;
 + 
 + 	offset = MAC_IVEIV_ENTRY(hw_key_idx);
@@ -8063,7 +11902,7 @@ index 0000000..879b4cc
 + #endif /* RT2800MMIO_H */
 +--- a/drivers/net/wireless/rt2x00/rt2800pci.c
 ++++ b/drivers/net/wireless/rt2x00/rt2800pci.c
-+@@ -69,7 +69,9 @@ static void rt2800pci_mcu_status(struct
++@@ -69,7 +69,9 @@ static void rt2800pci_mcu_status(struct 
 + 		return;
 + 
 + 	for (i = 0; i < 200; i++) {
@@ -8073,7 +11912,7 @@ index 0000000..879b4cc
 + 
 + 		if ((rt2x00_get_field32(reg, H2M_MAILBOX_CID_CMD0) == token) ||
 + 		    (rt2x00_get_field32(reg, H2M_MAILBOX_CID_CMD1) == token) ||
-+@@ -83,8 +85,10 @@ static void rt2800pci_mcu_status(struct
++@@ -83,8 +85,10 @@ static void rt2800pci_mcu_status(struct 
 + 	if (i == 200)
 + 		rt2x00_err(rt2x00dev, "MCU request failed, no response from hardware\n");
 + 
@@ -8222,7 +12061,7 @@ index 0000000..879b4cc
 + static const struct rt2x00lib_ops rt2800usb_rt2x00_ops = {
 diff --git a/package/mac80211/patches/600-0004-rt2x00-rt2800lib-fix-beacon-generation-on-RT3593.patch b/package/mac80211/patches/600-0004-rt2x00-rt2800lib-fix-beacon-generation-on-RT3593.patch
 new file mode 100644
-index 0000000..38dbb43
+index 0000000..5cb6eae
 --- /dev/null
 +++ b/package/mac80211/patches/600-0004-rt2x00-rt2800lib-fix-beacon-generation-on-RT3593.patch
 @@ -0,0 +1,131 @@
@@ -8339,7 +12178,7 @@ index 0000000..38dbb43
 + 	rt2800_shared_mem_unlock(rt2x00dev);
 + 
 + 	/*
-+@@ -1041,6 +1081,8 @@ static inline void rt2800_clear_beacon_r
++@@ -1040,6 +1080,8 @@ static inline void rt2800_clear_beacon_r
 + 
 + 	rt2800_shared_mem_lock(rt2x00dev);
 + 
@@ -8348,7 +12187,7 @@ index 0000000..38dbb43
 + 	/*
 + 	 * For the Beacon base registers we only need to clear
 + 	 * the whole TXWI which (when set to 0) will invalidate
-+@@ -1049,6 +1091,8 @@ static inline void rt2800_clear_beacon_r
++@@ -1048,6 +1090,8 @@ static inline void rt2800_clear_beacon_r
 + 	for (i = 0; i < txwi_desc_size; i += sizeof(__le32))
 + 		rt2800_register_write(rt2x00dev, beacon_base + i, 0);
 + 
@@ -8359,7 +12198,7 @@ index 0000000..38dbb43
 + 
 diff --git a/package/mac80211/patches/600-0005-rt2x00-rt2800lib-add-hw_beacon_count-field-to-struct.patch b/package/mac80211/patches/600-0005-rt2x00-rt2800lib-add-hw_beacon_count-field-to-struct.patch
 new file mode 100644
-index 0000000..3d97169
+index 0000000..d832f99
 --- /dev/null
 +++ b/package/mac80211/patches/600-0005-rt2x00-rt2800lib-add-hw_beacon_count-field-to-struct.patch
 @@ -0,0 +1,62 @@
@@ -8389,7 +12228,7 @@ index 0000000..3d97169
 +
 +--- a/drivers/net/wireless/rt2x00/rt2800lib.c
 ++++ b/drivers/net/wireless/rt2x00/rt2800lib.c
-+@@ -4584,6 +4584,7 @@ EXPORT_SYMBOL_GPL(rt2800_link_tuner);
++@@ -4583,6 +4583,7 @@ EXPORT_SYMBOL_GPL(rt2800_link_tuner);
 +  */
 + static int rt2800_init_registers(struct rt2x00_dev *rt2x00dev)
 + {
@@ -8397,7 +12236,7 @@ index 0000000..3d97169
 + 	u32 reg;
 + 	u16 eeprom;
 + 	unsigned int i;
-+@@ -4971,7 +4972,7 @@ static int rt2800_init_registers(struct
++@@ -4970,7 +4971,7 @@ static int rt2800_init_registers(struct 
 + 	/*
 + 	 * Clear all beacons
 + 	 */
@@ -8406,7 +12245,7 @@ index 0000000..3d97169
 + 		rt2800_clear_beacon_register(rt2x00dev, i);
 + 
 + 	if (rt2x00_is_usb(rt2x00dev)) {
-+@@ -7817,6 +7818,8 @@ int rt2800_probe_hw(struct rt2x00_dev *r
++@@ -7816,6 +7817,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);
 + 
@@ -8427,7 +12266,7 @@ index 0000000..3d97169
 + 
 diff --git a/package/mac80211/patches/600-0006-rt2x00-rt2800lib-init-additional-beacon-offset-regis.patch b/package/mac80211/patches/600-0006-rt2x00-rt2800lib-init-additional-beacon-offset-regis.patch
 new file mode 100644
-index 0000000..8c52713
+index 0000000..040c69c
 --- /dev/null
 +++ b/package/mac80211/patches/600-0006-rt2x00-rt2800lib-init-additional-beacon-offset-regis.patch
 @@ -0,0 +1,67 @@
@@ -8467,7 +12306,7 @@ index 0000000..8c52713
 +  */
 +--- a/drivers/net/wireless/rt2x00/rt2800lib.c
 ++++ b/drivers/net/wireless/rt2x00/rt2800lib.c
-+@@ -4618,6 +4618,30 @@ static int rt2800_init_registers(struct
++@@ -4617,6 +4617,30 @@ static int rt2800_init_registers(struct 
 + 			   rt2800_get_beacon_offset(rt2x00dev, 7));
 + 	rt2800_register_write(rt2x00dev, BCN_OFFSET1, reg);
 + 
@@ -8500,7 +12339,7 @@ index 0000000..8c52713
 + 
 diff --git a/package/mac80211/patches/600-0007-rt2x00-rt2800lib-fix-max-supported-beacon-count-for-.patch b/package/mac80211/patches/600-0007-rt2x00-rt2800lib-fix-max-supported-beacon-count-for-.patch
 new file mode 100644
-index 0000000..66e8245
+index 0000000..752cd89
 --- /dev/null
 +++ b/package/mac80211/patches/600-0007-rt2x00-rt2800lib-fix-max-supported-beacon-count-for-.patch
 @@ -0,0 +1,24 @@
@@ -8516,7 +12355,7 @@ index 0000000..66e8245
 +
 +--- a/drivers/net/wireless/rt2x00/rt2800lib.c
 ++++ b/drivers/net/wireless/rt2x00/rt2800lib.c
-+@@ -7842,7 +7842,10 @@ int rt2800_probe_hw(struct rt2x00_dev *r
++@@ -7841,7 +7841,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);
 + 
@@ -8566,7 +12405,7 @@ index 0000000..8a10c6e
 + 
 diff --git a/package/mac80211/patches/600-0009-rt2x00-rt2800lib-enable-support-for-RT3883.patch b/package/mac80211/patches/600-0009-rt2x00-rt2800lib-enable-support-for-RT3883.patch
 new file mode 100644
-index 0000000..e9d847a
+index 0000000..8cb93ec
 --- /dev/null
 +++ b/package/mac80211/patches/600-0009-rt2x00-rt2800lib-enable-support-for-RT3883.patch
 @@ -0,0 +1,20 @@
@@ -8582,7 +12421,7 @@ index 0000000..e9d847a
 +
 +--- a/drivers/net/wireless/rt2x00/rt2800lib.c
 ++++ b/drivers/net/wireless/rt2x00/rt2800lib.c
-+@@ -7812,6 +7812,7 @@ static int rt2800_probe_rt(struct rt2x00
++@@ -7811,6 +7811,7 @@ static int rt2800_probe_rt(struct rt2x00
 + 	case RT3390:
 + 	case RT3572:
 + 	case RT3593:
@@ -8592,7 +12431,7 @@ index 0000000..e9d847a
 + 	case RT5592:
 diff --git a/package/mac80211/patches/600-0010-rt2x00-rt2800lib-add-rf_vals-for-RF3853.patch b/package/mac80211/patches/600-0010-rt2x00-rt2800lib-add-rf_vals-for-RF3853.patch
 new file mode 100644
-index 0000000..b096f9f
+index 0000000..e85ae97
 --- /dev/null
 +++ b/package/mac80211/patches/600-0010-rt2x00-rt2800lib-add-rf_vals-for-RF3853.patch
 @@ -0,0 +1,112 @@
@@ -8629,7 +12468,7 @@ index 0000000..b096f9f
 + #define RF5372				0x5372
 +--- a/drivers/net/wireless/rt2x00/rt2800lib.c
 ++++ b/drivers/net/wireless/rt2x00/rt2800lib.c
-+@@ -7432,6 +7432,66 @@ static const struct rf_channel rf_vals_3
++@@ -7431,6 +7431,66 @@ static const struct rf_channel rf_vals_3
 + 	{173, 0x61, 0, 9},
 + };
 + 
@@ -8696,7 +12535,7 @@ index 0000000..b096f9f
 + static const struct rf_channel rf_vals_5592_xtal20[] = {
 + 	/* Channel, N, K, mod, R */
 + 	{1, 482, 4, 10, 3},
-+@@ -7660,6 +7720,11 @@ static int rt2800_probe_hw_mode(struct r
++@@ -7659,6 +7719,11 @@ static int rt2800_probe_hw_mode(struct r
 + 		spec->channels = rf_vals_3x;
 + 		break;
 + 
@@ -8710,7 +12549,7 @@ index 0000000..b096f9f
 + 		if (rt2x00_get_field32(reg, MAC_DEBUG_INDEX_XTAL)) {
 diff --git a/package/mac80211/patches/600-0011-rt2x00-rt2800lib-enable-VCO-calibration-for-RF3853.patch b/package/mac80211/patches/600-0011-rt2x00-rt2800lib-enable-VCO-calibration-for-RF3853.patch
 new file mode 100644
-index 0000000..4c9a3b4
+index 0000000..898e385
 --- /dev/null
 +++ b/package/mac80211/patches/600-0011-rt2x00-rt2800lib-enable-VCO-calibration-for-RF3853.patch
 @@ -0,0 +1,28 @@
@@ -8726,7 +12565,7 @@ index 0000000..4c9a3b4
 +
 +--- a/drivers/net/wireless/rt2x00/rt2800lib.c
 ++++ b/drivers/net/wireless/rt2x00/rt2800lib.c
-+@@ -4349,6 +4349,7 @@ void rt2800_vco_calibration(struct rt2x0
++@@ -4348,6 +4348,7 @@ void rt2800_vco_calibration(struct rt2x0
 + 	case RF3053:
 + 	case RF3070:
 + 	case RF3290:
@@ -8734,7 +12573,7 @@ index 0000000..4c9a3b4
 + 	case RF5360:
 + 	case RF5370:
 + 	case RF5372:
-+@@ -7839,6 +7840,7 @@ static int rt2800_probe_hw_mode(struct r
++@@ -7838,6 +7839,7 @@ static int rt2800_probe_hw_mode(struct r
 + 	case RF3053:
 + 	case RF3070:
 + 	case RF3290:
@@ -8744,7 +12583,7 @@ index 0000000..4c9a3b4
 + 	case RF5372:
 diff --git a/package/mac80211/patches/600-0012-rt2x00-rt2800lib-add-channel-configuration-function-.patch b/package/mac80211/patches/600-0012-rt2x00-rt2800lib-add-channel-configuration-function-.patch
 new file mode 100644
-index 0000000..e3460ff
+index 0000000..1de99ea
 --- /dev/null
 +++ b/package/mac80211/patches/600-0012-rt2x00-rt2800lib-add-channel-configuration-function-.patch
 @@ -0,0 +1,235 @@
@@ -8761,7 +12600,7 @@ index 0000000..e3460ff
 +
 +--- a/drivers/net/wireless/rt2x00/rt2800lib.c
 ++++ b/drivers/net/wireless/rt2x00/rt2800lib.c
-+@@ -2605,6 +2605,211 @@ static void rt2800_config_channel_rf3053
++@@ -2604,6 +2604,211 @@ static void rt2800_config_channel_rf3053
 + 	}
 + }
 + 
@@ -8973,7 +12812,7 @@ index 0000000..e3460ff
 + #define POWER_BOUND		0x27
 + #define POWER_BOUND_5G		0x2b
 + 
-+@@ -3217,6 +3422,9 @@ static void rt2800_config_channel(struct
++@@ -3216,6 +3421,9 @@ static void rt2800_config_channel(struct
 + 	case RF3322:
 + 		rt2800_config_channel_rf3322(rt2x00dev, conf, rf, info);
 + 		break;
@@ -8985,7 +12824,7 @@ index 0000000..e3460ff
 + 	case RF5370:
 diff --git a/package/mac80211/patches/600-0013-rt2x00-rt2800lib-enable-RF3853-support.patch b/package/mac80211/patches/600-0013-rt2x00-rt2800lib-enable-RF3853-support.patch
 new file mode 100644
-index 0000000..8719425
+index 0000000..e7e17a9
 --- /dev/null
 +++ b/package/mac80211/patches/600-0013-rt2x00-rt2800lib-enable-RF3853-support.patch
 @@ -0,0 +1,20 @@
@@ -9001,7 +12840,7 @@ index 0000000..8719425
 +
 +--- a/drivers/net/wireless/rt2x00/rt2800lib.c
 ++++ b/drivers/net/wireless/rt2x00/rt2800lib.c
-+@@ -7398,6 +7398,7 @@ static int rt2800_init_eeprom(struct rt2
++@@ -7397,6 +7397,7 @@ static int rt2800_init_eeprom(struct rt2
 + 	case RF3290:
 + 	case RF3320:
 + 	case RF3322:
@@ -9011,7 +12850,7 @@ index 0000000..8719425
 + 	case RF5372:
 diff --git a/package/mac80211/patches/600-0014-rt2x00-rt2800lib-add-MAC-register-initialization-for.patch b/package/mac80211/patches/600-0014-rt2x00-rt2800lib-add-MAC-register-initialization-for.patch
 new file mode 100644
-index 0000000..8632ddd
+index 0000000..95423d1
 --- /dev/null
 +++ b/package/mac80211/patches/600-0014-rt2x00-rt2800lib-add-MAC-register-initialization-for.patch
 @@ -0,0 +1,77 @@
@@ -9052,7 +12891,7 @@ index 0000000..8632ddd
 + #define RX_FILTER_CFG			0x1400
 +--- a/drivers/net/wireless/rt2x00/rt2800lib.c
 ++++ b/drivers/net/wireless/rt2x00/rt2800lib.c
-+@@ -4973,6 +4973,12 @@ static int rt2800_init_registers(struct
++@@ -4972,6 +4972,12 @@ static int rt2800_init_registers(struct 
 + 			rt2800_register_write(rt2x00dev, TX_SW_CFG2,
 + 					      0x00000000);
 + 		}
@@ -9065,7 +12904,7 @@ index 0000000..8632ddd
 + 	} else if (rt2x00_rt(rt2x00dev, RT5390) ||
 + 		   rt2x00_rt(rt2x00dev, RT5392) ||
 + 		   rt2x00_rt(rt2x00dev, RT5592)) {
-+@@ -5003,9 +5009,11 @@ static int rt2800_init_registers(struct
++@@ -5002,9 +5008,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);
@@ -9080,7 +12919,7 @@ index 0000000..8632ddd
 + 		rt2x00_set_field32(&reg, MAX_LEN_CFG_MAX_PSDU, 2);
 + 	else
 + 		rt2x00_set_field32(&reg, MAX_LEN_CFG_MAX_PSDU, 1);
-+@@ -5158,6 +5166,11 @@ static int rt2800_init_registers(struct
++@@ -5157,6 +5165,11 @@ static int rt2800_init_registers(struct 
 + 	reg = rt2x00_rt(rt2x00dev, RT5592) ? 0x00000082 : 0x00000002;
 + 	rt2800_register_write(rt2x00dev, TXOP_HLDR_ET, reg);
 + 
@@ -9130,7 +12969,7 @@ index 0000000..837c025
 + static int rt2800soc_set_device_state(struct rt2x00_dev *rt2x00dev,
 diff --git a/package/mac80211/patches/600-0016-rt2x00-rt2800lib-add-BBP-register-initialization-for.patch b/package/mac80211/patches/600-0016-rt2x00-rt2800lib-add-BBP-register-initialization-for.patch
 new file mode 100644
-index 0000000..967e36a
+index 0000000..d9694da
 --- /dev/null
 +++ b/package/mac80211/patches/600-0016-rt2x00-rt2800lib-add-BBP-register-initialization-for.patch
 @@ -0,0 +1,71 @@
@@ -9147,7 +12986,7 @@ index 0000000..967e36a
 +
 +--- a/drivers/net/wireless/rt2x00/rt2800lib.c
 ++++ b/drivers/net/wireless/rt2x00/rt2800lib.c
-+@@ -5776,6 +5776,47 @@ static void rt2800_init_bbp_3593(struct
++@@ -5775,6 +5775,47 @@ static void rt2800_init_bbp_3593(struct 
 + 		rt2800_bbp_write(rt2x00dev, 103, 0xc0);
 + }
 + 
@@ -9195,7 +13034,7 @@ index 0000000..967e36a
 + static void rt2800_init_bbp_53xx(struct rt2x00_dev *rt2x00dev)
 + {
 + 	int ant, div_mode;
-+@@ -5994,6 +6035,9 @@ static void rt2800_init_bbp(struct rt2x0
++@@ -5993,6 +6034,9 @@ static void rt2800_init_bbp(struct rt2x0
 + 	case RT3593:
 + 		rt2800_init_bbp_3593(rt2x00dev);
 + 		return;
@@ -9207,7 +13046,7 @@ index 0000000..967e36a
 + 		rt2800_init_bbp_53xx(rt2x00dev);
 diff --git a/package/mac80211/patches/600-0017-rt2x00-rt2800lib-add-RFCSR-initialization-for-RT3883.patch b/package/mac80211/patches/600-0017-rt2x00-rt2800lib-add-RFCSR-initialization-for-RT3883.patch
 new file mode 100644
-index 0000000..c568b99
+index 0000000..dc45109
 --- /dev/null
 +++ b/package/mac80211/patches/600-0017-rt2x00-rt2800lib-add-RFCSR-initialization-for-RT3883.patch
 @@ -0,0 +1,178 @@
@@ -9234,7 +13073,7 @@ index 0000000..c568b99
 + /*
 +--- a/drivers/net/wireless/rt2x00/rt2800lib.c
 ++++ b/drivers/net/wireless/rt2x00/rt2800lib.c
-+@@ -6811,6 +6811,144 @@ static void rt2800_init_rfcsr_3593(struc
++@@ -6810,6 +6810,144 @@ static void rt2800_init_rfcsr_3593(struc
 + 	/* TODO: enable stream mode support */
 + }
 + 
@@ -9379,7 +13218,7 @@ index 0000000..c568b99
 + static void rt2800_init_rfcsr_5390(struct rt2x00_dev *rt2x00dev)
 + {
 + 	rt2800_rf_init_calibration(rt2x00dev, 2);
-+@@ -7042,6 +7180,9 @@ static void rt2800_init_rfcsr(struct rt2
++@@ -7041,6 +7179,9 @@ static void rt2800_init_rfcsr(struct rt2
 + 	case RT3390:
 + 		rt2800_init_rfcsr_3390(rt2x00dev);
 + 		break;
@@ -9419,7 +13258,7 @@ index 0000000..57af961
 + 		map = rt2800_eeprom_map;
 diff --git a/package/mac80211/patches/600-0019-rt2x00-rt2800lib-force-rf-type-to-RF3853-on-RT3883.patch b/package/mac80211/patches/600-0019-rt2x00-rt2800lib-force-rf-type-to-RF3853-on-RT3883.patch
 new file mode 100644
-index 0000000..47eece0
+index 0000000..4bfe8e1
 --- /dev/null
 +++ b/package/mac80211/patches/600-0019-rt2x00-rt2800lib-force-rf-type-to-RF3853-on-RT3883.patch
 @@ -0,0 +1,21 @@
@@ -9435,7 +13274,7 @@ index 0000000..47eece0
 +
 +--- a/drivers/net/wireless/rt2x00/rt2800lib.c
 ++++ b/drivers/net/wireless/rt2x00/rt2800lib.c
-+@@ -7579,6 +7579,8 @@ static int rt2800_init_eeprom(struct rt2
++@@ -7578,6 +7578,8 @@ static int rt2800_init_eeprom(struct rt2
 + 	    rt2x00_rt(rt2x00dev, RT5390) ||
 + 	    rt2x00_rt(rt2x00dev, RT5392))
 + 		rt2800_eeprom_read(rt2x00dev, EEPROM_CHIP_ID, &rf);
@@ -9446,7 +13285,7 @@ index 0000000..47eece0
 + 
 diff --git a/package/mac80211/patches/600-0020-rt2x00-rt2800lib-add-channel-configuration-code-for-.patch b/package/mac80211/patches/600-0020-rt2x00-rt2800lib-add-channel-configuration-code-for-.patch
 new file mode 100644
-index 0000000..d9cbb33
+index 0000000..59b74ad
 --- /dev/null
 +++ b/package/mac80211/patches/600-0020-rt2x00-rt2800lib-add-channel-configuration-code-for-.patch
 @@ -0,0 +1,136 @@
@@ -9462,7 +13301,7 @@ index 0000000..d9cbb33
 +
 +--- a/drivers/net/wireless/rt2x00/rt2800lib.c
 ++++ b/drivers/net/wireless/rt2x00/rt2800lib.c
-+@@ -3385,6 +3385,36 @@ static char rt2800_txpower_to_dev(struct
++@@ -3384,6 +3384,36 @@ static char rt2800_txpower_to_dev(struct
 + 		return clamp_t(char, txpower, MIN_A_TXPOWER, MAX_A_TXPOWER);
 + }
 + 
@@ -9499,7 +13338,7 @@ index 0000000..d9cbb33
 + static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev,
 + 				  struct ieee80211_conf *conf,
 + 				  struct rf_channel *rf,
-+@@ -3403,6 +3433,12 @@ static void rt2800_config_channel(struct
++@@ -3402,6 +3432,12 @@ static void rt2800_config_channel(struct
 + 			rt2800_txpower_to_dev(rt2x00dev, rf->channel,
 + 					      info->default_power3);
 + 
@@ -9512,7 +13351,7 @@ index 0000000..d9cbb33
 + 	switch (rt2x00dev->chip.rf) {
 + 	case RF2020:
 + 	case RF3020:
-+@@ -3484,6 +3520,15 @@ static void rt2800_config_channel(struct
++@@ -3483,6 +3519,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);
@@ -9528,7 +13367,7 @@ index 0000000..d9cbb33
 + 	} else {
 + 		rt2800_bbp_write(rt2x00dev, 62, 0x37 - rt2x00dev->lna_gain);
 + 		rt2800_bbp_write(rt2x00dev, 63, 0x37 - rt2x00dev->lna_gain);
-+@@ -3496,6 +3541,7 @@ static void rt2800_config_channel(struct
++@@ -3495,6 +3540,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);
@@ -9536,7 +13375,7 @@ index 0000000..d9cbb33
 + 				rt2800_bbp_write(rt2x00dev, 75, 0x46);
 + 			} else {
 + 				if (rt2x00_rt(rt2x00dev, RT3593))
-+@@ -3504,19 +3550,22 @@ static void rt2800_config_channel(struct
++@@ -3503,19 +3549,22 @@ static void rt2800_config_channel(struct
 + 					rt2800_bbp_write(rt2x00dev, 82, 0x84);
 + 				rt2800_bbp_write(rt2x00dev, 75, 0x50);
 + 			}
@@ -9562,13 +13401,10 @@ index 0000000..d9cbb33
 + 			rt2800_bbp_write(rt2x00dev, 83, 0x9a);
 + 
 + 		if (rt2x00_has_cap_external_lna_a(rt2x00dev))
-+@@ -3638,6 +3687,23 @@ static void rt2800_config_channel(struct
-+ 
-+ 		rt2800_bbp_write_with_rx_chain(rt2x00dev, 66, reg);
++@@ -3640,6 +3689,23 @@ static void rt2800_config_channel(struct
++ 		usleep_range(1000, 1500);
++ 	}
 + 
-++		usleep_range(1000, 1500);
-++	}
-++
 ++	if (rt2x00_rt(rt2x00dev, RT3883)) {
 ++		if (!conf_is_ht40(conf))
 ++			rt2800_bbp_write(rt2x00dev, 105, 0x34);
@@ -9583,12 +13419,15 @@ index 0000000..d9cbb33
 ++
 ++		rt2800_bbp_write_with_rx_chain(rt2x00dev, 66, reg);
 ++
-+ 		usleep_range(1000, 1500);
-+ 	}
-+ 
+++		usleep_range(1000, 1500);
+++	}
+++
++ 	if (rt2x00_rt(rt2x00dev, RT5592)) {
++ 		rt2800_bbp_write(rt2x00dev, 195, 141);
++ 		rt2800_bbp_write(rt2x00dev, 196, conf_is_ht40(conf) ? 0x10 : 0x1a);
 diff --git a/package/mac80211/patches/600-0021-rt2x00-rt2800lib-fix-txpower_to_dev-function-for-RT3.patch b/package/mac80211/patches/600-0021-rt2x00-rt2800lib-fix-txpower_to_dev-function-for-RT3.patch
 new file mode 100644
-index 0000000..c927e45
+index 0000000..e88a7c6
 --- /dev/null
 +++ b/package/mac80211/patches/600-0021-rt2x00-rt2800lib-fix-txpower_to_dev-function-for-RT3.patch
 @@ -0,0 +1,30 @@
@@ -9604,7 +13443,7 @@ index 0000000..c927e45
 +
 +--- a/drivers/net/wireless/rt2x00/rt2800lib.c
 ++++ b/drivers/net/wireless/rt2x00/rt2800lib.c
-+@@ -3372,13 +3372,15 @@ static char rt2800_txpower_to_dev(struct
++@@ -3371,13 +3371,15 @@ static char rt2800_txpower_to_dev(struct
 + 				  unsigned int channel,
 + 				  char txpower)
 + {
@@ -9624,7 +13463,7 @@ index 0000000..c927e45
 + 	else
 diff --git a/package/mac80211/patches/600-0022-rt2x00-rt2800lib-use-correct-txpower-calculation-fun.patch b/package/mac80211/patches/600-0022-rt2x00-rt2800lib-use-correct-txpower-calculation-fun.patch
 new file mode 100644
-index 0000000..df826e5
+index 0000000..95484a0
 --- /dev/null
 +++ b/package/mac80211/patches/600-0022-rt2x00-rt2800lib-use-correct-txpower-calculation-fun.patch
 @@ -0,0 +1,23 @@
@@ -9641,7 +13480,7 @@ index 0000000..df826e5
 +
 +--- a/drivers/net/wireless/rt2x00/rt2800lib.c
 ++++ b/drivers/net/wireless/rt2x00/rt2800lib.c
-+@@ -4582,7 +4582,8 @@ static void rt2800_config_txpower(struct
++@@ -4581,7 +4581,8 @@ static void rt2800_config_txpower(struct
 + 				  struct ieee80211_channel *chan,
 + 				  int power_level)
 + {
@@ -9653,7 +13492,7 @@ index 0000000..df826e5
 + 		rt2800_config_txpower_rt28xx(rt2x00dev, chan, power_level);
 diff --git a/package/mac80211/patches/600-0023-rt2x00-rt2800lib-hardcode-txmixer-gain-values-to-zer.patch b/package/mac80211/patches/600-0023-rt2x00-rt2800lib-hardcode-txmixer-gain-values-to-zer.patch
 new file mode 100644
-index 0000000..8a43df2
+index 0000000..c57af60
 --- /dev/null
 +++ b/package/mac80211/patches/600-0023-rt2x00-rt2800lib-hardcode-txmixer-gain-values-to-zer.patch
 @@ -0,0 +1,33 @@
@@ -9670,7 +13509,7 @@ index 0000000..8a43df2
 +
 +--- a/drivers/net/wireless/rt2x00/rt2800lib.c
 ++++ b/drivers/net/wireless/rt2x00/rt2800lib.c
-+@@ -7461,7 +7461,8 @@ static u8 rt2800_get_txmixer_gain_24g(st
++@@ -7460,7 +7460,8 @@ static u8 rt2800_get_txmixer_gain_24g(st
 + {
 + 	u16 word;
 + 
@@ -9680,7 +13519,7 @@ index 0000000..8a43df2
 + 		return 0;
 + 
 + 	rt2800_eeprom_read(rt2x00dev, EEPROM_TXMIXER_GAIN_BG, &word);
-+@@ -7475,7 +7476,8 @@ static u8 rt2800_get_txmixer_gain_5g(str
++@@ -7474,7 +7475,8 @@ static u8 rt2800_get_txmixer_gain_5g(str
 + {
 + 	u16 word;
 + 
@@ -9746,7 +13585,7 @@ index 0000000..08f3f88
 + 	return HW_BEACON_BASE(index);
 diff --git a/package/mac80211/patches/600-0026-rt2x00-rt2800lib-use-correct-beacon-count-for-RT3883.patch b/package/mac80211/patches/600-0026-rt2x00-rt2800lib-use-correct-beacon-count-for-RT3883.patch
 new file mode 100644
-index 0000000..cb7a0ae
+index 0000000..f606ed4
 --- /dev/null
 +++ b/package/mac80211/patches/600-0026-rt2x00-rt2800lib-use-correct-beacon-count-for-RT3883.patch
 @@ -0,0 +1,22 @@
@@ -9762,7 +13601,7 @@ index 0000000..cb7a0ae
 +
 +--- a/drivers/net/wireless/rt2x00/rt2800lib.c
 ++++ b/drivers/net/wireless/rt2x00/rt2800lib.c
-+@@ -8393,7 +8393,8 @@ int rt2800_probe_hw(struct rt2x00_dev *r
++@@ -8392,7 +8392,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);
 + 
@@ -9774,7 +13613,7 @@ index 0000000..cb7a0ae
 + 		drv_data->hw_beacon_count = 8;
 diff --git a/package/mac80211/patches/600-0027-rt2x00-rt2800lib-fix-antenna-configuration-for-RT388.patch b/package/mac80211/patches/600-0027-rt2x00-rt2800lib-fix-antenna-configuration-for-RT388.patch
 new file mode 100644
-index 0000000..0919f90
+index 0000000..4096493
 --- /dev/null
 +++ b/package/mac80211/patches/600-0027-rt2x00-rt2800lib-fix-antenna-configuration-for-RT388.patch
 @@ -0,0 +1,22 @@
@@ -9790,7 +13629,7 @@ index 0000000..0919f90
 +
 +--- a/drivers/net/wireless/rt2x00/rt2800lib.c
 ++++ b/drivers/net/wireless/rt2x00/rt2800lib.c
-+@@ -1917,7 +1917,8 @@ void rt2800_config_ant(struct rt2x00_dev
++@@ -1916,7 +1916,8 @@ void rt2800_config_ant(struct rt2x00_dev
 + 	rt2800_bbp_write(rt2x00dev, 3, r3);
 + 	rt2800_bbp_write(rt2x00dev, 1, r1);
 + 
@@ -9802,7 +13641,7 @@ index 0000000..0919f90
 + 		else
 diff --git a/package/mac80211/patches/600-0028-rt2x00-rt2800lib-fix-LNA-gain-configuration-for-RT38.patch b/package/mac80211/patches/600-0028-rt2x00-rt2800lib-fix-LNA-gain-configuration-for-RT38.patch
 new file mode 100644
-index 0000000..e38ba78
+index 0000000..2fc9d9d
 --- /dev/null
 +++ b/package/mac80211/patches/600-0028-rt2x00-rt2800lib-fix-LNA-gain-configuration-for-RT38.patch
 @@ -0,0 +1,32 @@
@@ -9818,7 +13657,7 @@ index 0000000..e38ba78
 +
 +--- a/drivers/net/wireless/rt2x00/rt2800lib.c
 ++++ b/drivers/net/wireless/rt2x00/rt2800lib.c
-+@@ -1940,7 +1940,8 @@ static void rt2800_config_lna_gain(struc
++@@ -1939,7 +1939,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) {
@@ -9828,7 +13667,7 @@ index 0000000..e38ba78
 + 			rt2800_eeprom_read(rt2x00dev, EEPROM_EXT_LNA2, &eeprom);
 + 			lna_gain = rt2x00_get_field16(eeprom,
 + 						      EEPROM_EXT_LNA2_A1);
-+@@ -1950,7 +1951,8 @@ static void rt2800_config_lna_gain(struc
++@@ -1949,7 +1950,8 @@ static void rt2800_config_lna_gain(struc
 + 						      EEPROM_RSSI_BG2_LNA_A1);
 + 		}
 + 	} else {
@@ -9840,7 +13679,7 @@ index 0000000..e38ba78
 + 						      EEPROM_EXT_LNA2_A2);
 diff --git a/package/mac80211/patches/600-0029-rt2x00-rt2800lib-fix-VGC-setup-for-RT3883.patch b/package/mac80211/patches/600-0029-rt2x00-rt2800lib-fix-VGC-setup-for-RT3883.patch
 new file mode 100644
-index 0000000..4684599
+index 0000000..060d4c6
 --- /dev/null
 +++ b/package/mac80211/patches/600-0029-rt2x00-rt2800lib-fix-VGC-setup-for-RT3883.patch
 @@ -0,0 +1,44 @@
@@ -9856,7 +13695,7 @@ index 0000000..4684599
 +
 +--- a/drivers/net/wireless/rt2x00/rt2800lib.c
 ++++ b/drivers/net/wireless/rt2x00/rt2800lib.c
-+@@ -4781,7 +4781,8 @@ static u8 rt2800_get_default_vgc(struct
++@@ -4780,7 +4780,8 @@ static u8 rt2800_get_default_vgc(struct 
 + 		else
 + 			vgc = 0x2e + rt2x00dev->lna_gain;
 + 	} else { /* 5GHZ band */
@@ -9866,7 +13705,7 @@ index 0000000..4684599
 + 			vgc = 0x20 + (rt2x00dev->lna_gain * 5) / 3;
 + 		else if (rt2x00_rt(rt2x00dev, RT5592))
 + 			vgc = 0x24 + (2 * rt2x00dev->lna_gain);
-+@@ -4801,7 +4802,8 @@ static inline void rt2800_set_vgc(struct
++@@ -4800,7 +4801,8 @@ static inline void rt2800_set_vgc(struct
 + {
 + 	if (qual->vgc_level != vgc_level) {
 + 		if (rt2x00_rt(rt2x00dev, RT3572) ||
@@ -9876,7 +13715,7 @@ index 0000000..4684599
 + 			rt2800_bbp_write_with_rx_chain(rt2x00dev, 66,
 + 						       vgc_level);
 + 		} else if (rt2x00_rt(rt2x00dev, RT5592)) {
-+@@ -4848,6 +4850,11 @@ void rt2800_link_tuner(struct rt2x00_dev
++@@ -4847,6 +4849,11 @@ void rt2800_link_tuner(struct rt2x00_dev
 + 		}
 + 		break;
 + 
@@ -9890,7 +13729,7 @@ index 0000000..4684599
 + 			vgc += 0x20;
 diff --git a/package/mac80211/patches/600-0030-rt2x00-rt2800lib-fix-EEPROM-LNA-validation-for-RT388.patch b/package/mac80211/patches/600-0030-rt2x00-rt2800lib-fix-EEPROM-LNA-validation-for-RT388.patch
 new file mode 100644
-index 0000000..bc1548d
+index 0000000..3e9a7d9
 --- /dev/null
 +++ b/package/mac80211/patches/600-0030-rt2x00-rt2800lib-fix-EEPROM-LNA-validation-for-RT388.patch
 @@ -0,0 +1,42 @@
@@ -9906,7 +13745,7 @@ index 0000000..bc1548d
 +
 +--- a/drivers/net/wireless/rt2x00/rt2800lib.c
 ++++ b/drivers/net/wireless/rt2x00/rt2800lib.c
-+@@ -7598,7 +7598,8 @@ static int rt2800_validate_eeprom(struct
++@@ -7597,7 +7597,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);
@@ -9916,7 +13755,7 @@ index 0000000..bc1548d
 + 		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,
-+@@ -7618,7 +7619,8 @@ static int rt2800_validate_eeprom(struct
++@@ -7617,7 +7618,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);
@@ -9926,7 +13765,7 @@ index 0000000..bc1548d
 + 		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,
-+@@ -7626,7 +7628,8 @@ static int rt2800_validate_eeprom(struct
++@@ -7625,7 +7627,8 @@ static int rt2800_validate_eeprom(struct
 + 	}
 + 	rt2800_eeprom_write(rt2x00dev, EEPROM_RSSI_A2, word);
 + 
@@ -9938,7 +13777,7 @@ index 0000000..bc1548d
 + 		    rt2x00_get_field16(word, EEPROM_EXT_LNA2_A1) == 0xff)
 diff --git a/package/mac80211/patches/600-0031-rt2x00-rt2800lib-fix-txpower-compensation-for-RT3883.patch b/package/mac80211/patches/600-0031-rt2x00-rt2800lib-fix-txpower-compensation-for-RT3883.patch
 new file mode 100644
-index 0000000..d6295f4
+index 0000000..b87f36a
 --- /dev/null
 +++ b/package/mac80211/patches/600-0031-rt2x00-rt2800lib-fix-txpower-compensation-for-RT3883.patch
 @@ -0,0 +1,22 @@
@@ -9954,7 +13793,7 @@ index 0000000..d6295f4
 +
 +--- a/drivers/net/wireless/rt2x00/rt2800lib.c
 ++++ b/drivers/net/wireless/rt2x00/rt2800lib.c
-+@@ -3959,6 +3959,9 @@ static u8 rt2800_compensate_txpower(stru
++@@ -3958,6 +3958,9 @@ static u8 rt2800_compensate_txpower(stru
 + 	if (rt2x00_rt(rt2x00dev, RT3593))
 + 		return min_t(u8, txpower, 0xc);
 + 
@@ -9966,7 +13805,7 @@ index 0000000..d6295f4
 + 		 * Check if eirp txpower exceed txpower_limit.
 diff --git a/package/mac80211/patches/600-0032-rt2x00-rt2800lib-enable-RT2800_HAS_HIGH_SHARED_MEM-f.patch b/package/mac80211/patches/600-0032-rt2x00-rt2800lib-enable-RT2800_HAS_HIGH_SHARED_MEM-f.patch
 new file mode 100644
-index 0000000..c5f226a
+index 0000000..18d65e0
 --- /dev/null
 +++ b/package/mac80211/patches/600-0032-rt2x00-rt2800lib-enable-RT2800_HAS_HIGH_SHARED_MEM-f.patch
 @@ -0,0 +1,23 @@
@@ -9983,7 +13822,7 @@ index 0000000..c5f226a
 +
 +--- a/drivers/net/wireless/rt2x00/rt2800lib.c
 ++++ b/drivers/net/wireless/rt2x00/rt2800lib.c
-+@@ -8406,7 +8406,8 @@ int rt2800_probe_hw(struct rt2x00_dev *r
++@@ -8405,7 +8405,8 @@ int rt2800_probe_hw(struct rt2x00_dev *r
 + 	if (retval)
 + 		return retval;
 + 
@@ -10228,14 +14067,14 @@ index a910cc3..1db09a3 100644
   u32 rt2x00lib_get_bssidx(struct rt2x00_dev *rt2x00dev,
   			 struct ieee80211_vif *vif);
 diff --git a/package/mac80211/patches/610-rt2x00-fix-rt3352-ext-pa.patch b/package/mac80211/patches/610-rt2x00-fix-rt3352-ext-pa.patch
-index 83fbcd0..3d32ecc 100644
+index 83fbcd0..725f81f 100644
 --- a/package/mac80211/patches/610-rt2x00-fix-rt3352-ext-pa.patch
 +++ b/package/mac80211/patches/610-rt2x00-fix-rt3352-ext-pa.patch
 @@ -1,14 +1,15 @@
  --- a/drivers/net/wireless/rt2x00/rt2800lib.c
  +++ b/drivers/net/wireless/rt2x00/rt2800lib.c
 -@@ -3176,11 +3176,17 @@ static void rt2800_config_channel(struct
-+@@ -3506,11 +3506,18 @@ static void rt2800_config_channel(struct
++@@ -3505,11 +3505,18 @@ static void rt2800_config_channel(struct
   	/*
   	 * Change BBP settings
   	 */
@@ -10271,7 +14110,7 @@ index 83fbcd0..3d32ecc 100644
 - 	}
 - 
 -@@ -6125,6 +6125,12 @@ static void rt2800_init_rfcsr_3290(struc
-+@@ -6586,6 +6593,12 @@ static void rt2800_init_rfcsr_3290(struc
++@@ -6585,6 +6592,12 @@ static void rt2800_init_rfcsr_3290(struc
   
   static void rt2800_init_rfcsr_3352(struct rt2x00_dev *rt2x00dev)
   {
@@ -10280,7 +14119,7 @@ index 83fbcd0..3d32ecc 100644
   
   	rt2800_rfcsr_write(rt2x00dev, 0, 0xf0);
 -@@ -6160,15 +6166,30 @@ static void rt2800_init_rfcsr_3352(struc
-+@@ -6621,15 +6634,30 @@ static void rt2800_init_rfcsr_3352(struc
++@@ -6620,15 +6633,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);
@@ -10289,7 +14128,7 @@ index 83fbcd0..3d32ecc 100644
   	rt2800_rfcsr_write(rt2x00dev, 44, 0xdb);
   	rt2800_rfcsr_write(rt2x00dev, 45, 0xdb);
 -@@ -6176,15 +6197,20 @@ static void rt2800_init_rfcsr_3352(struc
-+@@ -6637,15 +6665,20 @@ static void rt2800_init_rfcsr_3352(struc
++@@ -6636,15 +6664,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);
@@ -10298,7 +14137,7 @@ index 83fbcd0..3d32ecc 100644
   	rt2800_rfcsr_write(rt2x00dev, 60, 0x00);
   	rt2800_rfcsr_write(rt2x00dev, 61, 0x00);
 -@@ -7051,6 +7077,7 @@ static int rt2800_init_eeprom(struct rt2
-+@@ -7666,6 +7699,7 @@ static int rt2800_init_eeprom(struct rt2
++@@ -7665,6 +7698,7 @@ static int rt2800_init_eeprom(struct rt2
   	 * RT53xx: defined in "EEPROM_CHIP_ID" field
   	 */
   	if (rt2x00_rt(rt2x00dev, RT3290) ||
@@ -10307,7 +14146,7 @@ index 83fbcd0..3d32ecc 100644
   	    rt2x00_rt(rt2x00dev, RT5392))
   		rt2800_eeprom_read(rt2x00dev, EEPROM_CHIP_ID, &rf);
 -@@ -7142,7 +7169,8 @@ static int rt2800_init_eeprom(struct rt2
-+@@ -7760,7 +7794,8 @@ static int rt2800_init_eeprom(struct rt2
++@@ -7759,7 +7793,8 @@ static int rt2800_init_eeprom(struct rt2
   	/*
   	 * Detect if this device has Bluetooth co-existence.
   	 */
@@ -10316,7 +14155,7 @@ index 83fbcd0..3d32ecc 100644
   
   	/*
 -@@ -7171,6 +7199,22 @@ static int rt2800_init_eeprom(struct rt2
-+@@ -7789,6 +7824,22 @@ static int rt2800_init_eeprom(struct rt2
++@@ -7788,6 +7823,22 @@ static int rt2800_init_eeprom(struct rt2
   					EIRP_MAX_TX_POWER_LIMIT)
   		__set_bit(CAPABILITY_POWER_LIMIT, &rt2x00dev->cap_flags);
   
@@ -10366,14 +14205,14 @@ index 83fbcd0..3d32ecc 100644
   #define EEPROM_NIC_CONF1_BT_COEXIST		FIELD16(0x4000)
   #define EEPROM_NIC_CONF1_DAC_TEST		FIELD16(0x8000)
 diff --git a/package/mac80211/patches/611-rt2x00-rf_vals-rt3352-xtal20.patch b/package/mac80211/patches/611-rt2x00-rf_vals-rt3352-xtal20.patch
-index 478a0f2..c69344c 100644
+index 478a0f2..6b29aa8 100644
 --- a/package/mac80211/patches/611-rt2x00-rf_vals-rt3352-xtal20.patch
 +++ b/package/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
 -@@ -7491,6 +7491,27 @@ static const struct rf_channel rf_vals_5
-+@@ -8176,6 +8176,27 @@ static const struct rf_channel rf_vals_5
++@@ -8175,6 +8175,27 @@ static const struct rf_channel rf_vals_5
   	{196, 83, 0, 12, 1},
   };
   
@@ -10382,7 +14221,7 @@ index 478a0f2..c69344c 100644
   {
   	struct hw_mode_spec *spec = &rt2x00dev->spec;
 -@@ -7579,7 +7600,10 @@ static int rt2800_probe_hw_mode(struct r
-+@@ -8263,7 +8284,10 @@ static int rt2800_probe_hw_mode(struct r
++@@ -8262,7 +8283,10 @@ static int rt2800_probe_hw_mode(struct r
   	case RF5390:
   	case RF5392:
   		spec->num_channels = 14;
@@ -10391,7 +14230,7 @@ index 478a0f2..c69344c 100644
   
   	case RF3052:
 -@@ -7755,6 +7779,19 @@ static int rt2800_probe_rt(struct rt2x00
-+@@ -8446,6 +8470,19 @@ static int rt2800_probe_rt(struct rt2x00
++@@ -8445,6 +8469,19 @@ static int rt2800_probe_rt(struct rt2x00
   	return 0;
   }
   
@@ -10402,7 +14241,7 @@ index 478a0f2..c69344c 100644
 - 	int retval;
 -@@ -7784,6 +7821,15 @@ int rt2800_probe_hw(struct rt2x00_dev *r
 + 	struct rt2800_drv_data *drv_data = rt2x00dev->drv_data;
-+@@ -8488,6 +8525,15 @@ int rt2800_probe_hw(struct rt2x00_dev *r
++@@ -8487,6 +8524,15 @@ int rt2800_probe_hw(struct rt2x00_dev *r
   	rt2800_register_write(rt2x00dev, GPIO_CTRL, reg);
   
   	/*
@@ -10420,7 +14259,7 @@ index f6b4808..119e95c 100644
   }
   
 diff --git a/package/mac80211/patches/616-rt2x00-support-rt5350.patch b/package/mac80211/patches/616-rt2x00-support-rt5350.patch
-index 3bafa16..2cc136c 100644
+index 3bafa16..fd897e9 100644
 --- a/package/mac80211/patches/616-rt2x00-support-rt5350.patch
 +++ b/package/mac80211/patches/616-rt2x00-support-rt5350.patch
 @@ -1,16 +1,16 @@
@@ -10439,7 +14278,7 @@ index 3bafa16..2cc136c 100644
  --- a/drivers/net/wireless/rt2x00/rt2800lib.c
  +++ b/drivers/net/wireless/rt2x00/rt2800lib.c
 -@@ -2704,6 +2704,13 @@ static void rt2800_config_channel_rf53xx
-+@@ -2994,6 +2994,13 @@ static void rt2800_config_channel_rf53xx
++@@ -2993,6 +2993,13 @@ static void rt2800_config_channel_rf53xx
   
   				rt2800_rfcsr_write(rt2x00dev, 59,
   						   r59_non_bt[idx]);
@@ -10449,7 +14288,7 @@ index 3bafa16..2cc136c 100644
   	}
 -@@ -3141,6 +3148,7 @@ static void rt2800_config_channel(struct
 - 		rt2800_config_channel_rf3322(rt2x00dev, conf, rf, info);
-+@@ -3472,6 +3479,7 @@ static void rt2800_config_channel(struct
++@@ -3471,6 +3478,7 @@ static void rt2800_config_channel(struct
 + 		rt2800_config_channel_rf3853(rt2x00dev, conf, rf, info);
   		break;
   	case RF3070:
@@ -10458,7 +14297,7 @@ index 3bafa16..2cc136c 100644
   	case RF5370:
   	case RF5372:
 -@@ -3158,6 +3166,7 @@ static void rt2800_config_channel(struct
-+@@ -3489,6 +3497,7 @@ static void rt2800_config_channel(struct
++@@ -3488,6 +3496,7 @@ static void rt2800_config_channel(struct
   	if (rt2x00_rf(rt2x00dev, RF3070) ||
   	    rt2x00_rf(rt2x00dev, RF3290) ||
   	    rt2x00_rf(rt2x00dev, RF3322) ||
@@ -10467,7 +14306,7 @@ index 3bafa16..2cc136c 100644
   	    rt2x00_rf(rt2x00dev, RF5370) ||
   	    rt2x00_rf(rt2x00dev, RF5372) ||
 -@@ -3398,7 +3407,8 @@ static void rt2800_config_channel(struct
-+@@ -3766,7 +3775,8 @@ static void rt2800_config_channel(struct
++@@ -3765,7 +3774,8 @@ static void rt2800_config_channel(struct
   	/*
   	 * Clear update flag
   	 */
@@ -10477,7 +14316,7 @@ index 3bafa16..2cc136c 100644
   		rt2800_bbp_write(rt2x00dev, 49, bbp);
 -@@ -4272,6 +4282,7 @@ void rt2800_vco_calibration(struct rt2x0
 - 	case RF3053:
-+@@ -4645,6 +4655,7 @@ void rt2800_vco_calibration(struct rt2x0
++@@ -4644,6 +4654,7 @@ void rt2800_vco_calibration(struct rt2x0
   	case RF3070:
   	case RF3290:
 + 	case RF3853:
@@ -10486,7 +14325,7 @@ index 3bafa16..2cc136c 100644
   	case RF5370:
   	case RF5372:
 -@@ -4668,6 +4679,8 @@ static int rt2800_init_registers(struct 
-+@@ -5079,6 +5090,8 @@ static int rt2800_init_registers(struct
++@@ -5078,6 +5089,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);
@@ -10495,7 +14334,7 @@ index 3bafa16..2cc136c 100644
   		rt2800_register_write(rt2x00dev, TX_SW_CFG0, 0x00000000);
   		rt2800_register_write(rt2x00dev, TX_SW_CFG1, 0x00080606);
 -@@ -5309,9 +5322,13 @@ static void rt2800_init_bbp_3352(struct 
-+@@ -5734,9 +5747,13 @@ static void rt2800_init_bbp_3352(struct
++@@ -5733,9 +5746,13 @@ static void rt2800_init_bbp_3352(struct 
   
   	rt2800_bbp_write(rt2x00dev, 82, 0x62);
   
@@ -10504,7 +14343,7 @@ index 3bafa16..2cc136c 100644
   	rt2800_bbp_write(rt2x00dev, 86, 0x38);
   
 -@@ -5325,9 +5342,13 @@ static void rt2800_init_bbp_3352(struct 
-+@@ -5750,9 +5767,13 @@ static void rt2800_init_bbp_3352(struct
++@@ -5749,9 +5766,13 @@ static void rt2800_init_bbp_3352(struct 
   
   	rt2800_bbp_write(rt2x00dev, 104, 0x92);
   
@@ -10513,7 +14352,7 @@ index 3bafa16..2cc136c 100644
   	rt2800_bbp_write(rt2x00dev, 120, 0x50);
   
 -@@ -5352,6 +5373,13 @@ static void rt2800_init_bbp_3352(struct 
-+@@ -5777,6 +5798,13 @@ static void rt2800_init_bbp_3352(struct
++@@ -5776,6 +5797,13 @@ static void rt2800_init_bbp_3352(struct 
   	rt2800_bbp_write(rt2x00dev, 143, 0xa2);
   
   	rt2800_bbp_write(rt2x00dev, 148, 0xc8);
@@ -10522,7 +14361,7 @@ index 3bafa16..2cc136c 100644
   
   static void rt2800_init_bbp_3390(struct rt2x00_dev *rt2x00dev)
 -@@ -5652,6 +5680,7 @@ static void rt2800_init_bbp(struct rt2x0
-+@@ -6118,6 +6146,7 @@ static void rt2800_init_bbp(struct rt2x0
++@@ -6117,6 +6145,7 @@ static void rt2800_init_bbp(struct rt2x0
   		rt2800_init_bbp_3290(rt2x00dev);
   		break;
   	case RT3352:
@@ -10532,7 +14371,7 @@ index 3bafa16..2cc136c 100644
   	case RT3390:
 -@@ -6462,6 +6491,76 @@ static void rt2800_init_rfcsr_3593(struc
 - 	/* TODO: enable stream mode support */
-+@@ -7069,6 +7098,76 @@ static void rt2800_init_rfcsr_3883(struc
++@@ -7068,6 +7097,76 @@ static void rt2800_init_rfcsr_3883(struc
 + 	rt2800_rfcsr_write(rt2x00dev, 20, rfcsr);
   }
   
@@ -10542,7 +14381,7 @@ index 3bafa16..2cc136c 100644
   {
   	rt2800_rf_init_calibration(rt2x00dev, 2);
 -@@ -6699,6 +6798,9 @@ static void rt2800_init_rfcsr(struct rt2
-+@@ -7309,6 +7408,9 @@ static void rt2800_init_rfcsr(struct rt2
++@@ -7308,6 +7407,9 @@ static void rt2800_init_rfcsr(struct rt2
   	case RT3593:
   		rt2800_init_rfcsr_3593(rt2x00dev);
   		break;
@@ -10551,7 +14390,7 @@ index 3bafa16..2cc136c 100644
   		rt2800_init_rfcsr_5390(rt2x00dev);
   		break;
 -@@ -6948,6 +7050,12 @@ static int rt2800_validate_eeprom(struct
-+@@ -7568,6 +7670,12 @@ static int rt2800_validate_eeprom(struct
++@@ -7567,6 +7669,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);
@@ -10562,7 +14401,7 @@ index 3bafa16..2cc136c 100644
 -@@ -7081,6 +7189,8 @@ static int rt2800_init_eeprom(struct rt2
 - 	    rt2x00_rt(rt2x00dev, RT5390) ||
 - 	    rt2x00_rt(rt2x00dev, RT5392))
-+@@ -7706,6 +7814,8 @@ static int rt2800_init_eeprom(struct rt2
++@@ -7705,6 +7813,8 @@ static int rt2800_init_eeprom(struct rt2
   		rt2800_eeprom_read(rt2x00dev, EEPROM_CHIP_ID, &rf);
 + 	else if (rt2x00_rt(rt2x00dev, RT3883))
 + 		rf = RF3853;
@@ -10573,7 +14412,7 @@ index 3bafa16..2cc136c 100644
   
 -@@ -7099,6 +7209,7 @@ static int rt2800_init_eeprom(struct rt2
 - 	case RF3290:
-+@@ -7725,6 +7835,7 @@ static int rt2800_init_eeprom(struct rt2
++@@ -7724,6 +7834,7 @@ static int rt2800_init_eeprom(struct rt2
   	case RF3320:
   	case RF3322:
 + 	case RF3853:
@@ -10582,7 +14421,7 @@ index 3bafa16..2cc136c 100644
   	case RF5370:
   	case RF5372:
 -@@ -7594,6 +7705,7 @@ static int rt2800_probe_hw_mode(struct r
-+@@ -8279,6 +8390,7 @@ static int rt2800_probe_hw_mode(struct r
++@@ -8278,6 +8389,7 @@ static int rt2800_probe_hw_mode(struct r
   	case RF3290:
   	case RF3320:
   	case RF3322:
@@ -10592,7 +14431,7 @@ index 3bafa16..2cc136c 100644
   	case RF5372:
 -@@ -7726,6 +7838,7 @@ static int rt2800_probe_hw_mode(struct r
 - 	case RF3053:
-+@@ -8417,6 +8529,7 @@ static int rt2800_probe_hw_mode(struct r
++@@ -8416,6 +8528,7 @@ static int rt2800_probe_hw_mode(struct r
   	case RF3070:
   	case RF3290:
 + 	case RF3853:
@@ -10602,7 +14441,7 @@ index 3bafa16..2cc136c 100644
   	case RF5372:
 -@@ -7764,6 +7877,7 @@ static int rt2800_probe_rt(struct rt2x00
 - 	case RT3390:
-+@@ -8456,6 +8569,7 @@ static int rt2800_probe_rt(struct rt2x00
++@@ -8455,6 +8568,7 @@ static int rt2800_probe_rt(struct rt2x00
   	case RT3572:
   	case RT3593:
 + 	case RT3883:
@@ -10610,20 +14449,28 @@ index 3bafa16..2cc136c 100644
   	case RT5390:
   	case RT5392:
 diff --git a/package/mac80211/patches/619-rt2x00-change-led-polarity-from-OF.patch b/package/mac80211/patches/619-rt2x00-change-led-polarity-from-OF.patch
-index f9186d8..fc56847 100644
+index f9186d8..ee473dc 100644
 --- a/package/mac80211/patches/619-rt2x00-change-led-polarity-from-OF.patch
 +++ b/package/mac80211/patches/619-rt2x00-change-led-polarity-from-OF.patch
+@@ -1,6 +1,6 @@
+ --- a/drivers/net/wireless/rt2x00/rt2800lib.c
+ +++ b/drivers/net/wireless/rt2x00/rt2800lib.c
+-@@ -36,6 +36,7 @@
++@@ -37,6 +37,7 @@
+  #include <linux/kernel.h>
+  #include <linux/module.h>
+  #include <linux/slab.h>
 @@ -8,7 +8,7 @@
   
   #include "rt2x00.h"
   #include "rt2800lib.h"
 -@@ -7298,6 +7299,17 @@ static int rt2800_init_eeprom(struct rt2
-+@@ -7924,6 +7925,17 @@ static int rt2800_init_eeprom(struct rt2
++@@ -7923,6 +7924,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/mac80211/patches/620-rt2x00-rt3352-rf-id.patch b/package/mac80211/patches/620-rt2x00-rt3352-rf-id.patch
-index 5e67344..a33c01f 100644
+index 5e67344..86a990c 100644
 --- a/package/mac80211/patches/620-rt2x00-rt3352-rf-id.patch
 +++ b/package/mac80211/patches/620-rt2x00-rt3352-rf-id.patch
 @@ -1,15 +1,11 @@
@@ -10634,7 +14481,7 @@ index 5e67344..a33c01f 100644
 - 	 */
 - 	if (rt2x00_rt(rt2x00dev, RT3290) ||
 --	    rt2x00_rt(rt2x00dev, RT3352) ||
-+@@ -7813,6 +7813,8 @@ static int rt2800_init_eeprom(struct rt2
++@@ -7812,6 +7812,8 @@ static int rt2800_init_eeprom(struct rt2
   	    rt2x00_rt(rt2x00dev, RT5390) ||
   	    rt2x00_rt(rt2x00dev, RT5392))
   		rt2800_eeprom_read(rt2x00dev, EEPROM_CHIP_ID, &rf);
@@ -10646,17 +14493,237 @@ index 5e67344..a33c01f 100644
 - 		rf = RF5350;
 - 	else
 diff --git a/package/mac80211/patches/700-mwl8k-missing-pci-id-for-WNR854T.patch b/package/mac80211/patches/700-mwl8k-missing-pci-id-for-WNR854T.patch
-index 484c075..752fb0e 100644
+index 484c075..ae7e927 100644
 --- a/package/mac80211/patches/700-mwl8k-missing-pci-id-for-WNR854T.patch
 +++ b/package/mac80211/patches/700-mwl8k-missing-pci-id-for-WNR854T.patch
 @@ -1,6 +1,6 @@
  --- a/drivers/net/wireless/mwl8k.c
  +++ b/drivers/net/wireless/mwl8k.c
 -@@ -5529,6 +5529,7 @@ MODULE_FIRMWARE("mwl8k/fmimage_8366.fw")
-+@@ -5714,6 +5714,7 @@ MODULE_FIRMWARE("mwl8k/fmimage_8366.fw")
++@@ -5682,6 +5682,7 @@ MODULE_FIRMWARE("mwl8k/fmimage_8366.fw")
   MODULE_FIRMWARE(MWL8K_8366_AP_FW(MWL8K_8366_AP_FW_API));
   
   static DEFINE_PCI_DEVICE_TABLE(mwl8k_pci_id_table) = {
+diff --git a/package/mac80211/patches/800-b43-gpio-mask-module-option.patch b/package/mac80211/patches/800-b43-gpio-mask-module-option.patch
+index fc874ad..e4d2f44 100644
+--- a/package/mac80211/patches/800-b43-gpio-mask-module-option.patch
++++ b/package/mac80211/patches/800-b43-gpio-mask-module-option.patch
+@@ -22,7 +22,7 @@
+  static int modparam_bad_frames_preempt;
+  module_param_named(bad_frames_preempt, modparam_bad_frames_preempt, int, 0444);
+  MODULE_PARM_DESC(bad_frames_preempt,
+-@@ -2747,10 +2752,10 @@ static int b43_gpio_init(struct b43_wlde
++@@ -2739,10 +2744,10 @@ static int b43_gpio_init(struct b43_wlde
+  	u32 mask, set;
+  
+  	b43_maskset32(dev, B43_MMIO_MACCTL, ~B43_MACCTL_GPOUTSMSK, 0);
+diff --git a/package/mac80211/patches/810-b43_no_pio.patch b/package/mac80211/patches/810-b43_no_pio.patch
+index 5cd1b8b..bc9fda2 100644
+--- a/package/mac80211/patches/810-b43_no_pio.patch
++++ b/package/mac80211/patches/810-b43_no_pio.patch
+@@ -11,7 +11,7 @@
+  b43-$(CPTCFG_B43_PCMCIA)	+= pcmcia.o
+ --- a/drivers/net/wireless/b43/main.c
+ +++ b/drivers/net/wireless/b43/main.c
+-@@ -1915,10 +1915,12 @@ static void b43_do_interrupt_thread(stru
++@@ -1899,10 +1899,12 @@ static void b43_do_interrupt_thread(stru
+  			dma_reason[0], dma_reason[1],
+  			dma_reason[2], dma_reason[3],
+  			dma_reason[4], dma_reason[5]);
+@@ -75,12 +75,12 @@
+  #endif /* B43_PIO_H_ */
+ --- a/drivers/net/wireless/b43/Kconfig
+ +++ b/drivers/net/wireless/b43/Kconfig
+-@@ -98,7 +98,7 @@ config B43_BCMA_PIO
++@@ -118,7 +118,7 @@ config B43_BCMA_PIO
+  	default y
+  
+  config B43_PIO
+ -	bool
+ +	bool "Broadcom 43xx PIO support"
+- 	depends on B43
++ 	depends on B43 && B43_SSB
+  	select SSB_BLOCKIO
+  	default y
+diff --git a/package/mac80211/patches/820-b43-add-antenna-control.patch b/package/mac80211/patches/820-b43-add-antenna-control.patch
+index dea9830..b55c669 100644
+--- a/package/mac80211/patches/820-b43-add-antenna-control.patch
++++ b/package/mac80211/patches/820-b43-add-antenna-control.patch
+@@ -1,6 +1,6 @@
+ --- a/drivers/net/wireless/b43/main.c
+ +++ b/drivers/net/wireless/b43/main.c
+-@@ -1562,7 +1562,7 @@ static void b43_write_beacon_template(st
++@@ -1546,7 +1546,7 @@ static void b43_write_beacon_template(st
+  				  len, ram_offset, shm_size_offset, rate);
+  
+  	/* Write the PHY TX control parameters. */
+@@ -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. */
+-@@ -3105,8 +3105,8 @@ static int b43_chip_init(struct b43_wlde
++@@ -3103,8 +3103,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);
+-@@ -3850,7 +3850,6 @@ static int b43_op_config(struct ieee8021
++@@ -3796,7 +3796,6 @@ static int b43_op_config(struct ieee8021
+  	struct b43_wldev *dev;
+  	struct b43_phy *phy;
+  	struct ieee80211_conf *conf = &hw->conf;
+@@ -28,7 +28,7 @@
+  	int err = 0;
+  	bool reload_bss = false;
+  
+-@@ -3904,11 +3903,9 @@ static int b43_op_config(struct ieee8021
++@@ -3850,11 +3849,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) {
+-@@ -5041,6 +5038,47 @@ static int b43_op_get_survey(struct ieee
++@@ -4978,6 +4975,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,
+-@@ -5062,6 +5100,8 @@ static const struct ieee80211_ops b43_hw
++@@ -4999,6 +5037,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.
+-@@ -5308,6 +5348,8 @@ static int b43_one_core_attach(struct b4
++@@ -5239,6 +5279,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;
+-@@ -5398,6 +5440,9 @@ static struct b43_wl *b43_wireless_init(
++@@ -5329,6 +5371,9 @@ static struct b43_wl *b43_wireless_init(
+  
+  	hw->wiphy->flags |= WIPHY_FLAG_IBSS_RSN;
+  
+diff --git a/package/mac80211/patches/830-b43-workaround-pcie-bcm4716.patch b/package/mac80211/patches/830-b43-workaround-pcie-bcm4716.patch
+index e76758c..86b61fc 100644
+--- a/package/mac80211/patches/830-b43-workaround-pcie-bcm4716.patch
++++ b/package/mac80211/patches/830-b43-workaround-pcie-bcm4716.patch
+@@ -19,7 +19,7 @@ Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
+ 
+ --- a/drivers/net/wireless/b43/b43.h
+ +++ b/drivers/net/wireless/b43/b43.h
+-@@ -1061,6 +1061,31 @@ static inline bool b43_using_pio_transfe
++@@ -1054,6 +1054,31 @@ static inline bool b43_using_pio_transfe
+  	return dev->__using_pio_transfers;
+  }
+  
+@@ -53,9 +53,9 @@ Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
+  __printf(2, 3) void b43err(struct b43_wl *wl, const char *fmt, ...);
+ --- a/drivers/net/wireless/b43/bus.h
+ +++ b/drivers/net/wireless/b43/bus.h
+-@@ -60,6 +60,16 @@ static inline bool b43_bus_host_is_sdio(
+- 	return (dev->bus_type == B43_BUS_SSB &&
+- 		dev->sdev->bus->bustype == SSB_BUSTYPE_SDIO);
++@@ -70,6 +70,16 @@ static inline bool b43_bus_host_is_sdio(
++ 	return false;
++ #endif
+  }
+ +static inline bool b43_bus_host_is_pci(struct b43_bus_dev *dev)
+ +{
+@@ -72,7 +72,7 @@ Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
+  struct b43_bus_dev *b43_bus_dev_ssb_init(struct ssb_device *sdev);
+ --- a/drivers/net/wireless/b43/main.c
+ +++ b/drivers/net/wireless/b43/main.c
+-@@ -4437,7 +4437,7 @@ static int b43_phy_versioning(struct b43
++@@ -4370,7 +4370,7 @@ static int b43_phy_versioning(struct b43
+  		u16 radio24[3];
+  
+  		for (tmp = 0; tmp < 3; tmp++) {
+@@ -81,7 +81,7 @@ Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
+  			radio24[tmp] = b43_read16(dev, B43_MMIO_RADIO24_DATA);
+  		}
+  
+-@@ -4456,10 +4456,10 @@ static int b43_phy_versioning(struct b43
++@@ -4389,10 +4389,10 @@ static int b43_phy_versioning(struct b43
+  			else
+  				tmp = 0x5205017F;
+  		} else {
+@@ -96,7 +96,7 @@ Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
+  				<< 16;
+ --- a/drivers/net/wireless/b43/phy_common.c
+ +++ b/drivers/net/wireless/b43/phy_common.c
+-@@ -266,6 +266,12 @@ void b43_phy_write(struct b43_wldev *dev
++@@ -267,6 +267,12 @@ void b43_phy_write(struct b43_wldev *dev
+  {
+  	assert_mac_suspended(dev);
+  	dev->phy.ops->phy_write(dev, reg, value);
+@@ -197,7 +197,7 @@ Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
+  
+ --- a/drivers/net/wireless/b43/phy_n.c
+ +++ b/drivers/net/wireless/b43/phy_n.c
+-@@ -5418,14 +5418,14 @@ static inline void check_phyreg(struct b
++@@ -5641,14 +5641,14 @@ static inline void check_phyreg(struct b
+  static u16 b43_nphy_op_read(struct b43_wldev *dev, u16 reg)
+  {
+  	check_phyreg(dev, reg);
+@@ -214,7 +214,7 @@ Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
+  	b43_write16(dev, B43_MMIO_PHY_DATA, value);
+  }
+  
+-@@ -5433,7 +5433,7 @@ static void b43_nphy_op_maskset(struct b
++@@ -5656,7 +5656,7 @@ static void b43_nphy_op_maskset(struct b
+  				 u16 set)
+  {
+  	check_phyreg(dev, reg);
+@@ -223,16 +223,16 @@ Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
+  	b43_maskset16(dev, B43_MMIO_PHY_DATA, mask, set);
+  }
+  
+-@@ -5444,7 +5444,7 @@ static u16 b43_nphy_op_radio_read(struct
+- 	/* N-PHY needs 0x100 for read access */
+- 	reg |= 0x100;
++@@ -5670,7 +5670,7 @@ static u16 b43_nphy_op_radio_read(struct
++ 	else
++ 		reg |= 0x100;
+  
+ -	b43_write16(dev, B43_MMIO_RADIO_CONTROL, reg);
+ +	b43_wflush16(dev, B43_MMIO_RADIO_CONTROL, reg);
+  	return b43_read16(dev, B43_MMIO_RADIO_DATA_LOW);
+  }
+  
+-@@ -5453,7 +5453,7 @@ static void b43_nphy_op_radio_write(stru
++@@ -5679,7 +5679,7 @@ static void b43_nphy_op_radio_write(stru
+  	/* Register 1 is a 32-bit register. */
+  	B43_WARN_ON(reg == 1);
+  
+diff --git a/package/mac80211/patches/845-b43-only-use-gpio-0-1-for-led.patch b/package/mac80211/patches/845-b43-only-use-gpio-0-1-for-led.patch
+index 50347cd..8555ccf 100644
+--- a/package/mac80211/patches/845-b43-only-use-gpio-0-1-for-led.patch
++++ b/package/mac80211/patches/845-b43-only-use-gpio-0-1-for-led.patch
+@@ -1,6 +1,6 @@
+ --- a/drivers/net/wireless/b43/main.c
+ +++ b/drivers/net/wireless/b43/main.c
+-@@ -2764,6 +2764,14 @@ static int b43_gpio_init(struct b43_wlde
++@@ -2756,6 +2756,14 @@ static int b43_gpio_init(struct b43_wlde
+  	} else if (dev->dev->chip_id == 0x5354) {
+  		/* Don't allow overtaking buttons GPIOs */
+  		set &= 0x2; /* 0x2 is LED GPIO on BCM5354 */
 diff --git a/package/mac80211/patches/900-wl1251-split-wl251-platform-data-to-a-separate-structure.patch b/package/mac80211/patches/900-wl1251-split-wl251-platform-data-to-a-separate-structure.patch
 deleted file mode 100644
 index a8af257..0000000
@@ -10774,7 +14841,7 @@ index a8af257..0000000
 - 	int ret;
 diff --git a/package/mac80211/patches/900-wlcore-Add-support-for-DT-platform-data.patch b/package/mac80211/patches/900-wlcore-Add-support-for-DT-platform-data.patch
 new file mode 100644
-index 0000000..967768a
+index 0000000..856dea8
 --- /dev/null
 +++ b/package/mac80211/patches/900-wlcore-Add-support-for-DT-platform-data.patch
 @@ -0,0 +1,139 @@
@@ -10868,22 +14935,22 @@ index 0000000..967768a
 + static int wl1271_probe(struct sdio_func *func,
 + 				  const struct sdio_device_id *id)
 + {
-+@@ -248,12 +304,9 @@ static int wl1271_probe(struct sdio_func
++@@ -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);
++-	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))
+++	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;
-+-	}
++ 	}
 + 
-+ 	/* if sdio can keep power while host is suspended, enable wow */
-+ 	mmcflags = sdio_get_host_pm_caps(func);
-+@@ -282,7 +335,7 @@ static int wl1271_probe(struct sdio_func
++@@ -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;
@@ -10892,7 +14959,7 @@ index 0000000..967768a
 + 	}
 + 
 + 	glue->core->dev.parent = &func->dev;
-+@@ -316,6 +369,9 @@ static int wl1271_probe(struct sdio_func
++@@ -313,6 +369,9 @@ static int wl1271_probe(struct sdio_func
 + out_dev_put:
 + 	platform_device_put(glue->core);
 + 
@@ -10902,7 +14969,7 @@ index 0000000..967768a
 + out_free_glue:
 + 	kfree(glue);
 + 
-+@@ -329,11 +385,14 @@ out:
++@@ -323,11 +382,14 @@ out:
 + static void wl1271_remove(struct sdio_func *func)
 + {
 + 	struct wl12xx_sdio_glue *glue = sdio_get_drvdata(func);
@@ -10917,59 +14984,48 @@ index 0000000..967768a
 + 	kfree(glue);
 + }
 + 
-diff --git a/package/mac80211/patches/901-wl18xx-align-event-mailbox-with-current-fw.patch b/package/mac80211/patches/901-wl18xx-align-event-mailbox-with-current-fw.patch
+diff --git a/package/mac80211/patches/901-wlcore-don-t-switch-channels-on-disconnected-STA-vif.patch b/package/mac80211/patches/901-wlcore-don-t-switch-channels-on-disconnected-STA-vif.patch
 new file mode 100644
-index 0000000..77647bb
+index 0000000..d90508e
 --- /dev/null
-+++ b/package/mac80211/patches/901-wl18xx-align-event-mailbox-with-current-fw.patch
-@@ -0,0 +1,47 @@
-+From fde3f0a7f3112527a18e06e32efdd9a354c91b02 Mon Sep 17 00:00:00 2001
-+From: Eliad Peller <eliad@wizery.com>
-+Date: Tue, 18 Mar 2014 13:19:48 +0200
-+Subject: [PATCH] wl18xx: align event mailbox with current fw
-+
-+Some fields are missing from the event mailbox
-+struct definitions, which cause issues when
-+trying to handle some events.
-+
-+Add the missing fields in order to align the
-+struct size (without adding actual support
-+for the new fields).
-+
-+Signed-off-by: Eliad Peller <eliad@wizery.com>
++++ b/package/mac80211/patches/901-wlcore-don-t-switch-channels-on-disconnected-STA-vif.patch
+@@ -0,0 +1,36 @@
++From 4101e8dc540d19f1f6c24930629149191786e4cd Mon Sep 17 00:00:00 2001
++From: Arik Nemtsov <arik@wizery.com>
++Date: Mon, 9 Sep 2013 16:48:59 +0300
++Subject: [PATCH 27/75] wlcore: don't switch channels on disconnected STA vifs
++
++Sending the FW a channel switch command on a disconnected vif may result
++in a beacon loss event. Avoid this edge case.
++
++Signed-off-by: Arik Nemtsov <arik@wizery.com>
 +---
-+ drivers/net/wireless/ti/wl18xx/event.h | 20 ++++++++++++++++++++
-+ 1 file changed, 20 insertions(+)
-+
-+--- a/drivers/net/wireless/ti/wl18xx/event.h
-++++ b/drivers/net/wireless/ti/wl18xx/event.h
-+@@ -68,6 +68,26 @@ struct wl18xx_event_mailbox {
-+ 
-+ 	/* bitmap of inactive stations (by HLID) */
-+ 	__le32 inactive_sta_bitmap;
-++
-++	/* rx BA win size indicated by RX_BA_WIN_SIZE_CHANGE_EVENT_ID */
-++	u8 rx_ba_role_id;
-++	u8 rx_ba_link_id;
-++	u8 rx_ba_win_size;
-++	u8 padding;
-++
-++	/* smart config */
-++	u8 sc_ssid_len;
-++	u8 sc_pwd_len;
-++	u8 sc_token_len;
-++	u8 padding1;
-++	u8 sc_ssid[32];
-++	u8 sc_pwd[32];
-++	u8 sc_token[32];
-++
-++	/* smart config sync channel */
-++	u8 sc_sync_channel;
-++	u8 sc_sync_band;
-++	u8 padding2[2];
-+ } __packed;
++ drivers/net/wireless/ti/wlcore/main.c | 7 +++++++
++ 1 file changed, 7 insertions(+)
++
++--- a/drivers/net/wireless/ti/wlcore/main.c
+++++ b/drivers/net/wireless/ti/wlcore/main.c
++@@ -5148,6 +5148,10 @@ static void wl12xx_op_channel_switch(str
++ 	if (unlikely(wl->state == WLCORE_STATE_OFF)) {
++ 		wl12xx_for_each_wlvif_sta(wl, wlvif) {
++ 			struct ieee80211_vif *vif = wl12xx_wlvif_to_vif(wlvif);
+++
+++			if (!test_bit(WLVIF_FLAG_STA_ASSOCIATED, &wlvif->flags))
+++				continue;
+++
++ 			ieee80211_chswitch_done(vif, false);
++ 		}
++ 		goto out;
++@@ -5163,6 +5167,9 @@ static void wl12xx_op_channel_switch(str
++ 	wl12xx_for_each_wlvif_sta(wl, wlvif) {
++ 		unsigned long delay_usec;
 + 
-+ int wl18xx_wait_for_event(struct wl1271 *wl, enum wlcore_wait_event event,
+++		if (!test_bit(WLVIF_FLAG_STA_ASSOCIATED, &wlvif->flags))
+++			continue;
+++
++ 		ret = wl->ops->channel_switch(wl, wlvif, ch_switch);
++ 		if (ret)
++ 			goto out_sleep;
 diff --git a/package/mac80211/patches/901-wlcore-set-irq_flags-in-the-board-files.patch b/package/mac80211/patches/901-wlcore-set-irq_flags-in-the-board-files.patch
 deleted file mode 100644
 index f2789a9..0000000
@@ -11094,48 +15150,6 @@ index f2789a9..0000000
 - 	/* number of currently active RX BA sessions */
 - 	int ba_rx_session_count;
 - 
-diff --git a/package/mac80211/patches/902-wlcore-don-t-switch-channels-on-disconnected-STA-vif.patch b/package/mac80211/patches/902-wlcore-don-t-switch-channels-on-disconnected-STA-vif.patch
-new file mode 100644
-index 0000000..3d501b2
---- /dev/null
-+++ b/package/mac80211/patches/902-wlcore-don-t-switch-channels-on-disconnected-STA-vif.patch
-@@ -0,0 +1,36 @@
-+From 4101e8dc540d19f1f6c24930629149191786e4cd Mon Sep 17 00:00:00 2001
-+From: Arik Nemtsov <arik@wizery.com>
-+Date: Mon, 9 Sep 2013 16:48:59 +0300
-+Subject: [PATCH 27/75] wlcore: don't switch channels on disconnected STA vifs
-+
-+Sending the FW a channel switch command on a disconnected vif may result
-+in a beacon loss event. Avoid this edge case.
-+
-+Signed-off-by: Arik Nemtsov <arik@wizery.com>
-+---
-+ drivers/net/wireless/ti/wlcore/main.c | 7 +++++++
-+ 1 file changed, 7 insertions(+)
-+
-+--- a/drivers/net/wireless/ti/wlcore/main.c
-++++ b/drivers/net/wireless/ti/wlcore/main.c
-+@@ -5181,6 +5181,10 @@ static void wl12xx_op_channel_switch(str
-+ 	if (unlikely(wl->state == WLCORE_STATE_OFF)) {
-+ 		wl12xx_for_each_wlvif_sta(wl, wlvif) {
-+ 			struct ieee80211_vif *vif = wl12xx_wlvif_to_vif(wlvif);
-++
-++			if (!test_bit(WLVIF_FLAG_STA_ASSOCIATED, &wlvif->flags))
-++				continue;
-++
-+ 			ieee80211_chswitch_done(vif, false);
-+ 		}
-+ 		goto out;
-+@@ -5196,6 +5200,9 @@ static void wl12xx_op_channel_switch(str
-+ 	wl12xx_for_each_wlvif_sta(wl, wlvif) {
-+ 		unsigned long delay_usec;
-+ 
-++		if (!test_bit(WLVIF_FLAG_STA_ASSOCIATED, &wlvif->flags))
-++			continue;
-++
-+ 		ret = wl->ops->channel_switch(wl, wlvif, ch_switch);
-+ 		if (ret)
-+ 			goto out_sleep;
 diff --git a/package/mac80211/patches/902-wlcore-remove-pwr_in_suspend-from-platform-data.patch b/package/mac80211/patches/902-wlcore-remove-pwr_in_suspend-from-platform-data.patch
 deleted file mode 100644
 index 6394377..0000000
@@ -11705,3 +15719,37 @@ index 6b09177..0000000
 - 		glue->tcxoclock = NULL;
 - 	} else {
 - 		clk_prepare_enable(glue->tcxoclock);
+diff --git a/package/mac80211/patches/a01-compat_fix_compile.patch b/package/mac80211/patches/a01-compat_fix_compile.patch
+new file mode 100644
+index 0000000..9e9e6c7
+--- /dev/null
++++ b/package/mac80211/patches/a01-compat_fix_compile.patch
+@@ -0,0 +1,15 @@
++--- a/compat/compat-3.6.c
+++++ b/compat/compat-3.6.c
++@@ -148,6 +148,7 @@ int sg_alloc_table_from_pages(struct sg_
++ }
++ EXPORT_SYMBOL_GPL(sg_alloc_table_from_pages);
++ 
+++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0))
++ /* whoopsie ! */
++ #ifndef CONFIG_COMMON_CLK
++ int clk_enable(struct clk *clk)
++@@ -161,3 +162,4 @@ void clk_disable(struct clk *clk)
++ }
++ EXPORT_SYMBOL_GPL(clk_disable);
++ #endif
+++#endif
+diff --git a/target/linux/generic/files/include/linux/ath9k_platform.h b/target/linux/generic/files/include/linux/ath9k_platform.h
+index a0b7531..03aa636 100644
+--- a/target/linux/generic/files/include/linux/ath9k_platform.h
++++ b/target/linux/generic/files/include/linux/ath9k_platform.h
+@@ -39,6 +39,8 @@ struct ath9k_platform_data {
+ 	int (*get_mac_revision)(void);
+ 	int (*external_reset)(void);
+ 
++	bool use_eeprom;
++
+ 	int num_leds;
+ 	const struct gpio_led *leds;
+ };
-- 
GitLab