From: Felix Fietkau Date: Tue, 20 May 2014 09:35:17 +0000 (+0000) Subject: mac80211: update to wireless-testing 2014-05-19 X-Git-Url: http://git.lede-project.org./?a=commitdiff_plain;h=8513629e3ed39ac7d6d3ca90f1ad745db5c449d6;p=openwrt%2Fstaging%2Fthess.git mac80211: update to wireless-testing 2014-05-19 Signed-off-by: Felix Fietkau SVN-Revision: 40800 --- diff --git a/package/kernel/mac80211/Makefile b/package/kernel/mac80211/Makefile index d1759fd01c..1dcb7bda30 100644 --- a/package/kernel/mac80211/Makefile +++ b/package/kernel/mac80211/Makefile @@ -10,11 +10,11 @@ include $(INCLUDE_DIR)/kernel.mk PKG_NAME:=mac80211 -PKG_VERSION:=2014-03-31 +PKG_VERSION:=2014-05-19 PKG_RELEASE:=1 PKG_SOURCE_URL:=http://mirror2.openwrt.org/sources PKG_BACKPORT_VERSION:= -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) @@ -357,7 +357,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 AutoProbe,rtl8180) endef diff --git a/package/kernel/mac80211/patches/001-fix_build.patch b/package/kernel/mac80211/patches/001-fix_build.patch index 26b327ac8e..99ef50e182 100644 --- a/package/kernel/mac80211/patches/001-fix_build.patch +++ b/package/kernel/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/kernel/mac80211/patches/003-remove_bogus_modparams.patch b/package/kernel/mac80211/patches/003-remove_bogus_modparams.patch index c969b195ae..ffb730b149 100644 --- a/package/kernel/mac80211/patches/003-remove_bogus_modparams.patch +++ b/package/kernel/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/kernel/mac80211/patches/007-select_queue.patch b/package/kernel/mac80211/patches/007-select_queue.patch index a326ee3cc1..0a1d2925cb 100644 --- a/package/kernel/mac80211/patches/007-select_queue.patch +++ b/package/kernel/mac80211/patches/007-select_queue.patch @@ -1,6 +1,6 @@ --- a/drivers/net/wireless/mwifiex/main.c +++ b/drivers/net/wireless/mwifiex/main.c -@@ -747,7 +747,7 @@ static struct net_device_stats *mwifiex_ +@@ -745,7 +745,7 @@ static struct net_device_stats *mwifiex_ return &priv->stats; } @@ -9,23 +9,3 @@ static u16 mwifiex_netdev_select_wmm_queue(struct net_device *dev, struct sk_buff *skb, void *accel_priv, select_queue_fallback_t fallback) ---- a/net/mac80211/iface.c -+++ b/net/mac80211/iface.c -@@ -1062,7 +1062,7 @@ static void ieee80211_uninit(struct net_ - ieee80211_teardown_sdata(IEEE80211_DEV_TO_SUB_IF(dev)); - } - --#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,15,0) -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,14,0) - static u16 ieee80211_netdev_select_queue(struct net_device *dev, - struct sk_buff *skb, - void *accel_priv, -@@ -1090,7 +1090,7 @@ static const struct net_device_ops ieee8 - .ndo_select_queue = ieee80211_netdev_select_queue, - }; - --#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,15,0) -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,14,0) - static u16 ieee80211_monitor_select_queue(struct net_device *dev, - struct sk_buff *skb, - void *accel_priv, diff --git a/package/kernel/mac80211/patches/020-disable_tty_set_termios.patch b/package/kernel/mac80211/patches/020-disable_tty_set_termios.patch deleted file mode 100644 index e6d4ff6e9d..0000000000 --- a/package/kernel/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 - #include - -+#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/kernel/mac80211/patches/050-lib80211_option.patch b/package/kernel/mac80211/patches/050-lib80211_option.patch index 5372114310..168871a1c8 100644 --- a/package/kernel/mac80211/patches/050-lib80211_option.patch +++ b/package/kernel/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/kernel/mac80211/patches/060-no_local_ssb_bcma.patch b/package/kernel/mac80211/patches/060-no_local_ssb_bcma.patch index 95f14f436e..d550bba6a5 100644 --- a/package/kernel/mac80211/patches/060-no_local_ssb_bcma.patch +++ b/package/kernel/mac80211/patches/060-no_local_ssb_bcma.patch @@ -1,6 +1,6 @@ --- a/.local-symbols +++ b/.local-symbols -@@ -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/kernel/mac80211/patches/070-add-missing-header.patch b/package/kernel/mac80211/patches/070-add-missing-header.patch index 9307804a07..e3ec7807e7 100644 --- a/package/kernel/mac80211/patches/070-add-missing-header.patch +++ b/package/kernel/mac80211/patches/070-add-missing-header.patch @@ -1,10 +1,10 @@ --- a/compat/backport-3.15.c +++ b/compat/backport-3.15.c -@@ -11,6 +11,7 @@ +@@ -12,6 +12,7 @@ #include #include #include +#include + #include - /** - * devm_kstrdup - Allocate resource managed space and + #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,5,0)) diff --git a/package/kernel/mac80211/patches/100-revert_aes_ccm_port.patch b/package/kernel/mac80211/patches/100-revert_aes_ccm_port.patch index ac7d6b3495..640d34e51f 100644 --- a/package/kernel/mac80211/patches/100-revert_aes_ccm_port.patch +++ b/package/kernel/mac80211/patches/100-revert_aes_ccm_port.patch @@ -1,111 +1,10 @@ ---- 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; -+ - /* - * 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; - - 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)); - - return 0; - } -@@ -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 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--- @@ -120,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; @@ -174,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) ++} ++ + +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)); @@ -197,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; @@ -232,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; @@ -288,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; -+ + +- 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); -+ + +- crypto_free_aead(tfm); +- return ERR_PTR(err); + return tfm; -+} -+ + } + +-void ieee80211_aes_key_free(struct crypto_aead *tfm) + +void ieee80211_aes_key_free(struct crypto_cipher *tfm) { @@ -345,3 +244,104 @@ u32 replays; /* dot11RSNAStatsCCMPReplays */ } ccmp; struct { +--- 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; ++ + /* + * 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) && +@@ -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); +- 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; + } +@@ -523,16 +528,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; + } + diff --git a/package/kernel/mac80211/patches/150-disable_addr_notifier.patch b/package/kernel/mac80211/patches/150-disable_addr_notifier.patch index 3f749e9bfd..c80b2bbb3d 100644 --- a/package/kernel/mac80211/patches/150-disable_addr_notifier.patch +++ b/package/kernel/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) { -@@ -1036,14 +1036,14 @@ int ieee80211_register_hw(struct ieee802 +@@ -1034,14 +1034,14 @@ int ieee80211_register_hw(struct ieee802 goto fail_pm_qos; } @@ -35,7 +35,7 @@ local->ifa6_notifier.notifier_call = ieee80211_ifa6_changed; result = register_inet6addr_notifier(&local->ifa6_notifier); if (result) -@@ -1052,13 +1052,13 @@ int ieee80211_register_hw(struct ieee802 +@@ -1050,13 +1050,13 @@ int ieee80211_register_hw(struct ieee802 return 0; @@ -52,7 +52,7 @@ fail_ifa: pm_qos_remove_notifier(PM_QOS_NETWORK_LATENCY, &local->network_latency_notifier); -@@ -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/kernel/mac80211/patches/300-pending_work.patch b/package/kernel/mac80211/patches/300-pending_work.patch index ef81721529..702b17b333 100644 --- a/package/kernel/mac80211/patches/300-pending_work.patch +++ b/package/kernel/mac80211/patches/300-pending_work.patch @@ -8,7 +8,7 @@ Date: Mon May 19 21:48:56 2014 +0200 Signed-off-by: Felix Fietkau -commit 27647baeaee1b12bc3c57ccf1c7eba53bcd7fe53 +commit ff9655bebd25d35ab13c2515a029723b69949720 Author: Felix Fietkau Date: Mon May 19 21:20:49 2014 +0200 @@ -21,710 +21,4351 @@ Date: Mon May 19 21:20:49 2014 +0200 Signed-off-by: Felix Fietkau -commit 92e9dd662542683856e62a5e7e43fcf5b9da5c4a -Author: Henning Rogge -Date: Thu May 1 10:03:46 2014 +0200 +commit 46c5d7d207a2a0725066c0928fd19b8c578b7d4f +Author: Oleksij Rempel +Date: Tue May 20 00:02:03 2014 +0200 - mac80211: Fix mac80211 station info rx bitrate for IBSS mode + ath9k_htc: fix build with disabled debug - Filter out incoming multicast packages before applying their bitrate - to the rx bitrate station info field to prevent them from setting the - rx bitrate to the basic multicast rate. + 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: Henning Rogge + Signed-off-by: Oleksij Rempel -commit 4c8a3486cb577d40c1ef75f0a8dc9a04773eef83 -Author: Nickolay Ledovskikh -Date: Fri Apr 25 22:53:34 2014 +0400 +commit 2d331334e9dc5659fdf9a89326c34c3db5a15279 +Author: Johannes Berg +Date: Mon May 19 17:59:50 2014 +0200 - ath5k: Fix AR5K_PHY_TXPOWER_RATE_MAX register value setting. + cfg80211: constify wowlan/coalesce mask/pattern pointers - 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. + This requires changing the nl80211 parsing code a bit to use + intermediate pointers for the allocation, but clarifies the + API towards the drivers. - Signed-off-by: Nikolay Ledovskikh - Acked-by: Nick Kossifidis - Signed-off-by: John W. Linville + Signed-off-by: Johannes Berg -commit 4d76248013dbb1948429555208900a585b0f351d -Author: Janusz Dziedzic -Date: Tue Apr 8 13:38:43 2014 +0200 +commit 6788105c46babaa6938cbacb72fdf20bec4bb2e3 +Author: Johannes Berg +Date: Mon May 19 17:53:16 2014 +0200 - ath9k: Enable DFS only when ATH9K_DFS_CERTIFIED + cfg80211: constify more pointers in the cfg80211 API - 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). + This also propagates through the drivers. - Reported-by: Cedric Voncken - Signed-off-by: Janusz Dziedzic - Signed-off-by: John W. Linville + 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 -commit c83a4e5156a4b4dd22137d33a5625440982d6d37 -Author: Rajkumar Manoharan -Date: Mon Apr 28 21:17:08 2014 +0530 +commit c3d95010fd881da0fa0a4e88532412f5d0c092f6 +Author: Johannes Berg +Date: Mon May 19 17:19:31 2014 +0200 - ath9k_hw: fix worse EVM for 11b rates + cfg80211: constify MAC addresses in cfg80211 ops - Adjust FIR filter co-efficients to improve EVM for 11b rates. + This propagates through all the drivers and mac80211. - Signed-off-by: Rajkumar Manoharan - Signed-off-by: John W. Linville + Signed-off-by: Johannes Berg -commit 8aab2c7a2f4a957e344db429dfb1190ae59ce8b5 -Author: Rajkumar Manoharan -Date: Mon Apr 28 21:17:07 2014 +0530 +commit ddf1e6f0f0354c601af7d42e5ace4b51f8b0bffc +Author: Luciano Coelho +Date: Thu May 15 20:32:08 2014 +0300 - ath9k_hw: update ar9300 initvals + mac80211: fix csa_counter_offs argument name in docbook + + The csa_counter_offs was erroneously described as csa_offs in + the docbook section. - * rfsat gainchange hysteresis of rf_gain stuck with large - interference present. + This fixes two warnings when making htmldocs (at least): - Signed-off-by: Rajkumar Manoharan - Signed-off-by: John W. Linville + 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' + + Signed-off-by: Luciano Coelho + Signed-off-by: Johannes Berg -commit 8c7ae357cc5b6bd037ad2d666e9f3789cf882925 -Author: Rajkumar Manoharan -Date: Wed Apr 23 15:07:57 2014 +0530 +commit 202322d1c04b8e498bd5bb78606fcf3941512b35 +Author: Luciano Coelho +Date: Thu May 15 20:18:09 2014 +0300 - ath9k: fix race in setting ATH_OP_INVALID + cfg80211: add documentation for max_num_csa_counters + + Move the comment in the structure to a description of the + max_num_csa_counters field in the docbook area. - 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. + This fixes a warning when building htmldocs (at least): - Signed-off-by: Rajkumar Manoharan - Signed-off-by: John W. Linville + Warning(include/net/cfg80211.h:3064): No description found for parameter 'max_num_csa_counters' + + Signed-off-by: Luciano Coelho + Signed-off-by: Johannes Berg -commit c82552c5b0cb1735dbcbad78b1ffc6d3c212dc56 -Author: Tim Harvey -Date: Mon Apr 21 16:14:57 2014 -0700 +commit 457a33192f64b7637e8fd0ae0e9f32701c908603 +Author: Johannes Berg +Date: Mon May 19 11:24:19 2014 +0200 - ath9k: add a recv budget + mac80211: minstrel-ht: small clarifications + + Antonio and I were looking over this code and some things + didn't immediately make sense, so we came up with two small + clarifications. - Implement a recv budget so that in cases of high traffic we still allow other - taskets to get processed. + Signed-off-by: Johannes Berg + +commit 1e35dce952a64a957de97ae1f2bb19301756b936 +Author: Andrei Otcheretianski +Date: Fri May 9 14:11:50 2014 +0300 + + mac80211: Handle the CSA counters correctly - 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. + 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. - The same thing was proposed previously by Ben: - http://www.spinics.net/lists/linux-wireless/msg112891.html + Signed-off-by: Andrei Otcheretianski + Signed-off-by: Luciano Coelho + Signed-off-by: Johannes Berg + +commit e7b5c449815d28a2105fde5b42e112f78cc711ac +Author: Andrei Otcheretianski +Date: Fri May 9 14:11:49 2014 +0300 + + mac80211: Provide ieee80211_beacon_get_template API - 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. + 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: Tim Harvey - Acked-by: Felix Fietkau - Signed-off-by: John W. Linville + Signed-off-by: Andrei Otcheretianski + Signed-off-by: Luciano Coelho + Signed-off-by: Johannes Berg -commit 3a758134e66ca74a9df792616b5288b2fa2cfd7f -Author: Tim Harvey -Date: Mon Apr 21 16:14:56 2014 -0700 +commit e54eda80273ce8aded058c3c9365dca2342e2e75 +Author: Andrei Otcheretianski +Date: Fri May 9 14:11:47 2014 +0300 - ath9k: fix possible hang on flush + mac80211: Support multiple CSA counters - If a flush is requested, make sure to clear the descriptor once we've - processed it. + Support up to IEEE80211_MAX_CSA_COUNTERS_NUM csa counters. + This is defined to be 2 now, to support both CSA and eCSA + counters. - This resolves a hang that will occur if all RX descriptors are full when a - flush is requested. + Signed-off-by: Andrei Otcheretianski + Signed-off-by: Luciano Coelho + Signed-off-by: Johannes Berg + +commit 678e87c3b929dd60d59470e8981eb551cee10319 +Author: Andrei Otcheretianski +Date: Fri May 9 14:11:46 2014 +0300 + + cfg80211: Support multiple CSA counters - Signed-off-by: Tim Harvey - Acked-by: Felix Fietkau - Signed-off-by: John W. Linville + 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 + Signed-off-by: Luciano Coelho + Signed-off-by: Johannes Berg -commit eefb1d6adc4c60d219182b8917e4567484ce07fc -Author: Felix Fietkau -Date: Mon Apr 28 18:27:41 2014 +0200 +commit 93f4867a966cc8645659031bbd44a9bb4b78485f +Author: Andrei Otcheretianski +Date: Fri May 9 14:11:45 2014 +0300 - ath9k: remove tid->paused flag + mac80211: Update CSA counters in mgmt frames - 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. + Track current csa counter value and use it + to update mgmt frames at the provided offsets. - 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. + Signed-off-by: Andrei Otcheretianski + Signed-off-by: Luciano Coelho + Signed-off-by: Johannes Berg + +commit 6c8461fcc03ff4d250027e47f53315b5e0ec43aa +Author: Andrei Otcheretianski +Date: Fri May 9 14:11:44 2014 +0300 + + cfg80211: Add API to update CSA counters in mgmt frames - mac80211 prevents new frames from entering the queue during setup. + 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. - Signed-off-by: Felix Fietkau + 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: Andrei Otcheretianski + Signed-off-by: Luciano Coelho + Signed-off-by: Johannes Berg -commit 98a713933d8495f4078f561c1e651b738dd5b531 -Author: Felix Fietkau -Date: Sun Apr 27 14:49:03 2014 +0200 +commit 7d09fc9f1903b3d5e7d046bdf10467f37a97c4f9 +Author: Luciano Coelho +Date: Thu May 15 13:05:39 2014 +0300 - ath9k_hw: do not lower ANI setting below default on AR913x + cfg80211: pass the actual iftype when calling cfg80211_chandef_dfs_required() - 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. + 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. - To fix this, keep noise immunity settings at or above ANI default level, - which will keep radio parameters at or above INI values. + Additionally, have cfg80211_chandef_dfs_required() WARN if the passed + interface type is NL80211_IFTYPE_UNSPECIFIED, so we can detect + problems more easily. - Signed-off-by: Felix Fietkau + Tested-by: Janusz Dziedzic + Reported-by: Eliad Peller + Signed-off-by: Luciano Coelho + Signed-off-by: Johannes Berg -commit 7cbb4c021bfd1e656f5b9953a947ab3c64e4e3b0 -Author: Felix Fietkau -Date: Thu Apr 10 10:49:01 2014 +0200 +commit 2b7443b15f26ecb98281474666383cf2a882fbad +Author: Janusz Dziedzic +Date: Wed May 14 13:25:04 2014 +0200 - mac80211: exclude AP_VLAN interfaces from tx power calculation + cfg80211: fix start_radar_detection issue - 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. + After patch: + cfg80211/mac80211: refactor cfg80211_chandef_dfs_required() - Cc: stable@vger.kernel.org - Signed-off-by: Felix Fietkau + start_radar_detection always fail with -EINVAL. + + Acked-by: Luciano Coelho + Signed-off-by: Janusz Dziedzic + Signed-off-by: Johannes Berg -commit 0ca13e26341733bf9577287fb04a3bef0d2f5cc9 +commit 4f46eb8b28f96aca212a364e0fa847eb5333df67 Author: Felix Fietkau -Date: Wed Apr 9 00:07:01 2014 +0200 +Date: Mon May 5 11:48:40 2014 +0200 - mac80211: suppress BSS info change notifications for AP_VLAN + cfg80211: allow restricting supported dfs regions - Fixes warnings on tx power changes + 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. Signed-off-by: Felix Fietkau + Signed-off-by: Johannes Berg -commit ec998e5991781ecdaad0911dc64f1c8d3749c308 -Author: Felix Fietkau -Date: Tue Apr 8 23:42:17 2014 +0200 +commit 0277b034768d1800a00829a755fc56b925aa6b95 +Author: Johannes Berg +Date: Wed Apr 30 14:19:04 2014 +0200 - ath9k: fix a scheduling while atomic bug in CSA handling + mac80211: handle failed restart/resume better - 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. + 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. - Signed-off-by: Felix Fietkau + 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 + Signed-off-by: Johannes Berg -commit 93f310a38a1d81a4bc8fcd9bf29628bd721cf2ef -Author: Felix Fietkau -Date: Sun Apr 6 23:35:28 2014 +0200 +commit 43fd71bc4b83d24981e90ca178f505cf6a6b16dc +Author: Luciano Coelho +Date: Wed May 7 20:05:12 2014 +0300 - ath9k_hw: reduce ANI firstep range for older chips + mac80211: fix sparse warning caused by __ieee80211_channel_switch() - 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. + Commit 59af6928 (mac80211: fix CSA tx queue stopping) introduced a + sparse warning: - Signed-off-by: Felix Fietkau + net/mac80211/cfg.c:3274:5: warning: symbol '__ieee80211_channel_switch' was not declared. Should it be static? + + Fix it by declaring the function static. + + Signed-off-by: Luciano Coelho + Signed-off-by: Johannes Berg + +commit dd4371e2957db19870bb22ab84e841e1ac6e8997 +Author: Luciano Coelho +Date: Wed May 7 19:07:05 2014 +0300 + + 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' + + Fix it by adding the iftype argument name to the + cfg80211_chandef_dfs_required() function declaration. + + Reported-and-tested-by: Masanari Iida + Signed-off-by: Luciano Coelho + Signed-off-by: Johannes Berg + +commit 56de850ae960f096c784ec07864ca5b71abd16e6 +Author: Michal Kazior +Date: Thu May 8 09:10:02 2014 +0200 + + mac80211: disconnect iface if CSA unexpectedly fails + + It doesn't make much sense to leave a crippled + interface running. + + As a side effect this will unblock tx queues with + CSA reason immediately after failure instead of + until after userspace requests interface to stop. + + This also gives userspace an opportunity to + indirectly see CSA failure. + + Signed-off-by: Michal Kazior + [small code cleanup] + Signed-off-by: Johannes Berg + +commit f5894c4f19e55bb1ea6376031fe9d47d7528be9e +Author: Loic Poulain +Date: Wed May 7 11:38:11 2014 +0200 + + rfkill-gpio: Use gpio cansleep version + + 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: Loic Poulain + Signed-off-by: Johannes Berg + +commit 47fdf5d4f3704d2db9d1c0f647f788edef104fc8 +Author: Michal Kazior +Date: Wed Apr 9 15:45:36 2014 +0200 + + mac80211: ignore cqm during csa + + 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 + Signed-off-by: Johannes Berg + +commit 1a8ed386e1684b266a15dacf675102ae53361ee5 +Author: Michal Kazior +Date: Wed Apr 9 15:11:01 2014 +0200 + + cfg80211: export interface stopping function + + This exports a new cfg80211_stop_iface() function. + + This is intended for driver internal interface + combination management and channel switching. + + Due to locking issues (it re-enters driver) the + call is asynchronous and uses cfg80211 event + list/worker. + + Signed-off-by: Michal Kazior + Signed-off-by: Johannes Berg + +commit 573f31d6d0e572ff8186c45a1ecd9273242233e6 +Author: Michal Kazior +Date: Wed Apr 9 15:11:00 2014 +0200 + + mac80211: split CSA finalize function + + Improves readability and modularity. + + Signed-off-by: Michal Kazior + Signed-off-by: Johannes Berg +commit 2d104d52e7c7640d68f29f2136dbe3938b7bc9ba +Author: Michal Kazior +Date: Wed Apr 9 15:10:59 2014 +0200 ---- 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; + 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 + Signed-off-by: Johannes Berg + +commit 6be615d6d42aa7fdab6c4278031d8fa0953e594f +Author: Johannes Berg +Date: Wed Apr 9 21:31:13 2014 +0200 + + mac80211: mark local variable __maybe_unused + + 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. + + While at it, fix some indentation where it's used. + + Reviewed-by: Luciano Coelho + Reviewed-by: Emmanuel Grumbach + Signed-off-by: Johannes Berg + +commit 43279e584aeb78aa0c853728db047b58156c0753 +Author: Arik Nemtsov +Date: Thu May 1 10:17:28 2014 +0300 + + mac80211: move TDLS code to another file + + With new additions planned, this code is getting too big for cfg.c. + + Signed-off-by: Arik Nemtsov + Signed-off-by: Johannes Berg + +commit bf9c234b83c77f1ebbcbab73de2a9e4a5d4aafc6 +Author: Arik Nemtsov +Date: Thu May 1 10:17:27 2014 +0300 + + mac80211: set an external flag for TDLS stations + + Expose a new tdls flag for the public ieee80211_sta struct. + This can be used in some rate control decisions. + + Signed-off-by: Arik Nemtsov + Signed-off-by: Johannes Berg + +commit 910e65141a17f645ab85dae1a497e64ebe63df70 +Author: Johannes Berg +Date: Tue Apr 29 17:55:26 2014 +0200 + + mac80211: remove BUG_ON usage + + 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. + + Leave the one BUG_ON where changing it would result in a NULL + pointer dereference. + + Signed-off-by: Johannes Berg + +commit ff36b582a10285530351aab036087b57ddb4ae2b +Author: Johannes Berg +Date: Tue Apr 29 17:52:36 2014 +0200 + + cfg80211: remove BUG_ON usage + + 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 + +--- a/drivers/net/wireless/ath/ath6kl/cfg80211.c ++++ b/drivers/net/wireless/ath/ath6kl/cfg80211.c +@@ -1759,7 +1759,7 @@ static bool is_rate_ht40(s32 rate, u8 *m + } -- 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); + 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) + { + 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 }; - 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 + static int ath6kl_del_station(struct wiphy *wiphy, struct net_device *dev, +- u8 *mac) ++ const u8 *mac) + { + struct ath6kl *ar = ath6kl_priv(dev); + struct ath6kl_vif *vif = netdev_priv(dev); +@@ -2985,7 +2985,8 @@ static int ath6kl_del_station(struct wip + } - void ath9k_csa_update(struct ath_softc *sc) + 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) { -- 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); + 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; } - 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 +-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 ieee80211_local *local = sdata->local; + 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) -- if (!changed) -+ if (!changed || sdata->vif.type == NL80211_IFTYPE_AP_VLAN) - return; + static inline void ath9k_htc_err_stat_rx(struct ath9k_htc_priv *priv, +- struct ath_htc_rx_status *rxs) ++ struct ath_rx_status *rs); + { + } - 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); - -+ if (AR_SREV_9100(ah) && immunityLevel < ATH9K_ANI_OFDM_DEF_LEVEL) -+ immunityLevel = ATH9K_ANI_OFDM_DEF_LEVEL; -+ - if (!scan) - aniState->ofdmNoiseImmunityLevel = immunityLevel; - -@@ -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); - -+ if (AR_SREV_9100(ah) && immunityLevel < ATH9K_ANI_CCK_DEF_LEVEL) -+ immunityLevel = ATH9K_ANI_CCK_DEF_LEVEL; -+ - 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; - }; +--- 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 ---- 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_ + 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 ath_atx_ac *ac = tid->ac; - -- if (tid->paused) -- return; -- - if (tid->sched) - return; + struct wil6210_priv *wil = wiphy_to_wil(wiphy); + int rc; +@@ -671,7 +671,7 @@ static int wil_cfg80211_stop_ap(struct w + } -@@ -1407,7 +1404,6 @@ int ath_tx_aggr_start(struct ath_softc * - ath_tx_tid_change_state(sc, txtid); - - txtid->active = true; -- txtid->paused = true; - *ssn = txtid->seq_start = txtid->seq_next; - txtid->bar_index = -1; - -@@ -1427,7 +1423,6 @@ void ath_tx_aggr_stop(struct ath_softc * - - 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 (!tid->paused && ath_tid_has_buffered(tid)) { -+ if (ath_tid_has_buffered(tid)) { - ath_tx_queue_tid(txq, tid); - ath_txq_schedule(sc, txq); - } -@@ -1510,7 +1505,6 @@ void ath_tx_aggr_resume(struct ath_softc - ath_txq_lock(sc, txq); - - tid->baw_size = IEEE80211_MIN_AMPDU_BUF << sta->ht_cap.ampdu_factor; -- tid->paused = false; - - if (ath_tid_has_buffered(tid)) { - ath_tx_queue_tid(txq, tid); -@@ -1544,8 +1538,6 @@ void ath9k_release_buffered_frames(struc - continue; - - tid = ATH_AN_2_TID(an, i); -- if (tid->paused) -- continue; - - 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; - -- if (tid->paused) -- continue; -- - 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 -@@ -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) + static int wil_cfg80211_del_station(struct wiphy *wiphy, +- struct net_device *dev, u8 *mac) ++ struct net_device *dev, const u8 *mac) { - 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); + struct wil6210_priv *wil = wiphy_to_wil(wiphy); -- 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); +--- 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)); + } - sc->rx.rxlink = &ds->ds_link; +-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; } --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) +-void wil6210_disconnect(struct wil6210_priv *wil, void *bssid) ++void wil6210_disconnect(struct wil6210_priv *wil, const u8 *bssid) { - if (sc->rx.buf_hold) -- ath_rx_buf_link(sc, sc->rx.buf_hold); -+ ath_rx_buf_link(sc, sc->rx.buf_hold, flush); + 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); - sc->rx.buf_hold = bf; + 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 + + 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 + + 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 } -@@ -106,7 +108,7 @@ static void ath_opmode_init(struct ath_s + + 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 + */ + + 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; + +--- 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 } - static bool ath_rx_edma_buf_link(struct ath_softc *sc, -- enum ath9k_rx_qtype qtype) -+ enum ath9k_rx_qtype qtype, bool flush) + 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 ath_hw *ah = sc->sc_ah; - struct ath_rx_edma *rx_edma; -@@ -127,7 +129,8 @@ static bool ath_rx_edma_buf_link(struct - ah->caps.rx_status_len, DMA_TO_DEVICE); - - SKB_CB_ATHBUF(skb) = bf; -- ath9k_hw_addrxbuf_edma(ah, bf->bf_buf_addr, qtype); -+ if (!flush) -+ ath9k_hw_addrxbuf_edma(ah, bf->bf_buf_addr, qtype); - __skb_queue_tail(&rx_edma->rx_fifo, skb); - - return true; -@@ -145,7 +148,7 @@ static void ath_rx_addbuffer_edma(struct - } + 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); - list_for_each_entry_safe(bf, tbf, &sc->rx.rxbuf, list) -- if (!ath_rx_edma_buf_link(sc, qtype)) -+ if (!ath_rx_edma_buf_link(sc, qtype, false)) - break; +@@ -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 + + 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); +@@ -2748,9 +2748,8 @@ mwifiex_cfg80211_tdls_oper(struct wiphy } -@@ -442,7 +445,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); - } - /* We could have deleted elements so the list may be empty now */ -@@ -636,7 +639,7 @@ static bool ath_edma_get_buffers(struct - if (ret == -EINVAL) { - /* corrupt descriptor, skip this one and the following one */ - list_add_tail(&bf->list, &sc->rx.rxbuf); -- ath_rx_edma_buf_link(sc, qtype); -+ ath_rx_edma_buf_link(sc, qtype, false); + 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); - skb = skb_peek(&rx_edma->rx_fifo); - if (skb) { -@@ -645,7 +648,7 @@ static bool ath_edma_get_buffers(struct +@@ -2765,9 +2764,9 @@ mwifiex_cfg80211_add_station(struct wiph + } - __skb_unlink(skb, &rx_edma->rx_fifo); - list_add_tail(&bf->list, &sc->rx.rxbuf); -- ath_rx_edma_buf_link(sc, qtype); -+ ath_rx_edma_buf_link(sc, qtype, false); - } + 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; - bf = NULL; -@@ -975,6 +978,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; + 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 - if (edma) - dma_type = DMA_BIDIRECTIONAL; -@@ -1113,15 +1117,17 @@ requeue_drop_frag: - } - requeue: - list_add_tail(&bf->list, &sc->rx.rxbuf); -- if (flush) -- continue; +-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; + } - if (edma) { -- ath_rx_edma_buf_link(sc, qtype); -+ ath_rx_edma_buf_link(sc, qtype, flush); - } else { -- ath_rx_buf_relink(sc, bf); -- ath9k_hw_rxena(ah); -+ ath_rx_buf_relink(sc, bf, flush); -+ if (!flush) -+ ath9k_hw_rxena(ah); - } -+ -+ if (!budget--) -+ break; - } while (1); +-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_ + } - if (!(ah->imask & ATH9K_INT_RXEOL)) { -@@ -1129,5 +1135,5 @@ requeue: - ath9k_hw_set_interrupts(ah); - } + 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 + } -- return 0; -+ return !budget; + 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_tdls_data *tf; + int ret; +@@ -506,7 +508,8 @@ static int mwifiex_prep_tdls_encap_data( } ---- 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; - err_irq: ---- a/drivers/net/wireless/ath/ath9k/init.c -+++ b/drivers/net/wireless/ath/ath9k/init.c -@@ -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 - }; + 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; - 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); - -+ /* Will be cleared in ath9k_start() */ -+ set_bit(ATH_OP_INVALID, &common->op_flags); -+ - /* 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 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); +@@ -520,8 +523,8 @@ mwifiex_tdls_add_link_ie(struct sk_buff + memcpy(lnkid->resp_sta, peer, ETH_ALEN); + } -- /* Will be cleared in ath9k_start() */ -- common = ath9k_hw_common(sc->sc_ah); -- set_bit(ATH_OP_INVALID, &common->op_flags); -- +-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 + } + + 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) + { +@@ -691,10 +695,10 @@ mwifiex_construct_tdls_action_frame(stru return 0; + } - 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); - } +-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 0; ---- a/net/mac80211/rx.c -+++ b/net/mac80211/rx.c -@@ -1231,7 +1231,8 @@ ieee80211_rx_h_sta_process(struct ieee80 - if (ether_addr_equal(bssid, rx->sdata->u.ibss.bssid) && - test_sta_flag(sta, WLAN_STA_AUTHORIZED)) { - sta->last_rx = jiffies; -- if (ieee80211_is_data(hdr->frame_control)) { -+ if (ieee80211_is_data(hdr->frame_control) && -+ !is_multicast_ether_addr(hdr->addr1)) { - sta->last_rx_rate_idx = status->rate_idx; - sta->last_rx_rate_flag = status->flag; - sta->last_rx_rate_vht_flag = status->vht_flag; ---- a/drivers/net/wireless/ath/ath9k/main.c -+++ b/drivers/net/wireless/ath/ath9k/main.c -@@ -442,6 +442,8 @@ void ath9k_tasklet(unsigned long data) - ath9k_ps_wakeup(sc); - spin_lock(&sc->sc_pcu_lock); + 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 + } -+ sc->intrstatus = 0; -+ - if (status & ATH9K_INT_FATAL) { - type = RESET_TYPE_FATAL_INT; - ath9k_queue_reset(sc, type); -@@ -510,10 +512,12 @@ void ath9k_tasklet(unsigned long data) - if (status & rxmask) { - /* Check for high priority Rx first */ - if ((ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) && -- (status & ATH9K_INT_RXHP)) -- ath_rx_tasklet(sc, 0, true); -+ (status & ATH9K_INT_RXHP) && -+ ath_rx_tasklet(sc, 0, true)) -+ sc->intrstatus |= ATH9K_INT_RXHP; + 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 + } -- ath_rx_tasklet(sc, 0, false); -+ if (ath_rx_tasklet(sc, 0, false)) -+ sc->intrstatus |= ATH9K_INT_RXLP; - } + 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 + } - if (status & ATH9K_INT_TX) { -@@ -541,6 +545,9 @@ void ath9k_tasklet(unsigned long data) + 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; + } - /* re-enable hardware interrupt */ - ath9k_hw_enable_interrupts(ah); -+ if (sc->intrstatus) -+ tasklet_schedule(&sc->intr_tq); +-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; + } + +-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; + +--- 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; + +@@ -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 + } + + /* 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; + +@@ -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); + + 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); + + 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 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); + + /** + * 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; + }; + + /** +@@ -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; + }; + + /** +@@ -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; ++ + char priv[0] __aligned(NETDEV_ALIGN); + }; + +@@ -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); ++ ++/** ++ * 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); ++ + /* 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); + ++#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_ + } + + /** ++ * 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 { + + NL80211_ATTR_IFACE_SOCKET_OWNER, + ++ 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 + } + + 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 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 + } + + 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; + } + ++bool ieee80211_csa_needs_block_tx(struct ieee80211_local *local) ++{ ++ struct ieee80211_sub_if_data *sdata; ++ ++ lockdep_assert_held(&local->mtx); ++ ++ rcu_read_lock(); ++ list_for_each_entry_rcu(sdata, &local->interfaces, list) { ++ if (!ieee80211_sdata_running(sdata)) ++ continue; ++ ++ if (!sdata->vif.csa_active) ++ continue; ++ ++ if (!sdata->csa_block_tx) ++ continue; ++ ++ rcu_read_unlock(); ++ return true; ++ } ++ rcu_read_unlock(); ++ ++ return false; ++} ++ + static int ieee80211_stop_ap(struct wiphy *wiphy, struct net_device *dev) + { + 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); + + /* 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; + +@@ -1425,7 +1457,8 @@ static int sta_apply_parameters(struct i + } + + 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; + } + + err = sta_apply_parameters(local, sta, params); +@@ -1492,7 +1527,7 @@ static int ieee80211_add_station(struct + } + + 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 + } + + 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: + + #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 + } + + 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); + +@@ -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 + } + + 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); + +-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; + +- 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 (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; + } + ++ ++ 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); + +- 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); + +- 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); ++ } + } + + 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; + + sdata_lock(sdata); ++ mutex_lock(&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); + + unlock: ++ mutex_unlock(&local->mtx); + sdata_unlock(sdata); + } + +@@ -3129,9 +3192,25 @@ static int ieee80211_set_csa_beacon(stru + if (params->count <= 1) + break; + +- 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; ++ ++ /* 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)); ++ ++ 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)); ++ + err = ieee80211_assign_beacon(sdata, ¶ms->beacon_csa); + if (err < 0) { + kfree(sdata->u.ap.next_beacon); +@@ -3220,8 +3299,9 @@ static int ieee80211_set_csa_beacon(stru + return 0; + } + +-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); ++ lockdep_assert_held(&local->mtx); + + if (!list_empty(&local->roc_list) || local->scanning) + return -EBUSY; +@@ -3272,15 +3353,16 @@ int ieee80211_channel_switch(struct wiph + return err; + + 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, ¶ms->chandef); +@@ -3292,6 +3374,20 @@ int ieee80211_channel_switch(struct wiph + return 0; + } + ++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; + + 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; ++ } + + IEEE80211_SKB_CB(skb)->flags = flags; + +@@ -3506,320 +3616,6 @@ static int ieee80211_set_rekey_data(stru + return 0; + } + +-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); + } + + static inline struct ieee80211_sub_if_data * +@@ -168,7 +168,8 @@ static inline int drv_change_interface(s + + 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( + { + might_sleep(); + +- check_sdata_in_driver(sdata); ++ if (!check_sdata_in_driver(sdata)) ++ return; + + 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; + +- check_sdata_in_driver(sdata); ++ if (!check_sdata_in_driver(sdata)) ++ return; + + 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(); + + sdata = get_bss_sdata(sdata); +- check_sdata_in_driver(sdata); ++ if (!check_sdata_in_driver(sdata)) ++ return -EIO; + + 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; + + sdata = get_bss_sdata(sdata); +- check_sdata_in_driver(sdata); ++ if (!check_sdata_in_driver(sdata)) ++ return; + + 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_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 + { + 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; + } + +--- 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); + +--- 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; + + 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; + + 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; + ++ ieee80211_bss_info_change_notify(sdata, changed); ++ ++ 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); ++ ++out: + sdata_unlock(sdata); + } + +@@ -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); + + sdata->encrypt_headroom = IEEE80211_ENCRYPT_HEADROOM; +@@ -2045,6 +2062,7 @@ EXPORT_SYMBOL(ieee80211_ap_probereq_get) + + 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]; + +@@ -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; + ++ 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; + ++ if (sdata->vif.csa_active) ++ return; ++ + ieee80211_queue_work(&local->hw, &ifmgd->monitor_work); + } + +--- 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) + + /* 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); + } + +--- 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) + { +- struct ieee80211_local *local = +- container_of(work, struct ieee80211_local, +- sched_scan_stopped_work); +- + mutex_lock(&local->mtx); + + 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); + } + ++void ieee80211_sched_scan_stopped_work(struct work_struct *work) ++{ ++ 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 ++ * Copyright 2014, Intel Corporation ++ * ++ * This file is GPLv2 as found in COPYING. ++ */ ++ ++#include ++#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; ++} ++ ++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) ++{ ++ 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; ++} ++ ++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) + { + 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--; ++ } + + 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(); + } + } + ++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); ++ ++ 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; + + 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); ++ } + + 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; + } + ++ /* 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); + +--- a/net/mac80211/util.c ++++ b/net/mac80211/util.c +@@ -1457,6 +1457,44 @@ void ieee80211_stop_device(struct ieee80 + drv_stop(local); + } + ++static void ieee80211_handle_reconfig_failure(struct ieee80211_local *local) ++{ ++ 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); ++ ++ 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 void ieee80211_assign_chanctx(struct ieee80211_local *local, + struct ieee80211_sub_if_data *sdata) + { +@@ -1520,9 +1558,11 @@ int ieee80211_reconfig(struct ieee80211_ + */ + 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; + } + +--- a/net/wireless/ap.c ++++ b/net/wireless/ap.c +@@ -6,8 +6,8 @@ + #include "rdev-ops.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 + } + } + +-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); + ++static int cfg80211_rfkill_set_block(void *data, bool blocked) ++{ ++ struct cfg80211_registered_device *rdev = data; ++ ++ if (!blocked) ++ return 0; ++ ++ rtnl_lock(); ++ cfg80211_shutdown_all_interfaces(&rdev->wiphy); + rtnl_unlock(); + + return 0; +@@ -401,6 +409,8 @@ struct wiphy *wiphy_new(const struct cfg + rdev->wiphy.rts_threshold = (u32) -1; + rdev->wiphy.coverage_class = 0; + ++ rdev->wiphy.max_num_csa_counters = 1; ++ + return &rdev->wiphy; + } + EXPORT_SYMBOL(wiphy_new); +@@ -697,7 +707,7 @@ void wiphy_unregister(struct wiphy *wiph + rtnl_lock(); + rdev->wiphy.registered = false; + +- BUG_ON(!list_empty(&rdev->wdev_list)); ++ WARN_ON(!list_empty(&rdev->wdev_list)); + + /* + * 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; + } + +-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; + + ASSERT_RTNL(); ++ ASSERT_WDEV_LOCK(wdev); + + 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); + +- 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; + } + } + ++void cfg80211_leave(struct cfg80211_registered_device *rdev, ++ struct wireless_dev *wdev) ++{ ++ wdev_lock(wdev); ++ __cfg80211_leave(rdev, wdev); ++ wdev_unlock(wdev); ++} ++ ++void cfg80211_stop_iface(struct wiphy *wiphy, struct wireless_dev *wdev, ++ gfp_t gfp) ++{ ++ struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy); ++ struct cfg80211_event *ev; ++ unsigned long flags; ++ ++ trace_cfg80211_stop_iface(wiphy, wdev); ++ ++ ev = kzalloc(sizeof(*ev), gfp); ++ if (!ev) ++ return; ++ ++ 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, + }; + + 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); + +--- 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--; + ++ 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; + } + +-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 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 }, + }; + + /* 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; + + err = cfg80211_chandef_dfs_required(wdev->wiphy, &chandef, +- NL80211_IFTYPE_UNSPECIFIED); ++ wdev->iftype); + if (err < 0) + return err; + +@@ -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; + + 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; + +- 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; + +- /* 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; + ++ 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; + +- 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; ++ } + } + + skip_beacons: +@@ -7793,6 +7833,27 @@ static int nl80211_tx_mgmt(struct sk_buf + if (!chandef.chan && params.offchan) + return -EINVAL; + ++ 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 + } + } + +- 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, ¶ms, &cookie); + if (err) +@@ -8507,6 +8566,8 @@ static int nl80211_set_wowlan(struct sk_ + + nla_for_each_nested(pat, tb[NL80211_WOWLAN_TRIG_PKT_PATTERN], + rem) { ++ u8 *mask_pat; ++ + 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 + + 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++; + } + +--- 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_ + } + + 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(¶ms->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) + ); + + 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)) + ); + ++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 */ + + #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); + + 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); + +@@ -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(); ++ } ++ + 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/main.c ++++ b/drivers/net/wireless/ath/ath9k/main.c +@@ -444,6 +444,8 @@ void ath9k_tasklet(unsigned long data) + ath9k_ps_wakeup(sc); + spin_lock(&sc->sc_pcu_lock); + ++ sc->intrstatus = 0; ++ + if (status & ATH9K_INT_FATAL) { + type = RESET_TYPE_FATAL_INT; + ath9k_queue_reset(sc, type); +@@ -512,10 +514,12 @@ void ath9k_tasklet(unsigned long data) + if (status & rxmask) { + /* Check for high priority Rx first */ + if ((ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) && +- (status & ATH9K_INT_RXHP)) +- ath_rx_tasklet(sc, 0, true); ++ (status & ATH9K_INT_RXHP) && ++ ath_rx_tasklet(sc, 0, true)) ++ sc->intrstatus |= ATH9K_INT_RXHP; + +- ath_rx_tasklet(sc, 0, false); ++ if (ath_rx_tasklet(sc, 0, false)) ++ sc->intrstatus |= ATH9K_INT_RXLP; + } + + if (status & ATH9K_INT_TX) { +@@ -543,6 +547,9 @@ void ath9k_tasklet(unsigned long data) + + /* re-enable hardware interrupt */ + ath9k_hw_enable_interrupts(ah); ++ if (sc->intrstatus) ++ tasklet_schedule(&sc->intr_tq); + out: spin_unlock(&sc->sc_pcu_lock); ath9k_ps_restore(sc); -@@ -607,7 +614,7 @@ irqreturn_t ath_isr(int irq, void *dev) +@@ -609,7 +616,7 @@ irqreturn_t ath_isr(int irq, void *dev) return IRQ_NONE; /* Cache the status */ @@ -733,3 +4374,73 @@ Date: Sun Apr 6 23:35:28 2014 +0200 if (status & SCHED_INTR) sched = true; +--- 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 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); + + 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); + } + + /* 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--) +@@ -1135,5 +1137,5 @@ requeue: + ath9k_hw_set_interrupts(ah); + } + +- return 0; ++ return !budget; + } diff --git a/package/kernel/mac80211/patches/310-ap_scan.patch b/package/kernel/mac80211/patches/310-ap_scan.patch index 87f165a5e0..a12e7e5bc7 100644 --- a/package/kernel/mac80211/patches/310-ap_scan.patch +++ b/package/kernel/mac80211/patches/310-ap_scan.patch @@ -1,6 +1,6 @@ --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c -@@ -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) */ diff --git a/package/kernel/mac80211/patches/402-ath9k-fix-invalid-mac-address-handling.patch b/package/kernel/mac80211/patches/402-ath9k-fix-invalid-mac-address-handling.patch index acaa317f76..63ab0dba6e 100644 --- a/package/kernel/mac80211/patches/402-ath9k-fix-invalid-mac-address-handling.patch +++ b/package/kernel/mac80211/patches/402-ath9k-fix-invalid-mac-address-handling.patch @@ -8,7 +8,7 @@ #include #include "hw.h" -@@ -448,8 +449,16 @@ static int ath9k_hw_init_macaddr(struct +@@ -449,8 +450,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/kernel/mac80211/patches/403-ath_regd_optional.patch b/package/kernel/mac80211/patches/403-ath_regd_optional.patch index 4a9b7e48fc..808e729238 100644 --- a/package/kernel/mac80211/patches/403-ath_regd_optional.patch +++ b/package/kernel/mac80211/patches/403-ath_regd_optional.patch @@ -58,7 +58,7 @@ ---help--- --- a/.local-symbols +++ b/.local-symbols -@@ -120,6 +120,7 @@ RTL8187_LEDS= +@@ -116,6 +116,7 @@ RTL8187_LEDS= ATH_COMMON= ATH_CARDS= ATH_DEBUG= diff --git a/package/kernel/mac80211/patches/405-regd_no_assoc_hints.patch b/package/kernel/mac80211/patches/405-regd_no_assoc_hints.patch index 4fa611f206..ef60f9e912 100644 --- a/package/kernel/mac80211/patches/405-regd_no_assoc_hints.patch +++ b/package/kernel/mac80211/patches/405-regd_no_assoc_hints.patch @@ -1,6 +1,6 @@ --- a/net/wireless/reg.c +++ b/net/wireless/reg.c -@@ -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; @@ -9,7 +9,7 @@ /* IE len must be evenly divisible by 2 */ if (country_ie_len & 0x01) return; -@@ -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/kernel/mac80211/patches/410-ath9k_allow_adhoc_and_ap.patch b/package/kernel/mac80211/patches/410-ath9k_allow_adhoc_and_ap.patch index 909a5f104d..ce752f147a 100644 --- a/package/kernel/mac80211/patches/410-ath9k_allow_adhoc_and_ap.patch +++ b/package/kernel/mac80211/patches/410-ath9k_allow_adhoc_and_ap.patch @@ -1,8 +1,8 @@ --- a/drivers/net/wireless/ath/ath9k/init.c +++ b/drivers/net/wireless/ath/ath9k/init.c -@@ -652,6 +652,7 @@ static const struct ieee80211_iface_limi - #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/kernel/mac80211/patches/500-ath9k_eeprom_debugfs.patch b/package/kernel/mac80211/patches/500-ath9k_eeprom_debugfs.patch index 36e01511ad..65821feb82 100644 --- a/package/kernel/mac80211/patches/500-ath9k_eeprom_debugfs.patch +++ b/package/kernel/mac80211/patches/500-ath9k_eeprom_debugfs.patch @@ -1,6 +1,6 @@ --- a/drivers/net/wireless/ath/ath9k/debug.c +++ b/drivers/net/wireless/ath/ath9k/debug.c -@@ -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); } @@ -54,7 +54,7 @@ int ath9k_init_debug(struct ath_hw *ah) { struct ath_common *common = ath9k_hw_common(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); diff --git a/package/kernel/mac80211/patches/502-ath9k_ahb_init.patch b/package/kernel/mac80211/patches/502-ath9k_ahb_init.patch index de61a9ed7d..0c8e813a37 100644 --- a/package/kernel/mac80211/patches/502-ath9k_ahb_init.patch +++ b/package/kernel/mac80211/patches/502-ath9k_ahb_init.patch @@ -1,6 +1,6 @@ --- a/drivers/net/wireless/ath/ath9k/init.c +++ b/drivers/net/wireless/ath/ath9k/init.c -@@ -897,23 +897,23 @@ static int __init ath9k_init(void) +@@ -904,23 +904,23 @@ static int __init ath9k_init(void) { int error; diff --git a/package/kernel/mac80211/patches/510-ath9k_intr_mitigation_tweak.patch b/package/kernel/mac80211/patches/510-ath9k_intr_mitigation_tweak.patch index c8189333d2..d7478ff590 100644 --- a/package/kernel/mac80211/patches/510-ath9k_intr_mitigation_tweak.patch +++ b/package/kernel/mac80211/patches/510-ath9k_intr_mitigation_tweak.patch @@ -1,6 +1,6 @@ --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c -@@ -358,13 +358,8 @@ static void ath9k_hw_init_config(struct +@@ -359,13 +359,8 @@ static void ath9k_hw_init_config(struct ah->config.rx_intr_mitigation = true; diff --git a/package/kernel/mac80211/patches/512-ath9k_channelbw_debugfs.patch b/package/kernel/mac80211/patches/512-ath9k_channelbw_debugfs.patch index 665d8aa64d..c0e173f1eb 100644 --- a/package/kernel/mac80211/patches/512-ath9k_channelbw_debugfs.patch +++ b/package/kernel/mac80211/patches/512-ath9k_channelbw_debugfs.patch @@ -1,6 +1,6 @@ --- a/drivers/net/wireless/ath/ath9k/debug.c +++ b/drivers/net/wireless/ath/ath9k/debug.c -@@ -1532,6 +1532,52 @@ static const struct file_operations fops +@@ -1336,6 +1336,52 @@ static const struct file_operations fops .owner = THIS_MODULE }; @@ -53,7 +53,7 @@ int ath9k_init_debug(struct ath_hw *ah) { struct ath_common *common = ath9k_hw_common(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); diff --git a/package/kernel/mac80211/patches/513-ath9k_add_pci_ids.patch b/package/kernel/mac80211/patches/513-ath9k_add_pci_ids.patch index 540198f01c..db4e6a1238 100644 --- a/package/kernel/mac80211/patches/513-ath9k_add_pci_ids.patch +++ b/package/kernel/mac80211/patches/513-ath9k_add_pci_ids.patch @@ -1,6 +1,6 @@ --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c -@@ -613,6 +613,7 @@ int ath9k_hw_init(struct ath_hw *ah) +@@ -614,6 +614,7 @@ int ath9k_hw_init(struct ath_hw *ah) /* These are all the AR5008/AR9001/AR9002/AR9003 hardware family of chipsets */ switch (ah->hw_version.devid) { diff --git a/package/kernel/mac80211/patches/520-mac80211_cur_txpower.patch b/package/kernel/mac80211/patches/520-mac80211_cur_txpower.patch index cb3f852498..b79a3c4432 100644 --- a/package/kernel/mac80211/patches/520-mac80211_cur_txpower.patch +++ b/package/kernel/mac80211/patches/520-mac80211_cur_txpower.patch @@ -1,6 +1,6 @@ --- a/include/net/mac80211.h +++ b/include/net/mac80211.h -@@ -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; @@ -10,7 +10,7 @@ u8 uapsd_queues; --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c -@@ -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); @@ -23,7 +23,7 @@ *dbm = sdata->vif.bss_conf.txpower; --- a/net/mac80211/main.c +++ b/net/mac80211/main.c -@@ -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/kernel/mac80211/patches/521-ath9k_cur_txpower.patch b/package/kernel/mac80211/patches/521-ath9k_cur_txpower.patch index ebc3633f60..d4d2989f6b 100644 --- a/package/kernel/mac80211/patches/521-ath9k_cur_txpower.patch +++ b/package/kernel/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); -@@ -1377,6 +1381,7 @@ static int ath9k_config(struct ieee80211 +@@ -1411,6 +1415,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/kernel/mac80211/patches/522-mac80211_configure_antenna_gain.patch b/package/kernel/mac80211/patches/522-mac80211_configure_antenna_gain.patch index 611f76326d..6ad04aca33 100644 --- a/package/kernel/mac80211/patches/522-mac80211_configure_antenna_gain.patch +++ b/package/kernel/mac80211/patches/522-mac80211_configure_antenna_gain.patch @@ -1,6 +1,6 @@ --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h -@@ -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 @@ -8,7 +8,7 @@ * * @set_wds_peer: set the WDS peer for a WDS interface * -@@ -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); @@ -36,9 +36,9 @@ u8 ps_dtim_period; --- a/include/uapi/linux/nl80211.h +++ b/include/uapi/linux/nl80211.h -@@ -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. @@ -46,9 +46,9 @@ * @NL80211_ATTR_MAX: highest attribute number currently defined * @__NL80211_ATTR_AFTER_LAST: internal use */ -@@ -1914,6 +1917,8 @@ enum nl80211_attrs { - - 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, + @@ -57,7 +57,7 @@ __NL80211_ATTR_AFTER_LAST, --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c -@@ -2345,6 +2345,19 @@ static int ieee80211_get_tx_power(struct +@@ -2388,6 +2388,19 @@ static int ieee80211_get_tx_power(struct return 0; } @@ -77,7 +77,7 @@ static int ieee80211_set_wds_peer(struct wiphy *wiphy, struct net_device *dev, const u8 *addr) { -@@ -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, @@ -87,7 +87,7 @@ CFG80211_TESTMODE_CMD(ieee80211_testmode_cmd) --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h -@@ -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 */ @@ -97,7 +97,7 @@ --- 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; @@ -106,7 +106,7 @@ u32 offchannel_flag; offchannel_flag = local->hw.conf.flags & IEEE80211_CONF_OFFCHANNEL; -@@ -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(); @@ -119,7 +119,7 @@ if (local->hw.conf.power_level != power) { changed |= IEEE80211_CONF_CHANGE_POWER; local->hw.cur_power_level = power; -@@ -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; @@ -129,15 +129,15 @@ local->user_power_level = IEEE80211_UNSET_POWER_LEVEL; --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c -@@ -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 */ -@@ -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; } diff --git a/package/kernel/mac80211/patches/523-ath9k_use_configured_antenna_gain.patch b/package/kernel/mac80211/patches/523-ath9k_use_configured_antenna_gain.patch index 2903bd9d14..2ea3fe08b9 100644 --- a/package/kernel/mac80211/patches/523-ath9k_use_configured_antenna_gain.patch +++ b/package/kernel/mac80211/patches/523-ath9k_use_configured_antenna_gain.patch @@ -10,7 +10,7 @@ --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c -@@ -2720,7 +2720,7 @@ void ath9k_hw_apply_txpower(struct ath_h +@@ -2721,7 +2721,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 -@@ -1377,7 +1377,10 @@ static int ath9k_config(struct ieee80211 +@@ -1411,7 +1411,10 @@ static int ath9k_config(struct ieee80211 } if (changed & IEEE80211_CONF_CHANGE_POWER) { diff --git a/package/kernel/mac80211/patches/530-ath9k_extra_leds.patch b/package/kernel/mac80211/patches/530-ath9k_extra_leds.patch index c78a3e55fb..4cf0700951 100644 --- a/package/kernel/mac80211/patches/530-ath9k_extra_leds.patch +++ b/package/kernel/mac80211/patches/530-ath9k_extra_leds.patch @@ -1,6 +1,6 @@ --- a/drivers/net/wireless/ath/ath9k/ath9k.h +++ b/drivers/net/wireless/ath/ath9k/ath9k.h -@@ -554,6 +554,9 @@ static inline int ath9k_dump_btcoex(stru +@@ -563,6 +563,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) { -@@ -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) @@ -24,7 +24,7 @@ struct ath_softc { struct ieee80211_hw *hw; struct device *dev; -@@ -731,9 +741,8 @@ struct ath_softc { +@@ -743,9 +753,8 @@ struct ath_softc { struct ath_beacon beacon; #ifdef CPTCFG_MAC80211_LEDS @@ -162,7 +162,7 @@ void ath_fill_led_pin(struct ath_softc *sc) --- a/drivers/net/wireless/ath/ath9k/init.c +++ b/drivers/net/wireless/ath/ath9k/init.c -@@ -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 */ @@ -173,7 +173,7 @@ #endif --- a/drivers/net/wireless/ath/ath9k/debug.c +++ b/drivers/net/wireless/ath/ath9k/debug.c -@@ -1577,6 +1577,61 @@ static const struct file_operations fops +@@ -1381,6 +1381,61 @@ static const struct file_operations fops .llseek = default_llseek, }; @@ -235,7 +235,7 @@ 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/kernel/mac80211/patches/531-ath9k_extra_platform_leds.patch b/package/kernel/mac80211/patches/531-ath9k_extra_platform_leds.patch index 6c9832c4a0..718a3d0cd4 100644 --- a/package/kernel/mac80211/patches/531-ath9k_extra_platform_leds.patch +++ b/package/kernel/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/kernel/mac80211/patches/542-ath9k_debugfs_diag.patch b/package/kernel/mac80211/patches/542-ath9k_debugfs_diag.patch index 419717ae0a..3db34bb8b9 100644 --- a/package/kernel/mac80211/patches/542-ath9k_debugfs_diag.patch +++ b/package/kernel/mac80211/patches/542-ath9k_debugfs_diag.patch @@ -1,6 +1,6 @@ --- a/drivers/net/wireless/ath/ath9k/debug.c +++ b/drivers/net/wireless/ath/ath9k/debug.c -@@ -1633,6 +1633,50 @@ static const struct file_operations fops +@@ -1437,6 +1437,50 @@ static const struct file_operations fops #endif @@ -51,7 +51,7 @@ int ath9k_init_debug(struct ath_hw *ah) { struct ath_common *common = ath9k_hw_common(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 -@@ -1734,6 +1734,20 @@ fail: +@@ -1735,6 +1735,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) { -@@ -1939,6 +1953,7 @@ int ath9k_hw_reset(struct ath_hw *ah, st +@@ -1940,6 +1954,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 -@@ -610,6 +610,11 @@ irqreturn_t ath_isr(int irq, void *dev) +@@ -612,6 +612,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/kernel/mac80211/patches/543-ath9k-allow-to-disable-bands-via-platform-data.patch b/package/kernel/mac80211/patches/543-ath9k-allow-to-disable-bands-via-platform-data.patch index e2e18c91a2..0501582272 100644 --- a/package/kernel/mac80211/patches/543-ath9k-allow-to-disable-bands-via-platform-data.patch +++ b/package/kernel/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 -@@ -2327,17 +2327,25 @@ int ath9k_hw_fill_cap_info(struct ath_hw +@@ -2328,17 +2328,25 @@ int ath9k_hw_fill_cap_info(struct ath_hw } eeval = ah->eep_ops->get_eeprom(ah, EEP_OP_MODE); diff --git a/package/kernel/mac80211/patches/550-ath9k_entropy_from_adc.patch b/package/kernel/mac80211/patches/550-ath9k_entropy_from_adc.patch index 439a574352..7210a021bd 100644 --- a/package/kernel/mac80211/patches/550-ath9k_entropy_from_adc.patch +++ b/package/kernel/mac80211/patches/550-ath9k_entropy_from_adc.patch @@ -55,7 +55,7 @@ ops->spectral_scan_config = ar9003_hw_spectral_scan_config; --- a/drivers/net/wireless/ath/ath9k/init.c +++ b/drivers/net/wireless/ath/ath9k/init.c -@@ -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); @@ -65,7 +65,7 @@ } 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); } @@ -84,7 +84,7 @@ int ath9k_init_device(u16 devid, struct ath_softc *sc, const struct ath_bus_ops *bus_ops) { -@@ -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 diff --git a/package/kernel/mac80211/patches/551-ath9k-ar933x-usb-hang-workaround.patch b/package/kernel/mac80211/patches/551-ath9k-ar933x-usb-hang-workaround.patch new file mode 100644 index 0000000000..10280d97ae --- /dev/null +++ b/package/kernel/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/kernel/mac80211/patches/551-ath9k_p2p_ifcomb.patch b/package/kernel/mac80211/patches/551-ath9k_p2p_ifcomb.patch deleted file mode 100644 index 579a633077..0000000000 --- a/package/kernel/mac80211/patches/551-ath9k_p2p_ifcomb.patch +++ /dev/null @@ -1,33 +0,0 @@ -From c997a1da25fe7c717ed099888b8eb35d4e139e70 Mon Sep 17 00:00:00 2001 -From: Felix Fietkau -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 ---- - 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 -@@ -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) | -- 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/kernel/mac80211/patches/552-ath9k_p2p_ps_support.patch b/package/kernel/mac80211/patches/552-ath9k_p2p_ps_support.patch deleted file mode 100644 index 3b09aef608..0000000000 --- a/package/kernel/mac80211/patches/552-ath9k_p2p_ps_support.patch +++ /dev/null @@ -1,249 +0,0 @@ -From 6744d0a7ea037c7d65e13ca906da93009b241d00 Mon Sep 17 00:00:00 2001 -From: Felix Fietkau -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 ---- - 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; - } - -@@ -1135,6 +1137,8 @@ static int ath9k_add_interface(struct ie - if (ath9k_uses_beacons(vif->type)) - ath9k_beacon_assign_slot(sc, vif); - -+ avp->vif = vif; -+ - an->sc = sc; - an->sta = NULL; - an->vif = vif; -@@ -1179,6 +1183,29 @@ static int ath9k_change_interface(struct - 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) - { -@@ -1190,6 +1217,13 @@ static void ath9k_remove_interface(struc - - 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; - -@@ -1656,6 +1690,72 @@ static void ath9k_bss_assoc_iter(void *d - 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; -+ unsigned long flags; -+ u32 tsf; -+ -+ if (!sc->p2p_ps_timer) -+ return; -+ -+ if (vif->type != NL80211_IFTYPE_STATION || !vif->p2p) -+ return; -+ -+ sc->p2p_ps_vif = 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, -@@ -1730,6 +1830,12 @@ static void ath9k_bss_info_changed(struc - } - } - -+ 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 -@@ -114,6 +114,9 @@ int ath_descdma_setup(struct ath_softc * - #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 -@@ -366,11 +369,15 @@ void ath9k_release_buffered_frames(struc - /********/ - - 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 { -@@ -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); -+void ath9k_p2p_ps_timer(void *priv); -+void ath9k_update_p2p_ps(struct ath_softc *sc, struct ieee80211_vif *vif); - - /**********/ - /* BTCOEX */ -@@ -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; -+ - unsigned long driver_data; - - u8 gtt_cnt; ---- a/drivers/net/wireless/ath/ath9k/init.c -+++ b/drivers/net/wireless/ath/ath9k/init.c -@@ -593,6 +593,9 @@ static int ath9k_init_softc(u16 devid, s - 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); -@@ -875,6 +878,9 @@ static void ath9k_deinit_softc(struct at - { - 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 -@@ -542,6 +542,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/kernel/mac80211/patches/566-ath9k-ar933x-usb-hang-workaround.patch b/package/kernel/mac80211/patches/566-ath9k-ar933x-usb-hang-workaround.patch deleted file mode 100644 index eddbc6c06e..0000000000 --- a/package/kernel/mac80211/patches/566-ath9k-ar933x-usb-hang-workaround.patch +++ /dev/null @@ -1,79 +0,0 @@ ---- a/drivers/net/wireless/ath/ath9k/hw.c -+++ b/drivers/net/wireless/ath/ath9k/hw.c -@@ -216,6 +216,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 */ - /******************/ -@@ -1336,6 +1349,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; - } - -@@ -1435,6 +1451,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; - } - -@@ -1729,8 +1748,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; - } - -@@ -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); - -+ 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/kernel/mac80211/patches/567-ath9k_ar953x_read_mac_rev.patch b/package/kernel/mac80211/patches/567-ath9k_ar953x_read_mac_rev.patch deleted file mode 100644 index 31778a4a21..0000000000 --- a/package/kernel/mac80211/patches/567-ath9k_ar953x_read_mac_rev.patch +++ /dev/null @@ -1,11 +0,0 @@ ---- 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/kernel/mac80211/patches/570-restrict_dfs_regions.patch b/package/kernel/mac80211/patches/570-restrict_dfs_regions.patch deleted file mode 100644 index 10157dc008..0000000000 --- a/package/kernel/mac80211/patches/570-restrict_dfs_regions.patch +++ /dev/null @@ -1,82 +0,0 @@ ---- 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 diff --git a/package/kernel/mac80211/patches/600-0002-rt2x00-rt2800lib-introduce-RT2800_HAS_HIGH_SHARED_ME.patch b/package/kernel/mac80211/patches/600-0002-rt2x00-rt2800lib-introduce-RT2800_HAS_HIGH_SHARED_ME.patch index 3b11b155c1..98c9203f13 100644 --- a/package/kernel/mac80211/patches/600-0002-rt2x00-rt2800lib-introduce-RT2800_HAS_HIGH_SHARED_ME.patch +++ b/package/kernel/mac80211/patches/600-0002-rt2x00-rt2800lib-introduce-RT2800_HAS_HIGH_SHARED_ME.patch @@ -24,7 +24,7 @@ Changes since v1: --- a/drivers/net/wireless/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/rt2x00/rt2800lib.c -@@ -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) { @@ -32,7 +32,7 @@ Changes since v1: 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; diff --git a/package/kernel/mac80211/patches/600-0003-rt2x00-rt2800-serialize-shared-memory-access.patch b/package/kernel/mac80211/patches/600-0003-rt2x00-rt2800-serialize-shared-memory-access.patch index 879b4cc9e7..97e213fb52 100644 --- a/package/kernel/mac80211/patches/600-0003-rt2x00-rt2800-serialize-shared-memory-access.patch +++ b/package/kernel/mac80211/patches/600-0003-rt2x00-rt2800-serialize-shared-memory-access.patch @@ -79,8 +79,8 @@ Changes since v1: --- + 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); @@ -89,7 +89,7 @@ Changes since v1: --- /* * 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); @@ -98,7 +98,7 @@ Changes since v1: --- } 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); @@ -108,7 +108,7 @@ Changes since v1: --- } 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. */ @@ -122,7 +122,7 @@ Changes since v1: --- } 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); @@ -130,7 +130,7 @@ Changes since v1: --- if (crypto->cmd == SET_KEY) { rt2800_register_read(rt2x00dev, offset, ®); rt2x00_set_field32(®, 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(®, MAC_WCID_ATTRIBUTE_RX_WIUDF, 0); rt2800_register_write(rt2x00dev, offset, reg); } @@ -138,7 +138,7 @@ Changes since v1: --- 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; @@ -150,7 +150,7 @@ Changes since v1: --- } 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); @@ -162,7 +162,7 @@ Changes since v1: --- } /* -@@ -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); @@ -175,7 +175,7 @@ Changes since v1: --- /* * 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); @@ -187,7 +187,7 @@ Changes since v1: --- } /* -@@ -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. */ @@ -207,7 +207,7 @@ Changes since v1: --- } /* -@@ -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. */ @@ -218,7 +218,7 @@ Changes since v1: --- 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. */ @@ -239,7 +239,7 @@ Changes since v1: --- 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; @@ -248,7 +248,7 @@ Changes since v1: --- 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); @@ -372,7 +372,7 @@ Changes since v1: --- #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++) { @@ -382,7 +382,7 @@ Changes since v1: --- 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"); diff --git a/package/kernel/mac80211/patches/600-0004-rt2x00-rt2800lib-fix-beacon-generation-on-RT3593.patch b/package/kernel/mac80211/patches/600-0004-rt2x00-rt2800lib-fix-beacon-generation-on-RT3593.patch index 38dbb439fc..5cb6eaec6b 100644 --- a/package/kernel/mac80211/patches/600-0004-rt2x00-rt2800lib-fix-beacon-generation-on-RT3593.patch +++ b/package/kernel/mac80211/patches/600-0004-rt2x00-rt2800lib-fix-beacon-generation-on-RT3593.patch @@ -111,7 +111,7 @@ Changes since v1: --- 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); @@ -120,7 +120,7 @@ Changes since v1: --- /* * 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); diff --git a/package/kernel/mac80211/patches/600-0005-rt2x00-rt2800lib-add-hw_beacon_count-field-to-struct.patch b/package/kernel/mac80211/patches/600-0005-rt2x00-rt2800lib-add-hw_beacon_count-field-to-struct.patch index 3d971691e4..d832f99404 100644 --- a/package/kernel/mac80211/patches/600-0005-rt2x00-rt2800lib-add-hw_beacon_count-field-to-struct.patch +++ b/package/kernel/mac80211/patches/600-0005-rt2x00-rt2800lib-add-hw_beacon_count-field-to-struct.patch @@ -24,7 +24,7 @@ Signed-off-by: Gabor Juhos --- 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) { @@ -32,7 +32,7 @@ Signed-off-by: Gabor Juhos 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 */ @@ -41,7 +41,7 @@ Signed-off-by: Gabor Juhos 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); diff --git a/package/kernel/mac80211/patches/600-0006-rt2x00-rt2800lib-init-additional-beacon-offset-regis.patch b/package/kernel/mac80211/patches/600-0006-rt2x00-rt2800lib-init-additional-beacon-offset-regis.patch index 8c527134f9..040c69c928 100644 --- a/package/kernel/mac80211/patches/600-0006-rt2x00-rt2800lib-init-additional-beacon-offset-regis.patch +++ b/package/kernel/mac80211/patches/600-0006-rt2x00-rt2800lib-init-additional-beacon-offset-regis.patch @@ -34,7 +34,7 @@ Signed-off-by: Gabor Juhos */ --- 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); diff --git a/package/kernel/mac80211/patches/600-0007-rt2x00-rt2800lib-fix-max-supported-beacon-count-for-.patch b/package/kernel/mac80211/patches/600-0007-rt2x00-rt2800lib-fix-max-supported-beacon-count-for-.patch index 66e82453d1..752cd89315 100644 --- a/package/kernel/mac80211/patches/600-0007-rt2x00-rt2800lib-fix-max-supported-beacon-count-for-.patch +++ b/package/kernel/mac80211/patches/600-0007-rt2x00-rt2800lib-fix-max-supported-beacon-count-for-.patch @@ -10,7 +10,7 @@ Signed-off-by: Gabor Juhos --- 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); diff --git a/package/kernel/mac80211/patches/600-0009-rt2x00-rt2800lib-enable-support-for-RT3883.patch b/package/kernel/mac80211/patches/600-0009-rt2x00-rt2800lib-enable-support-for-RT3883.patch index e9d847aad3..8cb93ecb60 100644 --- a/package/kernel/mac80211/patches/600-0009-rt2x00-rt2800lib-enable-support-for-RT3883.patch +++ b/package/kernel/mac80211/patches/600-0009-rt2x00-rt2800lib-enable-support-for-RT3883.patch @@ -10,7 +10,7 @@ Signed-off-by: Gabor Juhos --- 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: diff --git a/package/kernel/mac80211/patches/600-0010-rt2x00-rt2800lib-add-rf_vals-for-RF3853.patch b/package/kernel/mac80211/patches/600-0010-rt2x00-rt2800lib-add-rf_vals-for-RF3853.patch index b096f9f782..e85ae979cc 100644 --- a/package/kernel/mac80211/patches/600-0010-rt2x00-rt2800lib-add-rf_vals-for-RF3853.patch +++ b/package/kernel/mac80211/patches/600-0010-rt2x00-rt2800lib-add-rf_vals-for-RF3853.patch @@ -31,7 +31,7 @@ Signed-off-by: Gabor Juhos #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}, }; @@ -98,7 +98,7 @@ Signed-off-by: Gabor Juhos 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; diff --git a/package/kernel/mac80211/patches/600-0011-rt2x00-rt2800lib-enable-VCO-calibration-for-RF3853.patch b/package/kernel/mac80211/patches/600-0011-rt2x00-rt2800lib-enable-VCO-calibration-for-RF3853.patch index 4c9a3b4451..898e38597a 100644 --- a/package/kernel/mac80211/patches/600-0011-rt2x00-rt2800lib-enable-VCO-calibration-for-RF3853.patch +++ b/package/kernel/mac80211/patches/600-0011-rt2x00-rt2800lib-enable-VCO-calibration-for-RF3853.patch @@ -10,7 +10,7 @@ Signed-off-by: Gabor Juhos --- 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: @@ -18,7 +18,7 @@ Signed-off-by: Gabor Juhos 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: diff --git a/package/kernel/mac80211/patches/600-0012-rt2x00-rt2800lib-add-channel-configuration-function-.patch b/package/kernel/mac80211/patches/600-0012-rt2x00-rt2800lib-add-channel-configuration-function-.patch index e3460ff929..1de99ea1a9 100644 --- a/package/kernel/mac80211/patches/600-0012-rt2x00-rt2800lib-add-channel-configuration-function-.patch +++ b/package/kernel/mac80211/patches/600-0012-rt2x00-rt2800lib-add-channel-configuration-function-.patch @@ -11,7 +11,7 @@ Signed-off-by: Gabor Juhos --- 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 } } @@ -223,7 +223,7 @@ Signed-off-by: Gabor Juhos #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; diff --git a/package/kernel/mac80211/patches/600-0013-rt2x00-rt2800lib-enable-RF3853-support.patch b/package/kernel/mac80211/patches/600-0013-rt2x00-rt2800lib-enable-RF3853-support.patch index 87194251ab..e7e17a949e 100644 --- a/package/kernel/mac80211/patches/600-0013-rt2x00-rt2800lib-enable-RF3853-support.patch +++ b/package/kernel/mac80211/patches/600-0013-rt2x00-rt2800lib-enable-RF3853-support.patch @@ -10,7 +10,7 @@ Signed-off-by: Gabor Juhos --- 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: diff --git a/package/kernel/mac80211/patches/600-0014-rt2x00-rt2800lib-add-MAC-register-initialization-for.patch b/package/kernel/mac80211/patches/600-0014-rt2x00-rt2800lib-add-MAC-register-initialization-for.patch index 8632ddda97..95423d1755 100644 --- a/package/kernel/mac80211/patches/600-0014-rt2x00-rt2800lib-add-MAC-register-initialization-for.patch +++ b/package/kernel/mac80211/patches/600-0014-rt2x00-rt2800lib-add-MAC-register-initialization-for.patch @@ -35,7 +35,7 @@ Signed-off-by: Gabor Juhos #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); } @@ -48,7 +48,7 @@ Signed-off-by: Gabor Juhos } 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, ®); rt2x00_set_field32(®, MAX_LEN_CFG_MAX_MPDU, AGGREGATION_SIZE); @@ -63,7 +63,7 @@ Signed-off-by: Gabor Juhos rt2x00_set_field32(®, MAX_LEN_CFG_MAX_PSDU, 2); else rt2x00_set_field32(®, 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); diff --git a/package/kernel/mac80211/patches/600-0016-rt2x00-rt2800lib-add-BBP-register-initialization-for.patch b/package/kernel/mac80211/patches/600-0016-rt2x00-rt2800lib-add-BBP-register-initialization-for.patch index 967e36ac51..d9694da40d 100644 --- a/package/kernel/mac80211/patches/600-0016-rt2x00-rt2800lib-add-BBP-register-initialization-for.patch +++ b/package/kernel/mac80211/patches/600-0016-rt2x00-rt2800lib-add-BBP-register-initialization-for.patch @@ -11,7 +11,7 @@ Signed-off-by: Gabor Juhos --- 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); } @@ -59,7 +59,7 @@ Signed-off-by: Gabor Juhos 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; diff --git a/package/kernel/mac80211/patches/600-0017-rt2x00-rt2800lib-add-RFCSR-initialization-for-RT3883.patch b/package/kernel/mac80211/patches/600-0017-rt2x00-rt2800lib-add-RFCSR-initialization-for-RT3883.patch index c568b995f0..dc45109afa 100644 --- a/package/kernel/mac80211/patches/600-0017-rt2x00-rt2800lib-add-RFCSR-initialization-for-RT3883.patch +++ b/package/kernel/mac80211/patches/600-0017-rt2x00-rt2800lib-add-RFCSR-initialization-for-RT3883.patch @@ -21,7 +21,7 @@ Signed-off-by: Gabor Juhos /* --- 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 */ } @@ -166,7 +166,7 @@ Signed-off-by: Gabor Juhos 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; diff --git a/package/kernel/mac80211/patches/600-0019-rt2x00-rt2800lib-force-rf-type-to-RF3853-on-RT3883.patch b/package/kernel/mac80211/patches/600-0019-rt2x00-rt2800lib-force-rf-type-to-RF3853-on-RT3883.patch index 47eece0b7f..4bfe8e16d1 100644 --- a/package/kernel/mac80211/patches/600-0019-rt2x00-rt2800lib-force-rf-type-to-RF3853-on-RT3883.patch +++ b/package/kernel/mac80211/patches/600-0019-rt2x00-rt2800lib-force-rf-type-to-RF3853-on-RT3883.patch @@ -10,7 +10,7 @@ Signed-off-by: Gabor Juhos --- 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); diff --git a/package/kernel/mac80211/patches/600-0020-rt2x00-rt2800lib-add-channel-configuration-code-for-.patch b/package/kernel/mac80211/patches/600-0020-rt2x00-rt2800lib-add-channel-configuration-code-for-.patch index d9cbb33c7b..59b74adbe7 100644 --- a/package/kernel/mac80211/patches/600-0020-rt2x00-rt2800lib-add-channel-configuration-code-for-.patch +++ b/package/kernel/mac80211/patches/600-0020-rt2x00-rt2800lib-add-channel-configuration-code-for-.patch @@ -10,7 +10,7 @@ Signed-off-by: Gabor Juhos --- 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); } @@ -47,7 +47,7 @@ Signed-off-by: Gabor Juhos 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); @@ -60,7 +60,7 @@ Signed-off-by: Gabor Juhos 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); @@ -76,7 +76,7 @@ Signed-off-by: Gabor Juhos } 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); @@ -84,7 +84,7 @@ Signed-off-by: Gabor Juhos 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); } @@ -110,13 +110,10 @@ Signed-off-by: Gabor Juhos 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); @@ -131,6 +128,9 @@ Signed-off-by: Gabor Juhos + + 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/kernel/mac80211/patches/600-0021-rt2x00-rt2800lib-fix-txpower_to_dev-function-for-RT3.patch b/package/kernel/mac80211/patches/600-0021-rt2x00-rt2800lib-fix-txpower_to_dev-function-for-RT3.patch index c927e458d2..e88a7c6f60 100644 --- a/package/kernel/mac80211/patches/600-0021-rt2x00-rt2800lib-fix-txpower_to_dev-function-for-RT3.patch +++ b/package/kernel/mac80211/patches/600-0021-rt2x00-rt2800lib-fix-txpower_to_dev-function-for-RT3.patch @@ -10,7 +10,7 @@ Signed-off-by: Gabor Juhos --- 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) { diff --git a/package/kernel/mac80211/patches/600-0022-rt2x00-rt2800lib-use-correct-txpower-calculation-fun.patch b/package/kernel/mac80211/patches/600-0022-rt2x00-rt2800lib-use-correct-txpower-calculation-fun.patch index df826e5f5d..95484a0ca3 100644 --- a/package/kernel/mac80211/patches/600-0022-rt2x00-rt2800lib-use-correct-txpower-calculation-fun.patch +++ b/package/kernel/mac80211/patches/600-0022-rt2x00-rt2800lib-use-correct-txpower-calculation-fun.patch @@ -11,7 +11,7 @@ Signed-off-by: Gabor Juhos --- 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) { diff --git a/package/kernel/mac80211/patches/600-0023-rt2x00-rt2800lib-hardcode-txmixer-gain-values-to-zer.patch b/package/kernel/mac80211/patches/600-0023-rt2x00-rt2800lib-hardcode-txmixer-gain-values-to-zer.patch index 8a43df26b0..c57af608e4 100644 --- a/package/kernel/mac80211/patches/600-0023-rt2x00-rt2800lib-hardcode-txmixer-gain-values-to-zer.patch +++ b/package/kernel/mac80211/patches/600-0023-rt2x00-rt2800lib-hardcode-txmixer-gain-values-to-zer.patch @@ -11,7 +11,7 @@ Signed-off-by: Gabor Juhos --- 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; @@ -21,7 +21,7 @@ Signed-off-by: Gabor Juhos 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; diff --git a/package/kernel/mac80211/patches/600-0026-rt2x00-rt2800lib-use-correct-beacon-count-for-RT3883.patch b/package/kernel/mac80211/patches/600-0026-rt2x00-rt2800lib-use-correct-beacon-count-for-RT3883.patch index cb7a0ae9c0..f606ed4b0d 100644 --- a/package/kernel/mac80211/patches/600-0026-rt2x00-rt2800lib-use-correct-beacon-count-for-RT3883.patch +++ b/package/kernel/mac80211/patches/600-0026-rt2x00-rt2800lib-use-correct-beacon-count-for-RT3883.patch @@ -10,7 +10,7 @@ Signed-off-by: Gabor Juhos --- 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); diff --git a/package/kernel/mac80211/patches/600-0027-rt2x00-rt2800lib-fix-antenna-configuration-for-RT388.patch b/package/kernel/mac80211/patches/600-0027-rt2x00-rt2800lib-fix-antenna-configuration-for-RT388.patch index 0919f90c4b..4096493e0f 100644 --- a/package/kernel/mac80211/patches/600-0027-rt2x00-rt2800lib-fix-antenna-configuration-for-RT388.patch +++ b/package/kernel/mac80211/patches/600-0027-rt2x00-rt2800lib-fix-antenna-configuration-for-RT388.patch @@ -10,7 +10,7 @@ Signed-off-by: Gabor Juhos --- 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); diff --git a/package/kernel/mac80211/patches/600-0028-rt2x00-rt2800lib-fix-LNA-gain-configuration-for-RT38.patch b/package/kernel/mac80211/patches/600-0028-rt2x00-rt2800lib-fix-LNA-gain-configuration-for-RT38.patch index e38ba78b4c..2fc9d9d23a 100644 --- a/package/kernel/mac80211/patches/600-0028-rt2x00-rt2800lib-fix-LNA-gain-configuration-for-RT38.patch +++ b/package/kernel/mac80211/patches/600-0028-rt2x00-rt2800lib-fix-LNA-gain-configuration-for-RT38.patch @@ -10,7 +10,7 @@ Signed-off-by: Gabor Juhos --- 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) { @@ -20,7 +20,7 @@ Signed-off-by: Gabor Juhos 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 { diff --git a/package/kernel/mac80211/patches/600-0029-rt2x00-rt2800lib-fix-VGC-setup-for-RT3883.patch b/package/kernel/mac80211/patches/600-0029-rt2x00-rt2800lib-fix-VGC-setup-for-RT3883.patch index 4684599bcc..060d4c6465 100644 --- a/package/kernel/mac80211/patches/600-0029-rt2x00-rt2800lib-fix-VGC-setup-for-RT3883.patch +++ b/package/kernel/mac80211/patches/600-0029-rt2x00-rt2800lib-fix-VGC-setup-for-RT3883.patch @@ -10,7 +10,7 @@ Signed-off-by: Gabor Juhos --- 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 */ @@ -20,7 +20,7 @@ Signed-off-by: Gabor Juhos 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) || @@ -30,7 +30,7 @@ Signed-off-by: Gabor Juhos 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; diff --git a/package/kernel/mac80211/patches/600-0030-rt2x00-rt2800lib-fix-EEPROM-LNA-validation-for-RT388.patch b/package/kernel/mac80211/patches/600-0030-rt2x00-rt2800lib-fix-EEPROM-LNA-validation-for-RT388.patch index bc1548d8c0..3e9a7d9ad3 100644 --- a/package/kernel/mac80211/patches/600-0030-rt2x00-rt2800lib-fix-EEPROM-LNA-validation-for-RT388.patch +++ b/package/kernel/mac80211/patches/600-0030-rt2x00-rt2800lib-fix-EEPROM-LNA-validation-for-RT388.patch @@ -10,7 +10,7 @@ Signed-off-by: Gabor Juhos --- 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); @@ -20,7 +20,7 @@ Signed-off-by: Gabor Juhos 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); @@ -30,7 +30,7 @@ Signed-off-by: Gabor Juhos 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); diff --git a/package/kernel/mac80211/patches/600-0031-rt2x00-rt2800lib-fix-txpower-compensation-for-RT3883.patch b/package/kernel/mac80211/patches/600-0031-rt2x00-rt2800lib-fix-txpower-compensation-for-RT3883.patch index d6295f4bd0..b87f36aaa5 100644 --- a/package/kernel/mac80211/patches/600-0031-rt2x00-rt2800lib-fix-txpower-compensation-for-RT3883.patch +++ b/package/kernel/mac80211/patches/600-0031-rt2x00-rt2800lib-fix-txpower-compensation-for-RT3883.patch @@ -10,7 +10,7 @@ Signed-off-by: Gabor Juhos --- 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); diff --git a/package/kernel/mac80211/patches/600-0032-rt2x00-rt2800lib-enable-RT2800_HAS_HIGH_SHARED_MEM-f.patch b/package/kernel/mac80211/patches/600-0032-rt2x00-rt2800lib-enable-RT2800_HAS_HIGH_SHARED_MEM-f.patch index c5f226a874..18d65e0ca1 100644 --- a/package/kernel/mac80211/patches/600-0032-rt2x00-rt2800lib-enable-RT2800_HAS_HIGH_SHARED_MEM-f.patch +++ b/package/kernel/mac80211/patches/600-0032-rt2x00-rt2800lib-enable-RT2800_HAS_HIGH_SHARED_MEM-f.patch @@ -11,7 +11,7 @@ Signed-off-by: Gabor Juhos --- 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; diff --git a/package/kernel/mac80211/patches/610-rt2x00-fix-rt3352-ext-pa.patch b/package/kernel/mac80211/patches/610-rt2x00-fix-rt3352-ext-pa.patch index 3d32ecc434..725f81fea4 100644 --- a/package/kernel/mac80211/patches/610-rt2x00-fix-rt3352-ext-pa.patch +++ b/package/kernel/mac80211/patches/610-rt2x00-fix-rt3352-ext-pa.patch @@ -1,6 +1,6 @@ --- a/drivers/net/wireless/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/rt2x00/rt2800lib.c -@@ -3506,11 +3506,18 @@ static void rt2800_config_channel(struct +@@ -3505,11 +3505,18 @@ static void rt2800_config_channel(struct /* * Change BBP settings */ @@ -19,7 +19,7 @@ } else if (rt2x00_rt(rt2x00dev, RT3593)) { if (rf->channel > 14) { /* Disable CCK Packet detection on 5GHz */ -@@ -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) { @@ -32,7 +32,7 @@ rt2800_rf_init_calibration(rt2x00dev, 30); rt2800_rfcsr_write(rt2x00dev, 0, 0xf0); -@@ -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); @@ -66,7 +66,7 @@ rt2800_rfcsr_write(rt2x00dev, 43, 0xdb); rt2800_rfcsr_write(rt2x00dev, 44, 0xdb); rt2800_rfcsr_write(rt2x00dev, 45, 0xdb); -@@ -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); @@ -96,7 +96,7 @@ rt2800_rfcsr_write(rt2x00dev, 59, 0x00); rt2800_rfcsr_write(rt2x00dev, 60, 0x00); rt2800_rfcsr_write(rt2x00dev, 61, 0x00); -@@ -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) || @@ -104,7 +104,7 @@ rt2x00_rt(rt2x00dev, RT5390) || rt2x00_rt(rt2x00dev, RT5392)) rt2800_eeprom_read(rt2x00dev, EEPROM_CHIP_ID, &rf); -@@ -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. */ @@ -114,7 +114,7 @@ __set_bit(CAPABILITY_BT_COEXIST, &rt2x00dev->cap_flags); /* -@@ -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); diff --git a/package/kernel/mac80211/patches/611-rt2x00-rf_vals-rt3352-xtal20.patch b/package/kernel/mac80211/patches/611-rt2x00-rf_vals-rt3352-xtal20.patch index c69344cdbd..6b29aa83b4 100644 --- a/package/kernel/mac80211/patches/611-rt2x00-rf_vals-rt3352-xtal20.patch +++ b/package/kernel/mac80211/patches/611-rt2x00-rf_vals-rt3352-xtal20.patch @@ -1,6 +1,6 @@ --- a/drivers/net/wireless/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/rt2x00/rt2800lib.c -@@ -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}, }; @@ -28,7 +28,7 @@ static int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev) { struct hw_mode_spec *spec = &rt2x00dev->spec; -@@ -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; @@ -40,7 +40,7 @@ break; case RF3052: -@@ -8446,6 +8470,19 @@ static int rt2800_probe_rt(struct rt2x00 +@@ -8445,6 +8469,19 @@ static int rt2800_probe_rt(struct rt2x00 return 0; } @@ -60,7 +60,7 @@ int rt2800_probe_hw(struct rt2x00_dev *rt2x00dev) { struct rt2800_drv_data *drv_data = rt2x00dev->drv_data; -@@ -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); /* diff --git a/package/kernel/mac80211/patches/615-rt2x00-fix_20mhz_clk.patch b/package/kernel/mac80211/patches/615-rt2x00-fix_20mhz_clk.patch index aaabffc629..07b2f84d5b 100644 --- a/package/kernel/mac80211/patches/615-rt2x00-fix_20mhz_clk.patch +++ b/package/kernel/mac80211/patches/615-rt2x00-fix_20mhz_clk.patch @@ -8,7 +8,7 @@ #include "rt2x00.h" #include "rt2800lib.h" -@@ -8472,13 +8473,14 @@ static int rt2800_probe_rt(struct rt2x00 +@@ -8471,13 +8472,14 @@ static int rt2800_probe_rt(struct rt2x00 int rt2800_probe_clk(struct rt2x00_dev *rt2x00dev) { diff --git a/package/kernel/mac80211/patches/616-rt2x00-support-rt5350.patch b/package/kernel/mac80211/patches/616-rt2x00-support-rt5350.patch index 2cc136cca0..fd897e93c8 100644 --- a/package/kernel/mac80211/patches/616-rt2x00-support-rt5350.patch +++ b/package/kernel/mac80211/patches/616-rt2x00-support-rt5350.patch @@ -10,7 +10,7 @@ #define RF5372 0x5372 --- a/drivers/net/wireless/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/rt2x00/rt2800lib.c -@@ -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]); @@ -24,7 +24,7 @@ } } } -@@ -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: @@ -32,7 +32,7 @@ case RF5360: case RF5370: case RF5372: -@@ -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) || @@ -40,7 +40,7 @@ rt2x00_rf(rt2x00dev, RF5360) || rt2x00_rf(rt2x00dev, RF5370) || rt2x00_rf(rt2x00dev, RF5372) || -@@ -3766,7 +3775,8 @@ static void rt2800_config_channel(struct +@@ -3765,7 +3774,8 @@ static void rt2800_config_channel(struct /* * Clear update flag */ @@ -50,7 +50,7 @@ rt2800_bbp_read(rt2x00dev, 49, &bbp); rt2x00_set_field8(&bbp, BBP49_UPDATE_FLAG, 0); rt2800_bbp_write(rt2x00dev, 49, bbp); -@@ -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: @@ -58,7 +58,7 @@ case RF5360: case RF5370: case RF5372: -@@ -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); @@ -67,7 +67,7 @@ } else { rt2800_register_write(rt2x00dev, TX_SW_CFG0, 0x00000000); rt2800_register_write(rt2x00dev, TX_SW_CFG1, 0x00080606); -@@ -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); @@ -84,7 +84,7 @@ rt2800_bbp_write(rt2x00dev, 86, 0x38); -@@ -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); @@ -101,7 +101,7 @@ rt2800_bbp_write(rt2x00dev, 120, 0x50); -@@ -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); @@ -115,7 +115,7 @@ } static void rt2800_init_bbp_3390(struct rt2x00_dev *rt2x00dev) -@@ -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: @@ -123,7 +123,7 @@ rt2800_init_bbp_3352(rt2x00dev); break; case RT3390: -@@ -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); } @@ -200,7 +200,7 @@ static void rt2800_init_rfcsr_5390(struct rt2x00_dev *rt2x00dev) { rt2800_rf_init_calibration(rt2x00dev, 2); -@@ -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; @@ -210,7 +210,7 @@ case RT5390: rt2800_init_rfcsr_5390(rt2x00dev); break; -@@ -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); @@ -223,7 +223,7 @@ } else if (rt2x00_rt(rt2x00dev, RT2860) || rt2x00_rt(rt2x00dev, RT2872)) { /* -@@ -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; @@ -232,7 +232,7 @@ else rf = rt2x00_get_field16(eeprom, EEPROM_NIC_CONF0_RF_TYPE); -@@ -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: @@ -240,7 +240,7 @@ case RF5360: case RF5370: case RF5372: -@@ -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: @@ -248,7 +248,7 @@ case RF5360: case RF5370: case RF5372: -@@ -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: @@ -256,7 +256,7 @@ case RF5360: case RF5370: case RF5372: -@@ -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: diff --git a/package/kernel/mac80211/patches/619-rt2x00-change-led-polarity-from-OF.patch b/package/kernel/mac80211/patches/619-rt2x00-change-led-polarity-from-OF.patch index d2271d36b5..5da38534ce 100644 --- a/package/kernel/mac80211/patches/619-rt2x00-change-led-polarity-from-OF.patch +++ b/package/kernel/mac80211/patches/619-rt2x00-change-led-polarity-from-OF.patch @@ -8,7 +8,7 @@ #include "rt2x00.h" #include "rt2800lib.h" -@@ -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/kernel/mac80211/patches/620-rt2x00-rt3352-rf-id.patch b/package/kernel/mac80211/patches/620-rt2x00-rt3352-rf-id.patch index a33c01fb08..86a990ccdb 100644 --- a/package/kernel/mac80211/patches/620-rt2x00-rt3352-rf-id.patch +++ b/package/kernel/mac80211/patches/620-rt2x00-rt3352-rf-id.patch @@ -1,6 +1,6 @@ --- a/drivers/net/wireless/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/rt2x00/rt2800lib.c -@@ -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); diff --git a/package/kernel/mac80211/patches/700-mwl8k-missing-pci-id-for-WNR854T.patch b/package/kernel/mac80211/patches/700-mwl8k-missing-pci-id-for-WNR854T.patch index 752fb0eec9..ae7e92764e 100644 --- a/package/kernel/mac80211/patches/700-mwl8k-missing-pci-id-for-WNR854T.patch +++ b/package/kernel/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 -@@ -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/kernel/mac80211/patches/800-b43-gpio-mask-module-option.patch b/package/kernel/mac80211/patches/800-b43-gpio-mask-module-option.patch index fc874ad049..e4d2f44a32 100644 --- a/package/kernel/mac80211/patches/800-b43-gpio-mask-module-option.patch +++ b/package/kernel/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/kernel/mac80211/patches/810-b43_no_pio.patch b/package/kernel/mac80211/patches/810-b43_no_pio.patch index 5cd1b8bccd..bc9fda24ca 100644 --- a/package/kernel/mac80211/patches/810-b43_no_pio.patch +++ b/package/kernel/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/kernel/mac80211/patches/820-b43-add-antenna-control.patch b/package/kernel/mac80211/patches/820-b43-add-antenna-control.patch index dea98303cd..b55c6694fd 100644 --- a/package/kernel/mac80211/patches/820-b43-add-antenna-control.patch +++ b/package/kernel/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/kernel/mac80211/patches/830-b43-workaround-pcie-bcm4716.patch b/package/kernel/mac80211/patches/830-b43-workaround-pcie-bcm4716.patch index e76758ca63..86b61fc4c9 100644 --- a/package/kernel/mac80211/patches/830-b43-workaround-pcie-bcm4716.patch +++ b/package/kernel/mac80211/patches/830-b43-workaround-pcie-bcm4716.patch @@ -19,7 +19,7 @@ Signed-off-by: Hauke Mehrtens --- 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 __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 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 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 << 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 --- 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 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 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/kernel/mac80211/patches/845-b43-only-use-gpio-0-1-for-led.patch b/package/kernel/mac80211/patches/845-b43-only-use-gpio-0-1-for-led.patch index 50347cdc3c..8555ccf44e 100644 --- a/package/kernel/mac80211/patches/845-b43-only-use-gpio-0-1-for-led.patch +++ b/package/kernel/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/kernel/mac80211/patches/900-wlcore-Add-support-for-DT-platform-data.patch b/package/kernel/mac80211/patches/900-wlcore-Add-support-for-DT-platform-data.patch index 967768af05..856dea8de4 100644 --- a/package/kernel/mac80211/patches/900-wlcore-Add-support-for-DT-platform-data.patch +++ b/package/kernel/mac80211/patches/900-wlcore-Add-support-for-DT-platform-data.patch @@ -88,22 +88,22 @@ Signed-off-by: Arik Nemtsov 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; @@ -112,7 +112,7 @@ Signed-off-by: Arik Nemtsov } 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); @@ -122,7 +122,7 @@ Signed-off-by: Arik Nemtsov 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); diff --git a/package/kernel/mac80211/patches/901-wl18xx-align-event-mailbox-with-current-fw.patch b/package/kernel/mac80211/patches/901-wl18xx-align-event-mailbox-with-current-fw.patch deleted file mode 100644 index 77647bbcf6..0000000000 --- a/package/kernel/mac80211/patches/901-wl18xx-align-event-mailbox-with-current-fw.patch +++ /dev/null @@ -1,47 +0,0 @@ -From fde3f0a7f3112527a18e06e32efdd9a354c91b02 Mon Sep 17 00:00:00 2001 -From: Eliad Peller -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 ---- - 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; - - int wl18xx_wait_for_event(struct wl1271 *wl, enum wlcore_wait_event event, diff --git a/package/kernel/mac80211/patches/901-wlcore-don-t-switch-channels-on-disconnected-STA-vif.patch b/package/kernel/mac80211/patches/901-wlcore-don-t-switch-channels-on-disconnected-STA-vif.patch new file mode 100644 index 0000000000..d90508e2a8 --- /dev/null +++ b/package/kernel/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 +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 +--- + 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; + ++ 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/kernel/mac80211/patches/902-wlcore-don-t-switch-channels-on-disconnected-STA-vif.patch b/package/kernel/mac80211/patches/902-wlcore-don-t-switch-channels-on-disconnected-STA-vif.patch deleted file mode 100644 index 3d501b2fab..0000000000 --- a/package/kernel/mac80211/patches/902-wlcore-don-t-switch-channels-on-disconnected-STA-vif.patch +++ /dev/null @@ -1,36 +0,0 @@ -From 4101e8dc540d19f1f6c24930629149191786e4cd Mon Sep 17 00:00:00 2001 -From: Arik Nemtsov -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 ---- - 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/target/linux/generic/files/include/linux/ath9k_platform.h b/target/linux/generic/files/include/linux/ath9k_platform.h index 3498780e3c..9fa70167e6 100644 --- a/target/linux/generic/files/include/linux/ath9k_platform.h +++ b/target/linux/generic/files/include/linux/ath9k_platform.h @@ -40,6 +40,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; };