mac80211: update to wireless-testing 2014-05-19
authorFelix Fietkau <nbd@openwrt.org>
Tue, 20 May 2014 09:35:17 +0000 (09:35 +0000)
committerFelix Fietkau <nbd@openwrt.org>
Tue, 20 May 2014 09:35:17 +0000 (09:35 +0000)
Signed-off-by: Felix Fietkau <nbd@openwrt.org>
SVN-Revision: 40800

79 files changed:
package/kernel/mac80211/Makefile
package/kernel/mac80211/patches/001-fix_build.patch
package/kernel/mac80211/patches/003-remove_bogus_modparams.patch
package/kernel/mac80211/patches/007-select_queue.patch
package/kernel/mac80211/patches/020-disable_tty_set_termios.patch [deleted file]
package/kernel/mac80211/patches/050-lib80211_option.patch
package/kernel/mac80211/patches/060-no_local_ssb_bcma.patch
package/kernel/mac80211/patches/070-add-missing-header.patch
package/kernel/mac80211/patches/100-revert_aes_ccm_port.patch
package/kernel/mac80211/patches/150-disable_addr_notifier.patch
package/kernel/mac80211/patches/300-pending_work.patch
package/kernel/mac80211/patches/310-ap_scan.patch
package/kernel/mac80211/patches/402-ath9k-fix-invalid-mac-address-handling.patch
package/kernel/mac80211/patches/403-ath_regd_optional.patch
package/kernel/mac80211/patches/405-regd_no_assoc_hints.patch
package/kernel/mac80211/patches/410-ath9k_allow_adhoc_and_ap.patch
package/kernel/mac80211/patches/500-ath9k_eeprom_debugfs.patch
package/kernel/mac80211/patches/502-ath9k_ahb_init.patch
package/kernel/mac80211/patches/510-ath9k_intr_mitigation_tweak.patch
package/kernel/mac80211/patches/512-ath9k_channelbw_debugfs.patch
package/kernel/mac80211/patches/513-ath9k_add_pci_ids.patch
package/kernel/mac80211/patches/520-mac80211_cur_txpower.patch
package/kernel/mac80211/patches/521-ath9k_cur_txpower.patch
package/kernel/mac80211/patches/522-mac80211_configure_antenna_gain.patch
package/kernel/mac80211/patches/523-ath9k_use_configured_antenna_gain.patch
package/kernel/mac80211/patches/530-ath9k_extra_leds.patch
package/kernel/mac80211/patches/531-ath9k_extra_platform_leds.patch
package/kernel/mac80211/patches/542-ath9k_debugfs_diag.patch
package/kernel/mac80211/patches/543-ath9k-allow-to-disable-bands-via-platform-data.patch
package/kernel/mac80211/patches/550-ath9k_entropy_from_adc.patch
package/kernel/mac80211/patches/551-ath9k-ar933x-usb-hang-workaround.patch [new file with mode: 0644]
package/kernel/mac80211/patches/551-ath9k_p2p_ifcomb.patch [deleted file]
package/kernel/mac80211/patches/552-ath9k_p2p_ps_support.patch [deleted file]
package/kernel/mac80211/patches/566-ath9k-ar933x-usb-hang-workaround.patch [deleted file]
package/kernel/mac80211/patches/567-ath9k_ar953x_read_mac_rev.patch [deleted file]
package/kernel/mac80211/patches/570-restrict_dfs_regions.patch [deleted file]
package/kernel/mac80211/patches/600-0002-rt2x00-rt2800lib-introduce-RT2800_HAS_HIGH_SHARED_ME.patch
package/kernel/mac80211/patches/600-0003-rt2x00-rt2800-serialize-shared-memory-access.patch
package/kernel/mac80211/patches/600-0004-rt2x00-rt2800lib-fix-beacon-generation-on-RT3593.patch
package/kernel/mac80211/patches/600-0005-rt2x00-rt2800lib-add-hw_beacon_count-field-to-struct.patch
package/kernel/mac80211/patches/600-0006-rt2x00-rt2800lib-init-additional-beacon-offset-regis.patch
package/kernel/mac80211/patches/600-0007-rt2x00-rt2800lib-fix-max-supported-beacon-count-for-.patch
package/kernel/mac80211/patches/600-0009-rt2x00-rt2800lib-enable-support-for-RT3883.patch
package/kernel/mac80211/patches/600-0010-rt2x00-rt2800lib-add-rf_vals-for-RF3853.patch
package/kernel/mac80211/patches/600-0011-rt2x00-rt2800lib-enable-VCO-calibration-for-RF3853.patch
package/kernel/mac80211/patches/600-0012-rt2x00-rt2800lib-add-channel-configuration-function-.patch
package/kernel/mac80211/patches/600-0013-rt2x00-rt2800lib-enable-RF3853-support.patch
package/kernel/mac80211/patches/600-0014-rt2x00-rt2800lib-add-MAC-register-initialization-for.patch
package/kernel/mac80211/patches/600-0016-rt2x00-rt2800lib-add-BBP-register-initialization-for.patch
package/kernel/mac80211/patches/600-0017-rt2x00-rt2800lib-add-RFCSR-initialization-for-RT3883.patch
package/kernel/mac80211/patches/600-0019-rt2x00-rt2800lib-force-rf-type-to-RF3853-on-RT3883.patch
package/kernel/mac80211/patches/600-0020-rt2x00-rt2800lib-add-channel-configuration-code-for-.patch
package/kernel/mac80211/patches/600-0021-rt2x00-rt2800lib-fix-txpower_to_dev-function-for-RT3.patch
package/kernel/mac80211/patches/600-0022-rt2x00-rt2800lib-use-correct-txpower-calculation-fun.patch
package/kernel/mac80211/patches/600-0023-rt2x00-rt2800lib-hardcode-txmixer-gain-values-to-zer.patch
package/kernel/mac80211/patches/600-0026-rt2x00-rt2800lib-use-correct-beacon-count-for-RT3883.patch
package/kernel/mac80211/patches/600-0027-rt2x00-rt2800lib-fix-antenna-configuration-for-RT388.patch
package/kernel/mac80211/patches/600-0028-rt2x00-rt2800lib-fix-LNA-gain-configuration-for-RT38.patch
package/kernel/mac80211/patches/600-0029-rt2x00-rt2800lib-fix-VGC-setup-for-RT3883.patch
package/kernel/mac80211/patches/600-0030-rt2x00-rt2800lib-fix-EEPROM-LNA-validation-for-RT388.patch
package/kernel/mac80211/patches/600-0031-rt2x00-rt2800lib-fix-txpower-compensation-for-RT3883.patch
package/kernel/mac80211/patches/600-0032-rt2x00-rt2800lib-enable-RT2800_HAS_HIGH_SHARED_MEM-f.patch
package/kernel/mac80211/patches/610-rt2x00-fix-rt3352-ext-pa.patch
package/kernel/mac80211/patches/611-rt2x00-rf_vals-rt3352-xtal20.patch
package/kernel/mac80211/patches/615-rt2x00-fix_20mhz_clk.patch
package/kernel/mac80211/patches/616-rt2x00-support-rt5350.patch
package/kernel/mac80211/patches/619-rt2x00-change-led-polarity-from-OF.patch
package/kernel/mac80211/patches/620-rt2x00-rt3352-rf-id.patch
package/kernel/mac80211/patches/700-mwl8k-missing-pci-id-for-WNR854T.patch
package/kernel/mac80211/patches/800-b43-gpio-mask-module-option.patch
package/kernel/mac80211/patches/810-b43_no_pio.patch
package/kernel/mac80211/patches/820-b43-add-antenna-control.patch
package/kernel/mac80211/patches/830-b43-workaround-pcie-bcm4716.patch
package/kernel/mac80211/patches/845-b43-only-use-gpio-0-1-for-led.patch
package/kernel/mac80211/patches/900-wlcore-Add-support-for-DT-platform-data.patch
package/kernel/mac80211/patches/901-wl18xx-align-event-mailbox-with-current-fw.patch [deleted file]
package/kernel/mac80211/patches/901-wlcore-don-t-switch-channels-on-disconnected-STA-vif.patch [new file with mode: 0644]
package/kernel/mac80211/patches/902-wlcore-don-t-switch-channels-on-disconnected-STA-vif.patch [deleted file]
target/linux/generic/files/include/linux/ath9k_platform.h

index d1759fd..1dcb7bd 100644 (file)
@@ -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
 
index 26b327a..99ef50e 100644 (file)
  .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
        @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 */"            ;\
index c969b19..ffb730b 100644 (file)
@@ -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
  
index a326ee3..0a1d292 100644 (file)
@@ -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 (file)
index e6d4ff6..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
---- a/compat/compat-2.6.39.c
-+++ b/compat/compat-2.6.39.c
-@@ -13,6 +13,7 @@
- #include <linux/sched.h>
- #include <linux/module.h>
-+#ifdef CONFIG_COMPAT_BLUETOOTH
- #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27))
- #ifdef CONFIG_TTY
- /*
-@@ -114,4 +115,4 @@ int tty_set_termios(struct tty_struct *t
- EXPORT_SYMBOL_GPL(tty_set_termios);
- #endif /* CONFIG_TTY */
- #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27)) */
--
-+#endif
index 5372114..168871a 100644 (file)
@@ -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
index 95f14f4..d550bba 100644 (file)
@@ -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;
  
        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)
index 9307804..e3ec780 100644 (file)
@@ -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 <linux/kernel.h>
  #include <linux/device.h>
  #include <linux/of.h>
 +#include <linux/string.h>
+ #include <net/net_namespace.h>
  
- /**
-  * devm_kstrdup - Allocate resource managed space and
+ #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,5,0))
index ac7d6b3..640d34e 100644 (file)
---- 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---
   * 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;
 +      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));
 -      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;
 +                      *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;
 +                      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)
  {
                        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;
+       }
index 3f749e9..c80b2bb 100644 (file)
@@ -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);
index ef81721..702b17b 100644 (file)
@@ -8,7 +8,7 @@ Date:   Mon May 19 21:48:56 2014 +0200
     
     Signed-off-by: Felix Fietkau <nbd@openwrt.org>
 
-commit 27647baeaee1b12bc3c57ccf1c7eba53bcd7fe53
+commit ff9655bebd25d35ab13c2515a029723b69949720
 Author: Felix Fietkau <nbd@openwrt.org>
 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 <nbd@openwrt.org>
 
-commit 92e9dd662542683856e62a5e7e43fcf5b9da5c4a
-Author: Henning Rogge <hrogge@gmail.com>
-Date:   Thu May 1 10:03:46 2014 +0200
+commit 46c5d7d207a2a0725066c0928fd19b8c578b7d4f
+Author: Oleksij Rempel <linux@rempel-privat.de>
+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 <hrogge@gmail.com>
+    Signed-off-by: Oleksij Rempel <linux@rempel-privat.de>
 
-commit 4c8a3486cb577d40c1ef75f0a8dc9a04773eef83
-Author: Nickolay Ledovskikh <nledovskikh@gmail.com>
-Date:   Fri Apr 25 22:53:34 2014 +0400
+commit 2d331334e9dc5659fdf9a89326c34c3db5a15279
+Author: Johannes Berg <johannes.berg@intel.com>
+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 <nledovskikh@gmail.com>
-    Acked-by: Nick Kossifidis <mickflemm@gmail.com>
-    Signed-off-by: John W. Linville <linville@tuxdriver.com>
+    Signed-off-by: Johannes Berg <johannes.berg@intel.com>
 
-commit 4d76248013dbb1948429555208900a585b0f351d
-Author: Janusz Dziedzic <janusz.dziedzic@tieto.com>
-Date:   Tue Apr 8 13:38:43 2014 +0200
+commit 6788105c46babaa6938cbacb72fdf20bec4bb2e3
+Author: Johannes Berg <johannes.berg@intel.com>
+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 <cedric.voncken@acksys.fr>
-    Signed-off-by: Janusz Dziedzic <janusz.dziedzic@tieto.com>
-    Signed-off-by: John W. Linville <linville@tuxdriver.com>
+    The orinoco driver uses the cfg80211 API structs for internal
+    bookkeeping, and so needs a (void *) cast that removes the
+    const - but that's OK because it allocates those pointers.
+    
+    Signed-off-by: Johannes Berg <johannes.berg@intel.com>
 
-commit c83a4e5156a4b4dd22137d33a5625440982d6d37
-Author: Rajkumar Manoharan <rmanohar@qti.qualcomm.com>
-Date:   Mon Apr 28 21:17:08 2014 +0530
+commit c3d95010fd881da0fa0a4e88532412f5d0c092f6
+Author: Johannes Berg <johannes.berg@intel.com>
+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 <rmanohar@qti.qualcomm.com>
-    Signed-off-by: John W. Linville <linville@tuxdriver.com>
+    Signed-off-by: Johannes Berg <johannes.berg@intel.com>
 
-commit 8aab2c7a2f4a957e344db429dfb1190ae59ce8b5
-Author: Rajkumar Manoharan <rmanohar@qti.qualcomm.com>
-Date:   Mon Apr 28 21:17:07 2014 +0530
+commit ddf1e6f0f0354c601af7d42e5ace4b51f8b0bffc
+Author: Luciano Coelho <luciano.coelho@intel.com>
+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 <rmanohar@qti.qualcomm.com>
-    Signed-off-by: John W. Linville <linville@tuxdriver.com>
+    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 <luciano.coelho@intel.com>
+    Signed-off-by: Johannes Berg <johannes.berg@intel.com>
 
-commit 8c7ae357cc5b6bd037ad2d666e9f3789cf882925
-Author: Rajkumar Manoharan <rmanohar@qti.qualcomm.com>
-Date:   Wed Apr 23 15:07:57 2014 +0530
+commit 202322d1c04b8e498bd5bb78606fcf3941512b35
+Author: Luciano Coelho <luciano.coelho@intel.com>
+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 <rmanohar@qti.qualcomm.com>
-    Signed-off-by: John W. Linville <linville@tuxdriver.com>
+     Warning(include/net/cfg80211.h:3064): No description found for parameter 'max_num_csa_counters'
+    
+    Signed-off-by: Luciano Coelho <luciano.coelho@intel.com>
+    Signed-off-by: Johannes Berg <johannes.berg@intel.com>
 
-commit c82552c5b0cb1735dbcbad78b1ffc6d3c212dc56
-Author: Tim Harvey <tharvey@gateworks.com>
-Date:   Mon Apr 21 16:14:57 2014 -0700
+commit 457a33192f64b7637e8fd0ae0e9f32701c908603
+Author: Johannes Berg <johannes.berg@intel.com>
+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 <johannes.berg@intel.com>
+
+commit 1e35dce952a64a957de97ae1f2bb19301756b936
+Author: Andrei Otcheretianski <andrei.otcheretianski@intel.com>
+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 <andrei.otcheretianski@intel.com>
+    Signed-off-by: Luciano Coelho <luciano.coelho@intel.com>
+    Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+
+commit e7b5c449815d28a2105fde5b42e112f78cc711ac
+Author: Andrei Otcheretianski <andrei.otcheretianski@intel.com>
+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 <tharvey@gateworks.com>
-    Acked-by: Felix Fietkau <nbd@openwrt.org>
-    Signed-off-by: John W. Linville <linville@tuxdriver.com>
+    Signed-off-by: Andrei Otcheretianski <andrei.otcheretianski@intel.com>
+    Signed-off-by: Luciano Coelho <luciano.coelho@intel.com>
+    Signed-off-by: Johannes Berg <johannes.berg@intel.com>
 
-commit 3a758134e66ca74a9df792616b5288b2fa2cfd7f
-Author: Tim Harvey <tharvey@gateworks.com>
-Date:   Mon Apr 21 16:14:56 2014 -0700
+commit e54eda80273ce8aded058c3c9365dca2342e2e75
+Author: Andrei Otcheretianski <andrei.otcheretianski@intel.com>
+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 <andrei.otcheretianski@intel.com>
+    Signed-off-by: Luciano Coelho <luciano.coelho@intel.com>
+    Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+
+commit 678e87c3b929dd60d59470e8981eb551cee10319
+Author: Andrei Otcheretianski <andrei.otcheretianski@intel.com>
+Date:   Fri May 9 14:11:46 2014 +0300
+
+    cfg80211: Support multiple CSA counters
     
-    Signed-off-by: Tim Harvey <tharvey@gateworks.com>
-    Acked-by: Felix Fietkau <nbd@openwrt.org>
-    Signed-off-by: John W. Linville <linville@tuxdriver.com>
+    Change the type of NL80211_ATTR_CSA_C_OFF_BEACON and
+    NL80211_ATTR_CSA_C_OFF_PRESP to be NLA_BINARY which allows
+    userspace to use beacons and probe responses with
+    multiple CSA counters.
+    This isn't breaking the API since userspace can
+    continue to use nla_put_u16 for this attributes, which
+    is equivalent to a single element u16 array.
+    In addition advertise max number of supported CSA counters.
+    This is needed when using CSA and eCSA IEs together.
+    
+    Signed-off-by: Andrei Otcheretianski <andrei.otcheretianski@intel.com>
+    Signed-off-by: Luciano Coelho <luciano.coelho@intel.com>
+    Signed-off-by: Johannes Berg <johannes.berg@intel.com>
 
-commit eefb1d6adc4c60d219182b8917e4567484ce07fc
-Author: Felix Fietkau <nbd@openwrt.org>
-Date:   Mon Apr 28 18:27:41 2014 +0200
+commit 93f4867a966cc8645659031bbd44a9bb4b78485f
+Author: Andrei Otcheretianski <andrei.otcheretianski@intel.com>
+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 <andrei.otcheretianski@intel.com>
+    Signed-off-by: Luciano Coelho <luciano.coelho@intel.com>
+    Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+
+commit 6c8461fcc03ff4d250027e47f53315b5e0ec43aa
+Author: Andrei Otcheretianski <andrei.otcheretianski@intel.com>
+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 <nbd@openwrt.org>
+    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 <andrei.otcheretianski@intel.com>
+    Signed-off-by: Luciano Coelho <luciano.coelho@intel.com>
+    Signed-off-by: Johannes Berg <johannes.berg@intel.com>
 
-commit 98a713933d8495f4078f561c1e651b738dd5b531
-Author: Felix Fietkau <nbd@openwrt.org>
-Date:   Sun Apr 27 14:49:03 2014 +0200
+commit 7d09fc9f1903b3d5e7d046bdf10467f37a97c4f9
+Author: Luciano Coelho <luciano.coelho@intel.com>
+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 <nbd@openwrt.org>
+    Tested-by: Janusz Dziedzic <janusz.dziedzic@tieto.com>
+    Reported-by: Eliad Peller <eliad@wizery.com>
+    Signed-off-by: Luciano Coelho <luciano.coelho@intel.com>
+    Signed-off-by: Johannes Berg <johannes.berg@intel.com>
 
-commit 7cbb4c021bfd1e656f5b9953a947ab3c64e4e3b0
-Author: Felix Fietkau <nbd@openwrt.org>
-Date:   Thu Apr 10 10:49:01 2014 +0200
+commit 2b7443b15f26ecb98281474666383cf2a882fbad
+Author: Janusz Dziedzic <janusz.dziedzic@tieto.com>
+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 <nbd@openwrt.org>
+    start_radar_detection always fail with -EINVAL.
+    
+    Acked-by: Luciano Coelho <luciano.coelho@intel.com>
+    Signed-off-by: Janusz Dziedzic <janusz.dziedzic@tieto.com>
+    Signed-off-by: Johannes Berg <johannes.berg@intel.com>
 
-commit 0ca13e26341733bf9577287fb04a3bef0d2f5cc9
+commit 4f46eb8b28f96aca212a364e0fa847eb5333df67
 Author: Felix Fietkau <nbd@openwrt.org>
-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 <nbd@openwrt.org>
+    Signed-off-by: Johannes Berg <johannes.berg@intel.com>
 
-commit ec998e5991781ecdaad0911dc64f1c8d3749c308
-Author: Felix Fietkau <nbd@openwrt.org>
-Date:   Tue Apr 8 23:42:17 2014 +0200
+commit 0277b034768d1800a00829a755fc56b925aa6b95
+Author: Johannes Berg <johannes.berg@intel.com>
+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 <nbd@openwrt.org>
+    Address this by shutting down everything; we'll run into a
+    lot of warnings in the process but that's better than having
+    the whole stack get messed up.
+    
+    Reviewed-by: Arik Nemtsov <arik@wizery.com>
+    Signed-off-by: Johannes Berg <johannes.berg@intel.com>
 
-commit 93f310a38a1d81a4bc8fcd9bf29628bd721cf2ef
-Author: Felix Fietkau <nbd@openwrt.org>
-Date:   Sun Apr 6 23:35:28 2014 +0200
+commit 43fd71bc4b83d24981e90ca178f505cf6a6b16dc
+Author: Luciano Coelho <luciano.coelho@intel.com>
+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 <nbd@openwrt.org>
+    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 <luciano.coelho@intel.com>
+    Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+
+commit dd4371e2957db19870bb22ab84e841e1ac6e8997
+Author: Luciano Coelho <luciano.coelho@intel.com>
+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 <standby24x7@gmail.com>
+    Signed-off-by: Luciano Coelho <luciano.coelho@intel.com>
+    Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+
+commit 56de850ae960f096c784ec07864ca5b71abd16e6
+Author: Michal Kazior <michal.kazior@tieto.com>
+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 <michal.kazior@tieto.com>
+    [small code cleanup]
+    Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+
+commit f5894c4f19e55bb1ea6376031fe9d47d7528be9e
+Author: Loic Poulain <loic.poulain@intel.com>
+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 <loic.poulain@intel.com>
+    Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+
+commit 47fdf5d4f3704d2db9d1c0f647f788edef104fc8
+Author: Michal Kazior <michal.kazior@tieto.com>
+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 <michal.kazior@tieto.com>
+    Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+
+commit 1a8ed386e1684b266a15dacf675102ae53361ee5
+Author: Michal Kazior <michal.kazior@tieto.com>
+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 <michal.kazior@tieto.com>
+    Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+
+commit 573f31d6d0e572ff8186c45a1ecd9273242233e6
+Author: Michal Kazior <michal.kazior@tieto.com>
+Date:   Wed Apr 9 15:11:00 2014 +0200
+
+    mac80211: split CSA finalize function
+    
+    Improves readability and modularity.
+    
+    Signed-off-by: Michal Kazior <michal.kazior@tieto.com>
+    Signed-off-by: Johannes Berg <johannes.berg@intel.com>
 
+commit 2d104d52e7c7640d68f29f2136dbe3938b7bc9ba
+Author: Michal Kazior <michal.kazior@tieto.com>
+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 <michal.kazior@tieto.com>
+    Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+
+commit 6be615d6d42aa7fdab6c4278031d8fa0953e594f
+Author: Johannes Berg <johannes.berg@intel.com>
+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 <luciano.coelho@intel.com>
+    Reviewed-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
+    Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+
+commit 43279e584aeb78aa0c853728db047b58156c0753
+Author: Arik Nemtsov <arik@wizery.com>
+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 <arikx.nemtsov@intel.com>
+    Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+
+commit bf9c234b83c77f1ebbcbab73de2a9e4a5d4aafc6
+Author: Arik Nemtsov <arik@wizery.com>
+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 <arikx.nemtsov@intel.com>
+    Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+
+commit 910e65141a17f645ab85dae1a497e64ebe63df70
+Author: Johannes Berg <johannes.berg@intel.com>
+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 <johannes.berg@intel.com>
+
+commit ff36b582a10285530351aab036087b57ddb4ae2b
+Author: Johannes Berg <johannes.berg@intel.com>
+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 <johannes.berg@intel.com>
+
+--- 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, &params->beacon_csa);
+               if (err < 0) {
+                       kfree(sdata->u.ap.next_beacon);
+@@ -3220,8 +3299,9 @@ static int ieee80211_set_csa_beacon(stru
+       return 0;
+ }
+-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, &params->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 <johannes@sipsolutions.net>
++ * Copyright 2014, Intel Corporation
++ *
++ * This file is GPLv2 as found in COPYING.
++ */
++
++#include <linux/ieee80211.h>
++#include "ieee80211_i.h"
++
++static void ieee80211_tdls_add_ext_capab(struct sk_buff *skb)
++{
++      u8 *pos = (void *)skb_put(skb, 7);
++
++      *pos++ = WLAN_EID_EXT_CAPABILITY;
++      *pos++ = 5; /* len */
++      *pos++ = 0x0;
++      *pos++ = 0x0;
++      *pos++ = 0x0;
++      *pos++ = 0x0;
++      *pos++ = WLAN_EXT_CAPA5_TDLS_ENABLED;
++}
++
++static u16 ieee80211_get_tdls_sta_capab(struct ieee80211_sub_if_data *sdata)
++{
++      struct ieee80211_local *local = sdata->local;
++      u16 capab;
++
++      capab = 0;
++      if (ieee80211_get_sdata_band(sdata) != IEEE80211_BAND_2GHZ)
++              return capab;
++
++      if (!(local->hw.flags & IEEE80211_HW_2GHZ_SHORT_SLOT_INCAPABLE))
++              capab |= WLAN_CAPABILITY_SHORT_SLOT_TIME;
++      if (!(local->hw.flags & IEEE80211_HW_2GHZ_SHORT_PREAMBLE_INCAPABLE))
++              capab |= WLAN_CAPABILITY_SHORT_PREAMBLE;
++
++      return capab;
++}
++
++static void ieee80211_tdls_add_link_ie(struct sk_buff *skb, const u8 *src_addr,
++                                     const u8 *peer, const u8 *bssid)
++{
++      struct ieee80211_tdls_lnkie *lnkid;
++
++      lnkid = (void *)skb_put(skb, sizeof(struct ieee80211_tdls_lnkie));
++
++      lnkid->ie_type = WLAN_EID_LINK_ID;
++      lnkid->ie_len = sizeof(struct ieee80211_tdls_lnkie) - 2;
++
++      memcpy(lnkid->bssid, bssid, ETH_ALEN);
++      memcpy(lnkid->init_sta, src_addr, ETH_ALEN);
++      memcpy(lnkid->resp_sta, peer, ETH_ALEN);
++}
++
++static int
++ieee80211_prep_tdls_encap_data(struct wiphy *wiphy, struct net_device *dev,
++                             const u8 *peer, u8 action_code, u8 dialog_token,
++                             u16 status_code, struct sk_buff *skb)
++{
++      struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
++      enum ieee80211_band band = ieee80211_get_sdata_band(sdata);
++      struct ieee80211_tdls_data *tf;
++
++      tf = (void *)skb_put(skb, offsetof(struct ieee80211_tdls_data, u));
++
++      memcpy(tf->da, peer, ETH_ALEN);
++      memcpy(tf->sa, sdata->vif.addr, ETH_ALEN);
++      tf->ether_type = cpu_to_be16(ETH_P_TDLS);
++      tf->payload_type = WLAN_TDLS_SNAP_RFTYPE;
++
++      switch (action_code) {
++      case WLAN_TDLS_SETUP_REQUEST:
++              tf->category = WLAN_CATEGORY_TDLS;
++              tf->action_code = WLAN_TDLS_SETUP_REQUEST;
++
++              skb_put(skb, sizeof(tf->u.setup_req));
++              tf->u.setup_req.dialog_token = dialog_token;
++              tf->u.setup_req.capability =
++                      cpu_to_le16(ieee80211_get_tdls_sta_capab(sdata));
++
++              ieee80211_add_srates_ie(sdata, skb, false, band);
++              ieee80211_add_ext_srates_ie(sdata, skb, false, band);
++              ieee80211_tdls_add_ext_capab(skb);
++              break;
++      case WLAN_TDLS_SETUP_RESPONSE:
++              tf->category = WLAN_CATEGORY_TDLS;
++              tf->action_code = WLAN_TDLS_SETUP_RESPONSE;
++
++              skb_put(skb, sizeof(tf->u.setup_resp));
++              tf->u.setup_resp.status_code = cpu_to_le16(status_code);
++              tf->u.setup_resp.dialog_token = dialog_token;
++              tf->u.setup_resp.capability =
++                      cpu_to_le16(ieee80211_get_tdls_sta_capab(sdata));
++
++              ieee80211_add_srates_ie(sdata, skb, false, band);
++              ieee80211_add_ext_srates_ie(sdata, skb, false, band);
++              ieee80211_tdls_add_ext_capab(skb);
++              break;
++      case WLAN_TDLS_SETUP_CONFIRM:
++              tf->category = WLAN_CATEGORY_TDLS;
++              tf->action_code = WLAN_TDLS_SETUP_CONFIRM;
++
++              skb_put(skb, sizeof(tf->u.setup_cfm));
++              tf->u.setup_cfm.status_code = cpu_to_le16(status_code);
++              tf->u.setup_cfm.dialog_token = dialog_token;
++              break;
++      case WLAN_TDLS_TEARDOWN:
++              tf->category = WLAN_CATEGORY_TDLS;
++              tf->action_code = WLAN_TDLS_TEARDOWN;
++
++              skb_put(skb, sizeof(tf->u.teardown));
++              tf->u.teardown.reason_code = cpu_to_le16(status_code);
++              break;
++      case WLAN_TDLS_DISCOVERY_REQUEST:
++              tf->category = WLAN_CATEGORY_TDLS;
++              tf->action_code = WLAN_TDLS_DISCOVERY_REQUEST;
++
++              skb_put(skb, sizeof(tf->u.discover_req));
++              tf->u.discover_req.dialog_token = dialog_token;
++              break;
++      default:
++              return -EINVAL;
++      }
++
++      return 0;
++}
++
++static int
++ieee80211_prep_tdls_direct(struct wiphy *wiphy, struct net_device *dev,
++                         const u8 *peer, u8 action_code, u8 dialog_token,
++                         u16 status_code, struct sk_buff *skb)
++{
++      struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
++      enum ieee80211_band band = ieee80211_get_sdata_band(sdata);
++      struct ieee80211_mgmt *mgmt;
++
++      mgmt = (void *)skb_put(skb, 24);
++      memset(mgmt, 0, 24);
++      memcpy(mgmt->da, peer, ETH_ALEN);
++      memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN);
++      memcpy(mgmt->bssid, sdata->u.mgd.bssid, ETH_ALEN);
++
++      mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
++                                        IEEE80211_STYPE_ACTION);
++
++      switch (action_code) {
++      case WLAN_PUB_ACTION_TDLS_DISCOVER_RES:
++              skb_put(skb, 1 + sizeof(mgmt->u.action.u.tdls_discover_resp));
++              mgmt->u.action.category = WLAN_CATEGORY_PUBLIC;
++              mgmt->u.action.u.tdls_discover_resp.action_code =
++                      WLAN_PUB_ACTION_TDLS_DISCOVER_RES;
++              mgmt->u.action.u.tdls_discover_resp.dialog_token =
++                      dialog_token;
++              mgmt->u.action.u.tdls_discover_resp.capability =
++                      cpu_to_le16(ieee80211_get_tdls_sta_capab(sdata));
++
++              ieee80211_add_srates_ie(sdata, skb, false, band);
++              ieee80211_add_ext_srates_ie(sdata, skb, false, band);
++              ieee80211_tdls_add_ext_capab(skb);
++              break;
++      default:
++              return -EINVAL;
++      }
++
++      return 0;
++}
++
++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, &params, &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(&params->chandef);
+-              __entry->counter_offset_beacon = params->counter_offset_beacon;
+-              __entry->counter_offset_presp = params->counter_offset_presp;
+               __entry->radar_required = params->radar_required;
+               __entry->block_tx = params->block_tx;
+               __entry->count = params->count;
++              memcpy(__get_dynamic_array(bcn_ofs),
++                     params->counter_offsets_beacon,
++                     params->n_counter_offsets_beacon * sizeof(u16));
++
++              /* probe response offsets are optional */
++              if (params->n_counter_offsets_presp)
++                      memcpy(__get_dynamic_array(pres_ofs),
++                             params->counter_offsets_presp,
++                             params->n_counter_offsets_presp * sizeof(u16));
+       ),
+       TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", " CHAN_DEF_PR_FMT
+-                ", block_tx: %d, count: %u, radar_required: %d"
+-                ", counter offsets (beacon/presp): %u/%u",
++                ", block_tx: %d, count: %u, radar_required: %d",
+                 WIPHY_PR_ARG, NETDEV_PR_ARG, CHAN_DEF_PR_ARG,
+-                __entry->block_tx, __entry->count, __entry->radar_required,
+-                __entry->counter_offset_beacon,
+-                __entry->counter_offset_presp)
++                __entry->block_tx, __entry->count, __entry->radar_required)
+ );
+ 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;
+ }
index 87f165a..a12e7e5 100644 (file)
@@ -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)
                 */
index acaa317..63ab0db 100644 (file)
@@ -8,7 +8,7 @@
  #include <asm/unaligned.h>
  
  #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;
        }
index 4a9b7e4..808e729 100644 (file)
@@ -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=
index 4fa611f..ef60f9e 100644 (file)
@@ -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)
  {
index 909a5f1..ce752f1 100644 (file)
@@ -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) },
  };
index 36e0151..65821fe 100644 (file)
@@ -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);
  
index de61a9e..0c8e813 100644 (file)
@@ -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;
  
index c818933..d7478ff 100644 (file)
@@ -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;
  
index 665d8aa..c0e173f 100644 (file)
@@ -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);
index 540198f..db4e6a1 100644 (file)
@@ -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) {
index cb3f852..b79a3c4 100644 (file)
@@ -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;
index ebc3633..d4d2989 100644 (file)
@@ -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);
index 611f763..6ad04ac 100644 (file)
@@ -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;
        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();
  
        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;
        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;
        }
  
index 2903bd9..2ea3fe0 100644 (file)
@@ -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) {
index c78a3e5..4cf0700 100644 (file)
@@ -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
  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 */
  #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,
  };
  
  
  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);
index 6c9832c..718a3d0 100644 (file)
@@ -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;
index 419717a..3db34bb 100644 (file)
@@ -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;
  }
  
  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);
                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 */
  
index e2e18c9..0501582 100644 (file)
@@ -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);
index 439a574..7210a02 100644 (file)
@@ -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 (file)
index 0000000..10280d9
--- /dev/null
@@ -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 (file)
index 579a633..0000000
+++ /dev/null
@@ -1,33 +0,0 @@
-From c997a1da25fe7c717ed099888b8eb35d4e139e70 Mon Sep 17 00:00:00 2001
-From: Felix Fietkau <nbd@openwrt.org>
-Date: Sun, 8 Dec 2013 08:52:52 +0100
-Subject: [PATCH] ath9k: support only one P2P interface
-
-Preparation for adding P2P powersave and multi-channel support.
-
-Signed-off-by: Felix Fietkau <nbd@openwrt.org>
----
- drivers/net/wireless/ath/ath9k/init.c | 4 ++--
-  1 file changed, 2 insertions(+), 2 deletions(-)
-
---- a/drivers/net/wireless/ath/ath9k/init.c
-+++ b/drivers/net/wireless/ath/ath9k/init.c
-@@ -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 (file)
index 3b09aef..0000000
+++ /dev/null
@@ -1,249 +0,0 @@
-From 6744d0a7ea037c7d65e13ca906da93009b241d00 Mon Sep 17 00:00:00 2001
-From: Felix Fietkau <nbd@openwrt.org>
-Date: Tue, 11 Feb 2014 11:16:24 +0100
-Subject: [PATCH] ath9k: implement p2p client powersave support
-
-Use generic TSF timers to trigger powersave state changes based
-information from the P2P NoA attribute.
-Opportunistic Powersave is not handled, because the driver does not
-support powersave at the moment.
-
-Signed-off-by: Felix Fietkau <nbd@openwrt.org>
----
- drivers/net/wireless/ath/ath9k/ath9k.h |  12 ++++
- drivers/net/wireless/ath/ath9k/init.c  |   6 ++
- drivers/net/wireless/ath/ath9k/main.c  | 104 +++++++++++++++++++++++++++++++++
- drivers/net/wireless/ath/ath9k/recv.c  |   3 +
- 4 files changed, 125 insertions(+)
-
---- a/drivers/net/wireless/ath/ath9k/main.c
-+++ b/drivers/net/wireless/ath/ath9k/main.c
-@@ -261,6 +261,8 @@ static bool ath_complete_reset(struct at
-       sc->gtt_cnt = 0;
-       ieee80211_wake_queues(sc->hw);
-+      ath9k_p2p_ps_timer(sc);
-+
-       return true;
- }
-@@ -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 (file)
index eddbc6c..0000000
+++ /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 (file)
index 31778a4..0000000
+++ /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 (file)
index 10157dc..0000000
+++ /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
index 3b11b15..98c9203 100644 (file)
@@ -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;
  
index 879b4cc..97e213f 100644 (file)
@@ -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, &reg);
                rt2x00_set_field32(&reg, MAC_WCID_ATTRIBUTE_KEYTAB,
-@@ -1271,6 +1292,7 @@ static void rt2800_config_wcid_attr_ciph
+@@ -1270,6 +1291,7 @@ static void rt2800_config_wcid_attr_ciph
                rt2x00_set_field32(&reg, MAC_WCID_ATTRIBUTE_RX_WIUDF, 0);
                rt2800_register_write(rt2x00dev, offset, reg);
        }
@@ -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");
  
index 38dbb43..5cb6eae 100644 (file)
@@ -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);
  
index 3d97169..d832f99 100644 (file)
@@ -24,7 +24,7 @@ Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
 
 --- a/drivers/net/wireless/rt2x00/rt2800lib.c
 +++ b/drivers/net/wireless/rt2x00/rt2800lib.c
-@@ -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 <juhosg@openwrt.org>
        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 <juhosg@openwrt.org>
                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);
  
index 8c52713..040c69c 100644 (file)
@@ -34,7 +34,7 @@ Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
   */
 --- a/drivers/net/wireless/rt2x00/rt2800lib.c
 +++ b/drivers/net/wireless/rt2x00/rt2800lib.c
-@@ -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);
  
index 66e8245..752cd89 100644 (file)
@@ -10,7 +10,7 @@ Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
 
 --- a/drivers/net/wireless/rt2x00/rt2800lib.c
 +++ b/drivers/net/wireless/rt2x00/rt2800lib.c
-@@ -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);
  
index e9d847a..8cb93ec 100644 (file)
@@ -10,7 +10,7 @@ Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
 
 --- a/drivers/net/wireless/rt2x00/rt2800lib.c
 +++ b/drivers/net/wireless/rt2x00/rt2800lib.c
-@@ -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:
index b096f9f..e85ae97 100644 (file)
@@ -31,7 +31,7 @@ Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
  #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 <juhosg@openwrt.org>
  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;
  
index 4c9a3b4..898e385 100644 (file)
@@ -10,7 +10,7 @@ Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
 
 --- a/drivers/net/wireless/rt2x00/rt2800lib.c
 +++ b/drivers/net/wireless/rt2x00/rt2800lib.c
-@@ -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 <juhosg@openwrt.org>
        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:
index e3460ff..1de99ea 100644 (file)
@@ -11,7 +11,7 @@ Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
 
 --- a/drivers/net/wireless/rt2x00/rt2800lib.c
 +++ b/drivers/net/wireless/rt2x00/rt2800lib.c
-@@ -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 <juhosg@openwrt.org>
  #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;
index 8719425..e7e17a9 100644 (file)
@@ -10,7 +10,7 @@ Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
 
 --- a/drivers/net/wireless/rt2x00/rt2800lib.c
 +++ b/drivers/net/wireless/rt2x00/rt2800lib.c
-@@ -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:
index 8632ddd..95423d1 100644 (file)
@@ -35,7 +35,7 @@ Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
  #define RX_FILTER_CFG                 0x1400
 --- a/drivers/net/wireless/rt2x00/rt2800lib.c
 +++ b/drivers/net/wireless/rt2x00/rt2800lib.c
-@@ -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 <juhosg@openwrt.org>
        } else if (rt2x00_rt(rt2x00dev, RT5390) ||
                   rt2x00_rt(rt2x00dev, RT5392) ||
                   rt2x00_rt(rt2x00dev, RT5592)) {
-@@ -5003,9 +5009,11 @@ static int rt2800_init_registers(struct
+@@ -5002,9 +5008,11 @@ static int rt2800_init_registers(struct 
  
        rt2800_register_read(rt2x00dev, MAX_LEN_CFG, &reg);
        rt2x00_set_field32(&reg, MAX_LEN_CFG_MAX_MPDU, AGGREGATION_SIZE);
@@ -63,7 +63,7 @@ Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
                rt2x00_set_field32(&reg, MAX_LEN_CFG_MAX_PSDU, 2);
        else
                rt2x00_set_field32(&reg, MAX_LEN_CFG_MAX_PSDU, 1);
-@@ -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);
  
index 967e36a..d9694da 100644 (file)
@@ -11,7 +11,7 @@ Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
 
 --- a/drivers/net/wireless/rt2x00/rt2800lib.c
 +++ b/drivers/net/wireless/rt2x00/rt2800lib.c
-@@ -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 <juhosg@openwrt.org>
  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;
index c568b99..dc45109 100644 (file)
@@ -21,7 +21,7 @@ Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
  /*
 --- a/drivers/net/wireless/rt2x00/rt2800lib.c
 +++ b/drivers/net/wireless/rt2x00/rt2800lib.c
-@@ -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 <juhosg@openwrt.org>
  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;
index 47eece0..4bfe8e1 100644 (file)
@@ -10,7 +10,7 @@ Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
 
 --- a/drivers/net/wireless/rt2x00/rt2800lib.c
 +++ b/drivers/net/wireless/rt2x00/rt2800lib.c
-@@ -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);
index d9cbb33..59b74ad 100644 (file)
@@ -10,7 +10,7 @@ Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
 
 --- a/drivers/net/wireless/rt2x00/rt2800lib.c
 +++ b/drivers/net/wireless/rt2x00/rt2800lib.c
-@@ -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 <juhosg@openwrt.org>
  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 <juhosg@openwrt.org>
        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);
@@