]> Pileus Git - ~andy/linux/commitdiff
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wirel...
authorJohn W. Linville <linville@tuxdriver.com>
Tue, 11 Jun 2013 18:48:32 +0000 (14:48 -0400)
committerJohn W. Linville <linville@tuxdriver.com>
Tue, 11 Jun 2013 18:48:32 +0000 (14:48 -0400)
Conflicts:
drivers/net/wireless/ath/ath9k/debug.c
net/mac80211/iface.c

12 files changed:
1  2 
MAINTAINERS
drivers/net/wireless/ath/ath9k/Kconfig
drivers/net/wireless/ath/ath9k/ar9003_phy.c
drivers/net/wireless/ath/ath9k/ath9k.h
drivers/net/wireless/ath/ath9k/debug.c
drivers/net/wireless/ath/ath9k/debug.h
drivers/net/wireless/ath/ath9k/hw.c
drivers/net/wireless/ath/ath9k/init.c
drivers/net/wireless/ath/ath9k/mac.c
drivers/net/wireless/ath/ath9k/main.c
net/mac80211/iface.c
net/wireless/core.c

diff --combined MAINTAINERS
index f35a259a6564a4bc31a7dabbafd8f3f64e9c6a03,e5069c22339197fd3fad9d25518aa6be971b5c03..0518ec49467bfd93193b437f45f49fe3dc5a82de
@@@ -2299,6 -2299,11 +2299,11 @@@ M:    Jaya Kumar <jayakumar.alsa@gmail.com
  S:    Maintained
  F:    sound/pci/cs5535audio/
  
+ CW1200 WLAN driver
+ M:     Solomon Peachy <pizza@shaftnet.org>
+ S:     Maintained
+ F:     drivers/net/wireless/cw1200/
  CX18 VIDEO4LINUX DRIVER
  M:    Andy Walls <awalls@md.metrocast.net>
  L:    ivtv-devel@ivtvdriver.org (moderated for non-subscribers)
@@@ -3322,12 -3327,11 +3327,12 @@@ F:   drivers/net/wan/dlci.
  F:    drivers/net/wan/sdla.c
  
  FRAMEBUFFER LAYER
 -M:    Florian Tobias Schandinat <FlorianSchandinat@gmx.de>
 +M:    Jean-Christophe Plagniol-Villard <plagnioj@jcrosoft.com>
 +M:    Tomi Valkeinen <tomi.valkeinen@ti.com>
  L:    linux-fbdev@vger.kernel.org
  W:    http://linux-fbdev.sourceforge.net/
  Q:    http://patchwork.kernel.org/project/linux-fbdev/list/
 -T:    git git://github.com/schandinat/linux-2.6.git fbdev-next
 +T:    git git://git.kernel.org/pub/scm/linux/kernel/git/plagnioj/linux-fbdev.git
  S:    Maintained
  F:    Documentation/fb/
  F:    Documentation/devicetree/bindings/fb/
@@@ -3866,16 -3870,9 +3871,16 @@@ M:    K. Y. Srinivasan <kys@microsoft.com
  M:    Haiyang Zhang <haiyangz@microsoft.com>
  L:    devel@linuxdriverproject.org
  S:    Maintained
 -F:    drivers/hv/
 +F:    arch/x86/include/asm/mshyperv.h
 +F:    arch/x86/include/uapi/asm/hyperv.h
 +F:    arch/x86/kernel/cpu/mshyperv.c
  F:    drivers/hid/hid-hyperv.c
 +F:    drivers/hv/
  F:    drivers/net/hyperv/
 +F:    drivers/scsi/storvsc_drv.c
 +F:    drivers/video/hyperv_fb.c
 +F:    include/linux/hyperv.h
 +F:    tools/hv/
  
  I2C OVER PARALLEL PORT
  M:    Jean Delvare <khali@linux-fr.org>
@@@ -4649,13 -4646,12 +4654,13 @@@ F:   include/linux/sunrpc
  F:    include/uapi/linux/sunrpc/
  
  KERNEL VIRTUAL MACHINE (KVM)
 -M:    Marcelo Tosatti <mtosatti@redhat.com>
  M:    Gleb Natapov <gleb@redhat.com>
 +M:    Paolo Bonzini <pbonzini@redhat.com>
  L:    kvm@vger.kernel.org
 -W:    http://kvm.qumranet.com
 +W:    http://linux-kvm.org
  S:    Supported
 -F:    Documentation/*/kvm.txt
 +F:    Documentation/*/kvm*.txt
 +F:    Documentation/virtual/kvm/
  F:    arch/*/kvm/
  F:    arch/*/include/asm/kvm*
  F:    include/linux/kvm*
@@@ -4985,13 -4981,6 +4990,13 @@@ S:    Maintaine
  F:    Documentation/hwmon/lm90
  F:    drivers/hwmon/lm90.c
  
 +LM95234 HARDWARE MONITOR DRIVER
 +M:    Guenter Roeck <linux@roeck-us.net>
 +L:    lm-sensors@lm-sensors.org
 +S:    Maintained
 +F:    Documentation/hwmon/lm95234
 +F:    drivers/hwmon/lm95234.c
 +
  LME2510 MEDIA DRIVER
  M:    Malcolm Priestley <tvboxspy@gmail.com>
  L:    linux-media@vger.kernel.org
@@@ -5525,18 -5514,18 +5530,18 @@@ F:   Documentation/networking/s2io.tx
  F:    Documentation/networking/vxge.txt
  F:    drivers/net/ethernet/neterion/
  
 -NETFILTER/IPTABLES/IPCHAINS
 -P:    Harald Welte
 -P:    Jozsef Kadlecsik
 +NETFILTER/IPTABLES
  M:    Pablo Neira Ayuso <pablo@netfilter.org>
  M:    Patrick McHardy <kaber@trash.net>
 +M:    Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
  L:    netfilter-devel@vger.kernel.org
  L:    netfilter@vger.kernel.org
  L:    coreteam@netfilter.org
  W:    http://www.netfilter.org/
  W:    http://www.iptables.org/
 -T:    git git://1984.lsi.us.es/nf
 -T:    git git://1984.lsi.us.es/nf-next
 +Q:    http://patchwork.ozlabs.org/project/netfilter-devel/list/
 +T:    git git://git.kernel.org/pub/scm/linux/kernel/git/pablo/nf.git
 +T:    git git://git.kernel.org/pub/scm/linux/kernel/git/pablo/nf-next.git
  S:    Supported
  F:    include/linux/netfilter*
  F:    include/linux/netfilter/
@@@ -6085,18 -6074,9 +6090,18 @@@ L:    linux-parisc@vger.kernel.or
  W:    http://www.parisc-linux.org/
  Q:    http://patchwork.kernel.org/project/linux-parisc/list/
  T:    git git://git.kernel.org/pub/scm/linux/kernel/git/jejb/parisc-2.6.git
 +T:    git git://git.kernel.org/pub/scm/linux/kernel/git/deller/parisc-linux.git
  S:    Maintained
  F:    arch/parisc/
 +F:    Documentation/parisc/
  F:    drivers/parisc/
 +F:    drivers/char/agp/parisc-agp.c
 +F:    drivers/input/serio/gscps2.c
 +F:    drivers/parport/parport_gsc.*
 +F:    drivers/tty/serial/8250/8250_gsc.c
 +F:    drivers/video/sti*
 +F:    drivers/video/console/sti*
 +F:    drivers/video/logo/logo_parisc*
  
  PC87360 HARDWARE MONITORING DRIVER
  M:    Jim Cromie <jim.cromie@gmail.com>
@@@ -7879,7 -7859,7 +7884,7 @@@ L:      linux-scsi@vger.kernel.or
  L:    target-devel@vger.kernel.org
  L:    http://groups.google.com/group/linux-iscsi-target-dev
  W:    http://www.linux-iscsi.org
 -T:    git git://git.kernel.org/pub/scm/linux/kernel/git/nab/lio-core.git master
 +T:    git git://git.kernel.org/pub/scm/linux/kernel/git/nab/target-pending.git master
  S:    Supported
  F:    drivers/target/
  F:    include/target/
@@@ -8207,13 -8187,6 +8212,13 @@@ F:    drivers/mmc/host/sh_mobile_sdhi.
  F:    include/linux/mmc/tmio.h
  F:    include/linux/mmc/sh_mobile_sdhi.h
  
 +TMP401 HARDWARE MONITOR DRIVER
 +M:    Guenter Roeck <linux@roeck-us.net>
 +L:    lm-sensors@lm-sensors.org
 +S:    Maintained
 +F:    Documentation/hwmon/tmp401
 +F:    drivers/hwmon/tmp401.c
 +
  TMPFS (SHMEM FILESYSTEM)
  M:    Hugh Dickins <hughd@google.com>
  L:    linux-mm@kvack.org
index f3dc124c60c775577a322f6e0a6b7adc471fa88d,ec33c8007b29a123e2d12d1cee1038d5b4c75409..3b078515b422a4634942beefa8658be8e486b66f
@@@ -17,7 -17,7 +17,7 @@@ config ATH9K_BTCOEX_SUPPOR
  
  config ATH9K
        tristate "Atheros 802.11n wireless cards support"
 -      depends on MAC80211
 +      depends on MAC80211 && HAS_DMA
        select ATH9K_HW
        select MAC80211_LEDS
        select LEDS_CLASS
@@@ -84,14 -84,6 +84,6 @@@ config ATH9K_DFS_CERTIFIE
          developed. At this point enabling this option won't do anything
          except increase code size.
  
- config ATH9K_MAC_DEBUG
-       bool "Atheros MAC statistics"
-       depends on ATH9K_DEBUGFS
-       default y
-       ---help---
-         This option enables collection of statistics for Rx/Tx status
-         data and some other MAC related statistics
  config ATH9K_RATE_CONTROL
        bool "Atheros ath9k rate control"
        depends on ATH9K
index e1714d7c9eeb50d0c546a9ea01ad213a8bd51215,0d053503b8bf1cd1e83cfe1af190aa2164078407..83e03857c01496d08618ec7b4afce7d53cf746d2
@@@ -334,8 -334,7 +334,8 @@@ static void ar9003_hw_spur_ofdm(struct 
        REG_RMW_FIELD(ah, AR_PHY_SPUR_REG,
                      AR_PHY_SPUR_REG_EN_VIT_SPUR_RSSI, 1);
  
 -      if (REG_READ_FIELD(ah, AR_PHY_MODE,
 +      if (!AR_SREV_9340(ah) &&
 +          REG_READ_FIELD(ah, AR_PHY_MODE,
                           AR_PHY_MODE_DYNAMIC) == 0x1)
                REG_RMW_FIELD(ah, AR_PHY_SPUR_REG,
                              AR_PHY_SPUR_REG_ENABLE_NF_RSSI_SPUR_MIT, 1);
@@@ -905,7 -904,7 +905,7 @@@ static bool ar9003_hw_ani_control(struc
  {
        struct ath_common *common = ath9k_hw_common(ah);
        struct ath9k_channel *chan = ah->curchan;
-       struct ar5416AniState *aniState = &chan->ani;
+       struct ar5416AniState *aniState = &ah->ani;
        s32 value, value2;
  
        switch (cmd & ah->ani_function) {
@@@ -1173,7 -1172,7 +1173,7 @@@ static void ar9003_hw_ani_cache_ini_reg
        struct ath9k_ani_default *iniDef;
        u32 val;
  
-       aniState = &ah->curchan->ani;
+       aniState = &ah->ani;
        iniDef = &aniState->iniDef;
  
        ath_dbg(common, ANI, "ver %d.%d opmode %u chan %d Mhz/0x%x\n",
        /* these levels just got reset to defaults by the INI */
        aniState->spurImmunityLevel = ATH9K_ANI_SPUR_IMMUNE_LVL;
        aniState->firstepLevel = ATH9K_ANI_FIRSTEP_LVL;
-       aniState->ofdmWeakSigDetect = ATH9K_ANI_USE_OFDM_WEAK_SIG;
+       aniState->ofdmWeakSigDetect = true;
        aniState->mrcCCK = true;
  }
  
index 42b03dc39d1423561dff8fb08f95be67f54ea5bb,579ed9c40b3f293cce9a38f7c22152e4721407ee..18fcee4e9d6847a5bb07abf0c06bbf0b18c69bba
@@@ -251,9 -251,9 +251,9 @@@ struct ath_atx_tid 
        int tidno;
        int baw_head;   /* first un-acked tx buffer */
        int baw_tail;   /* next unused tx buffer slot */
 -      int sched;
 -      int paused;
 -      u8 state;
 +      bool sched;
 +      bool paused;
 +      bool active;
  };
  
  struct ath_node {
  #endif
  };
  
 -#define AGGR_CLEANUP         BIT(1)
 -#define AGGR_ADDBA_COMPLETE  BIT(2)
 -#define AGGR_ADDBA_PROGRESS  BIT(3)
 -
  struct ath_tx_control {
        struct ath_txq *txq;
        struct ath_node *an;
@@@ -642,6 -646,7 +642,7 @@@ enum sc_op_flags 
        SC_OP_ANI_RUN,
        SC_OP_PRIM_STA_VIF,
        SC_OP_HW_RESET,
+       SC_OP_SCANNING,
  };
  
  /* Powersave flags */
@@@ -755,7 -760,6 +756,6 @@@ struct ath_softc 
        struct rchan *rfs_chan_spec_scan;
        enum spectral_mode spectral_mode;
        struct ath_spec_scan spec_config;
-       int scanning;
  
  #ifdef CONFIG_PM_SLEEP
        atomic_t wow_got_bmiss_intr;
index 51cc0fa5cd3e4f3bb2b351ac780d8228e9a64685,7852f6e599649db9ff165681b7973fc3f59ddb70..87454f6c7b4f0b1af790d8cab084e108f44f1d8c
@@@ -69,7 -69,7 +69,7 @@@ static ssize_t write_file_debug(struct 
                return -EFAULT;
  
        buf[len] = '\0';
 -      if (strict_strtoul(buf, 0, &mask))
 +      if (kstrtoul(buf, 0, &mask))
                return -EINVAL;
  
        common->debug_mask = mask;
@@@ -114,7 -114,7 +114,7 @@@ static ssize_t write_file_tx_chainmask(
                return -EFAULT;
  
        buf[len] = '\0';
 -      if (strict_strtoul(buf, 0, &mask))
 +      if (kstrtoul(buf, 0, &mask))
                return -EINVAL;
  
        ah->txchainmask = mask;
@@@ -157,7 -157,7 +157,7 @@@ static ssize_t write_file_rx_chainmask(
                return -EFAULT;
  
        buf[len] = '\0';
 -      if (strict_strtoul(buf, 0, &mask))
 +      if (kstrtoul(buf, 0, &mask))
                return -EINVAL;
  
        ah->rxchainmask = mask;
@@@ -173,25 -173,69 +173,69 @@@ static const struct file_operations fop
        .llseek = default_llseek,
  };
  
- static ssize_t read_file_disable_ani(struct file *file, char __user *user_buf,
+ static ssize_t read_file_ani(struct file *file, char __user *user_buf,
                             size_t count, loff_t *ppos)
  {
        struct ath_softc *sc = file->private_data;
        struct ath_common *common = ath9k_hw_common(sc->sc_ah);
-       char buf[32];
-       unsigned int len;
+       struct ath_hw *ah = sc->sc_ah;
+       unsigned int len = 0, size = 1024;
+       ssize_t retval = 0;
+       char *buf;
  
-       len = sprintf(buf, "%d\n", common->disable_ani);
-       return simple_read_from_buffer(user_buf, count, ppos, buf, len);
+       buf = kzalloc(size, GFP_KERNEL);
+       if (buf == NULL)
+               return -ENOMEM;
+       if (common->disable_ani) {
+               len += snprintf(buf + len, size - len, "%s: %s\n",
+                               "ANI", "DISABLED");
+               goto exit;
+       }
+       len += snprintf(buf + len, size - len, "%15s: %s\n",
+                       "ANI", "ENABLED");
+       len += snprintf(buf + len, size - len, "%15s: %u\n",
+                       "ANI RESET", ah->stats.ast_ani_reset);
+       len += snprintf(buf + len, size - len, "%15s: %u\n",
+                       "SPUR UP", ah->stats.ast_ani_spurup);
+       len += snprintf(buf + len, size - len, "%15s: %u\n",
+                       "SPUR DOWN", ah->stats.ast_ani_spurup);
+       len += snprintf(buf + len, size - len, "%15s: %u\n",
+                       "OFDM WS-DET ON", ah->stats.ast_ani_ofdmon);
+       len += snprintf(buf + len, size - len, "%15s: %u\n",
+                       "OFDM WS-DET OFF", ah->stats.ast_ani_ofdmoff);
+       len += snprintf(buf + len, size - len, "%15s: %u\n",
+                       "MRC-CCK ON", ah->stats.ast_ani_ccklow);
+       len += snprintf(buf + len, size - len, "%15s: %u\n",
+                       "MRC-CCK OFF", ah->stats.ast_ani_cckhigh);
+       len += snprintf(buf + len, size - len, "%15s: %u\n",
+                       "FIR-STEP UP", ah->stats.ast_ani_stepup);
+       len += snprintf(buf + len, size - len, "%15s: %u\n",
+                       "FIR-STEP DOWN", ah->stats.ast_ani_stepdown);
+       len += snprintf(buf + len, size - len, "%15s: %u\n",
+                       "INV LISTENTIME", ah->stats.ast_ani_lneg_or_lzero);
+       len += snprintf(buf + len, size - len, "%15s: %u\n",
+                       "OFDM ERRORS", ah->stats.ast_ani_ofdmerrs);
+       len += snprintf(buf + len, size - len, "%15s: %u\n",
+                       "CCK ERRORS", ah->stats.ast_ani_cckerrs);
+ exit:
+       if (len > size)
+               len = size;
+       retval = simple_read_from_buffer(user_buf, count, ppos, buf, len);
+       kfree(buf);
+       return retval;
  }
  
- static ssize_t write_file_disable_ani(struct file *file,
-                                     const char __user *user_buf,
-                                     size_t count, loff_t *ppos)
+ static ssize_t write_file_ani(struct file *file,
+                             const char __user *user_buf,
+                             size_t count, loff_t *ppos)
  {
        struct ath_softc *sc = file->private_data;
        struct ath_common *common = ath9k_hw_common(sc->sc_ah);
-       unsigned long disable_ani;
+       unsigned long ani;
        char buf[32];
        ssize_t len;
  
                return -EFAULT;
  
        buf[len] = '\0';
-       if (kstrtoul(buf, 0, &disable_ani))
 -      if (strict_strtoul(buf, 0, &ani))
++      if (kstrtoul(buf, 0, &ani))
                return -EINVAL;
  
-       common->disable_ani = !!disable_ani;
+       if (ani < 0 || ani > 1)
+               return -EINVAL;
+       common->disable_ani = !ani;
  
-       if (disable_ani) {
+       if (common->disable_ani) {
                clear_bit(SC_OP_ANI_RUN, &sc->sc_flags);
                ath_stop_ani(sc);
        } else {
        return count;
  }
  
- static const struct file_operations fops_disable_ani = {
-       .read = read_file_disable_ani,
-       .write = write_file_disable_ani,
+ static const struct file_operations fops_ani = {
+       .read = read_file_ani,
+       .write = write_file_ani,
        .open = simple_open,
        .owner = THIS_MODULE,
        .llseek = default_llseek,
@@@ -253,7 -300,7 +300,7 @@@ static ssize_t write_file_ant_diversity
                goto exit;
  
        buf[len] = '\0';
 -      if (strict_strtoul(buf, 0, &antenna_diversity))
 +      if (kstrtoul(buf, 0, &antenna_diversity))
                return -EINVAL;
  
        common->antenna_diversity = !!antenna_diversity;
@@@ -738,8 -785,6 +785,6 @@@ void ath_debug_stat_tx(struct ath_soft
                       struct ath_tx_status *ts, struct ath_txq *txq,
                       unsigned int flags)
  {
- #define TX_SAMP_DBG(c) (sc->debug.bb_mac_samp[sc->debug.sampidx].ts\
-                       [sc->debug.tsidx].c)
        int qnum = txq->axq_qnum;
  
        TX_STAT_INC(qnum, tx_pkts_all);
                TX_STAT_INC(qnum, data_underrun);
        if (ts->ts_flags & ATH9K_TX_DELIM_UNDERRUN)
                TX_STAT_INC(qnum, delim_underrun);
- #ifdef CONFIG_ATH9K_MAC_DEBUG
-       spin_lock(&sc->debug.samp_lock);
-       TX_SAMP_DBG(jiffies) = jiffies;
-       TX_SAMP_DBG(rssi_ctl0) = ts->ts_rssi_ctl0;
-       TX_SAMP_DBG(rssi_ctl1) = ts->ts_rssi_ctl1;
-       TX_SAMP_DBG(rssi_ctl2) = ts->ts_rssi_ctl2;
-       TX_SAMP_DBG(rssi_ext0) = ts->ts_rssi_ext0;
-       TX_SAMP_DBG(rssi_ext1) = ts->ts_rssi_ext1;
-       TX_SAMP_DBG(rssi_ext2) = ts->ts_rssi_ext2;
-       TX_SAMP_DBG(rateindex) = ts->ts_rateindex;
-       TX_SAMP_DBG(isok) = !!(ts->ts_status & ATH9K_TXERR_MASK);
-       TX_SAMP_DBG(rts_fail_cnt) = ts->ts_shortretry;
-       TX_SAMP_DBG(data_fail_cnt) = ts->ts_longretry;
-       TX_SAMP_DBG(rssi) = ts->ts_rssi;
-       TX_SAMP_DBG(tid) = ts->tid;
-       TX_SAMP_DBG(qid) = ts->qid;
-       if (ts->ts_flags & ATH9K_TX_BA) {
-               TX_SAMP_DBG(ba_low) = ts->ba_low;
-               TX_SAMP_DBG(ba_high) = ts->ba_high;
-       } else {
-               TX_SAMP_DBG(ba_low) = 0;
-               TX_SAMP_DBG(ba_high) = 0;
-       }
-       sc->debug.tsidx = (sc->debug.tsidx + 1) % ATH_DBG_MAX_SAMPLES;
-       spin_unlock(&sc->debug.samp_lock);
- #endif
- #undef TX_SAMP_DBG
  }
  
  static const struct file_operations fops_xmit = {
@@@ -915,8 -929,6 +929,6 @@@ static ssize_t read_file_recv(struct fi
  void ath_debug_stat_rx(struct ath_softc *sc, struct ath_rx_status *rs)
  {
  #define RX_PHY_ERR_INC(c) sc->debug.stats.rxstats.phy_err_stats[c]++
- #define RX_SAMP_DBG(c) (sc->debug.bb_mac_samp[sc->debug.sampidx].rs\
-                       [sc->debug.rsidx].c)
  
        RX_STAT_INC(rx_pkts_all);
        sc->debug.stats.rxstats.rx_bytes_all += rs->rs_datalen;
                        RX_PHY_ERR_INC(rs->rs_phyerr);
        }
  
- #ifdef CONFIG_ATH9K_MAC_DEBUG
-       spin_lock(&sc->debug.samp_lock);
-       RX_SAMP_DBG(jiffies) = jiffies;
-       RX_SAMP_DBG(rssi_ctl0) = rs->rs_rssi_ctl0;
-       RX_SAMP_DBG(rssi_ctl1) = rs->rs_rssi_ctl1;
-       RX_SAMP_DBG(rssi_ctl2) = rs->rs_rssi_ctl2;
-       RX_SAMP_DBG(rssi_ext0) = rs->rs_rssi_ext0;
-       RX_SAMP_DBG(rssi_ext1) = rs->rs_rssi_ext1;
-       RX_SAMP_DBG(rssi_ext2) = rs->rs_rssi_ext2;
-       RX_SAMP_DBG(antenna) = rs->rs_antenna;
-       RX_SAMP_DBG(rssi) = rs->rs_rssi;
-       RX_SAMP_DBG(rate) = rs->rs_rate;
-       RX_SAMP_DBG(is_mybeacon) = rs->is_mybeacon;
-       sc->debug.rsidx = (sc->debug.rsidx + 1) % ATH_DBG_MAX_SAMPLES;
-       spin_unlock(&sc->debug.samp_lock);
- #endif
  #undef RX_PHY_ERR_INC
- #undef RX_SAMP_DBG
  }
  
  static const struct file_operations fops_recv = {
@@@ -1278,7 -1270,7 +1270,7 @@@ static ssize_t write_file_regidx(struc
                return -EFAULT;
  
        buf[len] = '\0';
 -      if (strict_strtoul(buf, 0, &regidx))
 +      if (kstrtoul(buf, 0, &regidx))
                return -EINVAL;
  
        sc->debug.regidx = regidx;
@@@ -1323,7 -1315,7 +1315,7 @@@ static ssize_t write_file_regval(struc
                return -EFAULT;
  
        buf[len] = '\0';
 -      if (strict_strtoul(buf, 0, &regval))
 +      if (kstrtoul(buf, 0, &regval))
                return -EINVAL;
  
        ath9k_ps_wakeup(sc);
@@@ -1485,283 -1477,6 +1477,6 @@@ static const struct file_operations fop
        .llseek = default_llseek,
  };
  
- #ifdef CONFIG_ATH9K_MAC_DEBUG
- void ath9k_debug_samp_bb_mac(struct ath_softc *sc)
- {
- #define ATH_SAMP_DBG(c) (sc->debug.bb_mac_samp[sc->debug.sampidx].c)
-       struct ath_hw *ah = sc->sc_ah;
-       struct ath_common *common = ath9k_hw_common(ah);
-       unsigned long flags;
-       int i;
-       ath9k_ps_wakeup(sc);
-       spin_lock_bh(&sc->debug.samp_lock);
-       spin_lock_irqsave(&common->cc_lock, flags);
-       ath_hw_cycle_counters_update(common);
-       ATH_SAMP_DBG(cc.cycles) = common->cc_ani.cycles;
-       ATH_SAMP_DBG(cc.rx_busy) = common->cc_ani.rx_busy;
-       ATH_SAMP_DBG(cc.rx_frame) = common->cc_ani.rx_frame;
-       ATH_SAMP_DBG(cc.tx_frame) = common->cc_ani.tx_frame;
-       spin_unlock_irqrestore(&common->cc_lock, flags);
-       ATH_SAMP_DBG(noise) = ah->noise;
-       REG_WRITE_D(ah, AR_MACMISC,
-                 ((AR_MACMISC_DMA_OBS_LINE_8 << AR_MACMISC_DMA_OBS_S) |
-                  (AR_MACMISC_MISC_OBS_BUS_1 <<
-                   AR_MACMISC_MISC_OBS_BUS_MSB_S)));
-       for (i = 0; i < ATH9K_NUM_DMA_DEBUG_REGS; i++)
-               ATH_SAMP_DBG(dma_dbg_reg_vals[i]) = REG_READ_D(ah,
-                               AR_DMADBG_0 + (i * sizeof(u32)));
-       ATH_SAMP_DBG(pcu_obs) = REG_READ_D(ah, AR_OBS_BUS_1);
-       ATH_SAMP_DBG(pcu_cr) = REG_READ_D(ah, AR_CR);
-       memcpy(ATH_SAMP_DBG(nfCalHist), sc->caldata.nfCalHist,
-                       sizeof(ATH_SAMP_DBG(nfCalHist)));
-       sc->debug.sampidx = (sc->debug.sampidx + 1) % ATH_DBG_MAX_SAMPLES;
-       spin_unlock_bh(&sc->debug.samp_lock);
-       ath9k_ps_restore(sc);
- #undef ATH_SAMP_DBG
- }
- static int open_file_bb_mac_samps(struct inode *inode, struct file *file)
- {
- #define ATH_SAMP_DBG(c) bb_mac_samp[sampidx].c
-       struct ath_softc *sc = inode->i_private;
-       struct ath_hw *ah = sc->sc_ah;
-       struct ath_common *common = ath9k_hw_common(ah);
-       struct ieee80211_conf *conf = &common->hw->conf;
-       struct ath_dbg_bb_mac_samp *bb_mac_samp;
-       struct ath9k_nfcal_hist *h;
-       int i, j, qcuOffset = 0, dcuOffset = 0;
-       u32 *qcuBase, *dcuBase, size = 30000, len = 0;
-       u32 sampidx = 0;
-       u8 *buf;
-       u8 chainmask = (ah->rxchainmask << 3) | ah->rxchainmask;
-       u8 nread;
-       if (test_bit(SC_OP_INVALID, &sc->sc_flags))
-               return -EAGAIN;
-       buf = vmalloc(size);
-       if (!buf)
-               return -ENOMEM;
-       bb_mac_samp = vmalloc(sizeof(*bb_mac_samp) * ATH_DBG_MAX_SAMPLES);
-       if (!bb_mac_samp) {
-               vfree(buf);
-               return -ENOMEM;
-       }
-       /* Account the current state too */
-       ath9k_debug_samp_bb_mac(sc);
-       spin_lock_bh(&sc->debug.samp_lock);
-       memcpy(bb_mac_samp, sc->debug.bb_mac_samp,
-                       sizeof(*bb_mac_samp) * ATH_DBG_MAX_SAMPLES);
-       len += snprintf(buf + len, size - len,
-                       "Current Sample Index: %d\n", sc->debug.sampidx);
-       spin_unlock_bh(&sc->debug.samp_lock);
-       len += snprintf(buf + len, size - len,
-                       "Raw DMA Debug Dump:\n");
-       len += snprintf(buf + len, size - len, "Sample |\t");
-       for (i = 0; i < ATH9K_NUM_DMA_DEBUG_REGS; i++)
-               len += snprintf(buf + len, size - len, " DMA Reg%d |\t", i);
-       len += snprintf(buf + len, size - len, "\n");
-       for (sampidx = 0; sampidx < ATH_DBG_MAX_SAMPLES; sampidx++) {
-               len += snprintf(buf + len, size - len, "%d\t", sampidx);
-               for (i = 0; i < ATH9K_NUM_DMA_DEBUG_REGS; i++)
-                       len += snprintf(buf + len, size - len, " %08x\t",
-                                       ATH_SAMP_DBG(dma_dbg_reg_vals[i]));
-               len += snprintf(buf + len, size - len, "\n");
-       }
-       len += snprintf(buf + len, size - len, "\n");
-       len += snprintf(buf + len, size - len,
-                       "Sample Num QCU: chain_st fsp_ok fsp_st DCU: chain_st\n");
-       for (sampidx = 0; sampidx < ATH_DBG_MAX_SAMPLES; sampidx++) {
-               qcuBase = &ATH_SAMP_DBG(dma_dbg_reg_vals[0]);
-               dcuBase = &ATH_SAMP_DBG(dma_dbg_reg_vals[4]);
-               for (i = 0; i < ATH9K_NUM_QUEUES; i++,
-                               qcuOffset += 4, dcuOffset += 5) {
-                       if (i == 8) {
-                               qcuOffset = 0;
-                               qcuBase++;
-                       }
-                       if (i == 6) {
-                               dcuOffset = 0;
-                               dcuBase++;
-                       }
-                       if (!sc->debug.stats.txstats[i].queued)
-                               continue;
-                       len += snprintf(buf + len, size - len,
-                               "%4d %7d    %2x      %1x     %2x         %2x\n",
-                               sampidx, i,
-                               (*qcuBase & (0x7 << qcuOffset)) >> qcuOffset,
-                               (*qcuBase & (0x8 << qcuOffset)) >>
-                               (qcuOffset + 3),
-                               ATH_SAMP_DBG(dma_dbg_reg_vals[2]) &
-                               (0x7 << (i * 3)) >> (i * 3),
-                               (*dcuBase & (0x1f << dcuOffset)) >> dcuOffset);
-               }
-               len += snprintf(buf + len, size - len, "\n");
-       }
-       len += snprintf(buf + len, size - len,
-                       "samp qcu_sh qcu_fh qcu_comp dcu_comp dcu_arb dcu_fp "
-                       "ch_idle_dur ch_idle_dur_val txfifo_val0 txfifo_val1 "
-                       "txfifo_dcu0 txfifo_dcu1 pcu_obs AR_CR\n");
-       for (sampidx = 0; sampidx < ATH_DBG_MAX_SAMPLES; sampidx++) {
-               qcuBase = &ATH_SAMP_DBG(dma_dbg_reg_vals[0]);
-               dcuBase = &ATH_SAMP_DBG(dma_dbg_reg_vals[4]);
-               len += snprintf(buf + len, size - len, "%4d %5x %5x ", sampidx,
-                       (ATH_SAMP_DBG(dma_dbg_reg_vals[3]) & 0x003c0000) >> 18,
-                       (ATH_SAMP_DBG(dma_dbg_reg_vals[3]) & 0x03c00000) >> 22);
-               len += snprintf(buf + len, size - len, "%7x %8x ",
-                       (ATH_SAMP_DBG(dma_dbg_reg_vals[3]) & 0x1c000000) >> 26,
-                       (ATH_SAMP_DBG(dma_dbg_reg_vals[6]) & 0x3));
-               len += snprintf(buf + len, size - len, "%7x %7x ",
-                       (ATH_SAMP_DBG(dma_dbg_reg_vals[5]) & 0x06000000) >> 25,
-                       (ATH_SAMP_DBG(dma_dbg_reg_vals[5]) & 0x38000000) >> 27);
-               len += snprintf(buf + len, size - len, "%7d %12d ",
-                       (ATH_SAMP_DBG(dma_dbg_reg_vals[6]) & 0x000003fc) >> 2,
-                       (ATH_SAMP_DBG(dma_dbg_reg_vals[6]) & 0x00000400) >> 10);
-               len += snprintf(buf + len, size - len, "%12d %12d ",
-                       (ATH_SAMP_DBG(dma_dbg_reg_vals[6]) & 0x00000800) >> 11,
-                       (ATH_SAMP_DBG(dma_dbg_reg_vals[6]) & 0x00001000) >> 12);
-               len += snprintf(buf + len, size - len, "%12d %12d ",
-                       (ATH_SAMP_DBG(dma_dbg_reg_vals[6]) & 0x0001e000) >> 13,
-                       (ATH_SAMP_DBG(dma_dbg_reg_vals[6]) & 0x001e0000) >> 17);
-               len += snprintf(buf + len, size - len, "0x%07x 0x%07x\n",
-                               ATH_SAMP_DBG(pcu_obs), ATH_SAMP_DBG(pcu_cr));
-       }
-       len += snprintf(buf + len, size - len,
-                       "Sample ChNoise Chain privNF #Reading Readings\n");
-       for (sampidx = 0; sampidx < ATH_DBG_MAX_SAMPLES; sampidx++) {
-               h = ATH_SAMP_DBG(nfCalHist);
-               if (!ATH_SAMP_DBG(noise))
-                       continue;
-               for (i = 0; i < NUM_NF_READINGS; i++) {
-                       if (!(chainmask & (1 << i)) ||
-                           ((i >= AR5416_MAX_CHAINS) && !conf_is_ht40(conf)))
-                               continue;
-                       nread = AR_PHY_CCA_FILTERWINDOW_LENGTH -
-                               h[i].invalidNFcount;
-                       len += snprintf(buf + len, size - len,
-                                       "%4d %5d %4d\t   %d\t %d\t",
-                                       sampidx, ATH_SAMP_DBG(noise),
-                                       i, h[i].privNF, nread);
-                       for (j = 0; j < nread; j++)
-                               len += snprintf(buf + len, size - len,
-                                       " %d", h[i].nfCalBuffer[j]);
-                       len += snprintf(buf + len, size - len, "\n");
-               }
-       }
-       len += snprintf(buf + len, size - len, "\nCycle counters:\n"
-                       "Sample Total    Rxbusy   Rxframes Txframes\n");
-       for (sampidx = 0; sampidx < ATH_DBG_MAX_SAMPLES; sampidx++) {
-               if (!ATH_SAMP_DBG(cc.cycles))
-                       continue;
-               len += snprintf(buf + len, size - len,
-                               "%4d %08x %08x %08x %08x\n",
-                               sampidx, ATH_SAMP_DBG(cc.cycles),
-                               ATH_SAMP_DBG(cc.rx_busy),
-                               ATH_SAMP_DBG(cc.rx_frame),
-                               ATH_SAMP_DBG(cc.tx_frame));
-       }
-       len += snprintf(buf + len, size - len, "Tx status Dump :\n");
-       len += snprintf(buf + len, size - len,
-                       "Sample rssi:- ctl0 ctl1 ctl2 ext0 ext1 ext2 comb "
-                       "isok rts_fail data_fail rate tid qid "
-                                       "ba_low  ba_high tx_before(ms)\n");
-       for (sampidx = 0; sampidx < ATH_DBG_MAX_SAMPLES; sampidx++) {
-               for (i = 0; i < ATH_DBG_MAX_SAMPLES; i++) {
-                       if (!ATH_SAMP_DBG(ts[i].jiffies))
-                               continue;
-                       len += snprintf(buf + len, size - len, "%-14d"
-                               "%-4d %-4d %-4d %-4d %-4d %-4d %-4d %-4d %-8d "
-                               "%-9d %-4d %-3d %-3d %08x %08x %-11d\n",
-                               sampidx,
-                               ATH_SAMP_DBG(ts[i].rssi_ctl0),
-                               ATH_SAMP_DBG(ts[i].rssi_ctl1),
-                               ATH_SAMP_DBG(ts[i].rssi_ctl2),
-                               ATH_SAMP_DBG(ts[i].rssi_ext0),
-                               ATH_SAMP_DBG(ts[i].rssi_ext1),
-                               ATH_SAMP_DBG(ts[i].rssi_ext2),
-                               ATH_SAMP_DBG(ts[i].rssi),
-                               ATH_SAMP_DBG(ts[i].isok),
-                               ATH_SAMP_DBG(ts[i].rts_fail_cnt),
-                               ATH_SAMP_DBG(ts[i].data_fail_cnt),
-                               ATH_SAMP_DBG(ts[i].rateindex),
-                               ATH_SAMP_DBG(ts[i].tid),
-                               ATH_SAMP_DBG(ts[i].qid),
-                               ATH_SAMP_DBG(ts[i].ba_low),
-                               ATH_SAMP_DBG(ts[i].ba_high),
-                               jiffies_to_msecs(jiffies -
-                                       ATH_SAMP_DBG(ts[i].jiffies)));
-               }
-       }
-       len += snprintf(buf + len, size - len, "Rx status Dump :\n");
-       len += snprintf(buf + len, size - len, "Sample rssi:- ctl0 ctl1 ctl2 "
-                       "ext0 ext1 ext2 comb beacon ant rate rx_before(ms)\n");
-       for (sampidx = 0; sampidx < ATH_DBG_MAX_SAMPLES; sampidx++) {
-               for (i = 0; i < ATH_DBG_MAX_SAMPLES; i++) {
-                       if (!ATH_SAMP_DBG(rs[i].jiffies))
-                               continue;
-                       len += snprintf(buf + len, size - len, "%-14d"
-                               "%-4d %-4d %-4d %-4d %-4d %-4d %-4d %-9s %-2d %02x %-13d\n",
-                               sampidx,
-                               ATH_SAMP_DBG(rs[i].rssi_ctl0),
-                               ATH_SAMP_DBG(rs[i].rssi_ctl1),
-                               ATH_SAMP_DBG(rs[i].rssi_ctl2),
-                               ATH_SAMP_DBG(rs[i].rssi_ext0),
-                               ATH_SAMP_DBG(rs[i].rssi_ext1),
-                               ATH_SAMP_DBG(rs[i].rssi_ext2),
-                               ATH_SAMP_DBG(rs[i].rssi),
-                               ATH_SAMP_DBG(rs[i].is_mybeacon) ?
-                               "True" : "False",
-                               ATH_SAMP_DBG(rs[i].antenna),
-                               ATH_SAMP_DBG(rs[i].rate),
-                               jiffies_to_msecs(jiffies -
-                                       ATH_SAMP_DBG(rs[i].jiffies)));
-               }
-       }
-       vfree(bb_mac_samp);
-       file->private_data = buf;
-       return 0;
- #undef ATH_SAMP_DBG
- }
- static const struct file_operations fops_samps = {
-       .open = open_file_bb_mac_samps,
-       .read = ath9k_debugfs_read_buf,
-       .release = ath9k_debugfs_release_buf,
-       .owner = THIS_MODULE,
-       .llseek = default_llseek,
- };
- #endif
  #ifdef CONFIG_ATH9K_BTCOEX_SUPPORT
  static ssize_t read_file_btcoex(struct file *file, char __user *user_buf,
                                size_t count, loff_t *ppos)
@@@ -2008,14 -1723,6 +1723,14 @@@ void ath9k_get_et_stats(struct ieee8021
        WARN_ON(i != ATH9K_SSTATS_LEN);
  }
  
 +void ath9k_deinit_debug(struct ath_softc *sc)
 +{
 +      if (config_enabled(CONFIG_ATH9K_DEBUGFS) && sc->rfs_chan_spec_scan) {
 +              relay_close(sc->rfs_chan_spec_scan);
 +              sc->rfs_chan_spec_scan = NULL;
 +      }
 +}
 +
  int ath9k_init_debug(struct ath_hw *ah)
  {
        struct ath_common *common = ath9k_hw_common(ah);
                            sc->debug.debugfs_phy, sc, &fops_rx_chainmask);
        debugfs_create_file("tx_chainmask", S_IRUSR | S_IWUSR,
                            sc->debug.debugfs_phy, sc, &fops_tx_chainmask);
-       debugfs_create_file("disable_ani", S_IRUSR | S_IWUSR,
-                           sc->debug.debugfs_phy, sc, &fops_disable_ani);
+       debugfs_create_file("ani", S_IRUSR | S_IWUSR,
+                           sc->debug.debugfs_phy, sc, &fops_ani);
        debugfs_create_bool("paprd", S_IRUSR | S_IWUSR, sc->debug.debugfs_phy,
                            &sc->sc_ah->config.enable_paprd);
        debugfs_create_file("regidx", S_IRUSR | S_IWUSR, sc->debug.debugfs_phy,
        debugfs_create_file("spectral_fft_period", S_IRUSR | S_IWUSR,
                            sc->debug.debugfs_phy, sc,
                            &fops_spectral_fft_period);
- #ifdef CONFIG_ATH9K_MAC_DEBUG
-       debugfs_create_file("samples", S_IRUSR, sc->debug.debugfs_phy, sc,
-                           &fops_samps);
- #endif
        debugfs_create_u32("gpio_mask", S_IRUSR | S_IWUSR,
                           sc->debug.debugfs_phy, &sc->sc_ah->gpio_mask);
        debugfs_create_u32("gpio_val", S_IRUSR | S_IWUSR,
index 9d49aab8b989fe733d98ea27793f2db01874d66a,9719378f7c73c941b48b9ca9d5fc1250f2d6ea6f..fc679198a0f38049a385fb53ab25209b23945827
@@@ -251,60 -251,13 +251,14 @@@ struct ath_stats 
        u32 reset[__RESET_TYPE_MAX];
  };
  
- #define ATH_DBG_MAX_SAMPLES   10
- struct ath_dbg_bb_mac_samp {
-       u32 dma_dbg_reg_vals[ATH9K_NUM_DMA_DEBUG_REGS];
-       u32 pcu_obs, pcu_cr, noise;
-       struct {
-               u64 jiffies;
-               int8_t rssi_ctl0;
-               int8_t rssi_ctl1;
-               int8_t rssi_ctl2;
-               int8_t rssi_ext0;
-               int8_t rssi_ext1;
-               int8_t rssi_ext2;
-               int8_t rssi;
-               bool isok;
-               u8 rts_fail_cnt;
-               u8 data_fail_cnt;
-               u8 rateindex;
-               u8 qid;
-               u8 tid;
-               u32 ba_low;
-               u32 ba_high;
-       } ts[ATH_DBG_MAX_SAMPLES];
-       struct {
-               u64 jiffies;
-               int8_t rssi_ctl0;
-               int8_t rssi_ctl1;
-               int8_t rssi_ctl2;
-               int8_t rssi_ext0;
-               int8_t rssi_ext1;
-               int8_t rssi_ext2;
-               int8_t rssi;
-               bool is_mybeacon;
-               u8 antenna;
-               u8 rate;
-       } rs[ATH_DBG_MAX_SAMPLES];
-       struct ath_cycle_counters cc;
-       struct ath9k_nfcal_hist nfCalHist[NUM_NF_READINGS];
- };
  struct ath9k_debug {
        struct dentry *debugfs_phy;
        u32 regidx;
        struct ath_stats stats;
- #ifdef CONFIG_ATH9K_MAC_DEBUG
-       spinlock_t samp_lock;
-       struct ath_dbg_bb_mac_samp bb_mac_samp[ATH_DBG_MAX_SAMPLES];
-       u8 sampidx;
-       u8 tsidx;
-       u8 rsidx;
- #endif
  };
  
  int ath9k_init_debug(struct ath_hw *ah);
 +void ath9k_deinit_debug(struct ath_softc *sc);
  
  void ath_debug_stat_interrupt(struct ath_softc *sc, enum ath9k_int status);
  void ath_debug_stat_tx(struct ath_softc *sc, struct ath_buf *bf,
@@@ -340,10 -293,6 +294,10 @@@ static inline int ath9k_init_debug(stru
        return 0;
  }
  
 +static inline void ath9k_deinit_debug(struct ath_softc *sc)
 +{
 +}
 +
  static inline void ath_debug_stat_interrupt(struct ath_softc *sc,
                                            enum ath9k_int status)
  {
@@@ -364,17 -313,4 +318,4 @@@ static inline void ath_debug_stat_rx(st
  
  #endif /* CONFIG_ATH9K_DEBUGFS */
  
- #ifdef CONFIG_ATH9K_MAC_DEBUG
- void ath9k_debug_samp_bb_mac(struct ath_softc *sc);
- #else
- static inline void ath9k_debug_samp_bb_mac(struct ath_softc *sc)
- {
- }
- #endif
  #endif /* DEBUG_H */
index 15dfefcf2d0fca7ef80f3eb64752c47c0bea5d45,a13f6cea2ba7042e805472763dd038d29318a3b3..d813ab8104d69bb3a7aca16764839d89f4b788c5
@@@ -452,7 -452,6 +452,6 @@@ static void ath9k_hw_init_config(struc
        ah->config.pcie_clock_req = 0;
        ah->config.pcie_waen = 0;
        ah->config.analog_shiftreg = 1;
-       ah->config.enable_ani = true;
  
        for (i = 0; i < AR_EEPROM_MODAL_SPURS; i++) {
                ah->config.spurchans[i][0] = AR_NO_SPUR;
@@@ -549,8 -548,7 +548,7 @@@ static int ath9k_hw_post_init(struct at
                ah->eep_ops->get_eeprom_ver(ah),
                ah->eep_ops->get_eeprom_rev(ah));
  
-       if (ah->config.enable_ani)
-               ath9k_hw_ani_init(ah);
+       ath9k_hw_ani_init(ah);
  
        return 0;
  }
@@@ -1172,7 -1170,6 +1170,7 @@@ u32 ath9k_regd_get_ctl(struct ath_regul
  static inline void ath9k_hw_set_dma(struct ath_hw *ah)
  {
        struct ath_common *common = ath9k_hw_common(ah);
 +      int txbuf_size;
  
        ENABLE_REGWRITE_BUFFER(ah);
  
                 * So set the usable tx buf size also to half to
                 * avoid data/delimiter underruns
                 */
 -              REG_WRITE(ah, AR_PCU_TXBUF_CTRL,
 -                        AR_9285_PCU_TXBUF_CTRL_USABLE_SIZE);
 -      } else if (!AR_SREV_9271(ah)) {
 -              REG_WRITE(ah, AR_PCU_TXBUF_CTRL,
 -                        AR_PCU_TXBUF_CTRL_USABLE_SIZE);
 +              txbuf_size = AR_9285_PCU_TXBUF_CTRL_USABLE_SIZE;
 +      } else if (AR_SREV_9340_13_OR_LATER(ah)) {
 +              /* Uses fewer entries for AR934x v1.3+ to prevent rx overruns */
 +              txbuf_size = AR_9340_PCU_TXBUF_CTRL_USABLE_SIZE;
 +      } else {
 +              txbuf_size = AR_PCU_TXBUF_CTRL_USABLE_SIZE;
        }
  
 +      if (!AR_SREV_9271(ah))
 +              REG_WRITE(ah, AR_PCU_TXBUF_CTRL, txbuf_size);
 +
        REGWRITE_BUFFER_FLUSH(ah);
  
        if (AR_SREV_9300_20_OR_LATER(ah))
@@@ -1250,10 -1243,10 +1248,10 @@@ static void ath9k_hw_set_operating_mode
  
        switch (opmode) {
        case NL80211_IFTYPE_ADHOC:
-       case NL80211_IFTYPE_MESH_POINT:
                set |= AR_STA_ID1_ADHOC;
                REG_SET_BIT(ah, AR_CFG, AR_CFG_AP_ADHOC_INDICATION);
                break;
+       case NL80211_IFTYPE_MESH_POINT:
        case NL80211_IFTYPE_AP:
                set |= AR_STA_ID1_STA_AP;
                /* fall through */
@@@ -1311,13 -1304,9 +1309,13 @@@ static bool ath9k_hw_set_reset(struct a
                        AR_RTC_RC_COLD_RESET | AR_RTC_RC_WARM_RESET;
        } else {
                tmpReg = REG_READ(ah, AR_INTR_SYNC_CAUSE);
 -              if (tmpReg &
 -                  (AR_INTR_SYNC_LOCAL_TIMEOUT |
 -                   AR_INTR_SYNC_RADM_CPL_TIMEOUT)) {
 +              if (AR_SREV_9340(ah))
 +                      tmpReg &= AR9340_INTR_SYNC_LOCAL_TIMEOUT;
 +              else
 +                      tmpReg &= AR_INTR_SYNC_LOCAL_TIMEOUT |
 +                                AR_INTR_SYNC_RADM_CPL_TIMEOUT;
 +
 +              if (tmpReg) {
                        u32 val;
                        REG_WRITE(ah, AR_INTR_SYNC_ENABLE, 0);
  
@@@ -2255,12 -2244,12 +2253,12 @@@ void ath9k_hw_beaconinit(struct ath_hw 
  
        switch (ah->opmode) {
        case NL80211_IFTYPE_ADHOC:
-       case NL80211_IFTYPE_MESH_POINT:
                REG_SET_BIT(ah, AR_TXCFG,
                            AR_TXCFG_ADHOC_BEACON_ATIM_TX_POLICY);
                REG_WRITE(ah, AR_NEXT_NDP_TIMER, next_beacon +
                          TU_TO_USEC(ah->atim_window ? ah->atim_window : 1));
                flags |= AR_NDP_TIMER_EN;
+       case NL80211_IFTYPE_MESH_POINT:
        case NL80211_IFTYPE_AP:
                REG_WRITE(ah, AR_NEXT_TBTT_TIMER, next_beacon);
                REG_WRITE(ah, AR_NEXT_DMA_BEACON_ALERT, next_beacon -
@@@ -2604,13 -2593,8 +2602,8 @@@ int ath9k_hw_fill_cap_info(struct ath_h
                        pCap->hw_caps |= ATH9K_HW_CAP_RTT;
        }
  
-       if (AR_SREV_9280_20_OR_LATER(ah)) {
-               pCap->hw_caps |= ATH9K_HW_WOW_DEVICE_CAPABLE |
-                                ATH9K_HW_WOW_PATTERN_MATCH_EXACT;
-               if (AR_SREV_9280(ah))
-                       pCap->hw_caps |= ATH9K_HW_WOW_PATTERN_MATCH_DWORD;
-       }
+       if (AR_SREV_9462(ah))
+               pCap->hw_caps |= ATH9K_HW_WOW_DEVICE_CAPABLE;
  
        if (AR_SREV_9300_20_OR_LATER(ah) &&
            ah->eep_ops->get_eeprom(ah, EEP_PAPRD))
index aba415103f942e51d2a29553a33ebd3c9a6be960,979bde3b8f9ef0fd8e50a3a6e064680f116d24ce..daba841808cfb8e5e22c5d2acc37ee36aadcdbad
@@@ -21,6 -21,7 +21,7 @@@
  #include <linux/ath9k_platform.h>
  #include <linux/module.h>
  #include <linux/relay.h>
+ #include <net/ieee80211_radiotap.h>
  
  #include "ath9k.h"
  
@@@ -613,9 -614,6 +614,6 @@@ static int ath9k_init_softc(u16 devid, 
        spin_lock_init(&sc->sc_serial_rw);
        spin_lock_init(&sc->sc_pm_lock);
        mutex_init(&sc->mutex);
- #ifdef CONFIG_ATH9K_MAC_DEBUG
-       spin_lock_init(&sc->debug.samp_lock);
- #endif
        tasklet_init(&sc->intr_tq, ath9k_tasklet, (unsigned long)sc);
        tasklet_init(&sc->bcon_tasklet, ath9k_beacon_tasklet,
                     (unsigned long)sc);
@@@ -769,12 -767,19 +767,19 @@@ void ath9k_set_hw_capab(struct ath_soft
                IEEE80211_HW_REPORTS_TX_ACK_STATUS |
                IEEE80211_HW_SUPPORTS_RC_TABLE;
  
-       if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_HT)
-                hw->flags |= IEEE80211_HW_AMPDU_AGGREGATION;
+       if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_HT) {
+               hw->flags |= IEEE80211_HW_AMPDU_AGGREGATION;
+               if (AR_SREV_9280_20_OR_LATER(ah))
+                       hw->radiotap_mcs_details |=
+                               IEEE80211_RADIOTAP_MCS_HAVE_STBC;
+       }
  
        if (AR_SREV_9160_10_OR_LATER(sc->sc_ah) || ath9k_modparam_nohwcrypt)
                hw->flags |= IEEE80211_HW_MFP_CAPABLE;
  
+       hw->wiphy->features |= NL80211_FEATURE_ACTIVE_MONITOR;
        hw->wiphy->interface_modes =
                BIT(NL80211_IFTYPE_P2P_GO) |
                BIT(NL80211_IFTYPE_P2P_CLIENT) |
        hw->wiphy->flags |= WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL;
  
  #ifdef CONFIG_PM_SLEEP
        if ((ah->caps.hw_caps & ATH9K_HW_WOW_DEVICE_CAPABLE) &&
            device_can_wakeup(sc->dev)) {
                hw->wiphy->wowlan.flags = WIPHY_WOWLAN_MAGIC_PKT |
                                          WIPHY_WOWLAN_DISCONNECT;
                hw->wiphy->wowlan.n_patterns = MAX_NUM_USER_PATTERN;
                hw->wiphy->wowlan.pattern_min_len = 1;
                hw->wiphy->wowlan.pattern_max_len = MAX_PATTERN_SIZE;
        }
  
        atomic_set(&sc->wow_sleep_proc_intr, -1);
        atomic_set(&sc->wow_got_bmiss_intr, -1);
  #endif
  
        hw->queues = 4;
@@@ -906,7 -907,7 +907,7 @@@ int ath9k_init_device(u16 devid, struc
        if (!ath_is_world_regd(reg)) {
                error = regulatory_hint(hw->wiphy, reg->alpha2);
                if (error)
 -                      goto unregister;
 +                      goto debug_cleanup;
        }
  
        ath_init_leds(sc);
  
        return 0;
  
 +debug_cleanup:
 +      ath9k_deinit_debug(sc);
  unregister:
        ieee80211_unregister_hw(hw);
  rx_cleanup:
@@@ -944,6 -943,11 +945,6 @@@ static void ath9k_deinit_softc(struct a
                sc->dfs_detector->exit(sc->dfs_detector);
  
        ath9k_eeprom_release(sc);
 -
 -      if (config_enabled(CONFIG_ATH9K_DEBUGFS) && sc->rfs_chan_spec_scan) {
 -              relay_close(sc->rfs_chan_spec_scan);
 -              sc->rfs_chan_spec_scan = NULL;
 -      }
  }
  
  void ath9k_deinit_device(struct ath_softc *sc)
  
        ath9k_ps_restore(sc);
  
 +      ath9k_deinit_debug(sc);
        ieee80211_unregister_hw(hw);
        ath_rx_cleanup(sc);
        ath9k_deinit_softc(sc);
index 566109a40fb3887e6236b3c56d00e8ebcc70354d,d055e389abfc80d7a7b156a58ba0aa29ca9f1945..2ef05ebffbcf4d7c2167ed46c26aa192060427ed
@@@ -410,7 -410,7 +410,7 @@@ bool ath9k_hw_resettxqueue(struct ath_h
  
        REG_WRITE(ah, AR_QMISC(q), AR_Q_MISC_DCU_EARLY_TERM_REQ);
  
 -      if (AR_SREV_9340(ah))
 +      if (AR_SREV_9340(ah) && !AR_SREV_9340_13_OR_LATER(ah))
                REG_WRITE(ah, AR_DMISC(q),
                          AR_D_MISC_CW_BKOFF_EN | AR_D_MISC_FRAG_WAIT_EN | 0x1);
        else
@@@ -547,6 -547,7 +547,7 @@@ int ath9k_hw_rxprocdesc(struct ath_hw *
  
        rs->rs_status = 0;
        rs->rs_flags = 0;
+       rs->flag = 0;
  
        rs->rs_datalen = ads.ds_rxstatus1 & AR_DataLen;
        rs->rs_tstamp = ads.AR_RcvTimestamp;
        rs->rs_moreaggr =
                (ads.ds_rxstatus8 & AR_RxMoreAggr) ? 1 : 0;
        rs->rs_antenna = MS(ads.ds_rxstatus3, AR_RxAntenna);
-       rs->rs_flags =
-               (ads.ds_rxstatus3 & AR_GI) ? ATH9K_RX_GI : 0;
-       rs->rs_flags |=
-               (ads.ds_rxstatus3 & AR_2040) ? ATH9K_RX_2040 : 0;
+       /* directly mapped flags for ieee80211_rx_status */
+       rs->flag |=
+               (ads.ds_rxstatus3 & AR_GI) ? RX_FLAG_SHORT_GI : 0;
+       rs->flag |=
+               (ads.ds_rxstatus3 & AR_2040) ? RX_FLAG_40MHZ : 0;
+       if (AR_SREV_9280_20_OR_LATER(ah))
+               rs->flag |=
+                       (ads.ds_rxstatus3 & AR_STBC) ?
+                               /* we can only Nss=1 STBC */
+                               (1 << RX_FLAG_STBC_SHIFT) : 0;
  
        if (ads.ds_rxstatus8 & AR_PreDelimCRCErr)
                rs->rs_flags |= ATH9K_RX_DELIM_CRC_PRE;
index 5092ecae7706ab7140bcf7d3f88f830be176cc38,cc5a98b8d187714f6e738295190aa704610443d8..e5b186b04b29a52e67f466fb972408b554a1f24c
@@@ -193,7 -193,6 +193,6 @@@ static bool ath_prepare_reset(struct at
        ath_stop_ani(sc);
        del_timer_sync(&sc->rx_poll_timer);
  
-       ath9k_debug_samp_bb_mac(sc);
        ath9k_hw_disable_interrupts(ah);
  
        if (!ath_drain_all_txq(sc))
@@@ -1273,7 -1272,7 +1272,7 @@@ static int ath9k_config(struct ieee8021
                                curchan->center_freq);
                } else {
                        /* perform spectral scan if requested. */
-                       if (sc->scanning &&
+                       if (test_bit(SC_OP_SCANNING, &sc->sc_flags) &&
                            sc->spectral_mode == SPECTRAL_CHANSCAN)
                                ath9k_spectral_scan_trigger(hw);
                }
@@@ -1687,10 -1686,9 +1686,10 @@@ static int ath9k_ampdu_action(struct ie
                              u16 tid, u16 *ssn, u8 buf_size)
  {
        struct ath_softc *sc = hw->priv;
 +      bool flush = false;
        int ret = 0;
  
-       local_bh_disable();
+       mutex_lock(&sc->mutex);
  
        switch (action) {
        case IEEE80211_AMPDU_RX_START:
                        ieee80211_start_tx_ba_cb_irqsafe(vif, sta->addr, tid);
                ath9k_ps_restore(sc);
                break;
 -      case IEEE80211_AMPDU_TX_STOP_CONT:
        case IEEE80211_AMPDU_TX_STOP_FLUSH:
        case IEEE80211_AMPDU_TX_STOP_FLUSH_CONT:
 +              flush = true;
 +      case IEEE80211_AMPDU_TX_STOP_CONT:
                ath9k_ps_wakeup(sc);
                ath_tx_aggr_stop(sc, sta, tid);
 -              ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid);
 +              if (!flush)
 +                      ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid);
                ath9k_ps_restore(sc);
                break;
        case IEEE80211_AMPDU_TX_OPERATIONAL:
                ath_err(ath9k_hw_common(sc->sc_ah), "Unknown AMPDU action\n");
        }
  
-       local_bh_enable();
+       mutex_unlock(&sc->mutex);
  
        return ret;
  }
@@@ -2007,7 -2003,6 +2006,6 @@@ static void ath9k_wow_add_disassoc_deau
  {
        struct ath_hw *ah = sc->sc_ah;
        struct ath_common *common = ath9k_hw_common(ah);
-       struct ath9k_hw_capabilities *pcaps = &ah->caps;
        int pattern_count = 0;
        int i, byte_cnt;
        u8 dis_deauth_pattern[MAX_PATTERN_SIZE];
  
        /* Create Disassociate pattern mask */
  
-       if (pcaps->hw_caps & ATH9K_HW_WOW_PATTERN_MATCH_EXACT) {
-               if (pcaps->hw_caps & ATH9K_HW_WOW_PATTERN_MATCH_DWORD) {
-                       /*
-                        * for AR9280, because of hardware limitation, the
-                        * first 4 bytes have to be matched for all patterns.
-                        * the mask for disassociation and de-auth pattern
-                        * matching need to enable the first 4 bytes.
-                        * also the duration field needs to be filled.
-                        */
-                       dis_deauth_mask[0] = 0xf0;
-                       /*
-                        * fill in duration field
-                        FIXME: what is the exact value ?
-                        */
-                       dis_deauth_pattern[2] = 0xff;
-                       dis_deauth_pattern[3] = 0xff;
-               } else {
-                       dis_deauth_mask[0] = 0xfe;
-               }
-               dis_deauth_mask[1] = 0x03;
-               dis_deauth_mask[2] = 0xc0;
-       } else {
-               dis_deauth_mask[0] = 0xef;
-               dis_deauth_mask[1] = 0x3f;
-               dis_deauth_mask[2] = 0x00;
-               dis_deauth_mask[3] = 0xfc;
-       }
+       dis_deauth_mask[0] = 0xfe;
+       dis_deauth_mask[1] = 0x03;
+       dis_deauth_mask[2] = 0xc0;
  
        ath_dbg(common, WOW, "Adding disassoc/deauth patterns for WoW\n");
  
@@@ -2342,15 -2310,13 +2313,13 @@@ static void ath9k_set_wakeup(struct iee
  static void ath9k_sw_scan_start(struct ieee80211_hw *hw)
  {
        struct ath_softc *sc = hw->priv;
-       sc->scanning = 1;
+       set_bit(SC_OP_SCANNING, &sc->sc_flags);
  }
  
  static void ath9k_sw_scan_complete(struct ieee80211_hw *hw)
  {
        struct ath_softc *sc = hw->priv;
-       sc->scanning = 0;
+       clear_bit(SC_OP_SCANNING, &sc->sc_flags);
  }
  
  struct ieee80211_ops ath9k_ops = {
diff --combined net/mac80211/iface.c
index 7c3ba8628d4e6aefe6ce98747dada70bbc04ab55,7cabaf261fede492c77f9aa93452000732c5cb15..cc117591f678463c2cd9a3eb4060af5e01bf51ca
@@@ -159,10 -159,10 +159,11 @@@ static int ieee80211_change_mtu(struct 
        return 0;
  }
  
- static int ieee80211_verify_mac(struct ieee80211_sub_if_data *sdata, u8 *addr)
 -static int ieee80211_verify_mac(struct ieee80211_local *local, u8 *addr,
++static int ieee80211_verify_mac(struct ieee80211_sub_if_data *sdata, u8 *addr,
+                               bool check_dup)
  {
 -      struct ieee80211_sub_if_data *sdata;
 +      struct ieee80211_local *local = sdata->local;
 +      struct ieee80211_sub_if_data *iter;
        u64 new, mask, tmp;
        u8 *m;
        int ret = 0;
                ((u64)m[2] << 3*8) | ((u64)m[3] << 2*8) |
                ((u64)m[4] << 1*8) | ((u64)m[5] << 0*8);
  
+       if (!check_dup)
+               return ret;
  
        mutex_lock(&local->iflist_mtx);
 -      list_for_each_entry(sdata, &local->interfaces, list) {
 -              if (sdata->vif.type == NL80211_IFTYPE_MONITOR &&
 -                  !(sdata->u.mntr_flags & MONITOR_FLAG_ACTIVE))
 +      list_for_each_entry(iter, &local->interfaces, list) {
 +              if (iter == sdata)
                        continue;
  
-               if (iter->vif.type == NL80211_IFTYPE_MONITOR)
 -              m = sdata->vif.addr;
++              if (iter->vif.type == NL80211_IFTYPE_MONITOR &&
++                  !(iter->u.mntr_flags & MONITOR_FLAG_ACTIVE))
 +                      continue;
 +
 +              m = iter->vif.addr;
                tmp =   ((u64)m[0] << 5*8) | ((u64)m[1] << 4*8) |
                        ((u64)m[2] << 3*8) | ((u64)m[3] << 2*8) |
                        ((u64)m[4] << 1*8) | ((u64)m[5] << 0*8);
@@@ -208,12 -208,17 +212,17 @@@ static int ieee80211_change_mac(struct 
  {
        struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
        struct sockaddr *sa = addr;
+       bool check_dup = true;
        int ret;
  
        if (ieee80211_sdata_running(sdata))
                return -EBUSY;
  
-       ret = ieee80211_verify_mac(sdata, sa->sa_data);
+       if (sdata->vif.type == NL80211_IFTYPE_MONITOR &&
+           !(sdata->u.mntr_flags & MONITOR_FLAG_ACTIVE))
+               check_dup = false;
 -      ret = ieee80211_verify_mac(sdata->local, sa->sa_data, check_dup);
++      ret = ieee80211_verify_mac(sdata, sa->sa_data, check_dup);
        if (ret)
                return ret;
  
@@@ -545,7 -550,11 +554,11 @@@ int ieee80211_do_open(struct wireless_d
                        break;
                }
  
-               if (local->monitors == 0 && local->open_count == 0) {
+               if (sdata->u.mntr_flags & MONITOR_FLAG_ACTIVE) {
+                       res = drv_add_interface(local, sdata);
+                       if (res)
+                               goto err_stop;
+               } else if (local->monitors == 0 && local->open_count == 0) {
                        res = ieee80211_add_virtual_monitor(local);
                        if (res)
                                goto err_stop;
@@@ -923,7 -932,11 +936,11 @@@ static void ieee80211_do_stop(struct ie
                mutex_lock(&local->mtx);
                ieee80211_recalc_idle(local);
                mutex_unlock(&local->mtx);
-               break;
+               if (!(sdata->u.mntr_flags & MONITOR_FLAG_ACTIVE))
+                       break;
+               /* fall through */
        default:
                if (going_down)
                        drv_remove_interface(local, sdata);
@@@ -1072,7 -1085,7 +1089,7 @@@ static const struct net_device_ops ieee
        .ndo_start_xmit         = ieee80211_monitor_start_xmit,
        .ndo_set_rx_mode        = ieee80211_set_multicast_list,
        .ndo_change_mtu         = ieee80211_change_mtu,
-       .ndo_set_mac_address    = eth_mac_addr,
+       .ndo_set_mac_address    = ieee80211_change_mac,
        .ndo_select_queue       = ieee80211_monitor_select_queue,
  };
  
@@@ -1490,17 -1503,7 +1507,17 @@@ static void ieee80211_assign_perm_addr(
                        break;
                }
  
 +              /*
 +               * Pick address of existing interface in case user changed
 +               * MAC address manually, default to perm_addr.
 +               */
                m = local->hw.wiphy->perm_addr;
 +              list_for_each_entry(sdata, &local->interfaces, list) {
 +                      if (sdata->vif.type == NL80211_IFTYPE_MONITOR)
 +                              continue;
 +                      m = sdata->vif.addr;
 +                      break;
 +              }
                start = ((u64)m[0] << 5*8) | ((u64)m[1] << 4*8) |
                        ((u64)m[2] << 3*8) | ((u64)m[3] << 2*8) |
                        ((u64)m[4] << 1*8) | ((u64)m[5] << 0*8);
@@@ -1747,9 -1750,10 +1764,9 @@@ void ieee80211_remove_interfaces(struc
  }
  
  static int netdev_notify(struct notifier_block *nb,
 -                       unsigned long state,
 -                       void *ndev)
 +                       unsigned long state, void *ptr)
  {
 -      struct net_device *dev = ndev;
 +      struct net_device *dev = netdev_notifier_info_to_dev(ptr);
        struct ieee80211_sub_if_data *sdata;
  
        if (state != NETDEV_CHANGENAME)
diff --combined net/wireless/core.c
index 01e41191f1bf7f59c502f4c2499ad71304e6e4e9,41cec1776f4f1d63f3b629178aae025b511b01c6..e4df77490229da723cafc07a313fd20236d1ee3d
  MODULE_AUTHOR("Johannes Berg");
  MODULE_LICENSE("GPL");
  MODULE_DESCRIPTION("wireless configuration support");
+ MODULE_ALIAS_GENL_FAMILY(NL80211_GENL_NAME);
  
- /* RCU-protected (and cfg80211_mutex for writers) */
+ /* RCU-protected (and RTNL for writers) */
  LIST_HEAD(cfg80211_rdev_list);
  int cfg80211_rdev_list_generation;
  
- DEFINE_MUTEX(cfg80211_mutex);
  /* for debugfs */
  static struct dentry *ieee80211_debugfs_dir;
  
@@@ -52,12 -51,11 +51,11 @@@ module_param(cfg80211_disable_40mhz_24g
  MODULE_PARM_DESC(cfg80211_disable_40mhz_24ghz,
                 "Disable 40MHz support in the 2.4GHz band");
  
- /* requires cfg80211_mutex to be held! */
  struct cfg80211_registered_device *cfg80211_rdev_by_wiphy_idx(int wiphy_idx)
  {
        struct cfg80211_registered_device *result = NULL, *rdev;
  
-       assert_cfg80211_lock();
+       ASSERT_RTNL();
  
        list_for_each_entry(rdev, &cfg80211_rdev_list, list) {
                if (rdev->wiphy_idx == wiphy_idx) {
@@@ -76,12 -74,11 +74,11 @@@ int get_wiphy_idx(struct wiphy *wiphy
        return rdev->wiphy_idx;
  }
  
- /* requires cfg80211_rdev_mutex to be held! */
  struct wiphy *wiphy_idx_to_wiphy(int wiphy_idx)
  {
        struct cfg80211_registered_device *rdev;
  
-       assert_cfg80211_lock();
+       ASSERT_RTNL();
  
        rdev = cfg80211_rdev_by_wiphy_idx(wiphy_idx);
        if (!rdev)
        return &rdev->wiphy;
  }
  
- struct cfg80211_registered_device *
- cfg80211_get_dev_from_ifindex(struct net *net, int ifindex)
- {
-       struct cfg80211_registered_device *rdev = ERR_PTR(-ENODEV);
-       struct net_device *dev;
-       mutex_lock(&cfg80211_mutex);
-       dev = dev_get_by_index(net, ifindex);
-       if (!dev)
-               goto out;
-       if (dev->ieee80211_ptr) {
-               rdev = wiphy_to_dev(dev->ieee80211_ptr->wiphy);
-               mutex_lock(&rdev->mtx);
-       } else
-               rdev = ERR_PTR(-ENODEV);
-       dev_put(dev);
-  out:
-       mutex_unlock(&cfg80211_mutex);
-       return rdev;
- }
- /* requires cfg80211_mutex to be held */
  int cfg80211_dev_rename(struct cfg80211_registered_device *rdev,
                        char *newname)
  {
        struct cfg80211_registered_device *rdev2;
        int wiphy_idx, taken = -1, result, digits;
  
-       assert_cfg80211_lock();
+       ASSERT_RTNL();
  
        /* prohibit calling the thing phy%d when %d is not its number */
        sscanf(newname, PHY_NAME "%d%n", &wiphy_idx, &taken);
@@@ -215,8 -190,7 +190,7 @@@ static void cfg80211_rfkill_poll(struc
  void cfg80211_stop_p2p_device(struct cfg80211_registered_device *rdev,
                              struct wireless_dev *wdev)
  {
-       lockdep_assert_held(&rdev->devlist_mtx);
-       lockdep_assert_held(&rdev->sched_scan_mtx);
+       ASSERT_RTNL();
  
        if (WARN_ON(wdev->iftype != NL80211_IFTYPE_P2P_DEVICE))
                return;
        rdev->opencount--;
  
        if (rdev->scan_req && rdev->scan_req->wdev == wdev) {
-               bool busy = work_busy(&rdev->scan_done_wk);
                /*
-                * If the work isn't pending or running (in which case it would
-                * be waiting for the lock we hold) the driver didn't properly
-                * cancel the scan when the interface was removed. In this case
-                * warn and leak the scan request object to not crash later.
+                * If the scan request wasn't notified as done, set it
+                * to aborted and leak it after a warning. The driver
+                * should have notified us that it ended at the latest
+                * during rdev_stop_p2p_device().
                 */
-               WARN_ON(!busy);
-               rdev->scan_req->aborted = true;
-               ___cfg80211_scan_done(rdev, !busy);
+               if (WARN_ON(!rdev->scan_req->notified))
+                       rdev->scan_req->aborted = true;
+               ___cfg80211_scan_done(rdev, !rdev->scan_req->notified);
        }
  }
  
@@@ -255,8 -226,6 +226,6 @@@ static int cfg80211_rfkill_set_block(vo
  
        rtnl_lock();
  
-       /* read-only iteration need not hold the devlist_mtx */
        list_for_each_entry(wdev, &rdev->wdev_list, list) {
                if (wdev->netdev) {
                        dev_close(wdev->netdev);
                /* otherwise, check iftype */
                switch (wdev->iftype) {
                case NL80211_IFTYPE_P2P_DEVICE:
-                       /* but this requires it */
-                       mutex_lock(&rdev->devlist_mtx);
-                       mutex_lock(&rdev->sched_scan_mtx);
                        cfg80211_stop_p2p_device(rdev, wdev);
-                       mutex_unlock(&rdev->sched_scan_mtx);
-                       mutex_unlock(&rdev->devlist_mtx);
                        break;
                default:
                        break;
@@@ -298,10 -262,7 +262,7 @@@ static void cfg80211_event_work(struct 
                            event_work);
  
        rtnl_lock();
-       cfg80211_lock_rdev(rdev);
        cfg80211_process_rdev_events(rdev);
-       cfg80211_unlock_rdev(rdev);
        rtnl_unlock();
  }
  
  
  struct wiphy *wiphy_new(const struct cfg80211_ops *ops, int sizeof_priv)
  {
-       static int wiphy_counter;
+       static atomic_t wiphy_counter = ATOMIC_INIT(0);
  
        struct cfg80211_registered_device *rdev;
        int alloc_size;
  
        rdev->ops = ops;
  
-       mutex_lock(&cfg80211_mutex);
-       rdev->wiphy_idx = wiphy_counter++;
+       rdev->wiphy_idx = atomic_inc_return(&wiphy_counter);
  
        if (unlikely(rdev->wiphy_idx < 0)) {
-               wiphy_counter--;
-               mutex_unlock(&cfg80211_mutex);
                /* ugh, wrapped! */
+               atomic_dec(&wiphy_counter);
                kfree(rdev);
                return NULL;
        }
  
-       mutex_unlock(&cfg80211_mutex);
        /* give it a proper name */
        dev_set_name(&rdev->wiphy.dev, PHY_NAME "%d", rdev->wiphy_idx);
  
-       mutex_init(&rdev->mtx);
-       mutex_init(&rdev->devlist_mtx);
-       mutex_init(&rdev->sched_scan_mtx);
        INIT_LIST_HEAD(&rdev->wdev_list);
        INIT_LIST_HEAD(&rdev->beacon_registrations);
        spin_lock_init(&rdev->beacon_registrations_lock);
@@@ -598,11 -551,11 +551,11 @@@ int wiphy_register(struct wiphy *wiphy
        /* check and set up bitrates */
        ieee80211_set_bitrate_flags(wiphy);
  
-       mutex_lock(&cfg80211_mutex);
+       rtnl_lock();
  
        res = device_add(&rdev->wiphy.dev);
        if (res) {
-               mutex_unlock(&cfg80211_mutex);
+               rtnl_unlock();
                return res;
        }
  
        }
  
        cfg80211_debugfs_rdev_add(rdev);
-       mutex_unlock(&cfg80211_mutex);
  
-       /*
-        * due to a locking dependency this has to be outside of the
-        * cfg80211_mutex lock
-        */
        res = rfkill_register(rdev->rfkill);
        if (res) {
                device_del(&rdev->wiphy.dev);
  
-               mutex_lock(&cfg80211_mutex);
                debugfs_remove_recursive(rdev->wiphy.debugfsdir);
                list_del_rcu(&rdev->list);
                wiphy_regulatory_deregister(wiphy);
-               mutex_unlock(&cfg80211_mutex);
+               rtnl_unlock();
                return res;
        }
  
-       rtnl_lock();
        rdev->wiphy.registered = true;
        rtnl_unlock();
        return 0;
@@@ -679,25 -625,19 +625,19 @@@ void wiphy_unregister(struct wiphy *wip
  {
        struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
  
-       rtnl_lock();
-       rdev->wiphy.registered = false;
-       rtnl_unlock();
-       rfkill_unregister(rdev->rfkill);
-       /* protect the device list */
-       mutex_lock(&cfg80211_mutex);
        wait_event(rdev->dev_wait, ({
                int __count;
-               mutex_lock(&rdev->devlist_mtx);
+               rtnl_lock();
                __count = rdev->opencount;
-               mutex_unlock(&rdev->devlist_mtx);
+               rtnl_unlock();
                __count == 0; }));
  
-       mutex_lock(&rdev->devlist_mtx);
+       rtnl_lock();
+       rdev->wiphy.registered = false;
+       rfkill_unregister(rdev->rfkill);
        BUG_ON(!list_empty(&rdev->wdev_list));
-       mutex_unlock(&rdev->devlist_mtx);
  
        /*
         * First remove the hardware from everywhere, this makes
        list_del_rcu(&rdev->list);
        synchronize_rcu();
  
-       /*
-        * Try to grab rdev->mtx. If a command is still in progress,
-        * hopefully the driver will refuse it since it's tearing
-        * down the device already. We wait for this command to complete
-        * before unlinking the item from the list.
-        * Note: as codified by the BUG_ON above we cannot get here if
-        * a virtual interface is still present. Hence, we can only get
-        * to lock contention here if userspace issues a command that
-        * identified the hardware by wiphy index.
-        */
-       cfg80211_lock_rdev(rdev);
-       /* nothing */
-       cfg80211_unlock_rdev(rdev);
        /*
         * If this device got a regulatory hint tell core its
         * free to listen now to a new shiny device regulatory hint
        cfg80211_rdev_list_generation++;
        device_del(&rdev->wiphy.dev);
  
-       mutex_unlock(&cfg80211_mutex);
+       rtnl_unlock();
  
        flush_work(&rdev->scan_done_wk);
        cancel_work_sync(&rdev->conn_work);
        flush_work(&rdev->event_work);
        cancel_delayed_work_sync(&rdev->dfs_update_channels_wk);
  
-       if (rdev->wowlan && rdev->ops->set_wakeup)
+ #ifdef CONFIG_PM
+       if (rdev->wiphy.wowlan_config && rdev->ops->set_wakeup)
                rdev_set_wakeup(rdev, false);
+ #endif
        cfg80211_rdev_free_wowlan(rdev);
  }
  EXPORT_SYMBOL(wiphy_unregister);
@@@ -748,9 -676,6 +676,6 @@@ void cfg80211_dev_free(struct cfg80211_
        struct cfg80211_internal_bss *scan, *tmp;
        struct cfg80211_beacon_registration *reg, *treg;
        rfkill_destroy(rdev->rfkill);
-       mutex_destroy(&rdev->mtx);
-       mutex_destroy(&rdev->devlist_mtx);
-       mutex_destroy(&rdev->sched_scan_mtx);
        list_for_each_entry_safe(reg, treg, &rdev->beacon_registrations, list) {
                list_del(&reg->list);
                kfree(reg);
@@@ -775,36 -700,6 +700,6 @@@ void wiphy_rfkill_set_hw_state(struct w
  }
  EXPORT_SYMBOL(wiphy_rfkill_set_hw_state);
  
- static void wdev_cleanup_work(struct work_struct *work)
- {
-       struct wireless_dev *wdev;
-       struct cfg80211_registered_device *rdev;
-       wdev = container_of(work, struct wireless_dev, cleanup_work);
-       rdev = wiphy_to_dev(wdev->wiphy);
-       mutex_lock(&rdev->sched_scan_mtx);
-       if (WARN_ON(rdev->scan_req && rdev->scan_req->wdev == wdev)) {
-               rdev->scan_req->aborted = true;
-               ___cfg80211_scan_done(rdev, true);
-       }
-       if (WARN_ON(rdev->sched_scan_req &&
-                   rdev->sched_scan_req->dev == wdev->netdev)) {
-               __cfg80211_stop_sched_scan(rdev, false);
-       }
-       mutex_unlock(&rdev->sched_scan_mtx);
-       mutex_lock(&rdev->devlist_mtx);
-       rdev->opencount--;
-       mutex_unlock(&rdev->devlist_mtx);
-       wake_up(&rdev->dev_wait);
-       dev_put(wdev->netdev);
- }
  void cfg80211_unregister_wdev(struct wireless_dev *wdev)
  {
        struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
        if (WARN_ON(wdev->netdev))
                return;
  
-       mutex_lock(&rdev->devlist_mtx);
-       mutex_lock(&rdev->sched_scan_mtx);
        list_del_rcu(&wdev->list);
        rdev->devlist_generation++;
  
                WARN_ON_ONCE(1);
                break;
        }
-       mutex_unlock(&rdev->sched_scan_mtx);
-       mutex_unlock(&rdev->devlist_mtx);
  }
  EXPORT_SYMBOL(cfg80211_unregister_wdev);
  
@@@ -847,7 -738,7 +738,7 @@@ void cfg80211_update_iface_num(struct c
  }
  
  void cfg80211_leave(struct cfg80211_registered_device *rdev,
-                  struct wireless_dev *wdev)
+                   struct wireless_dev *wdev)
  {
        struct net_device *dev = wdev->netdev;
  
                break;
        case NL80211_IFTYPE_P2P_CLIENT:
        case NL80211_IFTYPE_STATION:
-               mutex_lock(&rdev->sched_scan_mtx);
                __cfg80211_stop_sched_scan(rdev, false);
-               mutex_unlock(&rdev->sched_scan_mtx);
  
                wdev_lock(wdev);
  #ifdef CONFIG_CFG80211_WEXT
                wdev->wext.ie_len = 0;
                wdev->wext.connect.auth_type = NL80211_AUTHTYPE_AUTOMATIC;
  #endif
-               __cfg80211_disconnect(rdev, dev,
-                                     WLAN_REASON_DEAUTH_LEAVING, true);
+               cfg80211_disconnect(rdev, dev,
+                                   WLAN_REASON_DEAUTH_LEAVING, true);
                wdev_unlock(wdev);
                break;
        case NL80211_IFTYPE_MESH_POINT:
  }
  
  static int cfg80211_netdev_notifier_call(struct notifier_block *nb,
 -                                       unsigned long state,
 -                                       void *ndev)
 +                                       unsigned long state, void *ptr)
  {
 -      struct net_device *dev = ndev;
 +      struct net_device *dev = netdev_notifier_info_to_dev(ptr);
        struct wireless_dev *wdev = dev->ieee80211_ptr;
        struct cfg80211_registered_device *rdev;
        int ret;
                 * are added with nl80211.
                 */
                mutex_init(&wdev->mtx);
-               INIT_WORK(&wdev->cleanup_work, wdev_cleanup_work);
                INIT_LIST_HEAD(&wdev->event_list);
                spin_lock_init(&wdev->event_lock);
                INIT_LIST_HEAD(&wdev->mgmt_registrations);
                spin_lock_init(&wdev->mgmt_registrations_lock);
  
-               mutex_lock(&rdev->devlist_mtx);
                wdev->identifier = ++rdev->wdev_id;
                list_add_rcu(&wdev->list, &rdev->wdev_list);
                rdev->devlist_generation++;
                }
                wdev->netdev = dev;
                wdev->sme_state = CFG80211_SME_IDLE;
-               mutex_unlock(&rdev->devlist_mtx);
  #ifdef CONFIG_CFG80211_WEXT
                wdev->wext.default_key = -1;
                wdev->wext.default_mgmt_key = -1;
                break;
        case NETDEV_DOWN:
                cfg80211_update_iface_num(rdev, wdev->iftype, -1);
-               dev_hold(dev);
-               queue_work(cfg80211_wq, &wdev->cleanup_work);
+               if (rdev->scan_req && rdev->scan_req->wdev == wdev) {
+                       if (WARN_ON(!rdev->scan_req->notified))
+                               rdev->scan_req->aborted = true;
+                       ___cfg80211_scan_done(rdev, true);
+               }
+               if (WARN_ON(rdev->sched_scan_req &&
+                           rdev->sched_scan_req->dev == wdev->netdev)) {
+                       __cfg80211_stop_sched_scan(rdev, false);
+               }
+               rdev->opencount--;
+               wake_up(&rdev->dev_wait);
                break;
        case NETDEV_UP:
-               /*
-                * If we have a really quick DOWN/UP succession we may
-                * have this work still pending ... cancel it and see
-                * if it was pending, in which case we need to account
-                * for some of the work it would have done.
-                */
-               if (cancel_work_sync(&wdev->cleanup_work)) {
-                       mutex_lock(&rdev->devlist_mtx);
-                       rdev->opencount--;
-                       mutex_unlock(&rdev->devlist_mtx);
-                       dev_put(dev);
-               }
                cfg80211_update_iface_num(rdev, wdev->iftype, 1);
-               cfg80211_lock_rdev(rdev);
-               mutex_lock(&rdev->devlist_mtx);
-               mutex_lock(&rdev->sched_scan_mtx);
                wdev_lock(wdev);
                switch (wdev->iftype) {
  #ifdef CONFIG_CFG80211_WEXT
                        break;
                }
                wdev_unlock(wdev);
-               mutex_unlock(&rdev->sched_scan_mtx);
                rdev->opencount++;
-               mutex_unlock(&rdev->devlist_mtx);
-               cfg80211_unlock_rdev(rdev);
  
                /*
                 * Configure power management to the driver here so that its
                        }
                break;
        case NETDEV_UNREGISTER:
-               /*
-                * NB: cannot take rdev->mtx here because this may be
-                * called within code protected by it when interfaces
-                * are removed with nl80211.
-                */
-               mutex_lock(&rdev->devlist_mtx);
                /*
                 * It is possible to get NETDEV_UNREGISTER
                 * multiple times. To detect that, check
                        kfree(wdev->wext.keys);
  #endif
                }
-               mutex_unlock(&rdev->devlist_mtx);
                /*
                 * synchronise (so that we won't find this netdev
                 * from other code any more) and then clear the list
                        return notifier_from_errno(-EOPNOTSUPP);
                if (rfkill_blocked(rdev->rfkill))
                        return notifier_from_errno(-ERFKILL);
-               mutex_lock(&rdev->devlist_mtx);
                ret = cfg80211_can_add_interface(rdev, wdev->iftype);
-               mutex_unlock(&rdev->devlist_mtx);
                if (ret)
                        return notifier_from_errno(ret);
                break;
@@@ -1088,12 -959,10 +958,10 @@@ static void __net_exit cfg80211_pernet_
        struct cfg80211_registered_device *rdev;
  
        rtnl_lock();
-       mutex_lock(&cfg80211_mutex);
        list_for_each_entry(rdev, &cfg80211_rdev_list, list) {
                if (net_eq(wiphy_net(&rdev->wiphy), net))
                        WARN_ON(cfg80211_switch_netns(rdev, &init_net));
        }
-       mutex_unlock(&cfg80211_mutex);
        rtnl_unlock();
  }