ath9k: merge another round of upstream (or -pending) fixes and cleanups
authornbd <nbd@3c298f89-4303-0410-b956-a3cf2f4a3e73>
Thu, 19 Dec 2013 17:18:07 +0000 (17:18 +0000)
committernbd <nbd@3c298f89-4303-0410-b956-a3cf2f4a3e73>
Thu, 19 Dec 2013 17:18:07 +0000 (17:18 +0000)
Signed-off-by: Felix Fietkau <nbd@openwrt.org>
git-svn-id: svn://svn.openwrt.org/openwrt/trunk@39138 3c298f89-4303-0410-b956-a3cf2f4a3e73

17 files changed:
package/kernel/mac80211/patches/300-pending_work.patch
package/kernel/mac80211/patches/402-ath9k-fix-invalid-mac-address-handling.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/501-ath9k-eeprom_endianess.patch
package/kernel/mac80211/patches/502-ath9k_ahb_init.patch
package/kernel/mac80211/patches/510-ath9k_intr_mitigation_tweak.patch
package/kernel/mac80211/patches/511-ath9k_reduce_rxbuf.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/523-ath9k_use_configured_antenna_gain.patch
package/kernel/mac80211/patches/530-ath9k_extra_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

index b1b5f47..21ce445 100644 (file)
        depends on ATH9K
 --- a/drivers/net/wireless/ath/ath9k/Makefile
 +++ b/drivers/net/wireless/ath/ath9k/Makefile
        depends on ATH9K
 --- a/drivers/net/wireless/ath/ath9k/Makefile
 +++ b/drivers/net/wireless/ath/ath9k/Makefile
-@@ -13,9 +13,9 @@ ath9k-$(CPTCFG_ATH9K_PCI) += pci.o
+@@ -11,11 +11,13 @@ ath9k-$(CPTCFG_ATH9K_BTCOEX_SUPPORT) += 
+ ath9k-$(CPTCFG_ATH9K_LEGACY_RATE_CONTROL) += rc.o
+ ath9k-$(CPTCFG_ATH9K_PCI) += pci.o
  ath9k-$(CPTCFG_ATH9K_AHB) += ahb.o
  ath9k-$(CPTCFG_ATH9K_AHB) += ahb.o
- ath9k-$(CPTCFG_ATH9K_DEBUGFS) += debug.o
+-ath9k-$(CPTCFG_ATH9K_DEBUGFS) += debug.o
  ath9k-$(CPTCFG_ATH9K_DFS_DEBUGFS) += dfs_debug.o
 -ath9k-$(CPTCFG_ATH9K_DFS_CERTIFIED) += \
 -              dfs.o
  ath9k-$(CPTCFG_ATH9K_DFS_DEBUGFS) += dfs_debug.o
 -ath9k-$(CPTCFG_ATH9K_DFS_CERTIFIED) += \
 -              dfs.o
 +ath9k-$(CPTCFG_ATH9K_DFS_CERTIFIED) += dfs.o
 +ath9k-$(CPTCFG_ATH9K_TX99) += tx99.o
 +ath9k-$(CPTCFG_ATH9K_WOW) += wow.o
 +ath9k-$(CPTCFG_ATH9K_DFS_CERTIFIED) += dfs.o
 +ath9k-$(CPTCFG_ATH9K_TX99) += tx99.o
 +ath9k-$(CPTCFG_ATH9K_WOW) += wow.o
++
++ath9k-$(CPTCFG_ATH9K_DEBUGFS) += debug.o \
++                               spectral.o
  
  obj-$(CPTCFG_ATH9K) += ath9k.o
  
  
  obj-$(CPTCFG_ATH9K) += ath9k.o
  
-@@ -41,6 +41,8 @@ ath9k_hw-y:= \
+@@ -41,6 +43,8 @@ ath9k_hw-y:= \
                ar9003_eeprom.o \
                ar9003_paprd.o
  
                ar9003_eeprom.o \
                ar9003_paprd.o
  
  #endif /* INITVALS_9340_H */
 --- a/drivers/net/wireless/ath/ath9k/ath9k.h
 +++ b/drivers/net/wireless/ath/ath9k/ath9k.h
  #endif /* INITVALS_9340_H */
 --- a/drivers/net/wireless/ath/ath9k/ath9k.h
 +++ b/drivers/net/wireless/ath/ath9k/ath9k.h
-@@ -459,6 +459,7 @@ void ath_check_ani(struct ath_softc *sc)
+@@ -27,40 +27,15 @@
+ #include "common.h"
+ #include "mci.h"
+ #include "dfs.h"
+-
+-/*
+- * Header for the ath9k.ko driver core *only* -- hw code nor any other driver
+- * should rely on this file or its contents.
+- */
++#include "spectral.h"
+ struct ath_node;
++struct ath_rate_table;
+-/* Macro to expand scalars to 64-bit objects */
+-
+-#define       ito64(x) (sizeof(x) == 1) ?                     \
+-      (((unsigned long long int)(x)) & (0xff)) :      \
+-      (sizeof(x) == 2) ?                              \
+-      (((unsigned long long int)(x)) & 0xffff) :      \
+-      ((sizeof(x) == 4) ?                             \
+-       (((unsigned long long int)(x)) & 0xffffffff) : \
+-       (unsigned long long int)(x))
+-
+-/* increment with wrap-around */
+-#define INCR(_l, _sz)   do {                  \
+-              (_l)++;                         \
+-              (_l) &= ((_sz) - 1);            \
+-      } while (0)
+-
+-/* decrement with wrap-around */
+-#define DECR(_l,  _sz)  do {                  \
+-              (_l)--;                         \
+-              (_l) &= ((_sz) - 1);            \
+-      } while (0)
+-
+-#define TSF_TO_TU(_h,_l) \
+-      ((((u32)(_h)) << 22) | (((u32)(_l)) >> 10))
+-
+-#define       ATH_TXQ_SETUP(sc, i)        ((sc)->tx.txqsetup & (1<<i))
++extern struct ieee80211_ops ath9k_ops;
++extern int ath9k_modparam_nohwcrypt;
++extern int led_blink;
++extern bool is_ath9k_unloaded;
+ struct ath_config {
+       u16 txpowlimit;
+@@ -70,6 +45,17 @@ struct ath_config {
+ /* Descriptor Management */
+ /*************************/
++#define ATH_TXSTATUS_RING_SIZE 512
++
++/* Macro to expand scalars to 64-bit objects */
++#define       ito64(x) (sizeof(x) == 1) ?                     \
++      (((unsigned long long int)(x)) & (0xff)) :      \
++      (sizeof(x) == 2) ?                              \
++      (((unsigned long long int)(x)) & 0xffff) :      \
++      ((sizeof(x) == 4) ?                             \
++       (((unsigned long long int)(x)) & 0xffffffff) : \
++       (unsigned long long int)(x))
++
+ #define ATH_TXBUF_RESET(_bf) do {                             \
+               (_bf)->bf_lastbf = NULL;                        \
+               (_bf)->bf_next = NULL;                          \
+@@ -77,23 +63,6 @@ struct ath_config {
+                      sizeof(struct ath_buf_state));           \
+       } while (0)
+-/**
+- * enum buffer_type - Buffer type flags
+- *
+- * @BUF_AMPDU: This buffer is an ampdu, as part of an aggregate (during TX)
+- * @BUF_AGGR: Indicates whether the buffer can be aggregated
+- *    (used in aggregation scheduling)
+- */
+-enum buffer_type {
+-      BUF_AMPDU               = BIT(0),
+-      BUF_AGGR                = BIT(1),
+-};
+-
+-#define bf_isampdu(bf)                (bf->bf_state.bf_type & BUF_AMPDU)
+-#define bf_isaggr(bf)         (bf->bf_state.bf_type & BUF_AGGR)
+-
+-#define ATH_TXSTATUS_RING_SIZE 512
+-
+ #define       DS2PHYS(_dd, _ds)                                               \
+       ((_dd)->dd_desc_paddr + ((caddr_t)(_ds) - (caddr_t)(_dd)->dd_desc))
+ #define ATH_DESC_4KB_BOUND_CHECK(_daddr) ((((_daddr) & 0xFFF) > 0xF7F) ? 1 : 0)
+@@ -113,11 +82,20 @@ int ath_descdma_setup(struct ath_softc *
+ /* RX / TX */
+ /***********/
++#define       ATH_TXQ_SETUP(sc, i) ((sc)->tx.txqsetup & (1<<i))
++
++/* increment with wrap-around */
++#define INCR(_l, _sz)   do {                  \
++              (_l)++;                         \
++              (_l) &= ((_sz) - 1);            \
++      } while (0)
++
+ #define ATH_RXBUF               512
+ #define ATH_TXBUF               512
+ #define ATH_TXBUF_RESERVE       5
+ #define ATH_MAX_QDEPTH          (ATH_TXBUF / 4 - ATH_TXBUF_RESERVE)
+ #define ATH_TXMAXTRY            13
++#define ATH_MAX_SW_RETRIES      30
+ #define TID_TO_WME_AC(_tid)                           \
+       ((((_tid) == 0) || ((_tid) == 3)) ? IEEE80211_AC_BE :   \
+@@ -133,6 +111,9 @@ int ath_descdma_setup(struct ath_softc *
+ #define ATH_AGGR_MIN_QDEPTH        2
+ /* minimum h/w qdepth for non-aggregated traffic */
+ #define ATH_NON_AGGR_MIN_QDEPTH    8
++#define ATH_TX_COMPLETE_POLL_INT   1000
++#define ATH_TXFIFO_DEPTH           8
++#define ATH_TX_ERROR               0x01
+ #define IEEE80211_SEQ_SEQ_SHIFT    4
+ #define IEEE80211_SEQ_MAX          4096
+@@ -167,9 +148,6 @@ int ath_descdma_setup(struct ath_softc *
+ #define IS_CCK_RATE(rate) ((rate >= 0x18) && (rate <= 0x1e))
+-#define ATH_TX_COMPLETE_POLL_INT      1000
+-
+-#define ATH_TXFIFO_DEPTH 8
+ struct ath_txq {
+       int mac80211_qnum; /* mac80211 queue number, -1 means not mac80211 Q */
+       u32 axq_qnum; /* ath9k hardware queue number */
+@@ -214,6 +192,21 @@ struct ath_rxbuf {
+       dma_addr_t bf_buf_addr;
+ };
++/**
++ * enum buffer_type - Buffer type flags
++ *
++ * @BUF_AMPDU: This buffer is an ampdu, as part of an aggregate (during TX)
++ * @BUF_AGGR: Indicates whether the buffer can be aggregated
++ *    (used in aggregation scheduling)
++ */
++enum buffer_type {
++      BUF_AMPDU               = BIT(0),
++      BUF_AGGR                = BIT(1),
++};
++
++#define bf_isampdu(bf)                (bf->bf_state.bf_type & BUF_AMPDU)
++#define bf_isaggr(bf)         (bf->bf_state.bf_type & BUF_AGGR)
++
+ struct ath_buf_state {
+       u8 bf_type;
+       u8 bfs_paprd;
+@@ -278,7 +271,6 @@ struct ath_tx_control {
+       struct ieee80211_sta *sta;
+ };
+-#define ATH_TX_ERROR        0x01
+ /**
+  * @txq_map:  Index is mac80211 queue number.  This is
+@@ -372,6 +364,22 @@ struct ath_vif {
+       struct ath_buf *av_bcbuf;
+ };
++struct ath9k_vif_iter_data {
++      u8 hw_macaddr[ETH_ALEN]; /* address of the first vif */
++      u8 mask[ETH_ALEN]; /* bssid mask */
++      bool has_hw_macaddr;
++
++      int naps;      /* number of AP vifs */
++      int nmeshes;   /* number of mesh vifs */
++      int nstations; /* number of station vifs */
++      int nwds;      /* number of WDS vifs */
++      int nadhocs;   /* number of adhoc vifs */
++};
++
++void ath9k_calculate_iter_data(struct ieee80211_hw *hw,
++                             struct ieee80211_vif *vif,
++                             struct ath9k_vif_iter_data *iter_data);
++
+ /*******************/
+ /* Beacon Handling */
+ /*******************/
+@@ -387,6 +395,9 @@ struct ath_vif {
+ #define ATH_DEFAULT_BMISS_LIMIT       10
+ #define IEEE80211_MS_TO_TU(x)           (((x) * 1000) / 1024)
++#define TSF_TO_TU(_h,_l) \
++      ((((u32)(_h)) << 22) | (((u32)(_l)) >> 10))
++
+ struct ath_beacon_config {
+       int beacon_interval;
+       u16 listen_interval;
+@@ -420,12 +431,10 @@ struct ath_beacon {
+ };
+ void ath9k_beacon_tasklet(unsigned long data);
+-bool ath9k_allow_beacon_config(struct ath_softc *sc, struct ieee80211_vif *vif);
+ void ath9k_beacon_config(struct ath_softc *sc, struct ieee80211_vif *vif,
+                        u32 changed);
+ void ath9k_beacon_assign_slot(struct ath_softc *sc, struct ieee80211_vif *vif);
+ void ath9k_beacon_remove_slot(struct ath_softc *sc, struct ieee80211_vif *vif);
+-void ath9k_set_tsfadjust(struct ath_softc *sc, struct ieee80211_vif *vif);
+ void ath9k_set_beacon(struct ath_softc *sc);
+ bool ath9k_csa_is_finished(struct ath_softc *sc);
+@@ -440,10 +449,9 @@ bool ath9k_csa_is_finished(struct ath_so
+ #define ATH_LONG_CALINTERVAL_INT  1000    /* 1000 ms */
+ #define ATH_LONG_CALINTERVAL      30000   /* 30 seconds */
+ #define ATH_RESTART_CALINTERVAL   1200000 /* 20 minutes */
+-#define ATH_ANI_MAX_SKIP_COUNT  10
+-
+-#define ATH_PAPRD_TIMEOUT     100 /* msecs */
+-#define ATH_PLL_WORK_INTERVAL   100
++#define ATH_ANI_MAX_SKIP_COUNT    10
++#define ATH_PAPRD_TIMEOUT         100 /* msecs */
++#define ATH_PLL_WORK_INTERVAL     100
+ void ath_tx_complete_poll_work(struct work_struct *work);
+ void ath_reset_work(struct work_struct *work);
+@@ -459,6 +467,7 @@ void ath_check_ani(struct ath_softc *sc)
  int ath_update_survey_stats(struct ath_softc *sc);
  void ath_update_survey_nf(struct ath_softc *sc, int channel);
  void ath9k_queue_reset(struct ath_softc *sc, enum ath_reset_type type);
  int ath_update_survey_stats(struct ath_softc *sc);
  void ath_update_survey_nf(struct ath_softc *sc, int channel);
  void ath9k_queue_reset(struct ath_softc *sc, enum ath_reset_type type);
  
  /**********/
  /* BTCOEX */
  
  /**********/
  /* BTCOEX */
-@@ -476,20 +477,19 @@ enum bt_op_flags {
+@@ -476,20 +485,19 @@ enum bt_op_flags {
  };
  
  struct ath_btcoex {
  };
  
  struct ath_btcoex {
        struct ath_mci_profile mci;
        u8 stomp_audio;
  };
        struct ath_mci_profile mci;
        u8 stomp_audio;
  };
-@@ -570,6 +570,34 @@ static inline void ath_fill_led_pin(stru
+@@ -537,12 +545,6 @@ static inline int ath9k_dump_btcoex(stru
+ }
+ #endif /* CPTCFG_ATH9K_BTCOEX_SUPPORT */
+-struct ath9k_wow_pattern {
+-      u8 pattern_bytes[MAX_PATTERN_SIZE];
+-      u8 mask_bytes[MAX_PATTERN_SIZE];
+-      u32 pattern_len;
+-};
+-
+ /********************/
+ /*   LED Control    */
+ /********************/
+@@ -570,6 +572,40 @@ static inline void ath_fill_led_pin(stru
  }
  #endif
  
  }
  #endif
  
 +/* Wake on Wireless LAN */
 +/************************/
 +
 +/* Wake on Wireless LAN */
 +/************************/
 +
-+#ifdef CONFIG_ATH9K_WOW
++struct ath9k_wow_pattern {
++      u8 pattern_bytes[MAX_PATTERN_SIZE];
++      u8 mask_bytes[MAX_PATTERN_SIZE];
++      u32 pattern_len;
++};
++
++#ifdef CPTCFG_ATH9K_WOW
 +void ath9k_init_wow(struct ieee80211_hw *hw);
 +int ath9k_suspend(struct ieee80211_hw *hw,
 +                struct cfg80211_wowlan *wowlan);
 +void ath9k_init_wow(struct ieee80211_hw *hw);
 +int ath9k_suspend(struct ieee80211_hw *hw,
 +                struct cfg80211_wowlan *wowlan);
  /*******************************/
  /* Antenna diversity/combining */
  /*******************************/
  /*******************************/
  /* Antenna diversity/combining */
  /*******************************/
-@@ -632,15 +660,16 @@ void ath_ant_comb_scan(struct ath_softc 
+@@ -632,28 +668,24 @@ void ath_ant_comb_scan(struct ath_softc 
  /* Main driver core */
  /********************/
  
  /* Main driver core */
  /********************/
  
  
  /*
   * Default cache line size, in bytes.
  
  /*
   * Default cache line size, in bytes.
-@@ -723,6 +752,7 @@ struct ath_softc {
+  * Used when PCI device not fully initialized by bootrom/BIOS
+ */
+ #define DEFAULT_CACHELINE       32
+-#define ATH_REGCLASSIDS_MAX     10
+ #define ATH_CABQ_READY_TIME     80      /* % of beacon interval */
+-#define ATH_MAX_SW_RETRIES      30
+-#define ATH_CHAN_MAX            255
+-
+ #define ATH_TXPOWER_MAX         100     /* .5 dBm units */
+-#define ATH_RATE_DUMMY_MARKER   0
+ enum sc_op_flags {
+       SC_OP_INVALID,
+@@ -672,37 +704,6 @@ enum sc_op_flags {
+ #define PS_BEACON_SYNC            BIT(4)
+ #define PS_WAIT_FOR_ANI           BIT(5)
+-struct ath_rate_table;
+-
+-struct ath9k_vif_iter_data {
+-      u8 hw_macaddr[ETH_ALEN]; /* address of the first vif */
+-      u8 mask[ETH_ALEN]; /* bssid mask */
+-      bool has_hw_macaddr;
+-
+-      int naps;      /* number of AP vifs */
+-      int nmeshes;   /* number of mesh vifs */
+-      int nstations; /* number of station vifs */
+-      int nwds;      /* number of WDS vifs */
+-      int nadhocs;   /* number of adhoc vifs */
+-};
+-
+-/* enum spectral_mode:
+- *
+- * @SPECTRAL_DISABLED: spectral mode is disabled
+- * @SPECTRAL_BACKGROUND: hardware sends samples when it is not busy with
+- *    something else.
+- * @SPECTRAL_MANUAL: spectral scan is enabled, triggering for samples
+- *    is performed manually.
+- * @SPECTRAL_CHANSCAN: Like manual, but also triggered when changing channels
+- *    during a channel scan.
+- */
+-enum spectral_mode {
+-      SPECTRAL_DISABLED = 0,
+-      SPECTRAL_BACKGROUND,
+-      SPECTRAL_MANUAL,
+-      SPECTRAL_CHANSCAN,
+-};
+-
+ struct ath_softc {
+       struct ieee80211_hw *hw;
+       struct device *dev;
+@@ -723,6 +724,7 @@ struct ath_softc {
        struct work_struct hw_check_work;
        struct work_struct hw_reset_work;
        struct completion paprd_complete;
        struct work_struct hw_check_work;
        struct work_struct hw_reset_work;
        struct completion paprd_complete;
  
        unsigned int hw_busy_count;
        unsigned long sc_flags;
  
        unsigned int hw_busy_count;
        unsigned long sc_flags;
-@@ -759,6 +789,7 @@ struct ath_softc {
+@@ -759,6 +761,7 @@ struct ath_softc {
        struct delayed_work tx_complete_work;
        struct delayed_work hw_pll_work;
        struct timer_list rx_poll_timer;
        struct delayed_work tx_complete_work;
        struct delayed_work hw_pll_work;
        struct timer_list rx_poll_timer;
  
  #ifdef CPTCFG_ATH9K_BTCOEX_SUPPORT
        struct ath_btcoex btcoex;
  
  #ifdef CPTCFG_ATH9K_BTCOEX_SUPPORT
        struct ath_btcoex btcoex;
-@@ -783,7 +814,7 @@ struct ath_softc {
+@@ -783,199 +786,54 @@ struct ath_softc {
        bool tx99_state;
        s16 tx99_power;
  
        bool tx99_state;
        s16 tx99_power;
  
        atomic_t wow_got_bmiss_intr;
        atomic_t wow_sleep_proc_intr; /* in the middle of WoW sleep ? */
        u32 wow_intr_before_sleep;
        atomic_t wow_got_bmiss_intr;
        atomic_t wow_sleep_proc_intr; /* in the middle of WoW sleep ? */
        u32 wow_intr_before_sleep;
-@@ -946,10 +977,25 @@ struct fft_sample_ht20_40 {
-       u8 data[SPECTRAL_HT20_40_NUM_BINS];
- } __packed;
+ #endif
+ };
  
  
--int ath9k_tx99_init(struct ath_softc *sc);
--void ath9k_tx99_deinit(struct ath_softc *sc);
+-#define SPECTRAL_SCAN_BITMASK         0x10
+-/* Radar info packet format, used for DFS and spectral formats. */
+-struct ath_radar_info {
+-      u8 pulse_length_pri;
+-      u8 pulse_length_ext;
+-      u8 pulse_bw_info;
+-} __packed;
+-
+-/* The HT20 spectral data has 4 bytes of additional information at it's end.
+- *
+- * [7:0]: all bins {max_magnitude[1:0], bitmap_weight[5:0]}
+- * [7:0]: all bins  max_magnitude[9:2]
+- * [7:0]: all bins {max_index[5:0], max_magnitude[11:10]}
+- * [3:0]: max_exp (shift amount to size max bin to 8-bit unsigned)
+- */
+-struct ath_ht20_mag_info {
+-      u8 all_bins[3];
+-      u8 max_exp;
+-} __packed;
+-
+-#define SPECTRAL_HT20_NUM_BINS                56
+-
+-/* WARNING: don't actually use this struct! MAC may vary the amount of
+- * data by -1/+2. This struct is for reference only.
+- */
+-struct ath_ht20_fft_packet {
+-      u8 data[SPECTRAL_HT20_NUM_BINS];
+-      struct ath_ht20_mag_info mag_info;
+-      struct ath_radar_info radar_info;
+-} __packed;
+-
+-#define SPECTRAL_HT20_TOTAL_DATA_LEN  (sizeof(struct ath_ht20_fft_packet))
+-
+-/* Dynamic 20/40 mode:
+- *
+- * [7:0]: lower bins {max_magnitude[1:0], bitmap_weight[5:0]}
+- * [7:0]: lower bins  max_magnitude[9:2]
+- * [7:0]: lower bins {max_index[5:0], max_magnitude[11:10]}
+- * [7:0]: upper bins {max_magnitude[1:0], bitmap_weight[5:0]}
+- * [7:0]: upper bins  max_magnitude[9:2]
+- * [7:0]: upper bins {max_index[5:0], max_magnitude[11:10]}
+- * [3:0]: max_exp (shift amount to size max bin to 8-bit unsigned)
+- */
+-struct ath_ht20_40_mag_info {
+-      u8 lower_bins[3];
+-      u8 upper_bins[3];
+-      u8 max_exp;
+-} __packed;
+-
+-#define SPECTRAL_HT20_40_NUM_BINS             128
+-
+-/* WARNING: don't actually use this struct! MAC may vary the amount of
+- * data. This struct is for reference only.
+- */
+-struct ath_ht20_40_fft_packet {
+-      u8 data[SPECTRAL_HT20_40_NUM_BINS];
+-      struct ath_ht20_40_mag_info mag_info;
+-      struct ath_radar_info radar_info;
+-} __packed;
+-
+-
+-#define SPECTRAL_HT20_40_TOTAL_DATA_LEN       (sizeof(struct ath_ht20_40_fft_packet))
+-
+-/* grabs the max magnitude from the all/upper/lower bins */
+-static inline u16 spectral_max_magnitude(u8 *bins)
+-{
+-      return (bins[0] & 0xc0) >> 6 |
+-             (bins[1] & 0xff) << 2 |
+-             (bins[2] & 0x03) << 10;
+-}
 +/********/
 +/* TX99 */
 +/********/
 +/********/
 +/* TX99 */
 +/********/
-+
+-/* return the max magnitude from the all/upper/lower bins */
+-static inline u8 spectral_max_index(u8 *bins)
 +#ifdef CONFIG_ATH9K_TX99
 +void ath9k_tx99_init_debug(struct ath_softc *sc);
 +#ifdef CONFIG_ATH9K_TX99
 +void ath9k_tx99_init_debug(struct ath_softc *sc);
- int ath9k_tx99_send(struct ath_softc *sc, struct sk_buff *skb,
-                   struct ath_tx_control *txctl);
++int ath9k_tx99_send(struct ath_softc *sc, struct sk_buff *skb,
++                  struct ath_tx_control *txctl);
 +#else
 +static inline void ath9k_tx99_init_debug(struct ath_softc *sc)
 +#else
 +static inline void ath9k_tx99_init_debug(struct ath_softc *sc)
-+{
-+}
+ {
+-      s8 m = (bins[2] & 0xfc) >> 2;
+-
+-      /* TODO: this still doesn't always report the right values ... */
+-      if (m > 32)
+-              m |= 0xe0;
+-      else
+-              m &= ~0xe0;
+-
+-      return m + 29;
+ }
+-
+-/* return the bitmap weight from the all/upper/lower bins */
+-static inline u8 spectral_bitmap_weight(u8 *bins)
 +static inline int ath9k_tx99_send(struct ath_softc *sc,
 +                                struct sk_buff *skb,
 +                                struct ath_tx_control *txctl)
 +static inline int ath9k_tx99_send(struct ath_softc *sc,
 +                                struct sk_buff *skb,
 +                                struct ath_tx_control *txctl)
-+{
+ {
+-      return bins[0] & 0x3f;
 +      return 0;
 +      return 0;
-+}
+ }
+-
+-/* FFT sample format given to userspace via debugfs.
+- *
+- * Please keep the type/length at the front position and change
+- * other fields after adding another sample type
+- *
+- * TODO: this might need rework when switching to nl80211-based
+- * interface.
+- */
+-enum ath_fft_sample_type {
+-      ATH_FFT_SAMPLE_HT20 = 1,
+-      ATH_FFT_SAMPLE_HT20_40,
+-};
+-
+-struct fft_sample_tlv {
+-      u8 type;        /* see ath_fft_sample */
+-      __be16 length;
+-      /* type dependent data follows */
+-} __packed;
+-
+-struct fft_sample_ht20 {
+-      struct fft_sample_tlv tlv;
+-
+-      u8 max_exp;
+-
+-      __be16 freq;
+-      s8 rssi;
+-      s8 noise;
+-
+-      __be16 max_magnitude;
+-      u8 max_index;
+-      u8 bitmap_weight;
+-
+-      __be64 tsf;
+-
+-      u8 data[SPECTRAL_HT20_NUM_BINS];
+-} __packed;
+-
+-struct fft_sample_ht20_40 {
+-      struct fft_sample_tlv tlv;
+-
+-      u8 channel_type;
+-      __be16 freq;
+-
+-      s8 lower_rssi;
+-      s8 upper_rssi;
+-
+-      __be64 tsf;
+-
+-      s8 lower_noise;
+-      s8 upper_noise;
+-
+-      __be16 lower_max_magnitude;
+-      __be16 upper_max_magnitude;
+-
+-      u8 lower_max_index;
+-      u8 upper_max_index;
+-
+-      u8 lower_bitmap_weight;
+-      u8 upper_bitmap_weight;
+-
+-      u8 max_exp;
+-
+-      u8 data[SPECTRAL_HT20_40_NUM_BINS];
+-} __packed;
+-
+-int ath9k_tx99_init(struct ath_softc *sc);
+-void ath9k_tx99_deinit(struct ath_softc *sc);
+-int ath9k_tx99_send(struct ath_softc *sc, struct sk_buff *skb,
+-                  struct ath_tx_control *txctl);
+-
+-void ath9k_tasklet(unsigned long data);
+-int ath_cabq_update(struct ath_softc *);
 +#endif /* CONFIG_ATH9K_TX99 */
  
 +#endif /* CONFIG_ATH9K_TX99 */
  
- void ath9k_tasklet(unsigned long data);
- int ath_cabq_update(struct ath_softc *);
-@@ -966,6 +1012,9 @@ extern bool is_ath9k_unloaded;
+ static inline void ath_read_cachesize(struct ath_common *common, int *csz)
+ {
+       common->bus_ops->read_cachesize(common, csz);
+ }
  
  
+-extern struct ieee80211_ops ath9k_ops;
+-extern int ath9k_modparam_nohwcrypt;
+-extern int led_blink;
+-extern bool is_ath9k_unloaded;
+-
++void ath9k_tasklet(unsigned long data);
++int ath_cabq_update(struct ath_softc *);
  u8 ath9k_parse_mpdudensity(u8 mpdudensity);
  irqreturn_t ath_isr(int irq, void *dev);
 +int ath_reset(struct ath_softc *sc);
  u8 ath9k_parse_mpdudensity(u8 mpdudensity);
  irqreturn_t ath_isr(int irq, void *dev);
 +int ath_reset(struct ath_softc *sc);
  int ath9k_init_device(u16 devid, struct ath_softc *sc,
                    const struct ath_bus_ops *bus_ops);
  void ath9k_deinit_device(struct ath_softc *sc);
  int ath9k_init_device(u16 devid, struct ath_softc *sc,
                    const struct ath_bus_ops *bus_ops);
  void ath9k_deinit_device(struct ath_softc *sc);
+-void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw);
+ void ath9k_reload_chainmask_settings(struct ath_softc *sc);
+-
+-void ath9k_spectral_scan_trigger(struct ieee80211_hw *hw);
+-int ath9k_spectral_scan_config(struct ieee80211_hw *hw,
+-                             enum spectral_mode spectral_mode);
+-
++u8 ath_txchainmask_reduction(struct ath_softc *sc, u8 chainmask, u32 rate);
++void ath_start_rfkill_poll(struct ath_softc *sc);
++void ath9k_rfkill_poll_state(struct ieee80211_hw *hw);
++void ath9k_ps_wakeup(struct ath_softc *sc);
++void ath9k_ps_restore(struct ath_softc *sc);
+ #ifdef CPTCFG_ATH9K_PCI
+ int ath_pci_init(void);
+@@ -993,15 +851,4 @@ static inline int ath_ahb_init(void) { r
+ static inline void ath_ahb_exit(void) {};
+ #endif
+-void ath9k_ps_wakeup(struct ath_softc *sc);
+-void ath9k_ps_restore(struct ath_softc *sc);
+-
+-u8 ath_txchainmask_reduction(struct ath_softc *sc, u8 chainmask, u32 rate);
+-
+-void ath_start_rfkill_poll(struct ath_softc *sc);
+-extern void ath9k_rfkill_poll_state(struct ieee80211_hw *hw);
+-void ath9k_calculate_iter_data(struct ieee80211_hw *hw,
+-                             struct ieee80211_vif *vif,
+-                             struct ath9k_vif_iter_data *iter_data);
+-
+ #endif /* ATH9K_H */
 --- a/drivers/net/wireless/ath/ath9k/debug.c
 +++ b/drivers/net/wireless/ath/ath9k/debug.c
 --- a/drivers/net/wireless/ath/ath9k/debug.c
 +++ b/drivers/net/wireless/ath/ath9k/debug.c
-@@ -1782,111 +1782,6 @@ void ath9k_deinit_debug(struct ath_softc
-       }
- }
+@@ -17,7 +17,6 @@
+ #include <linux/slab.h>
+ #include <linux/vmalloc.h>
+ #include <linux/export.h>
+-#include <linux/relay.h>
+ #include <asm/unaligned.h>
  
  
--static ssize_t read_file_tx99(struct file *file, char __user *user_buf,
--                            size_t count, loff_t *ppos)
+ #include "ath9k.h"
+@@ -27,6 +26,47 @@
+ #define REG_READ_D(_ah, _reg) \
+       ath9k_hw_common(_ah)->ops->read((_ah), (_reg))
++void ath9k_debug_sync_cause(struct ath_softc *sc, u32 sync_cause)
++{
++      if (sync_cause)
++              sc->debug.stats.istats.sync_cause_all++;
++      if (sync_cause & AR_INTR_SYNC_RTC_IRQ)
++              sc->debug.stats.istats.sync_rtc_irq++;
++      if (sync_cause & AR_INTR_SYNC_MAC_IRQ)
++              sc->debug.stats.istats.sync_mac_irq++;
++      if (sync_cause & AR_INTR_SYNC_EEPROM_ILLEGAL_ACCESS)
++              sc->debug.stats.istats.eeprom_illegal_access++;
++      if (sync_cause & AR_INTR_SYNC_APB_TIMEOUT)
++              sc->debug.stats.istats.apb_timeout++;
++      if (sync_cause & AR_INTR_SYNC_PCI_MODE_CONFLICT)
++              sc->debug.stats.istats.pci_mode_conflict++;
++      if (sync_cause & AR_INTR_SYNC_HOST1_FATAL)
++              sc->debug.stats.istats.host1_fatal++;
++      if (sync_cause & AR_INTR_SYNC_HOST1_PERR)
++              sc->debug.stats.istats.host1_perr++;
++      if (sync_cause & AR_INTR_SYNC_TRCV_FIFO_PERR)
++              sc->debug.stats.istats.trcv_fifo_perr++;
++      if (sync_cause & AR_INTR_SYNC_RADM_CPL_EP)
++              sc->debug.stats.istats.radm_cpl_ep++;
++      if (sync_cause & AR_INTR_SYNC_RADM_CPL_DLLP_ABORT)
++              sc->debug.stats.istats.radm_cpl_dllp_abort++;
++      if (sync_cause & AR_INTR_SYNC_RADM_CPL_TLP_ABORT)
++              sc->debug.stats.istats.radm_cpl_tlp_abort++;
++      if (sync_cause & AR_INTR_SYNC_RADM_CPL_ECRC_ERR)
++              sc->debug.stats.istats.radm_cpl_ecrc_err++;
++      if (sync_cause & AR_INTR_SYNC_RADM_CPL_TIMEOUT)
++              sc->debug.stats.istats.radm_cpl_timeout++;
++      if (sync_cause & AR_INTR_SYNC_LOCAL_TIMEOUT)
++              sc->debug.stats.istats.local_timeout++;
++      if (sync_cause & AR_INTR_SYNC_PM_ACCESS)
++              sc->debug.stats.istats.pm_access++;
++      if (sync_cause & AR_INTR_SYNC_MAC_AWAKE)
++              sc->debug.stats.istats.mac_awake++;
++      if (sync_cause & AR_INTR_SYNC_MAC_ASLEEP)
++              sc->debug.stats.istats.mac_asleep++;
++      if (sync_cause & AR_INTR_SYNC_MAC_SLEEP_ACCESS)
++              sc->debug.stats.istats.mac_sleep_access++;
++}
+ static ssize_t ath9k_debugfs_read_buf(struct file *file, char __user *user_buf,
+                                     size_t count, loff_t *ppos)
+@@ -1016,297 +1056,6 @@ static const struct file_operations fops
+       .llseek = default_llseek,
+ };
+-static ssize_t read_file_spec_scan_ctl(struct file *file, char __user *user_buf,
+-                                     size_t count, loff_t *ppos)
 -{
 -      struct ath_softc *sc = file->private_data;
 -{
 -      struct ath_softc *sc = file->private_data;
--      char buf[3];
+-      char *mode = "";
 -      unsigned int len;
 -
 -      unsigned int len;
 -
--      len = sprintf(buf, "%d\n", sc->tx99_state);
--      return simple_read_from_buffer(user_buf, count, ppos, buf, len);
+-      switch (sc->spectral_mode) {
+-      case SPECTRAL_DISABLED:
+-              mode = "disable";
+-              break;
+-      case SPECTRAL_BACKGROUND:
+-              mode = "background";
+-              break;
+-      case SPECTRAL_CHANSCAN:
+-              mode = "chanscan";
+-              break;
+-      case SPECTRAL_MANUAL:
+-              mode = "manual";
+-              break;
+-      }
+-      len = strlen(mode);
+-      return simple_read_from_buffer(user_buf, count, ppos, mode, len);
 -}
 -
 -}
 -
--static ssize_t write_file_tx99(struct file *file, const char __user *user_buf,
--                             size_t count, loff_t *ppos)
+-static ssize_t write_file_spec_scan_ctl(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);
 -      char buf[32];
 -{
 -      struct ath_softc *sc = file->private_data;
 -      struct ath_common *common = ath9k_hw_common(sc->sc_ah);
 -      char buf[32];
--      bool start;
 -      ssize_t len;
 -      ssize_t len;
--      int r;
 -
 -
--      if (sc->nvifs > 1)
+-      if (config_enabled(CPTCFG_ATH9K_TX99))
 -              return -EOPNOTSUPP;
 -
 -      len = min(count, sizeof(buf) - 1);
 -      if (copy_from_user(buf, user_buf, len))
 -              return -EFAULT;
 -
 -              return -EOPNOTSUPP;
 -
 -      len = min(count, sizeof(buf) - 1);
 -      if (copy_from_user(buf, user_buf, len))
 -              return -EFAULT;
 -
--      if (strtobool(buf, &start))
+-      buf[len] = '\0';
+-
+-      if (strncmp("trigger", buf, 7) == 0) {
+-              ath9k_spectral_scan_trigger(sc->hw);
+-      } else if (strncmp("background", buf, 9) == 0) {
+-              ath9k_spectral_scan_config(sc->hw, SPECTRAL_BACKGROUND);
+-              ath_dbg(common, CONFIG, "spectral scan: background mode enabled\n");
+-      } else if (strncmp("chanscan", buf, 8) == 0) {
+-              ath9k_spectral_scan_config(sc->hw, SPECTRAL_CHANSCAN);
+-              ath_dbg(common, CONFIG, "spectral scan: channel scan mode enabled\n");
+-      } else if (strncmp("manual", buf, 6) == 0) {
+-              ath9k_spectral_scan_config(sc->hw, SPECTRAL_MANUAL);
+-              ath_dbg(common, CONFIG, "spectral scan: manual mode enabled\n");
+-      } else if (strncmp("disable", buf, 7) == 0) {
+-              ath9k_spectral_scan_config(sc->hw, SPECTRAL_DISABLED);
+-              ath_dbg(common, CONFIG, "spectral scan: disabled\n");
+-      } else {
 -              return -EINVAL;
 -              return -EINVAL;
--
--      if (start == sc->tx99_state) {
--              if (!start)
--                      return count;
--              ath_dbg(common, XMIT, "Resetting TX99\n");
--              ath9k_tx99_deinit(sc);
 -      }
 -
 -      }
 -
--      if (!start) {
--              ath9k_tx99_deinit(sc);
--              return count;
--      }
+-      return count;
+-}
 -
 -
--      r = ath9k_tx99_init(sc);
--      if (r)
--              return r;
+-static const struct file_operations fops_spec_scan_ctl = {
+-      .read = read_file_spec_scan_ctl,
+-      .write = write_file_spec_scan_ctl,
+-      .open = simple_open,
+-      .owner = THIS_MODULE,
+-      .llseek = default_llseek,
+-};
+-
+-static ssize_t read_file_spectral_short_repeat(struct file *file,
+-                                             char __user *user_buf,
+-                                             size_t count, loff_t *ppos)
+-{
+-      struct ath_softc *sc = file->private_data;
+-      char buf[32];
+-      unsigned int len;
+-
+-      len = sprintf(buf, "%d\n", sc->spec_config.short_repeat);
+-      return simple_read_from_buffer(user_buf, count, ppos, buf, len);
+-}
+-
+-static ssize_t write_file_spectral_short_repeat(struct file *file,
+-                                              const char __user *user_buf,
+-                                              size_t count, loff_t *ppos)
+-{
+-      struct ath_softc *sc = file->private_data;
+-      unsigned long val;
+-      char buf[32];
+-      ssize_t len;
+-
+-      len = min(count, sizeof(buf) - 1);
+-      if (copy_from_user(buf, user_buf, len))
+-              return -EFAULT;
+-
+-      buf[len] = '\0';
+-      if (kstrtoul(buf, 0, &val))
+-              return -EINVAL;
+-
+-      if (val < 0 || val > 1)
+-              return -EINVAL;
 -
 -
+-      sc->spec_config.short_repeat = val;
 -      return count;
 -}
 -
 -      return count;
 -}
 -
--static const struct file_operations fops_tx99 = {
--      .read = read_file_tx99,
--      .write = write_file_tx99,
+-static const struct file_operations fops_spectral_short_repeat = {
+-      .read = read_file_spectral_short_repeat,
+-      .write = write_file_spectral_short_repeat,
 -      .open = simple_open,
 -      .owner = THIS_MODULE,
 -      .llseek = default_llseek,
 -};
 -
 -      .open = simple_open,
 -      .owner = THIS_MODULE,
 -      .llseek = default_llseek,
 -};
 -
--static ssize_t read_file_tx99_power(struct file *file,
--                                  char __user *user_buf,
--                                  size_t count, loff_t *ppos)
+-static ssize_t read_file_spectral_count(struct file *file,
+-                                      char __user *user_buf,
+-                                      size_t count, loff_t *ppos)
 -{
 -      struct ath_softc *sc = file->private_data;
 -      char buf[32];
 -      unsigned int len;
 -
 -{
 -      struct ath_softc *sc = file->private_data;
 -      char buf[32];
 -      unsigned int len;
 -
--      len = sprintf(buf, "%d (%d dBm)\n",
--                    sc->tx99_power,
--                    sc->tx99_power / 2);
--
+-      len = sprintf(buf, "%d\n", sc->spec_config.count);
 -      return simple_read_from_buffer(user_buf, count, ppos, buf, len);
 -}
 -
 -      return simple_read_from_buffer(user_buf, count, ppos, buf, len);
 -}
 -
--static ssize_t write_file_tx99_power(struct file *file,
--                                   const char __user *user_buf,
--                                   size_t count, loff_t *ppos)
+-static ssize_t write_file_spectral_count(struct file *file,
+-                                       const char __user *user_buf,
+-                                       size_t count, loff_t *ppos)
 -{
 -      struct ath_softc *sc = file->private_data;
 -{
 -      struct ath_softc *sc = file->private_data;
--      int r;
--      u8 tx_power;
+-      unsigned long val;
+-      char buf[32];
+-      ssize_t len;
 -
 -
--      r = kstrtou8_from_user(user_buf, count, 0, &tx_power);
--      if (r)
--              return r;
+-      len = min(count, sizeof(buf) - 1);
+-      if (copy_from_user(buf, user_buf, len))
+-              return -EFAULT;
 -
 -
--      if (tx_power > MAX_RATE_POWER)
+-      buf[len] = '\0';
+-      if (kstrtoul(buf, 0, &val))
 -              return -EINVAL;
 -
 -              return -EINVAL;
 -
--      sc->tx99_power = tx_power;
--
--      ath9k_ps_wakeup(sc);
--      ath9k_hw_tx99_set_txpower(sc->sc_ah, sc->tx99_power);
--      ath9k_ps_restore(sc);
+-      if (val < 0 || val > 255)
+-              return -EINVAL;
 -
 -
+-      sc->spec_config.count = val;
 -      return count;
 -}
 -
 -      return count;
 -}
 -
--static const struct file_operations fops_tx99_power = {
--      .read = read_file_tx99_power,
--      .write = write_file_tx99_power,
+-static const struct file_operations fops_spectral_count = {
+-      .read = read_file_spectral_count,
+-      .write = write_file_spectral_count,
 -      .open = simple_open,
 -      .owner = THIS_MODULE,
 -      .llseek = default_llseek,
 -};
 -
 -      .open = simple_open,
 -      .owner = THIS_MODULE,
 -      .llseek = default_llseek,
 -};
 -
- int ath9k_init_debug(struct ath_hw *ah)
- {
-       struct ath_common *common = ath9k_hw_common(ah);
-@@ -1903,6 +1798,7 @@ int ath9k_init_debug(struct ath_hw *ah)
- #endif
-       ath9k_dfs_init_debug(sc);
-+      ath9k_tx99_init_debug(sc);
-       debugfs_create_file("dma", S_IRUSR, sc->debug.debugfs_phy, sc,
-                           &fops_dma);
-@@ -1978,15 +1874,6 @@ int ath9k_init_debug(struct ath_hw *ah)
-       debugfs_create_file("btcoex", S_IRUSR, sc->debug.debugfs_phy, sc,
-                           &fops_btcoex);
- #endif
--      if (config_enabled(CPTCFG_ATH9K_TX99) &&
--          AR_SREV_9300_20_OR_LATER(ah)) {
--              debugfs_create_file("tx99", S_IRUSR | S_IWUSR,
--                                  sc->debug.debugfs_phy, sc,
--                                  &fops_tx99);
--              debugfs_create_file("tx99_power", S_IRUSR | S_IWUSR,
--                                  sc->debug.debugfs_phy, sc,
--                                  &fops_tx99_power);
--      }
-       return 0;
- }
---- a/drivers/net/wireless/ath/ath9k/hw.c
-+++ b/drivers/net/wireless/ath/ath9k/hw.c
-@@ -17,6 +17,8 @@
- #include <linux/io.h>
- #include <linux/slab.h>
- #include <linux/module.h>
-+#include <linux/time.h>
-+#include <linux/bitops.h>
- #include <asm/unaligned.h>
- #include "hw.h"
-@@ -438,23 +440,13 @@ static bool ath9k_hw_chip_test(struct at
- static void ath9k_hw_init_config(struct ath_hw *ah)
- {
--      int i;
+-static ssize_t read_file_spectral_period(struct file *file,
+-                                       char __user *user_buf,
+-                                       size_t count, loff_t *ppos)
+-{
+-      struct ath_softc *sc = file->private_data;
+-      char buf[32];
+-      unsigned int len;
 -
 -
-       ah->config.dma_beacon_response_time = 1;
-       ah->config.sw_beacon_response_time = 6;
+-      len = sprintf(buf, "%d\n", sc->spec_config.period);
+-      return simple_read_from_buffer(user_buf, count, ppos, buf, len);
+-}
+-
+-static ssize_t write_file_spectral_period(struct file *file,
+-                                        const char __user *user_buf,
+-                                        size_t count, loff_t *ppos)
+-{
+-      struct ath_softc *sc = file->private_data;
+-      unsigned long val;
+-      char buf[32];
+-      ssize_t len;
+-
+-      len = min(count, sizeof(buf) - 1);
+-      if (copy_from_user(buf, user_buf, len))
+-              return -EFAULT;
+-
+-      buf[len] = '\0';
+-      if (kstrtoul(buf, 0, &val))
+-              return -EINVAL;
+-
+-      if (val < 0 || val > 255)
+-              return -EINVAL;
+-
+-      sc->spec_config.period = val;
+-      return count;
+-}
+-
+-static const struct file_operations fops_spectral_period = {
+-      .read = read_file_spectral_period,
+-      .write = write_file_spectral_period,
+-      .open = simple_open,
+-      .owner = THIS_MODULE,
+-      .llseek = default_llseek,
+-};
+-
+-static ssize_t read_file_spectral_fft_period(struct file *file,
+-                                           char __user *user_buf,
+-                                           size_t count, loff_t *ppos)
+-{
+-      struct ath_softc *sc = file->private_data;
+-      char buf[32];
+-      unsigned int len;
+-
+-      len = sprintf(buf, "%d\n", sc->spec_config.fft_period);
+-      return simple_read_from_buffer(user_buf, count, ppos, buf, len);
+-}
+-
+-static ssize_t write_file_spectral_fft_period(struct file *file,
+-                                            const char __user *user_buf,
+-                                            size_t count, loff_t *ppos)
+-{
+-      struct ath_softc *sc = file->private_data;
+-      unsigned long val;
+-      char buf[32];
+-      ssize_t len;
+-
+-      len = min(count, sizeof(buf) - 1);
+-      if (copy_from_user(buf, user_buf, len))
+-              return -EFAULT;
+-
+-      buf[len] = '\0';
+-      if (kstrtoul(buf, 0, &val))
+-              return -EINVAL;
+-
+-      if (val < 0 || val > 15)
+-              return -EINVAL;
+-
+-      sc->spec_config.fft_period = val;
+-      return count;
+-}
+-
+-static const struct file_operations fops_spectral_fft_period = {
+-      .read = read_file_spectral_fft_period,
+-      .write = write_file_spectral_fft_period,
+-      .open = simple_open,
+-      .owner = THIS_MODULE,
+-      .llseek = default_llseek,
+-};
+-
+-static struct dentry *create_buf_file_handler(const char *filename,
+-                                            struct dentry *parent,
+-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,3,0))
+-                                            umode_t mode,
+-#else
+-                                            int mode,
+-#endif
+-                                            struct rchan_buf *buf,
+-                                            int *is_global)
+-{
+-      struct dentry *buf_file;
+-
+-      buf_file = debugfs_create_file(filename, mode, parent, buf,
+-                                     &relay_file_operations);
+-      *is_global = 1;
+-      return buf_file;
+-}
+-
+-static int remove_buf_file_handler(struct dentry *dentry)
+-{
+-      debugfs_remove(dentry);
+-
+-      return 0;
+-}
+-
+-void ath_debug_send_fft_sample(struct ath_softc *sc,
+-                             struct fft_sample_tlv *fft_sample_tlv)
+-{
+-      int length;
+-      if (!sc->rfs_chan_spec_scan)
+-              return;
+-
+-      length = __be16_to_cpu(fft_sample_tlv->length) +
+-               sizeof(*fft_sample_tlv);
+-      relay_write(sc->rfs_chan_spec_scan, fft_sample_tlv, length);
+-}
+-
+-static struct rchan_callbacks rfs_spec_scan_cb = {
+-      .create_buf_file = create_buf_file_handler,
+-      .remove_buf_file = remove_buf_file_handler,
+-};
+-
+-
+ static ssize_t read_file_regidx(struct file *file, char __user *user_buf,
+                                 size_t count, loff_t *ppos)
+ {
+@@ -1776,117 +1525,9 @@ void ath9k_get_et_stats(struct ieee80211
+ void ath9k_deinit_debug(struct ath_softc *sc)
+ {
+-      if (config_enabled(CPTCFG_ATH9K_DEBUGFS) && sc->rfs_chan_spec_scan) {
+-              relay_close(sc->rfs_chan_spec_scan);
+-              sc->rfs_chan_spec_scan = NULL;
+-      }
++      ath9k_spectral_deinit_debug(sc);
+ }
+-static ssize_t read_file_tx99(struct file *file, char __user *user_buf,
+-                            size_t count, loff_t *ppos)
+-{
+-      struct ath_softc *sc = file->private_data;
+-      char buf[3];
+-      unsigned int len;
+-
+-      len = sprintf(buf, "%d\n", sc->tx99_state);
+-      return simple_read_from_buffer(user_buf, count, ppos, buf, len);
+-}
+-
+-static ssize_t write_file_tx99(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);
+-      char buf[32];
+-      bool start;
+-      ssize_t len;
+-      int r;
+-
+-      if (sc->nvifs > 1)
+-              return -EOPNOTSUPP;
+-
+-      len = min(count, sizeof(buf) - 1);
+-      if (copy_from_user(buf, user_buf, len))
+-              return -EFAULT;
+-
+-      if (strtobool(buf, &start))
+-              return -EINVAL;
+-
+-      if (start == sc->tx99_state) {
+-              if (!start)
+-                      return count;
+-              ath_dbg(common, XMIT, "Resetting TX99\n");
+-              ath9k_tx99_deinit(sc);
+-      }
+-
+-      if (!start) {
+-              ath9k_tx99_deinit(sc);
+-              return count;
+-      }
+-
+-      r = ath9k_tx99_init(sc);
+-      if (r)
+-              return r;
+-
+-      return count;
+-}
+-
+-static const struct file_operations fops_tx99 = {
+-      .read = read_file_tx99,
+-      .write = write_file_tx99,
+-      .open = simple_open,
+-      .owner = THIS_MODULE,
+-      .llseek = default_llseek,
+-};
+-
+-static ssize_t read_file_tx99_power(struct file *file,
+-                                  char __user *user_buf,
+-                                  size_t count, loff_t *ppos)
+-{
+-      struct ath_softc *sc = file->private_data;
+-      char buf[32];
+-      unsigned int len;
+-
+-      len = sprintf(buf, "%d (%d dBm)\n",
+-                    sc->tx99_power,
+-                    sc->tx99_power / 2);
+-
+-      return simple_read_from_buffer(user_buf, count, ppos, buf, len);
+-}
+-
+-static ssize_t write_file_tx99_power(struct file *file,
+-                                   const char __user *user_buf,
+-                                   size_t count, loff_t *ppos)
+-{
+-      struct ath_softc *sc = file->private_data;
+-      int r;
+-      u8 tx_power;
+-
+-      r = kstrtou8_from_user(user_buf, count, 0, &tx_power);
+-      if (r)
+-              return r;
+-
+-      if (tx_power > MAX_RATE_POWER)
+-              return -EINVAL;
+-
+-      sc->tx99_power = tx_power;
+-
+-      ath9k_ps_wakeup(sc);
+-      ath9k_hw_tx99_set_txpower(sc->sc_ah, sc->tx99_power);
+-      ath9k_ps_restore(sc);
+-
+-      return count;
+-}
+-
+-static const struct file_operations fops_tx99_power = {
+-      .read = read_file_tx99_power,
+-      .write = write_file_tx99_power,
+-      .open = simple_open,
+-      .owner = THIS_MODULE,
+-      .llseek = default_llseek,
+-};
+-
+ int ath9k_init_debug(struct ath_hw *ah)
+ {
+       struct ath_common *common = ath9k_hw_common(ah);
+@@ -1903,6 +1544,8 @@ int ath9k_init_debug(struct ath_hw *ah)
+ #endif
+       ath9k_dfs_init_debug(sc);
++      ath9k_tx99_init_debug(sc);
++      ath9k_spectral_init_debug(sc);
+       debugfs_create_file("dma", S_IRUSR, sc->debug.debugfs_phy, sc,
+                           &fops_dma);
+@@ -1949,23 +1592,6 @@ int ath9k_init_debug(struct ath_hw *ah)
+                           &fops_base_eeprom);
+       debugfs_create_file("modal_eeprom", S_IRUSR, sc->debug.debugfs_phy, sc,
+                           &fops_modal_eeprom);
+-      sc->rfs_chan_spec_scan = relay_open("spectral_scan",
+-                                          sc->debug.debugfs_phy,
+-                                          1024, 256, &rfs_spec_scan_cb,
+-                                          NULL);
+-      debugfs_create_file("spectral_scan_ctl", S_IRUSR | S_IWUSR,
+-                          sc->debug.debugfs_phy, sc,
+-                          &fops_spec_scan_ctl);
+-      debugfs_create_file("spectral_short_repeat", S_IRUSR | S_IWUSR,
+-                          sc->debug.debugfs_phy, sc,
+-                          &fops_spectral_short_repeat);
+-      debugfs_create_file("spectral_count", S_IRUSR | S_IWUSR,
+-                          sc->debug.debugfs_phy, sc, &fops_spectral_count);
+-      debugfs_create_file("spectral_period", S_IRUSR | S_IWUSR,
+-                          sc->debug.debugfs_phy, sc, &fops_spectral_period);
+-      debugfs_create_file("spectral_fft_period", S_IRUSR | S_IWUSR,
+-                          sc->debug.debugfs_phy, sc,
+-                          &fops_spectral_fft_period);
+       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,
+@@ -1978,15 +1604,6 @@ int ath9k_init_debug(struct ath_hw *ah)
+       debugfs_create_file("btcoex", S_IRUSR, sc->debug.debugfs_phy, sc,
+                           &fops_btcoex);
+ #endif
+-      if (config_enabled(CPTCFG_ATH9K_TX99) &&
+-          AR_SREV_9300_20_OR_LATER(ah)) {
+-              debugfs_create_file("tx99", S_IRUSR | S_IWUSR,
+-                                  sc->debug.debugfs_phy, sc,
+-                                  &fops_tx99);
+-              debugfs_create_file("tx99_power", S_IRUSR | S_IWUSR,
+-                                  sc->debug.debugfs_phy, sc,
+-                                  &fops_tx99_power);
+-      }
+       return 0;
+ }
+--- a/drivers/net/wireless/ath/ath9k/hw.c
++++ b/drivers/net/wireless/ath/ath9k/hw.c
+@@ -17,6 +17,8 @@
+ #include <linux/io.h>
+ #include <linux/slab.h>
+ #include <linux/module.h>
++#include <linux/time.h>
++#include <linux/bitops.h>
+ #include <asm/unaligned.h>
+ #include "hw.h"
+@@ -83,48 +85,6 @@ static void ath9k_hw_ani_cache_ini_regs(
+ #ifdef CPTCFG_ATH9K_DEBUGFS
+-void ath9k_debug_sync_cause(struct ath_common *common, u32 sync_cause)
+-{
+-      struct ath_softc *sc = common->priv;
+-      if (sync_cause)
+-              sc->debug.stats.istats.sync_cause_all++;
+-      if (sync_cause & AR_INTR_SYNC_RTC_IRQ)
+-              sc->debug.stats.istats.sync_rtc_irq++;
+-      if (sync_cause & AR_INTR_SYNC_MAC_IRQ)
+-              sc->debug.stats.istats.sync_mac_irq++;
+-      if (sync_cause & AR_INTR_SYNC_EEPROM_ILLEGAL_ACCESS)
+-              sc->debug.stats.istats.eeprom_illegal_access++;
+-      if (sync_cause & AR_INTR_SYNC_APB_TIMEOUT)
+-              sc->debug.stats.istats.apb_timeout++;
+-      if (sync_cause & AR_INTR_SYNC_PCI_MODE_CONFLICT)
+-              sc->debug.stats.istats.pci_mode_conflict++;
+-      if (sync_cause & AR_INTR_SYNC_HOST1_FATAL)
+-              sc->debug.stats.istats.host1_fatal++;
+-      if (sync_cause & AR_INTR_SYNC_HOST1_PERR)
+-              sc->debug.stats.istats.host1_perr++;
+-      if (sync_cause & AR_INTR_SYNC_TRCV_FIFO_PERR)
+-              sc->debug.stats.istats.trcv_fifo_perr++;
+-      if (sync_cause & AR_INTR_SYNC_RADM_CPL_EP)
+-              sc->debug.stats.istats.radm_cpl_ep++;
+-      if (sync_cause & AR_INTR_SYNC_RADM_CPL_DLLP_ABORT)
+-              sc->debug.stats.istats.radm_cpl_dllp_abort++;
+-      if (sync_cause & AR_INTR_SYNC_RADM_CPL_TLP_ABORT)
+-              sc->debug.stats.istats.radm_cpl_tlp_abort++;
+-      if (sync_cause & AR_INTR_SYNC_RADM_CPL_ECRC_ERR)
+-              sc->debug.stats.istats.radm_cpl_ecrc_err++;
+-      if (sync_cause & AR_INTR_SYNC_RADM_CPL_TIMEOUT)
+-              sc->debug.stats.istats.radm_cpl_timeout++;
+-      if (sync_cause & AR_INTR_SYNC_LOCAL_TIMEOUT)
+-              sc->debug.stats.istats.local_timeout++;
+-      if (sync_cause & AR_INTR_SYNC_PM_ACCESS)
+-              sc->debug.stats.istats.pm_access++;
+-      if (sync_cause & AR_INTR_SYNC_MAC_AWAKE)
+-              sc->debug.stats.istats.mac_awake++;
+-      if (sync_cause & AR_INTR_SYNC_MAC_ASLEEP)
+-              sc->debug.stats.istats.mac_asleep++;
+-      if (sync_cause & AR_INTR_SYNC_MAC_SLEEP_ACCESS)
+-              sc->debug.stats.istats.mac_sleep_access++;
+-}
+ #endif
+@@ -438,23 +398,13 @@ static bool ath9k_hw_chip_test(struct at
+ static void ath9k_hw_init_config(struct ath_hw *ah)
+ {
+-      int i;
+-
+       ah->config.dma_beacon_response_time = 1;
+       ah->config.sw_beacon_response_time = 6;
 -      ah->config.additional_swba_backoff = 0;
        ah->config.ack_6mb = 0x0;
        ah->config.cwm_ignore_extcca = 0;
 -      ah->config.additional_swba_backoff = 0;
        ah->config.ack_6mb = 0x0;
        ah->config.cwm_ignore_extcca = 0;
  
        /*
         * We need this for PCI devices only (Cardbus, PCI, miniPCI)
  
        /*
         * We need this for PCI devices only (Cardbus, PCI, miniPCI)
-@@ -486,7 +478,6 @@ static void ath9k_hw_init_defaults(struc
+@@ -486,7 +436,6 @@ static void ath9k_hw_init_defaults(struc
        ah->hw_version.magic = AR5416_MAGIC;
        ah->hw_version.subvendorid = 0;
  
        ah->hw_version.magic = AR5416_MAGIC;
        ah->hw_version.subvendorid = 0;
  
        ah->sta_id1_defaults =
                AR_STA_ID1_CRPT_MIC_ENABLE |
                AR_STA_ID1_MCAST_KSRCH;
        ah->sta_id1_defaults =
                AR_STA_ID1_CRPT_MIC_ENABLE |
                AR_STA_ID1_MCAST_KSRCH;
-@@ -549,11 +540,11 @@ static int ath9k_hw_post_init(struct ath
+@@ -549,11 +498,11 @@ static int ath9k_hw_post_init(struct ath
         * EEPROM needs to be initialized before we do this.
         * This is required for regulatory compliance.
         */
         * EEPROM needs to be initialized before we do this.
         * This is required for regulatory compliance.
         */
                }
        }
  
                }
        }
  
-@@ -1502,8 +1493,9 @@ static bool ath9k_hw_channel_change(stru
-       int r;
-       if (pCap->hw_caps & ATH9K_HW_CAP_FCC_BAND_SWITCH) {
--              band_switch = IS_CHAN_5GHZ(ah->curchan) != IS_CHAN_5GHZ(chan);
--              mode_diff = (chan->channelFlags != ah->curchan->channelFlags);
-+              u32 flags_diff = chan->channelFlags ^ ah->curchan->channelFlags;
-+              band_switch = !!(flags_diff & CHANNEL_5GHZ);
-+              mode_diff = !!(flags_diff & ~CHANNEL_HT);
-       }
-       for (qnum = 0; qnum < AR_NUM_QCU; qnum++) {
-@@ -1815,7 +1807,7 @@ static int ath9k_hw_do_fastcc(struct ath
-        * If cross-band fcc is not supoprted, bail out if channelFlags differ.
-        */
-       if (!(pCap->hw_caps & ATH9K_HW_CAP_FCC_BAND_SWITCH) &&
--          chan->channelFlags != ah->curchan->channelFlags)
-+          ((chan->channelFlags ^ ah->curchan->channelFlags) & ~CHANNEL_HT))
-               goto fail;
+@@ -1282,6 +1231,42 @@ void ath9k_hw_get_delta_slope_vals(struc
+       *coef_exponent = coef_exp - 16;
+ }
  
  
-       if (!ath9k_hw_check_alive(ah))
-@@ -1856,10 +1848,12 @@ int ath9k_hw_reset(struct ath_hw *ah, st
-                  struct ath9k_hw_cal_data *caldata, bool fastcc)
- {
-       struct ath_common *common = ath9k_hw_common(ah);
-+      struct timespec ts;
-       u32 saveLedState;
++/* AR9330 WAR:
++ * call external reset function to reset WMAC if:
++ * - doing a cold reset
++ * - we have pending frames in the TX queues.
++ */
++static bool ath9k_hw_ar9330_reset_war(struct ath_hw *ah, int type)
++{
++      int i, npend = 0;
++
++      for (i = 0; i < AR_NUM_QCU; i++) {
++              npend = ath9k_hw_numtxpending(ah, i);
++              if (npend)
++                      break;
++      }
++
++      if (ah->external_reset &&
++          (npend || type == ATH9K_RESET_COLD)) {
++              int reset_err = 0;
++
++              ath_dbg(ath9k_hw_common(ah), RESET,
++                      "reset MAC via external reset\n");
++
++              reset_err = ah->external_reset();
++              if (reset_err) {
++                      ath_err(ath9k_hw_common(ah),
++                              "External reset failed, err=%d\n",
++                              reset_err);
++                      return false;
++              }
++
++              REG_WRITE(ah, AR_RTC_RESET, 1);
++      }
++
++      return true;
++}
++
+ static bool ath9k_hw_set_reset(struct ath_hw *ah, int type)
+ {
+       u32 rst_flags;
+@@ -1332,38 +1317,8 @@ static bool ath9k_hw_set_reset(struct at
+       }
+       if (AR_SREV_9330(ah)) {
+-              int npend = 0;
+-              int i;
+-
+-              /* AR9330 WAR:
+-               * call external reset function to reset WMAC if:
+-               * - doing a cold reset
+-               * - we have pending frames in the TX queues
+-               */
+-
+-              for (i = 0; i < AR_NUM_QCU; i++) {
+-                      npend = ath9k_hw_numtxpending(ah, i);
+-                      if (npend)
+-                              break;
+-              }
+-
+-              if (ah->external_reset &&
+-                  (npend || type == ATH9K_RESET_COLD)) {
+-                      int reset_err = 0;
+-
+-                      ath_dbg(ath9k_hw_common(ah), RESET,
+-                              "reset MAC via external reset\n");
+-
+-                      reset_err = ah->external_reset();
+-                      if (reset_err) {
+-                              ath_err(ath9k_hw_common(ah),
+-                                      "External reset failed, err=%d\n",
+-                                      reset_err);
+-                              return false;
+-                      }
+-
+-                      REG_WRITE(ah, AR_RTC_RESET, 1);
+-              }
++              if (!ath9k_hw_ar9330_reset_war(ah, type))
++                      return false;
+       }
+       if (ath9k_hw_mci_is_enabled(ah))
+@@ -1373,7 +1328,12 @@ static bool ath9k_hw_set_reset(struct at
+       REGWRITE_BUFFER_FLUSH(ah);
+-      udelay(50);
++      if (AR_SREV_9300_20_OR_LATER(ah))
++              udelay(50);
++      else if (AR_SREV_9100(ah))
++              udelay(10000);
++      else
++              udelay(100);
+       REG_WRITE(ah, AR_RTC_RC, 0);
+       if (!ath9k_hw_wait(ah, AR_RTC_RC, AR_RTC_RC_M, 0, AH_WAIT_TIMEOUT)) {
+@@ -1409,8 +1369,7 @@ static bool ath9k_hw_set_reset_power_on(
+       REGWRITE_BUFFER_FLUSH(ah);
+-      if (!AR_SREV_9300_20_OR_LATER(ah))
+-              udelay(2);
++      udelay(2);
+       if (!AR_SREV_9100(ah) && !AR_SREV_9300_20_OR_LATER(ah))
+               REG_WRITE(ah, AR_RC, 0);
+@@ -1502,8 +1461,9 @@ static bool ath9k_hw_channel_change(stru
+       int r;
+       if (pCap->hw_caps & ATH9K_HW_CAP_FCC_BAND_SWITCH) {
+-              band_switch = IS_CHAN_5GHZ(ah->curchan) != IS_CHAN_5GHZ(chan);
+-              mode_diff = (chan->channelFlags != ah->curchan->channelFlags);
++              u32 flags_diff = chan->channelFlags ^ ah->curchan->channelFlags;
++              band_switch = !!(flags_diff & CHANNEL_5GHZ);
++              mode_diff = !!(flags_diff & ~CHANNEL_HT);
+       }
+       for (qnum = 0; qnum < AR_NUM_QCU; qnum++) {
+@@ -1815,7 +1775,7 @@ static int ath9k_hw_do_fastcc(struct ath
+        * If cross-band fcc is not supoprted, bail out if channelFlags differ.
+        */
+       if (!(pCap->hw_caps & ATH9K_HW_CAP_FCC_BAND_SWITCH) &&
+-          chan->channelFlags != ah->curchan->channelFlags)
++          ((chan->channelFlags ^ ah->curchan->channelFlags) & ~CHANNEL_HT))
+               goto fail;
+       if (!ath9k_hw_check_alive(ah))
+@@ -1856,10 +1816,12 @@ int ath9k_hw_reset(struct ath_hw *ah, st
+                  struct ath9k_hw_cal_data *caldata, bool fastcc)
+ {
+       struct ath_common *common = ath9k_hw_common(ah);
++      struct timespec ts;
+       u32 saveLedState;
        u32 saveDefAntenna;
        u32 macStaId1;
        u64 tsf = 0;
        u32 saveDefAntenna;
        u32 macStaId1;
        u64 tsf = 0;
        int r;
        bool start_mci_reset = false;
        bool save_fullsleep = ah->chip_fullsleep;
        int r;
        bool start_mci_reset = false;
        bool save_fullsleep = ah->chip_fullsleep;
-@@ -1902,10 +1896,10 @@ int ath9k_hw_reset(struct ath_hw *ah, st
+@@ -1902,10 +1864,10 @@ int ath9k_hw_reset(struct ath_hw *ah, st
  
        macStaId1 = REG_READ(ah, AR_STA_ID1) & AR_STA_ID1_BASE_RATE_11B;
  
  
        macStaId1 = REG_READ(ah, AR_STA_ID1) & AR_STA_ID1_BASE_RATE_11B;
  
  
        saveLedState = REG_READ(ah, AR_CFG_LED) &
                (AR_CFG_LED_ASSOC_CTL | AR_CFG_LED_MODE_SEL |
  
        saveLedState = REG_READ(ah, AR_CFG_LED) &
                (AR_CFG_LED_ASSOC_CTL | AR_CFG_LED_MODE_SEL |
-@@ -1938,8 +1932,9 @@ int ath9k_hw_reset(struct ath_hw *ah, st
+@@ -1938,8 +1900,9 @@ int ath9k_hw_reset(struct ath_hw *ah, st
        }
  
        /* Restore TSF */
        }
  
        /* Restore TSF */
  
        if (AR_SREV_9280_20_OR_LATER(ah))
                REG_SET_BIT(ah, AR_GPIO_INPUT_EN_VAL, AR_GPIO_JTAG_DISABLE);
  
        if (AR_SREV_9280_20_OR_LATER(ah))
                REG_SET_BIT(ah, AR_GPIO_INPUT_EN_VAL, AR_GPIO_JTAG_DISABLE);
-@@ -2261,9 +2256,6 @@ void ath9k_hw_beaconinit(struct ath_hw *
+@@ -2261,9 +2224,6 @@ void ath9k_hw_beaconinit(struct ath_hw *
        case NL80211_IFTYPE_ADHOC:
                REG_SET_BIT(ah, AR_TXCFG,
                            AR_TXCFG_ADHOC_BEACON_ATIM_TX_POLICY);
        case NL80211_IFTYPE_ADHOC:
                REG_SET_BIT(ah, AR_TXCFG,
                            AR_TXCFG_ADHOC_BEACON_ATIM_TX_POLICY);
        case NL80211_IFTYPE_MESH_POINT:
        case NL80211_IFTYPE_AP:
                REG_WRITE(ah, AR_NEXT_TBTT_TIMER, next_beacon);
        case NL80211_IFTYPE_MESH_POINT:
        case NL80211_IFTYPE_AP:
                REG_WRITE(ah, AR_NEXT_TBTT_TIMER, next_beacon);
-@@ -2284,7 +2276,6 @@ void ath9k_hw_beaconinit(struct ath_hw *
+@@ -2284,7 +2244,6 @@ void ath9k_hw_beaconinit(struct ath_hw *
        REG_WRITE(ah, AR_BEACON_PERIOD, beacon_period);
        REG_WRITE(ah, AR_DMA_BEACON_PERIOD, beacon_period);
        REG_WRITE(ah, AR_SWBA_PERIOD, beacon_period);
        REG_WRITE(ah, AR_BEACON_PERIOD, beacon_period);
        REG_WRITE(ah, AR_DMA_BEACON_PERIOD, beacon_period);
        REG_WRITE(ah, AR_SWBA_PERIOD, beacon_period);
  
        REGWRITE_BUFFER_FLUSH(ah);
  
  
        REGWRITE_BUFFER_FLUSH(ah);
  
-@@ -2301,12 +2292,9 @@ void ath9k_hw_set_sta_beacon_timers(stru
+@@ -2301,12 +2260,9 @@ void ath9k_hw_set_sta_beacon_timers(stru
  
        ENABLE_REGWRITE_BUFFER(ah);
  
  
        ENABLE_REGWRITE_BUFFER(ah);
  
  
        REGWRITE_BUFFER_FLUSH(ah);
  
  
        REGWRITE_BUFFER_FLUSH(ah);
  
-@@ -2334,9 +2322,8 @@ void ath9k_hw_set_sta_beacon_timers(stru
+@@ -2334,9 +2290,8 @@ void ath9k_hw_set_sta_beacon_timers(stru
  
        ENABLE_REGWRITE_BUFFER(ah);
  
  
        ENABLE_REGWRITE_BUFFER(ah);
  
  
        REG_WRITE(ah, AR_SLEEP1,
                  SM((CAB_TIMEOUT_VAL << 3), AR_SLEEP1_CAB_TIMEOUT)
  
        REG_WRITE(ah, AR_SLEEP1,
                  SM((CAB_TIMEOUT_VAL << 3), AR_SLEEP1_CAB_TIMEOUT)
-@@ -2350,8 +2337,8 @@ void ath9k_hw_set_sta_beacon_timers(stru
+@@ -2350,8 +2305,8 @@ void ath9k_hw_set_sta_beacon_timers(stru
        REG_WRITE(ah, AR_SLEEP2,
                  SM(beacontimeout, AR_SLEEP2_BEACON_TIMEOUT));
  
        REG_WRITE(ah, AR_SLEEP2,
                  SM(beacontimeout, AR_SLEEP2_BEACON_TIMEOUT));
  
  
        REGWRITE_BUFFER_FLUSH(ah);
  
  
        REGWRITE_BUFFER_FLUSH(ah);
  
-@@ -2987,20 +2974,6 @@ static const struct ath_gen_timer_config
+@@ -2987,20 +2942,6 @@ static const struct ath_gen_timer_config
  
  /* HW generic timer primitives */
  
  
  /* HW generic timer primitives */
  
  u32 ath9k_hw_gettsf32(struct ath_hw *ah)
  {
        return REG_READ(ah, AR_TSF_L32);
  u32 ath9k_hw_gettsf32(struct ath_hw *ah)
  {
        return REG_READ(ah, AR_TSF_L32);
-@@ -3016,6 +2989,10 @@ struct ath_gen_timer *ath_gen_timer_allo
+@@ -3016,6 +2957,10 @@ struct ath_gen_timer *ath_gen_timer_allo
        struct ath_gen_timer_table *timer_table = &ah->hw_gen_timers;
        struct ath_gen_timer *timer;
  
        struct ath_gen_timer_table *timer_table = &ah->hw_gen_timers;
        struct ath_gen_timer *timer;
  
        timer = kzalloc(sizeof(struct ath_gen_timer), GFP_KERNEL);
        if (timer == NULL)
                return NULL;
        timer = kzalloc(sizeof(struct ath_gen_timer), GFP_KERNEL);
        if (timer == NULL)
                return NULL;
-@@ -3033,23 +3010,13 @@ EXPORT_SYMBOL(ath_gen_timer_alloc);
+@@ -3033,23 +2978,13 @@ EXPORT_SYMBOL(ath_gen_timer_alloc);
  
  void ath9k_hw_gen_timer_start(struct ath_hw *ah,
                              struct ath_gen_timer *timer,
  
  void ath9k_hw_gen_timer_start(struct ath_hw *ah,
                              struct ath_gen_timer *timer,
 -      BUG_ON(!timer_period);
 -
 -      set_bit(timer->index, &timer_table->timer_mask.timer_bits);
 -      BUG_ON(!timer_period);
 -
 -      set_bit(timer->index, &timer_table->timer_mask.timer_bits);
--
--      tsf = ath9k_hw_gettsf32(ah);
 +      u32 mask = 0;
  
 +      u32 mask = 0;
  
+-      tsf = ath9k_hw_gettsf32(ah);
+-
 -      timer_next = tsf + trig_timeout;
 -
 -      ath_dbg(ath9k_hw_common(ah), BTCOEX,
 -      timer_next = tsf + trig_timeout;
 -
 -      ath_dbg(ath9k_hw_common(ah), BTCOEX,
  
        /*
         * Program generic timer registers
  
        /*
         * Program generic timer registers
-@@ -3075,10 +3042,19 @@ void ath9k_hw_gen_timer_start(struct ath
+@@ -3075,10 +3010,19 @@ void ath9k_hw_gen_timer_start(struct ath
                                       (1 << timer->index));
        }
  
                                       (1 << timer->index));
        }
  
  }
  EXPORT_SYMBOL(ath9k_hw_gen_timer_start);
  
  }
  EXPORT_SYMBOL(ath9k_hw_gen_timer_start);
  
-@@ -3086,11 +3062,6 @@ void ath9k_hw_gen_timer_stop(struct ath_
+@@ -3086,11 +3030,6 @@ void ath9k_hw_gen_timer_stop(struct ath_
  {
        struct ath_gen_timer_table *timer_table = &ah->hw_gen_timers;
  
  {
        struct ath_gen_timer_table *timer_table = &ah->hw_gen_timers;
  
        /* Clear generic timer enable bits. */
        REG_CLR_BIT(ah, gen_tmr_configuration[timer->index].mode_addr,
                        gen_tmr_configuration[timer->index].mode_mask);
        /* Clear generic timer enable bits. */
        REG_CLR_BIT(ah, gen_tmr_configuration[timer->index].mode_addr,
                        gen_tmr_configuration[timer->index].mode_mask);
-@@ -3110,7 +3081,12 @@ void ath9k_hw_gen_timer_stop(struct ath_
+@@ -3110,7 +3049,12 @@ void ath9k_hw_gen_timer_stop(struct ath_
                (SM(AR_GENTMR_BIT(timer->index), AR_IMR_S5_GENTIMER_THRESH) |
                SM(AR_GENTMR_BIT(timer->index), AR_IMR_S5_GENTIMER_TRIG)));
  
                (SM(AR_GENTMR_BIT(timer->index), AR_IMR_S5_GENTIMER_THRESH) |
                SM(AR_GENTMR_BIT(timer->index), AR_IMR_S5_GENTIMER_TRIG)));
  
  }
  EXPORT_SYMBOL(ath9k_hw_gen_timer_stop);
  
  }
  EXPORT_SYMBOL(ath9k_hw_gen_timer_stop);
  
-@@ -3131,32 +3107,32 @@ void ath_gen_timer_isr(struct ath_hw *ah
+@@ -3131,32 +3075,32 @@ void ath_gen_timer_isr(struct ath_hw *ah
  {
        struct ath_gen_timer_table *timer_table = &ah->hw_gen_timers;
        struct ath_gen_timer *timer;
  {
        struct ath_gen_timer_table *timer_table = &ah->hw_gen_timers;
        struct ath_gen_timer *timer;
  };
  
  struct ath_hw_antcomb_conf {
  };
  
  struct ath_hw_antcomb_conf {
-@@ -785,7 +763,6 @@ struct ath_hw {
+@@ -689,7 +667,8 @@ struct ath_hw_ops {
+                         struct ath9k_channel *chan,
+                         u8 rxchainmask,
+                         bool longcal);
+-      bool (*get_isr)(struct ath_hw *ah, enum ath9k_int *masked);
++      bool (*get_isr)(struct ath_hw *ah, enum ath9k_int *masked,
++                      u32 *sync_cause_p);
+       void (*set_txdesc)(struct ath_hw *ah, void *ds,
+                          struct ath_tx_info *i);
+       int (*proc_txdesc)(struct ath_hw *ah, void *ds,
+@@ -785,7 +764,6 @@ struct ath_hw {
        u32 txurn_interrupt_mask;
        atomic_t intr_ref_cnt;
        bool chip_fullsleep;
        u32 txurn_interrupt_mask;
        atomic_t intr_ref_cnt;
        bool chip_fullsleep;
        u32 modes_index;
  
        /* Calibration */
        u32 modes_index;
  
        /* Calibration */
-@@ -864,6 +841,7 @@ struct ath_hw {
+@@ -864,6 +842,7 @@ struct ath_hw {
        u32 gpio_mask;
        u32 gpio_val;
  
        u32 gpio_mask;
        u32 gpio_val;
  
        struct ar5416IniArray iniModes;
        struct ar5416IniArray iniCommon;
        struct ar5416IniArray iniBB_RfGain;
        struct ar5416IniArray iniModes;
        struct ar5416IniArray iniCommon;
        struct ar5416IniArray iniBB_RfGain;
-@@ -920,7 +898,7 @@ struct ath_hw {
+@@ -920,7 +899,7 @@ struct ath_hw {
        /* Enterprise mode cap */
        u32 ent_mode;
  
        /* Enterprise mode cap */
        u32 ent_mode;
  
        u32 wow_event_mask;
  #endif
        bool is_clk_25mhz;
        u32 wow_event_mask;
  #endif
        bool is_clk_25mhz;
-@@ -1126,7 +1104,7 @@ ath9k_hw_get_btcoex_scheme(struct ath_hw
+@@ -1016,13 +995,6 @@ bool ath9k_hw_check_alive(struct ath_hw 
+ bool ath9k_hw_setpower(struct ath_hw *ah, enum ath9k_power_mode mode);
+-#ifdef CPTCFG_ATH9K_DEBUGFS
+-void ath9k_debug_sync_cause(struct ath_common *common, u32 sync_cause);
+-#else
+-static inline void ath9k_debug_sync_cause(struct ath_common *common,
+-                                        u32 sync_cause) {}
+-#endif
+-
+ /* Generic hw timer primitives */
+ struct ath_gen_timer *ath_gen_timer_alloc(struct ath_hw *ah,
+                                         void (*trigger)(void *),
+@@ -1126,7 +1098,7 @@ ath9k_hw_get_btcoex_scheme(struct ath_hw
  #endif /* CPTCFG_ATH9K_BTCOEX_SUPPORT */
  
  
  #endif /* CPTCFG_ATH9K_BTCOEX_SUPPORT */
  
  
                                u8 *user_mask, int pattern_count,
 --- a/drivers/net/wireless/ath/ath9k/init.c
 +++ b/drivers/net/wireless/ath/ath9k/init.c
                                u8 *user_mask, int pattern_count,
 --- a/drivers/net/wireless/ath/ath9k/init.c
 +++ b/drivers/net/wireless/ath/ath9k/init.c
-@@ -554,7 +554,7 @@ static void ath9k_init_misc(struct ath_s
+@@ -470,7 +470,6 @@ static int ath9k_init_queues(struct ath_
+       sc->beacon.beaconq = ath9k_hw_beaconq_setup(sc->sc_ah);
+       sc->beacon.cabq = ath_txq_setup(sc, ATH9K_TX_QUEUE_CAB, 0);
+-
+       ath_cabq_update(sc);
+       sc->tx.uapsdq = ath_txq_setup(sc, ATH9K_TX_QUEUE_UAPSD, 0);
+@@ -554,7 +553,7 @@ static void ath9k_init_misc(struct ath_s
        sc->spec_config.fft_period = 0xF;
  }
  
        sc->spec_config.fft_period = 0xF;
  }
  
  {
        struct ath_hw *ah = sc->sc_ah;
        struct ath9k_hw_capabilities *pCap = &ah->caps;
  {
        struct ath_hw *ah = sc->sc_ah;
        struct ath9k_hw_capabilities *pCap = &ah->caps;
-@@ -609,6 +609,11 @@ static void ath9k_init_platform(struct a
+@@ -609,6 +608,11 @@ static void ath9k_init_platform(struct a
                ah->config.pcie_waen = 0x0040473b;
                ath_info(common, "Enable WAR for ASPM D3/L1\n");
        }
                ah->config.pcie_waen = 0x0040473b;
                ath_info(common, "Enable WAR for ASPM D3/L1\n");
        }
  }
  
  static void ath9k_eeprom_request_cb(const struct firmware *eeprom_blob,
  }
  
  static void ath9k_eeprom_request_cb(const struct firmware *eeprom_blob,
-@@ -656,6 +661,27 @@ static void ath9k_eeprom_release(struct 
+@@ -656,6 +660,27 @@ static void ath9k_eeprom_release(struct 
        release_firmware(sc->sc_ah->eeprom_blob);
  }
  
        release_firmware(sc->sc_ah->eeprom_blob);
  }
  
  static int ath9k_init_softc(u16 devid, struct ath_softc *sc,
                            const struct ath_bus_ops *bus_ops)
  {
  static int ath9k_init_softc(u16 devid, struct ath_softc *sc,
                            const struct ath_bus_ops *bus_ops)
  {
-@@ -683,6 +709,7 @@ static int ath9k_init_softc(u16 devid, s
+@@ -676,13 +701,13 @@ static int ath9k_init_softc(u16 devid, s
+       ah->reg_ops.read = ath9k_ioread32;
+       ah->reg_ops.write = ath9k_iowrite32;
+       ah->reg_ops.rmw = ath9k_reg_rmw;
+-      atomic_set(&ah->intr_ref_cnt, -1);
+       sc->sc_ah = ah;
+       pCap = &ah->caps;
        common = ath9k_hw_common(ah);
        sc->dfs_detector = dfs_pattern_detector_init(common, NL80211_DFS_UNSET);
        sc->tx99_power = MAX_RATE_POWER + 1;
        common = ath9k_hw_common(ah);
        sc->dfs_detector = dfs_pattern_detector_init(common, NL80211_DFS_UNSET);
        sc->tx99_power = MAX_RATE_POWER + 1;
  
        if (!pdata) {
                ah->ah_flags |= AH_USE_EEPROM;
  
        if (!pdata) {
                ah->ah_flags |= AH_USE_EEPROM;
-@@ -708,7 +735,11 @@ static int ath9k_init_softc(u16 devid, s
+@@ -708,7 +733,11 @@ static int ath9k_init_softc(u16 devid, s
        /*
         * Platform quirks.
         */
        /*
         * Platform quirks.
         */
  
        /*
         * Enable WLAN/BT RX Antenna diversity only when:
  
        /*
         * Enable WLAN/BT RX Antenna diversity only when:
-@@ -722,7 +753,6 @@ static int ath9k_init_softc(u16 devid, s
+@@ -722,7 +751,6 @@ static int ath9k_init_softc(u16 devid, s
                common->bt_ant_diversity = 1;
  
        spin_lock_init(&common->cc_lock);
                common->bt_ant_diversity = 1;
  
        spin_lock_init(&common->cc_lock);
        spin_lock_init(&sc->sc_serial_rw);
        spin_lock_init(&sc->sc_pm_lock);
        mutex_init(&sc->mutex);
        spin_lock_init(&sc->sc_serial_rw);
        spin_lock_init(&sc->sc_pm_lock);
        mutex_init(&sc->mutex);
-@@ -730,6 +760,7 @@ static int ath9k_init_softc(u16 devid, s
+@@ -730,6 +758,7 @@ static int ath9k_init_softc(u16 devid, s
        tasklet_init(&sc->bcon_tasklet, ath9k_beacon_tasklet,
                     (unsigned long)sc);
  
        tasklet_init(&sc->bcon_tasklet, ath9k_beacon_tasklet,
                     (unsigned long)sc);
  
        INIT_WORK(&sc->hw_reset_work, ath_reset_work);
        INIT_WORK(&sc->hw_check_work, ath_hw_check);
        INIT_WORK(&sc->paprd_work, ath_paprd_calibrate);
        INIT_WORK(&sc->hw_reset_work, ath_reset_work);
        INIT_WORK(&sc->hw_check_work, ath_hw_check);
        INIT_WORK(&sc->paprd_work, ath_paprd_calibrate);
-@@ -743,12 +774,6 @@ static int ath9k_init_softc(u16 devid, s
+@@ -743,12 +772,6 @@ static int ath9k_init_softc(u16 devid, s
        ath_read_cachesize(common, &csz);
        common->cachelsz = csz << 2; /* convert to bytes */
  
        ath_read_cachesize(common, &csz);
        common->cachelsz = csz << 2; /* convert to bytes */
  
        /* Initializes the hardware for all supported chipsets */
        ret = ath9k_hw_init(ah);
        if (ret)
        /* Initializes the hardware for all supported chipsets */
        ret = ath9k_hw_init(ah);
        if (ret)
-@@ -845,7 +870,8 @@ static const struct ieee80211_iface_limi
+@@ -845,7 +868,8 @@ static const struct ieee80211_iface_limi
  };
  
  static const struct ieee80211_iface_limit if_dfs_limits[] = {
  };
  
  static const struct ieee80211_iface_limit if_dfs_limits[] = {
  };
  
  static const struct ieee80211_iface_combination if_comb[] = {
  };
  
  static const struct ieee80211_iface_combination if_comb[] = {
-@@ -862,20 +888,11 @@ static const struct ieee80211_iface_comb
+@@ -862,21 +886,12 @@ static const struct ieee80211_iface_comb
                .max_interfaces = 1,
                .num_different_channels = 1,
                .beacon_int_infra_match = true,
                .max_interfaces = 1,
                .num_different_channels = 1,
                .beacon_int_infra_match = true,
 -};
 -#endif
 -
 -};
 -#endif
 -
- void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw)
+-void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw)
++static void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw)
  {
        struct ath_hw *ah = sc->sc_ah;
  {
        struct ath_hw *ah = sc->sc_ah;
-@@ -925,16 +942,6 @@ void ath9k_set_hw_capab(struct ath_softc
+       struct ath_common *common = ath9k_hw_common(ah);
+@@ -925,16 +940,6 @@ void ath9k_set_hw_capab(struct ath_softc
        hw->wiphy->flags |= WIPHY_FLAG_SUPPORTS_5_10_MHZ;
        hw->wiphy->flags |= WIPHY_FLAG_HAS_CHANNEL_SWITCH;
  
        hw->wiphy->flags |= WIPHY_FLAG_SUPPORTS_5_10_MHZ;
        hw->wiphy->flags |= WIPHY_FLAG_HAS_CHANNEL_SWITCH;
  
        hw->queues = 4;
        hw->max_rates = 4;
        hw->channel_change_time = 5000;
        hw->queues = 4;
        hw->max_rates = 4;
        hw->channel_change_time = 5000;
-@@ -960,6 +967,7 @@ void ath9k_set_hw_capab(struct ath_softc
+@@ -960,6 +965,7 @@ void ath9k_set_hw_capab(struct ath_softc
                hw->wiphy->bands[IEEE80211_BAND_5GHZ] =
                        &sc->sbands[IEEE80211_BAND_5GHZ];
  
                hw->wiphy->bands[IEEE80211_BAND_5GHZ] =
                        &sc->sbands[IEEE80211_BAND_5GHZ];
  
        ath9k_reload_chainmask_settings(sc);
  
        SET_IEEE80211_PERM_ADDR(hw, common->macaddr);
        ath9k_reload_chainmask_settings(sc);
  
        SET_IEEE80211_PERM_ADDR(hw, common->macaddr);
-@@ -1058,6 +1066,7 @@ static void ath9k_deinit_softc(struct at
+@@ -1058,6 +1064,7 @@ static void ath9k_deinit_softc(struct at
                if (ATH_TXQ_SETUP(sc, i))
                        ath_tx_cleanupq(sc, &sc->tx.txq[i]);
  
                if (ATH_TXQ_SETUP(sc, i))
                        ath_tx_cleanupq(sc, &sc->tx.txq[i]);
  
        ath9k_btcoex_handle_interrupt(sc, status);
  
        /* re-enable hardware interrupt */
        ath9k_btcoex_handle_interrupt(sc, status);
  
        /* re-enable hardware interrupt */
-@@ -579,7 +601,8 @@ irqreturn_t ath_isr(int irq, void *dev)
+@@ -519,6 +541,7 @@ irqreturn_t ath_isr(int irq, void *dev)
+       struct ath_hw *ah = sc->sc_ah;
+       struct ath_common *common = ath9k_hw_common(ah);
+       enum ath9k_int status;
++      u32 sync_cause;
+       bool sched = false;
+       /*
+@@ -545,7 +568,8 @@ irqreturn_t ath_isr(int irq, void *dev)
+        * bits we haven't explicitly enabled so we mask the
+        * value to insure we only process bits we requested.
+        */
+-      ath9k_hw_getisr(ah, &status);   /* NB: clears ISR too */
++      ath9k_hw_getisr(ah, &status, &sync_cause); /* NB: clears ISR too */
++      ath9k_debug_sync_cause(sc, sync_cause);
+       status &= ah->imask;    /* discard unasked-for bits */
+       /*
+@@ -579,7 +603,8 @@ irqreturn_t ath_isr(int irq, void *dev)
  
                goto chip_reset;
        }
  
                goto chip_reset;
        }
        if (status & ATH9K_INT_BMISS) {
                if (atomic_read(&sc->wow_sleep_proc_intr) == 0) {
                        ath_dbg(common, ANY, "during WoW we got a BMISS\n");
        if (status & ATH9K_INT_BMISS) {
                if (atomic_read(&sc->wow_sleep_proc_intr) == 0) {
                        ath_dbg(common, ANY, "during WoW we got a BMISS\n");
-@@ -588,6 +611,8 @@ irqreturn_t ath_isr(int irq, void *dev)
+@@ -588,6 +613,8 @@ irqreturn_t ath_isr(int irq, void *dev)
                }
        }
  #endif
                }
        }
  #endif
        if (status & ATH9K_INT_SWBA)
                tasklet_schedule(&sc->bcon_tasklet);
  
        if (status & ATH9K_INT_SWBA)
                tasklet_schedule(&sc->bcon_tasklet);
  
-@@ -627,7 +652,7 @@ chip_reset:
+@@ -627,7 +654,7 @@ chip_reset:
  #undef SCHED_INTR
  }
  
  #undef SCHED_INTR
  }
  
  {
        int r;
  
  {
        int r;
  
-@@ -735,6 +760,8 @@ static int ath9k_start(struct ieee80211_
+@@ -735,6 +762,8 @@ static int ath9k_start(struct ieee80211_
         */
        ath9k_cmn_init_crypto(sc->sc_ah);
  
         */
        ath9k_cmn_init_crypto(sc->sc_ah);
  
        spin_unlock_bh(&sc->sc_pcu_lock);
  
        mutex_unlock(&sc->mutex);
        spin_unlock_bh(&sc->sc_pcu_lock);
  
        mutex_unlock(&sc->mutex);
-@@ -1817,13 +1844,31 @@ static void ath9k_set_coverage_class(str
+@@ -1635,13 +1664,8 @@ static void ath9k_bss_info_changed(struc
+       }
+       if ((changed & BSS_CHANGED_BEACON_ENABLED) ||
+-          (changed & BSS_CHANGED_BEACON_INT)) {
+-              if (ah->opmode == NL80211_IFTYPE_AP &&
+-                  bss_conf->enable_beacon)
+-                      ath9k_set_tsfadjust(sc, vif);
+-              if (ath9k_allow_beacon_config(sc, vif))
+-                      ath9k_beacon_config(sc, vif, changed);
+-      }
++          (changed & BSS_CHANGED_BEACON_INT))
++              ath9k_beacon_config(sc, vif, changed);
+       if (changed & BSS_CHANGED_ERP_SLOT) {
+               if (bss_conf->use_short_slot)
+@@ -1817,13 +1841,31 @@ static void ath9k_set_coverage_class(str
        mutex_unlock(&sc->mutex);
  }
  
        mutex_unlock(&sc->mutex);
  }
  
        bool drain_txq;
  
        mutex_lock(&sc->mutex);
        bool drain_txq;
  
        mutex_lock(&sc->mutex);
-@@ -1841,25 +1886,9 @@ static void ath9k_flush(struct ieee80211
+@@ -1841,25 +1883,9 @@ static void ath9k_flush(struct ieee80211
                return;
        }
  
                return;
        }
  
  
        if (drop) {
                ath9k_ps_wakeup(sc);
  
        if (drop) {
                ath9k_ps_wakeup(sc);
-@@ -2021,333 +2050,6 @@ static int ath9k_get_antenna(struct ieee
+@@ -2021,333 +2047,6 @@ static int ath9k_get_antenna(struct ieee
        return 0;
  }
  
        return 0;
  }
  
  static void ath9k_sw_scan_start(struct ieee80211_hw *hw)
  {
        struct ath_softc *sc = hw->priv;
  static void ath9k_sw_scan_start(struct ieee80211_hw *hw)
  {
        struct ath_softc *sc = hw->priv;
-@@ -2373,134 +2075,6 @@ static void ath9k_channel_switch_beacon(
+@@ -2373,134 +2072,6 @@ static void ath9k_channel_switch_beacon(
        sc->csa_vif = vif;
  }
  
        sc->csa_vif = vif;
  }
  
  struct ieee80211_ops ath9k_ops = {
        .tx                 = ath9k_tx,
        .start              = ath9k_start,
  struct ieee80211_ops ath9k_ops = {
        .tx                 = ath9k_tx,
        .start              = ath9k_start,
-@@ -2531,7 +2105,7 @@ struct ieee80211_ops ath9k_ops = {
+@@ -2531,7 +2102,7 @@ struct ieee80211_ops ath9k_ops = {
        .set_antenna        = ath9k_set_antenna,
        .get_antenna        = ath9k_get_antenna,
  
        .set_antenna        = ath9k_set_antenna,
        .get_antenna        = ath9k_get_antenna,
  
 -EXPORT_SYMBOL(ath9k_hw_wow_enable);
 --- a/drivers/net/wireless/ath/ath9k/xmit.c
 +++ b/drivers/net/wireless/ath/ath9k/xmit.c
 -EXPORT_SYMBOL(ath9k_hw_wow_enable);
 --- a/drivers/net/wireless/ath/ath9k/xmit.c
 +++ b/drivers/net/wireless/ath/ath9k/xmit.c
-@@ -1276,6 +1276,10 @@ static void ath_tx_fill_desc(struct ath_
+@@ -174,14 +174,7 @@ static void ath_txq_skb_done(struct ath_
+ static struct ath_atx_tid *
+ ath_get_skb_tid(struct ath_softc *sc, struct ath_node *an, struct sk_buff *skb)
+ {
+-      struct ieee80211_hdr *hdr;
+-      u8 tidno = 0;
+-
+-      hdr = (struct ieee80211_hdr *) skb->data;
+-      if (ieee80211_is_data_qos(hdr->frame_control))
+-              tidno = ieee80211_get_qos_ctl(hdr)[0];
+-
+-      tidno &= IEEE80211_QOS_CTL_TID_MASK;
++      u8 tidno = skb->priority & IEEE80211_QOS_CTL_TID_MASK;
+       return ATH_AN_2_TID(an, tidno);
+ }
+@@ -1276,6 +1269,10 @@ static void ath_tx_fill_desc(struct ath_
                                if (!rts_thresh || (len > rts_thresh))
                                        rts = true;
                        }
                                if (!rts_thresh || (len > rts_thresh))
                                        rts = true;
                        }
                        ath_buf_set_rate(sc, bf, &info, len, rts);
                }
  
                        ath_buf_set_rate(sc, bf, &info, len, rts);
                }
  
-@@ -1786,6 +1790,9 @@ bool ath_drain_all_txq(struct ath_softc 
+@@ -1786,6 +1783,9 @@ bool ath_drain_all_txq(struct ath_softc 
                if (!ATH_TXQ_SETUP(sc, i))
                        continue;
  
                if (!ATH_TXQ_SETUP(sc, i))
                        continue;
  
                if (ath9k_hw_numtxpending(ah, sc->tx.txq[i].axq_qnum))
                        npend |= BIT(i);
        }
                if (ath9k_hw_numtxpending(ah, sc->tx.txq[i].axq_qnum))
                        npend |= BIT(i);
        }
-@@ -2749,6 +2756,8 @@ void ath_tx_node_cleanup(struct ath_soft
+@@ -2749,6 +2749,8 @@ void ath_tx_node_cleanup(struct ath_soft
        }
  }
  
        }
  }
  
  int ath9k_tx99_send(struct ath_softc *sc, struct sk_buff *skb,
                    struct ath_tx_control *txctl)
  {
  int ath9k_tx99_send(struct ath_softc *sc, struct sk_buff *skb,
                    struct ath_tx_control *txctl)
  {
-@@ -2791,3 +2800,5 @@ int ath9k_tx99_send(struct ath_softc *sc
+@@ -2791,3 +2793,5 @@ int ath9k_tx99_send(struct ath_softc *sc
  
        return 0;
  }
  
        return 0;
  }
                goto fail_rcu;
  
        ieee80211_xmit(sdata, skb, chan->band);
                goto fail_rcu;
  
        ieee80211_xmit(sdata, skb, chan->band);
+@@ -2530,7 +2531,8 @@ struct sk_buff *ieee80211_beacon_get_tim
+                        */
+                       skb = dev_alloc_skb(local->tx_headroom +
+                                           beacon->head_len +
+-                                          beacon->tail_len + 256);
++                                          beacon->tail_len + 256 +
++                                          local->hw.extra_beacon_tailroom);
+                       if (!skb)
+                               goto out;
+@@ -2562,7 +2564,8 @@ struct sk_buff *ieee80211_beacon_get_tim
+                       ieee80211_update_csa(sdata, presp);
+-              skb = dev_alloc_skb(local->tx_headroom + presp->head_len);
++              skb = dev_alloc_skb(local->tx_headroom + presp->head_len +
++                                  local->hw.extra_beacon_tailroom);
+               if (!skb)
+                       goto out;
+               skb_reserve(skb, local->tx_headroom);
+@@ -2589,7 +2592,8 @@ struct sk_buff *ieee80211_beacon_get_tim
+               skb = dev_alloc_skb(local->tx_headroom +
+                                   bcn->head_len +
+                                   256 + /* TIM IE */
+-                                  bcn->tail_len);
++                                  bcn->tail_len +
++                                  local->hw.extra_beacon_tailroom);
+               if (!skb)
+                       goto out;
+               skb_reserve(skb, local->tx_headroom);
 --- a/net/mac80211/util.c
 +++ b/net/mac80211/util.c
 @@ -2259,14 +2259,17 @@ u64 ieee80211_calculate_rx_timestamp(str
 --- a/net/mac80211/util.c
 +++ b/net/mac80211/util.c
 @@ -2259,14 +2259,17 @@ u64 ieee80211_calculate_rx_timestamp(str
                                           NL80211_RADAR_CAC_ABORTED,
                                           GFP_KERNEL);
                }
                                           NL80211_RADAR_CAC_ABORTED,
                                           GFP_KERNEL);
                }
-@@ -2459,14 +2462,9 @@ int ieee80211_send_action_csa(struct iee
+@@ -2459,16 +2462,146 @@ int ieee80211_send_action_csa(struct iee
                          WLAN_EID_CHAN_SWITCH_PARAM_TX_RESTRICT : 0x00;
                put_unaligned_le16(WLAN_REASON_MESH_CHAN, pos); /* Reason Cd */
                pos += 2;
                          WLAN_EID_CHAN_SWITCH_PARAM_TX_RESTRICT : 0x00;
                put_unaligned_le16(WLAN_REASON_MESH_CHAN, pos); /* Reason Cd */
                pos += 2;
        }
  
        ieee80211_tx_skb(sdata, skb);
        }
  
        ieee80211_tx_skb(sdata, skb);
+       return 0;
+ }
++
++static bool
++ieee80211_extend_noa_desc(struct ieee80211_noa_data *data, u32 tsf, int i)
++{
++      s32 end = data->desc[i].start + data->desc[i].duration - (tsf + 1);
++      int skip;
++
++      if (end > 0)
++              return false;
++
++      /* End time is in the past, check for repetitions */
++      skip = DIV_ROUND_UP(-end, data->desc[i].interval);
++      if (data->count[i] < 255) {
++              if (data->count[i] <= skip) {
++                      data->count[i] = 0;
++                      return false;
++              }
++
++              data->count[i] -= skip;
++      }
++
++      data->desc[i].start += skip * data->desc[i].interval;
++
++      return true;
++}
++
++static bool
++ieee80211_extend_absent_time(struct ieee80211_noa_data *data, u32 tsf,
++                           s32 *offset)
++{
++      bool ret = false;
++      int i;
++
++      for (i = 0; i < IEEE80211_P2P_NOA_DESC_MAX; i++) {
++              s32 cur;
++
++              if (!data->count[i])
++                      continue;
++
++              if (ieee80211_extend_noa_desc(data, tsf + *offset, i))
++                      ret = true;
++
++              cur = data->desc[i].start - tsf;
++              if (cur > *offset)
++                      continue;
++
++              cur = data->desc[i].start + data->desc[i].duration - tsf;
++              if (cur > *offset)
++                      *offset = cur;
++      }
++
++      return ret;
++}
++
++static u32
++ieee80211_get_noa_absent_time(struct ieee80211_noa_data *data, u32 tsf)
++{
++      s32 offset = 0;
++      int tries = 0;
++
++      ieee80211_extend_absent_time(data, tsf, &offset);
++      do {
++              if (!ieee80211_extend_absent_time(data, tsf, &offset))
++                      break;
++
++              tries++;
++      } while (tries < 5);
++
++      return offset;
++}
++
++void ieee80211_update_p2p_noa(struct ieee80211_noa_data *data, u32 tsf)
++{
++      u32 next_offset = BIT(31) - 1;
++      int i;
++
++      data->absent = 0;
++      data->has_next_tsf = false;
++      for (i = 0; i < IEEE80211_P2P_NOA_DESC_MAX; i++) {
++              s32 start;
++
++              if (!data->count[i])
++                      continue;
++
++              ieee80211_extend_noa_desc(data, tsf, i);
++              start = data->desc[i].start - tsf;
++              if (start <= 0)
++                      data->absent |= BIT(i);
++
++              if (next_offset > start)
++                      next_offset = start;
++
++              data->has_next_tsf = true;
++      }
++
++      if (data->absent)
++              next_offset = ieee80211_get_noa_absent_time(data, tsf);
++
++      data->next_tsf = tsf + next_offset;
++}
++EXPORT_SYMBOL(ieee80211_update_p2p_noa);
++
++int ieee80211_parse_p2p_noa(const struct ieee80211_p2p_noa_attr *attr,
++                          struct ieee80211_noa_data *data, u32 tsf)
++{
++      int ret = 0;
++      int i;
++
++      memset(data, 0, sizeof(*data));
++
++      for (i = 0; i < IEEE80211_P2P_NOA_DESC_MAX; i++) {
++              const struct ieee80211_p2p_noa_desc *desc = &attr->desc[i];
++
++              if (!desc->count || !desc->duration)
++                      continue;
++
++              data->count[i] = desc->count;
++              data->desc[i].start = le32_to_cpu(desc->start_time);
++              data->desc[i].duration = le32_to_cpu(desc->duration);
++              data->desc[i].interval = le32_to_cpu(desc->interval);
++
++              if (data->count[i] > 1 &&
++                  data->desc[i].interval < data->desc[i].duration)
++                      continue;
++
++              ieee80211_extend_noa_desc(data, tsf, i);
++              ret++;
++      }
++
++      if (ret)
++              ieee80211_update_p2p_noa(data, tsf);
++
++      return ret;
++}
++EXPORT_SYMBOL(ieee80211_parse_p2p_noa);
 --- a/net/wireless/chan.c
 +++ b/net/wireless/chan.c
 @@ -277,6 +277,32 @@ void cfg80211_set_dfs_state(struct wiphy
 --- a/net/wireless/chan.c
 +++ b/net/wireless/chan.c
 @@ -277,6 +277,32 @@ void cfg80211_set_dfs_state(struct wiphy
  static void ar9003_hw_set_radar_conf(struct ath_hw *ah)
 --- a/drivers/net/wireless/ath/ath9k/ar9003_phy.h
 +++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.h
  static void ar9003_hw_set_radar_conf(struct ath_hw *ah)
 --- a/drivers/net/wireless/ath/ath9k/ar9003_phy.h
 +++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.h
+@@ -270,7 +270,7 @@
+ #define AR_PHY_AGC              (AR_AGC_BASE + 0x14)
+ #define AR_PHY_EXT_ATTEN_CTL_0  (AR_AGC_BASE + 0x18)
+ #define AR_PHY_CCA_0            (AR_AGC_BASE + 0x1c)
+-#define AR_PHY_EXT_CCA0         (AR_AGC_BASE + 0x20)
++#define AR_PHY_CCA_CTRL_0       (AR_AGC_BASE + 0x20)
+ #define AR_PHY_RESTART          (AR_AGC_BASE + 0x24)
+ /*
 @@ -341,14 +341,15 @@
  #define AR_PHY_CCA_MAX_GOOD_VAL_9300_2GHZ     -95
  #define AR_PHY_CCA_MAX_GOOD_VAL_9300_5GHZ     -100
 @@ -341,14 +341,15 @@
  #define AR_PHY_CCA_MAX_GOOD_VAL_9300_2GHZ     -95
  #define AR_PHY_CCA_MAX_GOOD_VAL_9300_5GHZ     -100
  
  #define AR_PHY_CCA_NOM_VAL_9330_2GHZ          -118
  
  
  #define AR_PHY_CCA_NOM_VAL_9330_2GHZ          -118
  
-@@ -656,13 +657,24 @@
+@@ -397,6 +398,8 @@
+ #define AR9280_PHY_CCA_THRESH62_S   12
+ #define AR_PHY_EXT_CCA0_THRESH62    0x000000FF
+ #define AR_PHY_EXT_CCA0_THRESH62_S  0
++#define AR_PHY_EXT_CCA0_THRESH62_1    0x000001FF
++#define AR_PHY_EXT_CCA0_THRESH62_1_S  0
+ #define AR_PHY_CCK_DETECT_WEAK_SIG_THR_CCK          0x0000003F
+ #define AR_PHY_CCK_DETECT_WEAK_SIG_THR_CCK_S        0
+ #define AR_PHY_CCK_DETECT_ANT_SWITCH_TIME           0x00001FC0
+@@ -656,13 +659,24 @@
  #define AR_PHY_SYNTH4_LONG_SHIFT_SELECT   ((AR_SREV_9462(ah) || AR_SREV_9565(ah)) ? 0x00000001 : 0x00000002)
  #define AR_PHY_SYNTH4_LONG_SHIFT_SELECT_S ((AR_SREV_9462(ah) || AR_SREV_9565(ah)) ? 0 : 1)
  #define AR_PHY_65NM_CH0_SYNTH7      0x16098
  #define AR_PHY_SYNTH4_LONG_SHIFT_SELECT   ((AR_SREV_9462(ah) || AR_SREV_9565(ah)) ? 0x00000001 : 0x00000002)
  #define AR_PHY_SYNTH4_LONG_SHIFT_SELECT_S ((AR_SREV_9462(ah) || AR_SREV_9565(ah)) ? 0 : 1)
  #define AR_PHY_65NM_CH0_SYNTH7      0x16098
  }
 --- a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c
 +++ b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c
  }
 --- a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c
 +++ b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c
-@@ -3965,7 +3965,7 @@ static void ar9003_hw_apply_tuning_caps(
+@@ -131,6 +131,7 @@ static const struct ar9300_eeprom ar9300
+               .thresh62 = 28,
+               .papdRateMaskHt20 = LE32(0x0cf0e0e0),
+               .papdRateMaskHt40 = LE32(0x6cf0e0e0),
++              .switchcomspdt = 0,
+               .xlna_bias_strength = 0,
+               .futureModal = {
+                       0, 0, 0, 0, 0, 0, 0,
+@@ -138,7 +139,7 @@ static const struct ar9300_eeprom ar9300
+        },
+       .base_ext1 = {
+               .ant_div_control = 0,
+-              .future = {0, 0, 0},
++              .future = {0, 0},
+               .tempslopextension = {0, 0, 0, 0, 0, 0, 0, 0}
+       },
+       .calFreqPier2G = {
+@@ -333,6 +334,7 @@ static const struct ar9300_eeprom ar9300
+               .thresh62 = 28,
+               .papdRateMaskHt20 = LE32(0x0c80c080),
+               .papdRateMaskHt40 = LE32(0x0080c080),
++              .switchcomspdt = 0,
+               .xlna_bias_strength = 0,
+               .futureModal = {
+                       0, 0, 0, 0, 0, 0, 0,
+@@ -707,6 +709,7 @@ static const struct ar9300_eeprom ar9300
+               .thresh62 = 28,
+               .papdRateMaskHt20 = LE32(0x0c80c080),
+               .papdRateMaskHt40 = LE32(0x0080c080),
++              .switchcomspdt = 0,
+               .xlna_bias_strength = 0,
+               .futureModal = {
+                       0, 0, 0, 0, 0, 0, 0,
+@@ -714,7 +717,7 @@ static const struct ar9300_eeprom ar9300
+        },
+        .base_ext1 = {
+               .ant_div_control = 0,
+-              .future = {0, 0, 0},
++              .future = {0, 0},
+               .tempslopextension = {0, 0, 0, 0, 0, 0, 0, 0}
+        },
+       .calFreqPier2G = {
+@@ -909,6 +912,7 @@ static const struct ar9300_eeprom ar9300
+               .thresh62 = 28,
+               .papdRateMaskHt20 = LE32(0x0cf0e0e0),
+               .papdRateMaskHt40 = LE32(0x6cf0e0e0),
++              .switchcomspdt = 0,
+               .xlna_bias_strength = 0,
+               .futureModal = {
+                       0, 0, 0, 0, 0, 0, 0,
+@@ -1284,6 +1288,7 @@ static const struct ar9300_eeprom ar9300
+               .thresh62 = 28,
+               .papdRateMaskHt20 = LE32(0x0c80c080),
+               .papdRateMaskHt40 = LE32(0x0080c080),
++              .switchcomspdt = 0,
+               .xlna_bias_strength = 0,
+               .futureModal = {
+                       0, 0, 0, 0, 0, 0, 0,
+@@ -1291,7 +1296,7 @@ static const struct ar9300_eeprom ar9300
+       },
+       .base_ext1 = {
+               .ant_div_control = 0,
+-              .future = {0, 0, 0},
++              .future = {0, 0},
+               .tempslopextension = {0, 0, 0, 0, 0, 0, 0, 0}
+       },
+       .calFreqPier2G = {
+@@ -1486,6 +1491,7 @@ static const struct ar9300_eeprom ar9300
+               .thresh62 = 28,
+               .papdRateMaskHt20 = LE32(0x0cf0e0e0),
+               .papdRateMaskHt40 = LE32(0x6cf0e0e0),
++              .switchcomspdt = 0,
+               .xlna_bias_strength = 0,
+               .futureModal = {
+                       0, 0, 0, 0, 0, 0, 0,
+@@ -1861,6 +1867,7 @@ static const struct ar9300_eeprom ar9300
+               .thresh62 = 28,
+               .papdRateMaskHt20 = LE32(0x0c80c080),
+               .papdRateMaskHt40 = LE32(0x0080c080),
++              .switchcomspdt = 0,
+               .xlna_bias_strength = 0,
+               .futureModal = {
+                       0, 0, 0, 0, 0, 0, 0,
+@@ -1868,7 +1875,7 @@ static const struct ar9300_eeprom ar9300
+       },
+       .base_ext1 = {
+               .ant_div_control = 0,
+-              .future = {0, 0, 0},
++              .future = {0, 0},
+               .tempslopextension = {0, 0, 0, 0, 0, 0, 0, 0}
+       },
+       .calFreqPier2G = {
+@@ -2063,6 +2070,7 @@ static const struct ar9300_eeprom ar9300
+               .thresh62 = 28,
+               .papdRateMaskHt20 = LE32(0x0cf0e0e0),
+               .papdRateMaskHt40 = LE32(0x6cf0e0e0),
++              .switchcomspdt = 0,
+               .xlna_bias_strength = 0,
+               .futureModal = {
+                       0, 0, 0, 0, 0, 0, 0,
+@@ -2437,6 +2445,7 @@ static const struct ar9300_eeprom ar9300
+               .thresh62 = 28,
+               .papdRateMaskHt20 = LE32(0x0c80C080),
+               .papdRateMaskHt40 = LE32(0x0080C080),
++              .switchcomspdt = 0,
+               .xlna_bias_strength = 0,
+               .futureModal = {
+                       0, 0, 0, 0, 0, 0, 0,
+@@ -2444,7 +2453,7 @@ static const struct ar9300_eeprom ar9300
+        },
+        .base_ext1 = {
+               .ant_div_control = 0,
+-              .future = {0, 0, 0},
++              .future = {0, 0},
+               .tempslopextension = {0, 0, 0, 0, 0, 0, 0, 0}
+        },
+       .calFreqPier2G = {
+@@ -2639,6 +2648,7 @@ static const struct ar9300_eeprom ar9300
+               .thresh62 = 28,
+               .papdRateMaskHt20 = LE32(0x0cf0e0e0),
+               .papdRateMaskHt40 = LE32(0x6cf0e0e0),
++              .switchcomspdt = 0,
+               .xlna_bias_strength = 0,
+               .futureModal = {
+                       0, 0, 0, 0, 0, 0, 0,
+@@ -3965,7 +3975,7 @@ static void ar9003_hw_apply_tuning_caps(
        struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep;
        u8 tuning_caps_param = eep->baseEepHeader.params_for_tuning_caps[0];
  
        struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep;
        u8 tuning_caps_param = eep->baseEepHeader.params_for_tuning_caps[0];
  
                return;
  
        if (eep->baseEepHeader.featureEnable & 0x40) {
                return;
  
        if (eep->baseEepHeader.featureEnable & 0x40) {
-@@ -3984,18 +3984,20 @@ static void ar9003_hw_quick_drop_apply(s
+@@ -3984,18 +3994,20 @@ static void ar9003_hw_quick_drop_apply(s
        int quick_drop;
        s32 t[3], f[3] = {5180, 5500, 5785};
  
        int quick_drop;
        s32 t[3], f[3] = {5180, 5500, 5785};
  
  }
  
  static void ar9003_hw_txend_to_xpa_off_apply(struct ath_hw *ah, bool is2ghz)
  }
  
  static void ar9003_hw_txend_to_xpa_off_apply(struct ath_hw *ah, bool is2ghz)
-@@ -4035,7 +4037,7 @@ static void ar9003_hw_xlna_bias_strength
+@@ -4035,7 +4047,7 @@ static void ar9003_hw_xlna_bias_strength
        struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep;
        u8 bias;
  
        struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep;
        u8 bias;
  
                return;
  
        if (!AR_SREV_9300(ah))
                return;
  
        if (!AR_SREV_9300(ah))
-@@ -4120,7 +4122,7 @@ static void ath9k_hw_ar9300_set_board_va
+@@ -4109,6 +4121,37 @@ static void ar9003_hw_thermo_cal_apply(s
+       }
+ }
++static void ar9003_hw_apply_minccapwr_thresh(struct ath_hw *ah,
++                                           bool is2ghz)
++{
++      struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep;
++      const u_int32_t cca_ctrl[AR9300_MAX_CHAINS] = {
++              AR_PHY_CCA_CTRL_0,
++              AR_PHY_CCA_CTRL_1,
++              AR_PHY_CCA_CTRL_2,
++      };
++      int chain;
++      u32 val;
++
++      if (is2ghz) {
++              if (!(eep->base_ext1.misc_enable & BIT(2)))
++                      return;
++      } else {
++              if (!(eep->base_ext1.misc_enable & BIT(3)))
++                      return;
++      }
++
++      for (chain = 0; chain < AR9300_MAX_CHAINS; chain++) {
++              if (!(ah->caps.tx_chainmask & BIT(chain)))
++                      continue;
++
++              val = ar9003_modal_header(ah, is2ghz)->noiseFloorThreshCh[chain];
++              REG_RMW_FIELD(ah, cca_ctrl[chain],
++                            AR_PHY_EXT_CCA0_THRESH62_1, val);
++      }
++
++}
++
+ static void ath9k_hw_ar9300_set_board_values(struct ath_hw *ah,
+                                            struct ath9k_channel *chan)
+ {
+@@ -4120,9 +4163,10 @@ static void ath9k_hw_ar9300_set_board_va
        ar9003_hw_xlna_bias_strength_apply(ah, is2ghz);
        ar9003_hw_atten_apply(ah, chan);
        ar9003_hw_quick_drop_apply(ah, chan->channel);
        ar9003_hw_xlna_bias_strength_apply(ah, is2ghz);
        ar9003_hw_atten_apply(ah, chan);
        ar9003_hw_quick_drop_apply(ah, chan->channel);
 +      if (!AR_SREV_9330(ah) && !AR_SREV_9340(ah))
                ar9003_hw_internal_regulator_apply(ah);
        ar9003_hw_apply_tuning_caps(ah);
 +      if (!AR_SREV_9330(ah) && !AR_SREV_9340(ah))
                ar9003_hw_internal_regulator_apply(ah);
        ar9003_hw_apply_tuning_caps(ah);
++      ar9003_hw_apply_minccapwr_thresh(ah, chan);
        ar9003_hw_txend_to_xpa_off_apply(ah, is2ghz);
        ar9003_hw_txend_to_xpa_off_apply(ah, is2ghz);
+       ar9003_hw_thermometer_apply(ah);
+       ar9003_hw_thermo_cal_apply(ah);
 --- a/net/mac80211/ieee80211_i.h
 +++ b/net/mac80211/ieee80211_i.h
 @@ -735,6 +735,7 @@ struct ieee80211_sub_if_data {
 --- a/net/mac80211/ieee80211_i.h
 +++ b/net/mac80211/ieee80211_i.h
 @@ -735,6 +735,7 @@ struct ieee80211_sub_if_data {
 +#endif /* INITVALS_9003_BUFFALO_H */
 --- a/drivers/net/wireless/ath/ath9k/ar9002_mac.c
 +++ b/drivers/net/wireless/ath/ath9k/ar9002_mac.c
 +#endif /* INITVALS_9003_BUFFALO_H */
 --- a/drivers/net/wireless/ath/ath9k/ar9002_mac.c
 +++ b/drivers/net/wireless/ath/ath9k/ar9002_mac.c
-@@ -76,9 +76,16 @@ static bool ar9002_hw_get_isr(struct ath
+@@ -29,7 +29,8 @@ static void ar9002_hw_set_desc_link(void
+       ((struct ath_desc*) ds)->ds_link = ds_link;
+ }
+-static bool ar9002_hw_get_isr(struct ath_hw *ah, enum ath9k_int *masked)
++static bool ar9002_hw_get_isr(struct ath_hw *ah, enum ath9k_int *masked,
++                            u32 *sync_cause_p)
+ {
+       u32 isr = 0;
+       u32 mask2 = 0;
+@@ -76,9 +77,16 @@ static bool ar9002_hw_get_isr(struct ath
                                mask2 |= ATH9K_INT_CST;
                        if (isr2 & AR_ISR_S2_TSFOOR)
                                mask2 |= ATH9K_INT_TSFOOR;
                                mask2 |= ATH9K_INT_CST;
                        if (isr2 & AR_ISR_S2_TSFOOR)
                                mask2 |= ATH9K_INT_TSFOOR;
                if (isr == 0xffffffff) {
                        *masked = 0;
                        return false;
                if (isr == 0xffffffff) {
                        *masked = 0;
                        return false;
-@@ -97,11 +104,23 @@ static bool ar9002_hw_get_isr(struct ath
+@@ -97,11 +105,23 @@ static bool ar9002_hw_get_isr(struct ath
  
                        *masked |= ATH9K_INT_TX;
  
  
                        *masked |= ATH9K_INT_TX;
  
                        ah->intr_txqs |= MS(s1_s, AR_ISR_S1_QCU_TXERR);
                        ah->intr_txqs |= MS(s1_s, AR_ISR_S1_QCU_TXEOL);
                }
                        ah->intr_txqs |= MS(s1_s, AR_ISR_S1_QCU_TXERR);
                        ah->intr_txqs |= MS(s1_s, AR_ISR_S1_QCU_TXEOL);
                }
-@@ -114,13 +133,23 @@ static bool ar9002_hw_get_isr(struct ath
+@@ -114,13 +134,23 @@ static bool ar9002_hw_get_isr(struct ath
                *masked |= mask2;
        }
  
                *masked |= mask2;
        }
  
                ah->intr_gen_timer_trigger =
                                MS(s5_s, AR_ISR_S5_GENTIMER_TRIG);
  
                ah->intr_gen_timer_trigger =
                                MS(s5_s, AR_ISR_S5_GENTIMER_TRIG);
  
-@@ -133,6 +162,11 @@ static bool ar9002_hw_get_isr(struct ath
+@@ -133,10 +163,16 @@ static bool ar9002_hw_get_isr(struct ath
                if ((s5_s & AR_ISR_S5_TIM_TIMER) &&
                    !(pCap->hw_caps & ATH9K_HW_CAP_AUTOSLEEP))
                        *masked |= ATH9K_INT_TIM_TIMER;
                if ((s5_s & AR_ISR_S5_TIM_TIMER) &&
                    !(pCap->hw_caps & ATH9K_HW_CAP_AUTOSLEEP))
                        *masked |= ATH9K_INT_TIM_TIMER;
        }
  
        if (sync_cause) {
        }
  
        if (sync_cause) {
+-              ath9k_debug_sync_cause(common, sync_cause);
++              if (sync_cause_p)
++                      *sync_cause_p = sync_cause;
+               fatal_int =
+                       (sync_cause &
+                        (AR_INTR_SYNC_HOST1_FATAL | AR_INTR_SYNC_HOST1_PERR))
 --- a/drivers/net/wireless/ath/ath9k/antenna.c
 +++ b/drivers/net/wireless/ath/ath9k/antenna.c
 @@ -724,14 +724,14 @@ void ath_ant_comb_scan(struct ath_softc 
 --- a/drivers/net/wireless/ath/ath9k/antenna.c
 +++ b/drivers/net/wireless/ath/ath9k/antenna.c
 @@ -724,14 +724,14 @@ void ath_ant_comb_scan(struct ath_softc 
  
 --- a/drivers/net/wireless/ath/ath9k/ar9003_mac.c
 +++ b/drivers/net/wireless/ath/ath9k/ar9003_mac.c
  
 --- a/drivers/net/wireless/ath/ath9k/ar9003_mac.c
 +++ b/drivers/net/wireless/ath/ath9k/ar9003_mac.c
-@@ -476,12 +476,12 @@ int ath9k_hw_process_rxdesc_edma(struct 
+@@ -175,7 +175,8 @@ static void ar9003_hw_set_desc_link(void
+       ads->ctl10 |= ar9003_calc_ptr_chksum(ads);
+ }
+-static bool ar9003_hw_get_isr(struct ath_hw *ah, enum ath9k_int *masked)
++static bool ar9003_hw_get_isr(struct ath_hw *ah, enum ath9k_int *masked,
++                            u32 *sync_cause_p)
+ {
+       u32 isr = 0;
+       u32 mask2 = 0;
+@@ -310,7 +311,8 @@ static bool ar9003_hw_get_isr(struct ath
+               ar9003_mci_get_isr(ah, masked);
+       if (sync_cause) {
+-              ath9k_debug_sync_cause(common, sync_cause);
++              if (sync_cause_p)
++                      *sync_cause_p = sync_cause;
+               fatal_int =
+                       (sync_cause &
+                        (AR_INTR_SYNC_HOST1_FATAL | AR_INTR_SYNC_HOST1_PERR))
+@@ -476,12 +478,12 @@ int ath9k_hw_process_rxdesc_edma(struct 
  
        /* XXX: Keycache */
        rxs->rs_rssi = MS(rxsp->status5, AR_RxRSSICombined);
  
        /* XXX: Keycache */
        rxs->rs_rssi = MS(rxsp->status5, AR_RxRSSICombined);
                rxs->rs_keyix = MS(rxsp->status11, AR_KeyIdx);
 --- a/drivers/net/wireless/ath/ath9k/beacon.c
 +++ b/drivers/net/wireless/ath/ath9k/beacon.c
                rxs->rs_keyix = MS(rxsp->status11, AR_KeyIdx);
 --- a/drivers/net/wireless/ath/ath9k/beacon.c
 +++ b/drivers/net/wireless/ath/ath9k/beacon.c
-@@ -431,6 +431,33 @@ static void ath9k_beacon_init(struct ath
+@@ -274,18 +274,19 @@ static int ath9k_beacon_choose_slot(stru
+       return slot;
+ }
+-void ath9k_set_tsfadjust(struct ath_softc *sc, struct ieee80211_vif *vif)
++static void ath9k_set_tsfadjust(struct ath_softc *sc, struct ieee80211_vif *vif)
+ {
+       struct ath_common *common = ath9k_hw_common(sc->sc_ah);
+       struct ath_beacon_config *cur_conf = &sc->cur_beacon_conf;
+       struct ath_vif *avp = (void *)vif->drv_priv;
+-      u64 tsfadjust;
++      u32 tsfadjust;
+       if (avp->av_bslot == 0)
+               return;
+-      tsfadjust = cur_conf->beacon_interval * avp->av_bslot / ATH_BCBUF;
+-      avp->tsf_adjust = cpu_to_le64(TU_TO_USEC(tsfadjust));
++      tsfadjust = cur_conf->beacon_interval * avp->av_bslot;
++      tsfadjust = TU_TO_USEC(tsfadjust) / ATH_BCBUF;
++      avp->tsf_adjust = cpu_to_le64(tsfadjust);
+       ath_dbg(common, CONFIG, "tsfadjust is: %llu for bslot: %d\n",
+               (unsigned long long)tsfadjust, avp->av_bslot);
+@@ -431,6 +432,33 @@ static void ath9k_beacon_init(struct ath
        ath9k_hw_enable_interrupts(ah);
  }
  
        ath9k_hw_enable_interrupts(ah);
  }
  
  /*
   * For multi-bss ap support beacons are either staggered evenly over N slots or
   * burst together.  For the former arrange for the SWBA to be delivered for each
  /*
   * For multi-bss ap support beacons are either staggered evenly over N slots or
   * burst together.  For the former arrange for the SWBA to be delivered for each
-@@ -446,7 +473,8 @@ static void ath9k_beacon_config_ap(struc
+@@ -446,7 +474,8 @@ static void ath9k_beacon_config_ap(struc
        /* NB: the beacon interval is kept internally in TU's */
        intval = TU_TO_USEC(conf->beacon_interval);
        intval /= ATH_BCBUF;
        /* NB: the beacon interval is kept internally in TU's */
        intval = TU_TO_USEC(conf->beacon_interval);
        intval /= ATH_BCBUF;
  
        if (conf->enable_beacon)
                ah->imask |= ATH9K_INT_SWBA;
  
        if (conf->enable_beacon)
                ah->imask |= ATH9K_INT_SWBA;
-@@ -458,7 +486,7 @@ static void ath9k_beacon_config_ap(struc
+@@ -458,7 +487,7 @@ static void ath9k_beacon_config_ap(struc
                (conf->enable_beacon) ? "Enable" : "Disable",
                nexttbtt, intval, conf->beacon_interval);
  
                (conf->enable_beacon) ? "Enable" : "Disable",
                nexttbtt, intval, conf->beacon_interval);
  
  }
  
  /*
  }
  
  /*
-@@ -475,11 +503,9 @@ static void ath9k_beacon_config_sta(stru
+@@ -475,11 +504,9 @@ static void ath9k_beacon_config_sta(stru
        struct ath_hw *ah = sc->sc_ah;
        struct ath_common *common = ath9k_hw_common(ah);
        struct ath9k_beacon_state bs;
        struct ath_hw *ah = sc->sc_ah;
        struct ath_common *common = ath9k_hw_common(ah);
        struct ath9k_beacon_state bs;
  
        /* No need to configure beacon if we are not associated */
        if (!test_bit(SC_OP_PRIM_STA_VIF, &sc->sc_flags)) {
  
        /* No need to configure beacon if we are not associated */
        if (!test_bit(SC_OP_PRIM_STA_VIF, &sc->sc_flags)) {
-@@ -492,53 +518,25 @@ static void ath9k_beacon_config_sta(stru
+@@ -492,53 +519,25 @@ static void ath9k_beacon_config_sta(stru
        intval = conf->beacon_interval;
  
        /*
        intval = conf->beacon_interval;
  
        /*
         */
        tsf = ath9k_hw_gettsf64(ah);
 -      tsftu = TSF_TO_TU(tsf>>32, tsf) + FUDGE;
         */
        tsf = ath9k_hw_gettsf64(ah);
 -      tsftu = TSF_TO_TU(tsf>>32, tsf) + FUDGE;
--
++      nexttbtt = ath9k_get_next_tbtt(sc, tsf, intval);
 -      num_beacons = tsftu / intval + 1;
 -      offset = tsftu % intval;
 -      nexttbtt = tsftu - offset;
 -      num_beacons = tsftu / intval + 1;
 -      offset = tsftu % intval;
 -      nexttbtt = tsftu - offset;
 -      cfpcount -= cfp_dec_count;
 -      if (cfpcount < 0)
 -              cfpcount += cfpperiod;
 -      cfpcount -= cfp_dec_count;
 -      if (cfpcount < 0)
 -              cfpcount += cfpperiod;
-+      nexttbtt = ath9k_get_next_tbtt(sc, tsf, intval);
+-
 -      bs.bs_intval = intval;
 +      bs.bs_intval = TU_TO_USEC(intval);
 +      bs.bs_dtimperiod = conf->dtim_period * bs.bs_intval;
 -      bs.bs_intval = intval;
 +      bs.bs_intval = TU_TO_USEC(intval);
 +      bs.bs_dtimperiod = conf->dtim_period * bs.bs_intval;
  
        /*
         * Calculate the number of consecutive beacons to miss* before taking
  
        /*
         * Calculate the number of consecutive beacons to miss* before taking
-@@ -566,18 +564,16 @@ static void ath9k_beacon_config_sta(stru
+@@ -566,18 +565,16 @@ static void ath9k_beacon_config_sta(stru
         * XXX fixed at 100ms
         */
  
         * XXX fixed at 100ms
         */
  
  
        /* Set the computed STA beacon timers */
  
  
        /* Set the computed STA beacon timers */
  
-@@ -600,25 +596,11 @@ static void ath9k_beacon_config_adhoc(st
+@@ -600,25 +597,11 @@ static void ath9k_beacon_config_adhoc(st
  
        intval = TU_TO_USEC(conf->beacon_interval);
  
  
        intval = TU_TO_USEC(conf->beacon_interval);
  
  
        if (conf->enable_beacon)
                ah->imask |= ATH9K_INT_SWBA;
  
        if (conf->enable_beacon)
                ah->imask |= ATH9K_INT_SWBA;
+@@ -640,7 +623,8 @@ static void ath9k_beacon_config_adhoc(st
+               set_bit(SC_OP_BEACONS, &sc->sc_flags);
+ }
+-bool ath9k_allow_beacon_config(struct ath_softc *sc, struct ieee80211_vif *vif)
++static bool ath9k_allow_beacon_config(struct ath_softc *sc,
++                                    struct ieee80211_vif *vif)
+ {
+       struct ath_common *common = ath9k_hw_common(sc->sc_ah);
+       struct ath_vif *avp = (void *)vif->drv_priv;
+@@ -711,12 +695,17 @@ void ath9k_beacon_config(struct ath_soft
+       unsigned long flags;
+       bool skip_beacon = false;
++      if (vif->type == NL80211_IFTYPE_AP)
++              ath9k_set_tsfadjust(sc, vif);
++
++      if (!ath9k_allow_beacon_config(sc, vif))
++              return;
++
+       if (sc->sc_ah->opmode == NL80211_IFTYPE_STATION) {
+               ath9k_cache_beacon_config(sc, bss_conf);
+               ath9k_set_beacon(sc);
+               set_bit(SC_OP_BEACONS, &sc->sc_flags);
+               return;
+-
+       }
+       /*
 --- a/drivers/net/wireless/ath/ath9k/btcoex.c
 +++ b/drivers/net/wireless/ath/ath9k/btcoex.c
 @@ -66,7 +66,6 @@ void ath9k_hw_init_btcoex_hw(struct ath_
 --- a/drivers/net/wireless/ath/ath9k/btcoex.c
 +++ b/drivers/net/wireless/ath/ath9k/btcoex.c
 @@ -66,7 +66,6 @@ void ath9k_hw_init_btcoex_hw(struct ath_
        ath9k_hw_btcoex_enable(sc->sc_ah);
 --- a/drivers/net/wireless/ath/ath9k/recv.c
 +++ b/drivers/net/wireless/ath/ath9k/recv.c
        ath9k_hw_btcoex_enable(sc->sc_ah);
 --- a/drivers/net/wireless/ath/ath9k/recv.c
 +++ b/drivers/net/wireless/ath/ath9k/recv.c
-@@ -906,6 +906,7 @@ static void ath9k_process_rssi(struct at
+@@ -15,7 +15,6 @@
+  */
+ #include <linux/dma-mapping.h>
+-#include <linux/relay.h>
+ #include "ath9k.h"
+ #include "ar9003_mac.h"
+@@ -906,6 +905,7 @@ static void ath9k_process_rssi(struct at
        struct ath_hw *ah = common->ah;
        int last_rssi;
        int rssi = rx_stats->rs_rssi;
        struct ath_hw *ah = common->ah;
        int last_rssi;
        int rssi = rx_stats->rs_rssi;
  
        /*
         * RSSI is not available for subframes in an A-MPDU.
  
        /*
         * RSSI is not available for subframes in an A-MPDU.
-@@ -924,6 +925,20 @@ static void ath9k_process_rssi(struct at
+@@ -924,6 +924,20 @@ static void ath9k_process_rssi(struct at
                return;
        }
  
                return;
        }
  
        /*
         * Update Beacon RSSI, this is used by ANI.
         */
        /*
         * Update Beacon RSSI, this is used by ANI.
         */
-@@ -1073,14 +1088,14 @@ static int ath_process_fft(struct ath_so
-               fft_sample_40.channel_type = chan_type;
+@@ -960,186 +974,6 @@ static void ath9k_process_tsf(struct ath
+               rxs->mactime += 0x100000000ULL;
+ }
  
  
-               if (chan_type == NL80211_CHAN_HT40PLUS) {
+-#ifdef CPTCFG_ATH9K_DEBUGFS
+-static s8 fix_rssi_inv_only(u8 rssi_val)
+-{
+-      if (rssi_val == 128)
+-              rssi_val = 0;
+-      return (s8) rssi_val;
+-}
+-#endif
+-
+-/* returns 1 if this was a spectral frame, even if not handled. */
+-static int ath_process_fft(struct ath_softc *sc, struct ieee80211_hdr *hdr,
+-                         struct ath_rx_status *rs, u64 tsf)
+-{
+-#ifdef CPTCFG_ATH9K_DEBUGFS
+-      struct ath_hw *ah = sc->sc_ah;
+-      u8 num_bins, *bins, *vdata = (u8 *)hdr;
+-      struct fft_sample_ht20 fft_sample_20;
+-      struct fft_sample_ht20_40 fft_sample_40;
+-      struct fft_sample_tlv *tlv;
+-      struct ath_radar_info *radar_info;
+-      int len = rs->rs_datalen;
+-      int dc_pos;
+-      u16 fft_len, length, freq = ah->curchan->chan->center_freq;
+-      enum nl80211_channel_type chan_type;
+-
+-      /* AR9280 and before report via ATH9K_PHYERR_RADAR, AR93xx and newer
+-       * via ATH9K_PHYERR_SPECTRAL. Haven't seen ATH9K_PHYERR_FALSE_RADAR_EXT
+-       * yet, but this is supposed to be possible as well.
+-       */
+-      if (rs->rs_phyerr != ATH9K_PHYERR_RADAR &&
+-          rs->rs_phyerr != ATH9K_PHYERR_FALSE_RADAR_EXT &&
+-          rs->rs_phyerr != ATH9K_PHYERR_SPECTRAL)
+-              return 0;
+-
+-      /* check if spectral scan bit is set. This does not have to be checked
+-       * if received through a SPECTRAL phy error, but shouldn't hurt.
+-       */
+-      radar_info = ((struct ath_radar_info *)&vdata[len]) - 1;
+-      if (!(radar_info->pulse_bw_info & SPECTRAL_SCAN_BITMASK))
+-              return 0;
+-
+-      chan_type = cfg80211_get_chandef_type(&sc->hw->conf.chandef);
+-      if ((chan_type == NL80211_CHAN_HT40MINUS) ||
+-          (chan_type == NL80211_CHAN_HT40PLUS)) {
+-              fft_len = SPECTRAL_HT20_40_TOTAL_DATA_LEN;
+-              num_bins = SPECTRAL_HT20_40_NUM_BINS;
+-              bins = (u8 *)fft_sample_40.data;
+-      } else {
+-              fft_len = SPECTRAL_HT20_TOTAL_DATA_LEN;
+-              num_bins = SPECTRAL_HT20_NUM_BINS;
+-              bins = (u8 *)fft_sample_20.data;
+-      }
+-
+-      /* Variation in the data length is possible and will be fixed later */
+-      if ((len > fft_len + 2) || (len < fft_len - 1))
+-              return 1;
+-
+-      switch (len - fft_len) {
+-      case 0:
+-              /* length correct, nothing to do. */
+-              memcpy(bins, vdata, num_bins);
+-              break;
+-      case -1:
+-              /* first byte missing, duplicate it. */
+-              memcpy(&bins[1], vdata, num_bins - 1);
+-              bins[0] = vdata[0];
+-              break;
+-      case 2:
+-              /* MAC added 2 extra bytes at bin 30 and 32, remove them. */
+-              memcpy(bins, vdata, 30);
+-              bins[30] = vdata[31];
+-              memcpy(&bins[31], &vdata[33], num_bins - 31);
+-              break;
+-      case 1:
+-              /* MAC added 2 extra bytes AND first byte is missing. */
+-              bins[0] = vdata[0];
+-              memcpy(&bins[1], vdata, 30);
+-              bins[31] = vdata[31];
+-              memcpy(&bins[32], &vdata[33], num_bins - 32);
+-              break;
+-      default:
+-              return 1;
+-      }
+-
+-      /* DC value (value in the middle) is the blind spot of the spectral
+-       * sample and invalid, interpolate it.
+-       */
+-      dc_pos = num_bins / 2;
+-      bins[dc_pos] = (bins[dc_pos + 1] + bins[dc_pos - 1]) / 2;
+-
+-      if ((chan_type == NL80211_CHAN_HT40MINUS) ||
+-          (chan_type == NL80211_CHAN_HT40PLUS)) {
+-              s8 lower_rssi, upper_rssi;
+-              s16 ext_nf;
+-              u8 lower_max_index, upper_max_index;
+-              u8 lower_bitmap_w, upper_bitmap_w;
+-              u16 lower_mag, upper_mag;
+-              struct ath9k_hw_cal_data *caldata = ah->caldata;
+-              struct ath_ht20_40_mag_info *mag_info;
+-
+-              if (caldata)
+-                      ext_nf = ath9k_hw_getchan_noise(ah, ah->curchan,
+-                                      caldata->nfCalHist[3].privNF);
+-              else
+-                      ext_nf = ATH_DEFAULT_NOISE_FLOOR;
+-
+-              length = sizeof(fft_sample_40) - sizeof(struct fft_sample_tlv);
+-              fft_sample_40.tlv.type = ATH_FFT_SAMPLE_HT20_40;
+-              fft_sample_40.tlv.length = __cpu_to_be16(length);
+-              fft_sample_40.freq = __cpu_to_be16(freq);
+-              fft_sample_40.channel_type = chan_type;
+-
+-              if (chan_type == NL80211_CHAN_HT40PLUS) {
 -                      lower_rssi = fix_rssi_inv_only(rs->rs_rssi_ctl0);
 -                      upper_rssi = fix_rssi_inv_only(rs->rs_rssi_ext0);
 -                      lower_rssi = fix_rssi_inv_only(rs->rs_rssi_ctl0);
 -                      upper_rssi = fix_rssi_inv_only(rs->rs_rssi_ext0);
-+                      lower_rssi = fix_rssi_inv_only(rs->rs_rssi_ctl[0]);
-+                      upper_rssi = fix_rssi_inv_only(rs->rs_rssi_ext[0]);
-                       fft_sample_40.lower_noise = ah->noise;
-                       fft_sample_40.upper_noise = ext_nf;
-               } else {
+-
+-                      fft_sample_40.lower_noise = ah->noise;
+-                      fft_sample_40.upper_noise = ext_nf;
+-              } else {
 -                      lower_rssi = fix_rssi_inv_only(rs->rs_rssi_ext0);
 -                      upper_rssi = fix_rssi_inv_only(rs->rs_rssi_ctl0);
 -                      lower_rssi = fix_rssi_inv_only(rs->rs_rssi_ext0);
 -                      upper_rssi = fix_rssi_inv_only(rs->rs_rssi_ctl0);
-+                      lower_rssi = fix_rssi_inv_only(rs->rs_rssi_ext[0]);
-+                      upper_rssi = fix_rssi_inv_only(rs->rs_rssi_ctl[0]);
+-
+-                      fft_sample_40.lower_noise = ext_nf;
+-                      fft_sample_40.upper_noise = ah->noise;
+-              }
+-              fft_sample_40.lower_rssi = lower_rssi;
+-              fft_sample_40.upper_rssi = upper_rssi;
+-
+-              mag_info = ((struct ath_ht20_40_mag_info *)radar_info) - 1;
+-              lower_mag = spectral_max_magnitude(mag_info->lower_bins);
+-              upper_mag = spectral_max_magnitude(mag_info->upper_bins);
+-              fft_sample_40.lower_max_magnitude = __cpu_to_be16(lower_mag);
+-              fft_sample_40.upper_max_magnitude = __cpu_to_be16(upper_mag);
+-              lower_max_index = spectral_max_index(mag_info->lower_bins);
+-              upper_max_index = spectral_max_index(mag_info->upper_bins);
+-              fft_sample_40.lower_max_index = lower_max_index;
+-              fft_sample_40.upper_max_index = upper_max_index;
+-              lower_bitmap_w = spectral_bitmap_weight(mag_info->lower_bins);
+-              upper_bitmap_w = spectral_bitmap_weight(mag_info->upper_bins);
+-              fft_sample_40.lower_bitmap_weight = lower_bitmap_w;
+-              fft_sample_40.upper_bitmap_weight = upper_bitmap_w;
+-              fft_sample_40.max_exp = mag_info->max_exp & 0xf;
+-
+-              fft_sample_40.tsf = __cpu_to_be64(tsf);
+-
+-              tlv = (struct fft_sample_tlv *)&fft_sample_40;
+-      } else {
+-              u8 max_index, bitmap_w;
+-              u16 magnitude;
+-              struct ath_ht20_mag_info *mag_info;
+-
+-              length = sizeof(fft_sample_20) - sizeof(struct fft_sample_tlv);
+-              fft_sample_20.tlv.type = ATH_FFT_SAMPLE_HT20;
+-              fft_sample_20.tlv.length = __cpu_to_be16(length);
+-              fft_sample_20.freq = __cpu_to_be16(freq);
+-
+-              fft_sample_20.rssi = fix_rssi_inv_only(rs->rs_rssi_ctl0);
+-              fft_sample_20.noise = ah->noise;
+-
+-              mag_info = ((struct ath_ht20_mag_info *)radar_info) - 1;
+-              magnitude = spectral_max_magnitude(mag_info->all_bins);
+-              fft_sample_20.max_magnitude = __cpu_to_be16(magnitude);
+-              max_index = spectral_max_index(mag_info->all_bins);
+-              fft_sample_20.max_index = max_index;
+-              bitmap_w = spectral_bitmap_weight(mag_info->all_bins);
+-              fft_sample_20.bitmap_weight = bitmap_w;
+-              fft_sample_20.max_exp = mag_info->max_exp & 0xf;
+-
+-              fft_sample_20.tsf = __cpu_to_be64(tsf);
+-
+-              tlv = (struct fft_sample_tlv *)&fft_sample_20;
+-      }
+-
+-      ath_debug_send_fft_sample(sc, tlv);
+-      return 1;
+-#else
+-      return 0;
+-#endif
+-}
+-
+ static bool ath9k_is_mybeacon(struct ath_softc *sc, struct ieee80211_hdr *hdr)
+ {
+       struct ath_hw *ah = sc->sc_ah;
+--- a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.h
++++ b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.h
+@@ -270,10 +270,20 @@ struct cal_ctl_data_5g {
+       u8 ctlEdges[AR9300_NUM_BAND_EDGES_5G];
+ } __packed;
  
  
-                       fft_sample_40.lower_noise = ext_nf;
-                       fft_sample_40.upper_noise = ah->noise;
-@@ -1116,7 +1131,7 @@ static int ath_process_fft(struct ath_so
-               fft_sample_20.tlv.length = __cpu_to_be16(length);
-               fft_sample_20.freq = __cpu_to_be16(freq);
++#define MAX_BASE_EXTENSION_FUTURE 2
++
+ struct ar9300_BaseExtension_1 {
+       u8 ant_div_control;
+-      u8 future[3];
+-      u8 tempslopextension[8];
++      u8 future[MAX_BASE_EXTENSION_FUTURE];
++      /*
++       * misc_enable:
++       *
++       * BIT 0   - TX Gain Cap enable.
++       * BIT 1   - Uncompressed Checksum enable.
++       * BIT 2/3 - MinCCApwr enable 2g/5g.
++       */
++      u8 misc_enable;
++      int8_t tempslopextension[8];
+       int8_t quick_drop_low;
+       int8_t quick_drop_high;
+ } __packed;
+--- a/drivers/net/wireless/ath/ath9k/debug.h
++++ b/drivers/net/wireless/ath/ath9k/debug.h
+@@ -292,11 +292,11 @@ void ath9k_sta_add_debugfs(struct ieee80
+                          struct ieee80211_vif *vif,
+                          struct ieee80211_sta *sta,
+                          struct dentry *dir);
+-void ath_debug_send_fft_sample(struct ath_softc *sc,
+-                             struct fft_sample_tlv *fft_sample);
+ void ath9k_debug_stat_ant(struct ath_softc *sc,
+                         struct ath_hw_antcomb_conf *div_ant_conf,
+                         int main_rssi_avg, int alt_rssi_avg);
++void ath9k_debug_sync_cause(struct ath_softc *sc, u32 sync_cause);
++
+ #else
+ #define RX_STAT_INC(c) /* NOP */
+@@ -331,6 +331,11 @@ static inline void ath9k_debug_stat_ant(
  
  
--              fft_sample_20.rssi = fix_rssi_inv_only(rs->rs_rssi_ctl0);
+ }
++static inline void
++ath9k_debug_sync_cause(struct ath_softc *sc, u32 sync_cause)
++{
++}
++
+ #endif /* CPTCFG_ATH9K_DEBUGFS */
+ #endif /* DEBUG_H */
+--- /dev/null
++++ b/drivers/net/wireless/ath/ath9k/spectral.c
+@@ -0,0 +1,543 @@
++/*
++ * Copyright (c) 2013 Qualcomm Atheros, Inc.
++ *
++ * Permission to use, copy, modify, and/or distribute this software for any
++ * purpose with or without fee is hereby granted, provided that the above
++ * copyright notice and this permission notice appear in all copies.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
++ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
++ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
++ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
++ */
++
++#include <linux/relay.h>
++#include "ath9k.h"
++
++static s8 fix_rssi_inv_only(u8 rssi_val)
++{
++      if (rssi_val == 128)
++              rssi_val = 0;
++      return (s8) rssi_val;
++}
++
++static void ath_debug_send_fft_sample(struct ath_softc *sc,
++                                    struct fft_sample_tlv *fft_sample_tlv)
++{
++      int length;
++      if (!sc->rfs_chan_spec_scan)
++              return;
++
++      length = __be16_to_cpu(fft_sample_tlv->length) +
++               sizeof(*fft_sample_tlv);
++      relay_write(sc->rfs_chan_spec_scan, fft_sample_tlv, length);
++}
++
++/* returns 1 if this was a spectral frame, even if not handled. */
++int ath_process_fft(struct ath_softc *sc, struct ieee80211_hdr *hdr,
++                  struct ath_rx_status *rs, u64 tsf)
++{
++      struct ath_hw *ah = sc->sc_ah;
++      u8 num_bins, *bins, *vdata = (u8 *)hdr;
++      struct fft_sample_ht20 fft_sample_20;
++      struct fft_sample_ht20_40 fft_sample_40;
++      struct fft_sample_tlv *tlv;
++      struct ath_radar_info *radar_info;
++      int len = rs->rs_datalen;
++      int dc_pos;
++      u16 fft_len, length, freq = ah->curchan->chan->center_freq;
++      enum nl80211_channel_type chan_type;
++
++      /* AR9280 and before report via ATH9K_PHYERR_RADAR, AR93xx and newer
++       * via ATH9K_PHYERR_SPECTRAL. Haven't seen ATH9K_PHYERR_FALSE_RADAR_EXT
++       * yet, but this is supposed to be possible as well.
++       */
++      if (rs->rs_phyerr != ATH9K_PHYERR_RADAR &&
++          rs->rs_phyerr != ATH9K_PHYERR_FALSE_RADAR_EXT &&
++          rs->rs_phyerr != ATH9K_PHYERR_SPECTRAL)
++              return 0;
++
++      /* check if spectral scan bit is set. This does not have to be checked
++       * if received through a SPECTRAL phy error, but shouldn't hurt.
++       */
++      radar_info = ((struct ath_radar_info *)&vdata[len]) - 1;
++      if (!(radar_info->pulse_bw_info & SPECTRAL_SCAN_BITMASK))
++              return 0;
++
++      chan_type = cfg80211_get_chandef_type(&sc->hw->conf.chandef);
++      if ((chan_type == NL80211_CHAN_HT40MINUS) ||
++          (chan_type == NL80211_CHAN_HT40PLUS)) {
++              fft_len = SPECTRAL_HT20_40_TOTAL_DATA_LEN;
++              num_bins = SPECTRAL_HT20_40_NUM_BINS;
++              bins = (u8 *)fft_sample_40.data;
++      } else {
++              fft_len = SPECTRAL_HT20_TOTAL_DATA_LEN;
++              num_bins = SPECTRAL_HT20_NUM_BINS;
++              bins = (u8 *)fft_sample_20.data;
++      }
++
++      /* Variation in the data length is possible and will be fixed later */
++      if ((len > fft_len + 2) || (len < fft_len - 1))
++              return 1;
++
++      switch (len - fft_len) {
++      case 0:
++              /* length correct, nothing to do. */
++              memcpy(bins, vdata, num_bins);
++              break;
++      case -1:
++              /* first byte missing, duplicate it. */
++              memcpy(&bins[1], vdata, num_bins - 1);
++              bins[0] = vdata[0];
++              break;
++      case 2:
++              /* MAC added 2 extra bytes at bin 30 and 32, remove them. */
++              memcpy(bins, vdata, 30);
++              bins[30] = vdata[31];
++              memcpy(&bins[31], &vdata[33], num_bins - 31);
++              break;
++      case 1:
++              /* MAC added 2 extra bytes AND first byte is missing. */
++              bins[0] = vdata[0];
++              memcpy(&bins[1], vdata, 30);
++              bins[31] = vdata[31];
++              memcpy(&bins[32], &vdata[33], num_bins - 32);
++              break;
++      default:
++              return 1;
++      }
++
++      /* DC value (value in the middle) is the blind spot of the spectral
++       * sample and invalid, interpolate it.
++       */
++      dc_pos = num_bins / 2;
++      bins[dc_pos] = (bins[dc_pos + 1] + bins[dc_pos - 1]) / 2;
++
++      if ((chan_type == NL80211_CHAN_HT40MINUS) ||
++          (chan_type == NL80211_CHAN_HT40PLUS)) {
++              s8 lower_rssi, upper_rssi;
++              s16 ext_nf;
++              u8 lower_max_index, upper_max_index;
++              u8 lower_bitmap_w, upper_bitmap_w;
++              u16 lower_mag, upper_mag;
++              struct ath9k_hw_cal_data *caldata = ah->caldata;
++              struct ath_ht20_40_mag_info *mag_info;
++
++              if (caldata)
++                      ext_nf = ath9k_hw_getchan_noise(ah, ah->curchan,
++                                      caldata->nfCalHist[3].privNF);
++              else
++                      ext_nf = ATH_DEFAULT_NOISE_FLOOR;
++
++              length = sizeof(fft_sample_40) - sizeof(struct fft_sample_tlv);
++              fft_sample_40.tlv.type = ATH_FFT_SAMPLE_HT20_40;
++              fft_sample_40.tlv.length = __cpu_to_be16(length);
++              fft_sample_40.freq = __cpu_to_be16(freq);
++              fft_sample_40.channel_type = chan_type;
++
++              if (chan_type == NL80211_CHAN_HT40PLUS) {
++                      lower_rssi = fix_rssi_inv_only(rs->rs_rssi_ctl[0]);
++                      upper_rssi = fix_rssi_inv_only(rs->rs_rssi_ext[0]);
++
++                      fft_sample_40.lower_noise = ah->noise;
++                      fft_sample_40.upper_noise = ext_nf;
++              } else {
++                      lower_rssi = fix_rssi_inv_only(rs->rs_rssi_ext[0]);
++                      upper_rssi = fix_rssi_inv_only(rs->rs_rssi_ctl[0]);
++
++                      fft_sample_40.lower_noise = ext_nf;
++                      fft_sample_40.upper_noise = ah->noise;
++              }
++              fft_sample_40.lower_rssi = lower_rssi;
++              fft_sample_40.upper_rssi = upper_rssi;
++
++              mag_info = ((struct ath_ht20_40_mag_info *)radar_info) - 1;
++              lower_mag = spectral_max_magnitude(mag_info->lower_bins);
++              upper_mag = spectral_max_magnitude(mag_info->upper_bins);
++              fft_sample_40.lower_max_magnitude = __cpu_to_be16(lower_mag);
++              fft_sample_40.upper_max_magnitude = __cpu_to_be16(upper_mag);
++              lower_max_index = spectral_max_index(mag_info->lower_bins);
++              upper_max_index = spectral_max_index(mag_info->upper_bins);
++              fft_sample_40.lower_max_index = lower_max_index;
++              fft_sample_40.upper_max_index = upper_max_index;
++              lower_bitmap_w = spectral_bitmap_weight(mag_info->lower_bins);
++              upper_bitmap_w = spectral_bitmap_weight(mag_info->upper_bins);
++              fft_sample_40.lower_bitmap_weight = lower_bitmap_w;
++              fft_sample_40.upper_bitmap_weight = upper_bitmap_w;
++              fft_sample_40.max_exp = mag_info->max_exp & 0xf;
++
++              fft_sample_40.tsf = __cpu_to_be64(tsf);
++
++              tlv = (struct fft_sample_tlv *)&fft_sample_40;
++      } else {
++              u8 max_index, bitmap_w;
++              u16 magnitude;
++              struct ath_ht20_mag_info *mag_info;
++
++              length = sizeof(fft_sample_20) - sizeof(struct fft_sample_tlv);
++              fft_sample_20.tlv.type = ATH_FFT_SAMPLE_HT20;
++              fft_sample_20.tlv.length = __cpu_to_be16(length);
++              fft_sample_20.freq = __cpu_to_be16(freq);
++
 +              fft_sample_20.rssi = fix_rssi_inv_only(rs->rs_rssi_ctl[0]);
 +              fft_sample_20.rssi = fix_rssi_inv_only(rs->rs_rssi_ctl[0]);
-               fft_sample_20.noise = ah->noise;
++              fft_sample_20.noise = ah->noise;
++
++              mag_info = ((struct ath_ht20_mag_info *)radar_info) - 1;
++              magnitude = spectral_max_magnitude(mag_info->all_bins);
++              fft_sample_20.max_magnitude = __cpu_to_be16(magnitude);
++              max_index = spectral_max_index(mag_info->all_bins);
++              fft_sample_20.max_index = max_index;
++              bitmap_w = spectral_bitmap_weight(mag_info->all_bins);
++              fft_sample_20.bitmap_weight = bitmap_w;
++              fft_sample_20.max_exp = mag_info->max_exp & 0xf;
++
++              fft_sample_20.tsf = __cpu_to_be64(tsf);
++
++              tlv = (struct fft_sample_tlv *)&fft_sample_20;
++      }
++
++      ath_debug_send_fft_sample(sc, tlv);
++
++      return 1;
++}
++
++/*********************/
++/* spectral_scan_ctl */
++/*********************/
++
++static ssize_t read_file_spec_scan_ctl(struct file *file, char __user *user_buf,
++                                     size_t count, loff_t *ppos)
++{
++      struct ath_softc *sc = file->private_data;
++      char *mode = "";
++      unsigned int len;
++
++      switch (sc->spectral_mode) {
++      case SPECTRAL_DISABLED:
++              mode = "disable";
++              break;
++      case SPECTRAL_BACKGROUND:
++              mode = "background";
++              break;
++      case SPECTRAL_CHANSCAN:
++              mode = "chanscan";
++              break;
++      case SPECTRAL_MANUAL:
++              mode = "manual";
++              break;
++      }
++      len = strlen(mode);
++      return simple_read_from_buffer(user_buf, count, ppos, mode, len);
++}
++
++static ssize_t write_file_spec_scan_ctl(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);
++      char buf[32];
++      ssize_t len;
++
++      if (config_enabled(CPTCFG_ATH9K_TX99))
++              return -EOPNOTSUPP;
++
++      len = min(count, sizeof(buf) - 1);
++      if (copy_from_user(buf, user_buf, len))
++              return -EFAULT;
++
++      buf[len] = '\0';
++
++      if (strncmp("trigger", buf, 7) == 0) {
++              ath9k_spectral_scan_trigger(sc->hw);
++      } else if (strncmp("background", buf, 9) == 0) {
++              ath9k_spectral_scan_config(sc->hw, SPECTRAL_BACKGROUND);
++              ath_dbg(common, CONFIG, "spectral scan: background mode enabled\n");
++      } else if (strncmp("chanscan", buf, 8) == 0) {
++              ath9k_spectral_scan_config(sc->hw, SPECTRAL_CHANSCAN);
++              ath_dbg(common, CONFIG, "spectral scan: channel scan mode enabled\n");
++      } else if (strncmp("manual", buf, 6) == 0) {
++              ath9k_spectral_scan_config(sc->hw, SPECTRAL_MANUAL);
++              ath_dbg(common, CONFIG, "spectral scan: manual mode enabled\n");
++      } else if (strncmp("disable", buf, 7) == 0) {
++              ath9k_spectral_scan_config(sc->hw, SPECTRAL_DISABLED);
++              ath_dbg(common, CONFIG, "spectral scan: disabled\n");
++      } else {
++              return -EINVAL;
++      }
++
++      return count;
++}
++
++static const struct file_operations fops_spec_scan_ctl = {
++      .read = read_file_spec_scan_ctl,
++      .write = write_file_spec_scan_ctl,
++      .open = simple_open,
++      .owner = THIS_MODULE,
++      .llseek = default_llseek,
++};
++
++/*************************/
++/* spectral_short_repeat */
++/*************************/
++
++static ssize_t read_file_spectral_short_repeat(struct file *file,
++                                             char __user *user_buf,
++                                             size_t count, loff_t *ppos)
++{
++      struct ath_softc *sc = file->private_data;
++      char buf[32];
++      unsigned int len;
++
++      len = sprintf(buf, "%d\n", sc->spec_config.short_repeat);
++      return simple_read_from_buffer(user_buf, count, ppos, buf, len);
++}
++
++static ssize_t write_file_spectral_short_repeat(struct file *file,
++                                              const char __user *user_buf,
++                                              size_t count, loff_t *ppos)
++{
++      struct ath_softc *sc = file->private_data;
++      unsigned long val;
++      char buf[32];
++      ssize_t len;
++
++      len = min(count, sizeof(buf) - 1);
++      if (copy_from_user(buf, user_buf, len))
++              return -EFAULT;
++
++      buf[len] = '\0';
++      if (kstrtoul(buf, 0, &val))
++              return -EINVAL;
++
++      if (val < 0 || val > 1)
++              return -EINVAL;
++
++      sc->spec_config.short_repeat = val;
++      return count;
++}
++
++static const struct file_operations fops_spectral_short_repeat = {
++      .read = read_file_spectral_short_repeat,
++      .write = write_file_spectral_short_repeat,
++      .open = simple_open,
++      .owner = THIS_MODULE,
++      .llseek = default_llseek,
++};
++
++/******************/
++/* spectral_count */
++/******************/
++
++static ssize_t read_file_spectral_count(struct file *file,
++                                      char __user *user_buf,
++                                      size_t count, loff_t *ppos)
++{
++      struct ath_softc *sc = file->private_data;
++      char buf[32];
++      unsigned int len;
++
++      len = sprintf(buf, "%d\n", sc->spec_config.count);
++      return simple_read_from_buffer(user_buf, count, ppos, buf, len);
++}
++
++static ssize_t write_file_spectral_count(struct file *file,
++                                       const char __user *user_buf,
++                                       size_t count, loff_t *ppos)
++{
++      struct ath_softc *sc = file->private_data;
++      unsigned long val;
++      char buf[32];
++      ssize_t len;
++
++      len = min(count, sizeof(buf) - 1);
++      if (copy_from_user(buf, user_buf, len))
++              return -EFAULT;
++
++      buf[len] = '\0';
++      if (kstrtoul(buf, 0, &val))
++              return -EINVAL;
++
++      if (val < 0 || val > 255)
++              return -EINVAL;
++
++      sc->spec_config.count = val;
++      return count;
++}
++
++static const struct file_operations fops_spectral_count = {
++      .read = read_file_spectral_count,
++      .write = write_file_spectral_count,
++      .open = simple_open,
++      .owner = THIS_MODULE,
++      .llseek = default_llseek,
++};
++
++/*******************/
++/* spectral_period */
++/*******************/
++
++static ssize_t read_file_spectral_period(struct file *file,
++                                       char __user *user_buf,
++                                       size_t count, loff_t *ppos)
++{
++      struct ath_softc *sc = file->private_data;
++      char buf[32];
++      unsigned int len;
++
++      len = sprintf(buf, "%d\n", sc->spec_config.period);
++      return simple_read_from_buffer(user_buf, count, ppos, buf, len);
++}
++
++static ssize_t write_file_spectral_period(struct file *file,
++                                        const char __user *user_buf,
++                                        size_t count, loff_t *ppos)
++{
++      struct ath_softc *sc = file->private_data;
++      unsigned long val;
++      char buf[32];
++      ssize_t len;
++
++      len = min(count, sizeof(buf) - 1);
++      if (copy_from_user(buf, user_buf, len))
++              return -EFAULT;
++
++      buf[len] = '\0';
++      if (kstrtoul(buf, 0, &val))
++              return -EINVAL;
++
++      if (val < 0 || val > 255)
++              return -EINVAL;
++
++      sc->spec_config.period = val;
++      return count;
++}
++
++static const struct file_operations fops_spectral_period = {
++      .read = read_file_spectral_period,
++      .write = write_file_spectral_period,
++      .open = simple_open,
++      .owner = THIS_MODULE,
++      .llseek = default_llseek,
++};
++
++/***********************/
++/* spectral_fft_period */
++/***********************/
++
++static ssize_t read_file_spectral_fft_period(struct file *file,
++                                           char __user *user_buf,
++                                           size_t count, loff_t *ppos)
++{
++      struct ath_softc *sc = file->private_data;
++      char buf[32];
++      unsigned int len;
++
++      len = sprintf(buf, "%d\n", sc->spec_config.fft_period);
++      return simple_read_from_buffer(user_buf, count, ppos, buf, len);
++}
++
++static ssize_t write_file_spectral_fft_period(struct file *file,
++                                            const char __user *user_buf,
++                                            size_t count, loff_t *ppos)
++{
++      struct ath_softc *sc = file->private_data;
++      unsigned long val;
++      char buf[32];
++      ssize_t len;
++
++      len = min(count, sizeof(buf) - 1);
++      if (copy_from_user(buf, user_buf, len))
++              return -EFAULT;
++
++      buf[len] = '\0';
++      if (kstrtoul(buf, 0, &val))
++              return -EINVAL;
++
++      if (val < 0 || val > 15)
++              return -EINVAL;
++
++      sc->spec_config.fft_period = val;
++      return count;
++}
++
++static const struct file_operations fops_spectral_fft_period = {
++      .read = read_file_spectral_fft_period,
++      .write = write_file_spectral_fft_period,
++      .open = simple_open,
++      .owner = THIS_MODULE,
++      .llseek = default_llseek,
++};
++
++/*******************/
++/* Relay interface */
++/*******************/
++
++static struct dentry *create_buf_file_handler(const char *filename,
++                                            struct dentry *parent,
++                                            umode_t mode,
++                                            struct rchan_buf *buf,
++                                            int *is_global)
++{
++      struct dentry *buf_file;
++
++      buf_file = debugfs_create_file(filename, mode, parent, buf,
++                                     &relay_file_operations);
++      *is_global = 1;
++      return buf_file;
++}
++
++static int remove_buf_file_handler(struct dentry *dentry)
++{
++      debugfs_remove(dentry);
++
++      return 0;
++}
++
++struct rchan_callbacks rfs_spec_scan_cb = {
++      .create_buf_file = create_buf_file_handler,
++      .remove_buf_file = remove_buf_file_handler,
++};
++
++/*********************/
++/* Debug Init/Deinit */
++/*********************/
++
++void ath9k_spectral_deinit_debug(struct ath_softc *sc)
++{
++      if (config_enabled(CPTCFG_ATH9K_DEBUGFS) && sc->rfs_chan_spec_scan) {
++              relay_close(sc->rfs_chan_spec_scan);
++              sc->rfs_chan_spec_scan = NULL;
++      }
++}
++
++void ath9k_spectral_init_debug(struct ath_softc *sc)
++{
++      sc->rfs_chan_spec_scan = relay_open("spectral_scan",
++                                          sc->debug.debugfs_phy,
++                                          1024, 256, &rfs_spec_scan_cb,
++                                          NULL);
++      debugfs_create_file("spectral_scan_ctl",
++                          S_IRUSR | S_IWUSR,
++                          sc->debug.debugfs_phy, sc,
++                          &fops_spec_scan_ctl);
++      debugfs_create_file("spectral_short_repeat",
++                          S_IRUSR | S_IWUSR,
++                          sc->debug.debugfs_phy, sc,
++                          &fops_spectral_short_repeat);
++      debugfs_create_file("spectral_count",
++                          S_IRUSR | S_IWUSR,
++                          sc->debug.debugfs_phy, sc,
++                          &fops_spectral_count);
++      debugfs_create_file("spectral_period",
++                          S_IRUSR | S_IWUSR,
++                          sc->debug.debugfs_phy, sc,
++                          &fops_spectral_period);
++      debugfs_create_file("spectral_fft_period",
++                          S_IRUSR | S_IWUSR,
++                          sc->debug.debugfs_phy, sc,
++                          &fops_spectral_fft_period);
++}
+--- /dev/null
++++ b/drivers/net/wireless/ath/ath9k/spectral.h
+@@ -0,0 +1,212 @@
++/*
++ * Copyright (c) 2013 Qualcomm Atheros, Inc.
++ *
++ * Permission to use, copy, modify, and/or distribute this software for any
++ * purpose with or without fee is hereby granted, provided that the above
++ * copyright notice and this permission notice appear in all copies.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
++ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
++ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
++ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
++ */
++
++#ifndef SPECTRAL_H
++#define SPECTRAL_H
++
++/* enum spectral_mode:
++ *
++ * @SPECTRAL_DISABLED: spectral mode is disabled
++ * @SPECTRAL_BACKGROUND: hardware sends samples when it is not busy with
++ *    something else.
++ * @SPECTRAL_MANUAL: spectral scan is enabled, triggering for samples
++ *    is performed manually.
++ * @SPECTRAL_CHANSCAN: Like manual, but also triggered when changing channels
++ *    during a channel scan.
++ */
++enum spectral_mode {
++      SPECTRAL_DISABLED = 0,
++      SPECTRAL_BACKGROUND,
++      SPECTRAL_MANUAL,
++      SPECTRAL_CHANSCAN,
++};
++
++#define SPECTRAL_SCAN_BITMASK         0x10
++/* Radar info packet format, used for DFS and spectral formats. */
++struct ath_radar_info {
++      u8 pulse_length_pri;
++      u8 pulse_length_ext;
++      u8 pulse_bw_info;
++} __packed;
++
++/* The HT20 spectral data has 4 bytes of additional information at it's end.
++ *
++ * [7:0]: all bins {max_magnitude[1:0], bitmap_weight[5:0]}
++ * [7:0]: all bins  max_magnitude[9:2]
++ * [7:0]: all bins {max_index[5:0], max_magnitude[11:10]}
++ * [3:0]: max_exp (shift amount to size max bin to 8-bit unsigned)
++ */
++struct ath_ht20_mag_info {
++      u8 all_bins[3];
++      u8 max_exp;
++} __packed;
++
++#define SPECTRAL_HT20_NUM_BINS                56
++
++/* WARNING: don't actually use this struct! MAC may vary the amount of
++ * data by -1/+2. This struct is for reference only.
++ */
++struct ath_ht20_fft_packet {
++      u8 data[SPECTRAL_HT20_NUM_BINS];
++      struct ath_ht20_mag_info mag_info;
++      struct ath_radar_info radar_info;
++} __packed;
++
++#define SPECTRAL_HT20_TOTAL_DATA_LEN  (sizeof(struct ath_ht20_fft_packet))
++
++/* Dynamic 20/40 mode:
++ *
++ * [7:0]: lower bins {max_magnitude[1:0], bitmap_weight[5:0]}
++ * [7:0]: lower bins  max_magnitude[9:2]
++ * [7:0]: lower bins {max_index[5:0], max_magnitude[11:10]}
++ * [7:0]: upper bins {max_magnitude[1:0], bitmap_weight[5:0]}
++ * [7:0]: upper bins  max_magnitude[9:2]
++ * [7:0]: upper bins {max_index[5:0], max_magnitude[11:10]}
++ * [3:0]: max_exp (shift amount to size max bin to 8-bit unsigned)
++ */
++struct ath_ht20_40_mag_info {
++      u8 lower_bins[3];
++      u8 upper_bins[3];
++      u8 max_exp;
++} __packed;
++
++#define SPECTRAL_HT20_40_NUM_BINS             128
++
++/* WARNING: don't actually use this struct! MAC may vary the amount of
++ * data. This struct is for reference only.
++ */
++struct ath_ht20_40_fft_packet {
++      u8 data[SPECTRAL_HT20_40_NUM_BINS];
++      struct ath_ht20_40_mag_info mag_info;
++      struct ath_radar_info radar_info;
++} __packed;
++
++
++#define SPECTRAL_HT20_40_TOTAL_DATA_LEN       (sizeof(struct ath_ht20_40_fft_packet))
++
++/* grabs the max magnitude from the all/upper/lower bins */
++static inline u16 spectral_max_magnitude(u8 *bins)
++{
++      return (bins[0] & 0xc0) >> 6 |
++             (bins[1] & 0xff) << 2 |
++             (bins[2] & 0x03) << 10;
++}
++
++/* return the max magnitude from the all/upper/lower bins */
++static inline u8 spectral_max_index(u8 *bins)
++{
++      s8 m = (bins[2] & 0xfc) >> 2;
++
++      /* TODO: this still doesn't always report the right values ... */
++      if (m > 32)
++              m |= 0xe0;
++      else
++              m &= ~0xe0;
++
++      return m + 29;
++}
++
++/* return the bitmap weight from the all/upper/lower bins */
++static inline u8 spectral_bitmap_weight(u8 *bins)
++{
++      return bins[0] & 0x3f;
++}
++
++/* FFT sample format given to userspace via debugfs.
++ *
++ * Please keep the type/length at the front position and change
++ * other fields after adding another sample type
++ *
++ * TODO: this might need rework when switching to nl80211-based
++ * interface.
++ */
++enum ath_fft_sample_type {
++      ATH_FFT_SAMPLE_HT20 = 1,
++      ATH_FFT_SAMPLE_HT20_40,
++};
++
++struct fft_sample_tlv {
++      u8 type;        /* see ath_fft_sample */
++      __be16 length;
++      /* type dependent data follows */
++} __packed;
++
++struct fft_sample_ht20 {
++      struct fft_sample_tlv tlv;
++
++      u8 max_exp;
++
++      __be16 freq;
++      s8 rssi;
++      s8 noise;
++
++      __be16 max_magnitude;
++      u8 max_index;
++      u8 bitmap_weight;
++
++      __be64 tsf;
++
++      u8 data[SPECTRAL_HT20_NUM_BINS];
++} __packed;
++
++struct fft_sample_ht20_40 {
++      struct fft_sample_tlv tlv;
++
++      u8 channel_type;
++      __be16 freq;
++
++      s8 lower_rssi;
++      s8 upper_rssi;
++
++      __be64 tsf;
++
++      s8 lower_noise;
++      s8 upper_noise;
++
++      __be16 lower_max_magnitude;
++      __be16 upper_max_magnitude;
++
++      u8 lower_max_index;
++      u8 upper_max_index;
++
++      u8 lower_bitmap_weight;
++      u8 upper_bitmap_weight;
++
++      u8 max_exp;
++
++      u8 data[SPECTRAL_HT20_40_NUM_BINS];
++} __packed;
++
++void ath9k_spectral_init_debug(struct ath_softc *sc);
++void ath9k_spectral_deinit_debug(struct ath_softc *sc);
++
++void ath9k_spectral_scan_trigger(struct ieee80211_hw *hw);
++int ath9k_spectral_scan_config(struct ieee80211_hw *hw,
++                             enum spectral_mode spectral_mode);
++
++#ifdef CPTCFG_ATH9K_DEBUGFS
++int ath_process_fft(struct ath_softc *sc, struct ieee80211_hdr *hdr,
++                  struct ath_rx_status *rs, u64 tsf);
++#else
++static inline int ath_process_fft(struct ath_softc *sc,
++                                struct ieee80211_hdr *hdr,
++                                struct ath_rx_status *rs, u64 tsf)
++{
++      return 0;
++}
++#endif /* CPTCFG_ATH9K_DEBUGFS */
++
++#endif /* SPECTRAL_H */
+--- a/include/net/mac80211.h
++++ b/include/net/mac80211.h
+@@ -1566,6 +1566,9 @@ enum ieee80211_hw_flags {
+  * @extra_tx_headroom: headroom to reserve in each transmit skb
+  *    for use by the driver (e.g. for transmit headers.)
+  *
++ * @extra_beacon_tailroom: tailroom to reserve in each beacon tx skb.
++ *    Can be used by drivers to add extra IEs.
++ *
+  * @channel_change_time: time (in microseconds) it takes to change channels.
+  *
+  * @max_signal: Maximum value for signal (rssi) in RX information, used
+@@ -1644,6 +1647,7 @@ struct ieee80211_hw {
+       void *priv;
+       u32 flags;
+       unsigned int extra_tx_headroom;
++      unsigned int extra_beacon_tailroom;
+       int channel_change_time;
+       int vif_data_size;
+       int sta_data_size;
+@@ -4595,4 +4599,49 @@ bool ieee80211_tx_prepare_skb(struct iee
+                             struct ieee80211_vif *vif, struct sk_buff *skb,
+                             int band, struct ieee80211_sta **sta);
++/**
++ * struct ieee80211_noa_data - holds temporary data for tracking P2P NoA state
++ *
++ * @next_tsf: TSF timestamp of the next absent state change
++ * @has_next_tsf: next absent state change event pending
++ *
++ * @absent: descriptor bitmask, set if GO is currently absent
++ *
++ * private:
++ *
++ * @count: count fields from the NoA descriptors
++ * @desc: adjusted data from the NoA
++ */
++struct ieee80211_noa_data {
++      u32 next_tsf;
++      bool has_next_tsf;
++
++      u8 absent;
++
++      u8 count[IEEE80211_P2P_NOA_DESC_MAX];
++      struct {
++              u32 start;
++              u32 duration;
++              u32 interval;
++      } desc[IEEE80211_P2P_NOA_DESC_MAX];
++};
++
++/**
++ * ieee80211_parse_p2p_noa - initialize NoA tracking data from P2P IE
++ *
++ * @attr: P2P NoA IE
++ * @data: NoA tracking data
++ * @tsf: current TSF timestamp
++ */
++int ieee80211_parse_p2p_noa(const struct ieee80211_p2p_noa_attr *attr,
++                          struct ieee80211_noa_data *data, u32 tsf);
++
++/**
++ * ieee80211_update_p2p_noa - get next pending P2P GO absent state change
++ *
++ * @data: NoA tracking data
++ * @tsf: current TSF timestamp
++ */
++void ieee80211_update_p2p_noa(struct ieee80211_noa_data *data, u32 tsf);
++
+ #endif /* MAC80211_H */
+--- a/drivers/net/wireless/ath/ath9k/hw-ops.h
++++ b/drivers/net/wireless/ath/ath9k/hw-ops.h
+@@ -49,9 +49,10 @@ static inline bool ath9k_hw_calibrate(st
+       return ath9k_hw_ops(ah)->calibrate(ah, chan, rxchainmask, longcal);
+ }
+-static inline bool ath9k_hw_getisr(struct ath_hw *ah, enum ath9k_int *masked)
++static inline bool ath9k_hw_getisr(struct ath_hw *ah, enum ath9k_int *masked,
++                                 u32 *sync_cause_p)
+ {
+-      return ath9k_hw_ops(ah)->get_isr(ah, masked);
++      return ath9k_hw_ops(ah)->get_isr(ah, masked, sync_cause_p);
+ }
  
  
-               mag_info = ((struct ath_ht20_mag_info *)radar_info) - 1;
+ static inline void ath9k_hw_set_txdesc(struct ath_hw *ah, void *ds,
index e900349..39096a5 100644 (file)
@@ -8,7 +8,7 @@
  #include <asm/unaligned.h>
  
  #include "hw.h"
  #include <asm/unaligned.h>
  
  #include "hw.h"
-@@ -504,8 +505,16 @@ static int ath9k_hw_init_macaddr(struct 
+@@ -462,8 +463,16 @@ static int ath9k_hw_init_macaddr(struct 
                common->macaddr[2 * i] = eeval >> 8;
                common->macaddr[2 * i + 1] = eeval & 0xff;
        }
                common->macaddr[2 * i] = eeval >> 8;
                common->macaddr[2 * i + 1] = eeval & 0xff;
        }
index a4c73e2..96e2f6d 100644 (file)
@@ -1,6 +1,6 @@
 --- a/drivers/net/wireless/ath/ath9k/init.c
 +++ b/drivers/net/wireless/ath/ath9k/init.c
 --- a/drivers/net/wireless/ath/ath9k/init.c
 +++ b/drivers/net/wireless/ath/ath9k/init.c
-@@ -867,6 +867,7 @@ static const struct ieee80211_iface_limi
+@@ -865,6 +865,7 @@ static const struct ieee80211_iface_limi
  #endif
                                 BIT(NL80211_IFTYPE_AP) |
                                 BIT(NL80211_IFTYPE_P2P_GO) },
  #endif
                                 BIT(NL80211_IFTYPE_AP) |
                                 BIT(NL80211_IFTYPE_P2P_GO) },
index 321e75e..4c81ef1 100644 (file)
@@ -1,7 +1,7 @@
 --- a/drivers/net/wireless/ath/ath9k/debug.c
 +++ b/drivers/net/wireless/ath/ath9k/debug.c
 --- a/drivers/net/wireless/ath/ath9k/debug.c
 +++ b/drivers/net/wireless/ath/ath9k/debug.c
-@@ -1782,6 +1782,53 @@ void ath9k_deinit_debug(struct ath_softc
-       }
+@@ -1528,6 +1528,53 @@ void ath9k_deinit_debug(struct ath_softc
+       ath9k_spectral_deinit_debug(sc);
  }
  
 +static ssize_t read_file_eeprom(struct file *file, char __user *user_buf,
  }
  
 +static ssize_t read_file_eeprom(struct file *file, char __user *user_buf,
@@ -54,9 +54,9 @@
  int ath9k_init_debug(struct ath_hw *ah)
  {
        struct ath_common *common = ath9k_hw_common(ah);
  int ath9k_init_debug(struct ath_hw *ah)
  {
        struct ath_common *common = ath9k_hw_common(ah);
-@@ -1800,6 +1847,8 @@ int ath9k_init_debug(struct ath_hw *ah)
-       ath9k_dfs_init_debug(sc);
+@@ -1547,6 +1594,8 @@ int ath9k_init_debug(struct ath_hw *ah)
        ath9k_tx99_init_debug(sc);
        ath9k_tx99_init_debug(sc);
+       ath9k_spectral_init_debug(sc);
  
 +      debugfs_create_file("eeprom", S_IRUSR, sc->debug.debugfs_phy, sc,
 +                          &fops_eeprom);
  
 +      debugfs_create_file("eeprom", S_IRUSR, sc->debug.debugfs_phy, sc,
 +                          &fops_eeprom);
index 4eca75a..b2bd51c 100644 (file)
@@ -71,7 +71,7 @@
  
 --- a/drivers/net/wireless/ath/ath9k/hw.h
 +++ b/drivers/net/wireless/ath/ath9k/hw.h
  
 --- a/drivers/net/wireless/ath/ath9k/hw.h
 +++ b/drivers/net/wireless/ath/ath9k/hw.h
-@@ -706,6 +706,7 @@ enum ath_cal_list {
+@@ -707,6 +707,7 @@ enum ath_cal_list {
  #define AH_USE_EEPROM   0x1
  #define AH_UNPLUGGED    0x2 /* The card has been physically removed. */
  #define AH_FASTCC       0x4
  #define AH_USE_EEPROM   0x1
  #define AH_UNPLUGGED    0x2 /* The card has been physically removed. */
  #define AH_FASTCC       0x4
@@ -81,7 +81,7 @@
        struct ath_ops reg_ops;
 --- a/drivers/net/wireless/ath/ath9k/init.c
 +++ b/drivers/net/wireless/ath/ath9k/init.c
        struct ath_ops reg_ops;
 --- a/drivers/net/wireless/ath/ath9k/init.c
 +++ b/drivers/net/wireless/ath/ath9k/init.c
-@@ -721,6 +721,8 @@ static int ath9k_init_softc(u16 devid, s
+@@ -719,6 +719,8 @@ static int ath9k_init_softc(u16 devid, s
                ah->is_clk_25mhz = pdata->is_clk_25mhz;
                ah->get_mac_revision = pdata->get_mac_revision;
                ah->external_reset = pdata->external_reset;
                ah->is_clk_25mhz = pdata->is_clk_25mhz;
                ah->get_mac_revision = pdata->get_mac_revision;
                ah->external_reset = pdata->external_reset;
index 1f50580..f57ded2 100644 (file)
@@ -1,6 +1,6 @@
 --- a/drivers/net/wireless/ath/ath9k/init.c
 +++ b/drivers/net/wireless/ath/ath9k/init.c
 --- a/drivers/net/wireless/ath/ath9k/init.c
 +++ b/drivers/net/wireless/ath/ath9k/init.c
-@@ -1110,23 +1110,23 @@ static int __init ath9k_init(void)
+@@ -1108,23 +1108,23 @@ static int __init ath9k_init(void)
                goto err_out;
        }
  
                goto err_out;
        }
  
index 647bde2..e9e51c1 100644 (file)
@@ -1,6 +1,6 @@
 --- a/drivers/net/wireless/ath/ath9k/hw.c
 +++ b/drivers/net/wireless/ath/ath9k/hw.c
 --- a/drivers/net/wireless/ath/ath9k/hw.c
 +++ b/drivers/net/wireless/ath/ath9k/hw.c
-@@ -2010,8 +2010,8 @@ int ath9k_hw_reset(struct ath_hw *ah, st
+@@ -1978,8 +1978,8 @@ int ath9k_hw_reset(struct ath_hw *ah, st
                REG_WRITE(ah, AR_OBS, 8);
  
        if (ah->config.rx_intr_mitigation) {
                REG_WRITE(ah, AR_OBS, 8);
  
        if (ah->config.rx_intr_mitigation) {
index 4e2121a..ef0b9a1 100644 (file)
@@ -1,8 +1,8 @@
 --- a/drivers/net/wireless/ath/ath9k/ath9k.h
 +++ b/drivers/net/wireless/ath/ath9k/ath9k.h
 --- a/drivers/net/wireless/ath/ath9k/ath9k.h
 +++ b/drivers/net/wireless/ath/ath9k/ath9k.h
-@@ -113,7 +113,7 @@ int ath_descdma_setup(struct ath_softc *
- /* RX / TX */
- /***********/
+@@ -90,7 +90,7 @@ int ath_descdma_setup(struct ath_softc *
+               (_l) &= ((_sz) - 1);            \
+       } while (0)
  
 -#define ATH_RXBUF               512
 +#define ATH_RXBUF               256
  
 -#define ATH_RXBUF               512
 +#define ATH_RXBUF               256
index 88e0756..73e0092 100644 (file)
@@ -1,6 +1,6 @@
 --- a/drivers/net/wireless/ath/ath9k/debug.c
 +++ b/drivers/net/wireless/ath/ath9k/debug.c
 --- a/drivers/net/wireless/ath/ath9k/debug.c
 +++ b/drivers/net/wireless/ath/ath9k/debug.c
-@@ -1829,6 +1829,52 @@ static const struct file_operations fops
+@@ -1575,6 +1575,52 @@ static const struct file_operations fops
        .owner = THIS_MODULE
  };
  
        .owner = THIS_MODULE
  };
  
@@ -53,7 +53,7 @@
  int ath9k_init_debug(struct ath_hw *ah)
  {
        struct ath_common *common = ath9k_hw_common(ah);
  int ath9k_init_debug(struct ath_hw *ah)
  {
        struct ath_common *common = ath9k_hw_common(ah);
-@@ -1849,6 +1895,8 @@ int ath9k_init_debug(struct ath_hw *ah)
+@@ -1596,6 +1642,8 @@ int ath9k_init_debug(struct ath_hw *ah)
  
        debugfs_create_file("eeprom", S_IRUSR, sc->debug.debugfs_phy, sc,
                            &fops_eeprom);
  
        debugfs_create_file("eeprom", S_IRUSR, sc->debug.debugfs_phy, sc,
                            &fops_eeprom);
index 70a333c..cae555a 100644 (file)
@@ -1,6 +1,6 @@
 --- a/drivers/net/wireless/ath/ath9k/hw.c
 +++ b/drivers/net/wireless/ath/ath9k/hw.c
 --- a/drivers/net/wireless/ath/ath9k/hw.c
 +++ b/drivers/net/wireless/ath/ath9k/hw.c
-@@ -724,6 +724,7 @@ int ath9k_hw_init(struct ath_hw *ah)
+@@ -682,6 +682,7 @@ int ath9k_hw_init(struct ath_hw *ah)
        case AR9300_DEVID_AR9462:
        case AR9485_DEVID_AR1111:
        case AR9300_DEVID_AR9565:
        case AR9300_DEVID_AR9462:
        case AR9485_DEVID_AR1111:
        case AR9300_DEVID_AR9565:
index 9361365..6457380 100644 (file)
@@ -1,6 +1,6 @@
 --- a/include/net/mac80211.h
 +++ b/include/net/mac80211.h
 --- a/include/net/mac80211.h
 +++ b/include/net/mac80211.h
-@@ -1659,6 +1659,7 @@ struct ieee80211_hw {
+@@ -1663,6 +1663,7 @@ struct ieee80211_hw {
        u8 max_tx_aggregation_subframes;
        u8 offchannel_tx_hw_queue;
        u8 radiotap_mcs_details;
        u8 max_tx_aggregation_subframes;
        u8 offchannel_tx_hw_queue;
        u8 radiotap_mcs_details;
index 8e0c562..0a5a71f 100644 (file)
@@ -14,7 +14,7 @@
  
  out:
        spin_unlock_bh(&sc->sc_pcu_lock);
  
  out:
        spin_unlock_bh(&sc->sc_pcu_lock);
-@@ -1345,6 +1349,7 @@ static int ath9k_config(struct ieee80211
+@@ -1347,6 +1351,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);
                sc->config.txpowlimit = 2 * conf->power_level;
                ath9k_cmn_update_txpow(ah, sc->curtxpow,
                                       sc->config.txpowlimit, &sc->curtxpow);
index afc5ba6..f960519 100644 (file)
@@ -10,7 +10,7 @@
  
 --- a/drivers/net/wireless/ath/ath9k/hw.c
 +++ b/drivers/net/wireless/ath/ath9k/hw.c
  
 --- a/drivers/net/wireless/ath/ath9k/hw.c
 +++ b/drivers/net/wireless/ath/ath9k/hw.c
-@@ -2841,7 +2841,7 @@ void ath9k_hw_apply_txpower(struct ath_h
+@@ -2809,7 +2809,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);
        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
        if (ant_gain > max_gain)
 --- a/drivers/net/wireless/ath/ath9k/main.c
 +++ b/drivers/net/wireless/ath/ath9k/main.c
-@@ -1345,7 +1345,10 @@ static int ath9k_config(struct ieee80211
+@@ -1347,7 +1347,10 @@ static int ath9k_config(struct ieee80211
        }
  
        if (changed & IEEE80211_CONF_CHANGE_POWER) {
        }
  
        if (changed & IEEE80211_CONF_CHANGE_POWER) {
index 4557c27..5665c13 100644 (file)
@@ -1,6 +1,6 @@
 --- a/drivers/net/wireless/ath/ath9k/ath9k.h
 +++ b/drivers/net/wireless/ath/ath9k/ath9k.h
 --- a/drivers/net/wireless/ath/ath9k/ath9k.h
 +++ b/drivers/net/wireless/ath/ath9k/ath9k.h
-@@ -557,6 +557,9 @@ struct ath9k_wow_pattern {
+@@ -559,6 +559,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);
  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,9 +10,9 @@
  #else
  static inline void ath_init_leds(struct ath_softc *sc)
  {
  #else
  static inline void ath_init_leds(struct ath_softc *sc)
  {
-@@ -732,6 +735,13 @@ enum spectral_mode {
-       SPECTRAL_CHANSCAN,
- };
+@@ -704,6 +707,13 @@ enum sc_op_flags {
+ #define PS_BEACON_SYNC            BIT(4)
+ #define PS_WAIT_FOR_ANI           BIT(5)
  
 +struct ath_led {
 +      struct list_head list;
  
 +struct ath_led {
 +      struct list_head list;
@@ -24,7 +24,7 @@
  struct ath_softc {
        struct ieee80211_hw *hw;
        struct device *dev;
  struct ath_softc {
        struct ieee80211_hw *hw;
        struct device *dev;
-@@ -774,9 +784,8 @@ struct ath_softc {
+@@ -746,9 +756,8 @@ struct ath_softc {
        struct ieee80211_supported_band sbands[IEEE80211_NUM_BANDS];
  
  #ifdef CPTCFG_MAC80211_LEDS
        struct ieee80211_supported_band sbands[IEEE80211_NUM_BANDS];
  
  #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
  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
-@@ -1016,7 +1016,7 @@ int ath9k_init_device(u16 devid, struct 
+@@ -1014,7 +1014,7 @@ int ath9k_init_device(u16 devid, struct 
  
  #ifdef CPTCFG_MAC80211_LEDS
        /* must be initialized before ieee80211_register_hw */
  
  #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
  #endif
 --- a/drivers/net/wireless/ath/ath9k/debug.c
 +++ b/drivers/net/wireless/ath/ath9k/debug.c
-@@ -1874,6 +1874,61 @@ static const struct file_operations fops
+@@ -1620,6 +1620,61 @@ static const struct file_operations fops
        .llseek = default_llseek,
  };
  
        .llseek = default_llseek,
  };
  
  
  int ath9k_init_debug(struct ath_hw *ah)
  {
  
  int ath9k_init_debug(struct ath_hw *ah)
  {
-@@ -1897,6 +1952,10 @@ int ath9k_init_debug(struct ath_hw *ah)
+@@ -1644,6 +1699,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);
                            &fops_eeprom);
        debugfs_create_file("chanbw", S_IRUSR | S_IWUSR, sc->debug.debugfs_phy,
                            sc, &fops_chanbw);
index cf5bbbe..35a0041 100644 (file)
@@ -1,6 +1,6 @@
 --- a/drivers/net/wireless/ath/ath9k/debug.c
 +++ b/drivers/net/wireless/ath/ath9k/debug.c
 --- a/drivers/net/wireless/ath/ath9k/debug.c
 +++ b/drivers/net/wireless/ath/ath9k/debug.c
-@@ -1930,6 +1930,50 @@ static const struct file_operations fops
+@@ -1676,6 +1676,50 @@ static const struct file_operations fops
  #endif
  
  
  #endif
  
  
@@ -51,7 +51,7 @@
  int ath9k_init_debug(struct ath_hw *ah)
  {
        struct ath_common *common = ath9k_hw_common(ah);
  int ath9k_init_debug(struct ath_hw *ah)
  {
        struct ath_common *common = ath9k_hw_common(ah);
-@@ -1956,6 +2000,8 @@ int ath9k_init_debug(struct ath_hw *ah)
+@@ -1703,6 +1747,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
        debugfs_create_file("gpio_led", S_IWUSR,
                           sc->debug.debugfs_phy, sc, &fops_gpio_led);
  #endif
@@ -75,7 +75,7 @@
  struct ath9k_hw_version {
        u32 magic;
        u16 devid;
  struct ath9k_hw_version {
        u32 magic;
        u16 devid;
-@@ -744,6 +750,8 @@ struct ath_hw {
+@@ -745,6 +751,8 @@ struct ath_hw {
        u32 rfkill_polarity;
        u32 ah_flags;
  
        u32 rfkill_polarity;
        u32 ah_flags;
  
        bool reset_power_on;
        bool htc_reset_init;
  
        bool reset_power_on;
        bool htc_reset_init;
  
-@@ -995,6 +1003,7 @@ void ath9k_hw_check_nav(struct ath_hw *a
+@@ -996,6 +1004,7 @@ void ath9k_hw_check_nav(struct ath_hw *a
  bool ath9k_hw_check_alive(struct ath_hw *ah);
  
  bool ath9k_hw_setpower(struct ath_hw *ah, enum ath9k_power_mode mode);
 +void ath9k_hw_update_diag(struct ath_hw *ah);
  
  bool ath9k_hw_check_alive(struct ath_hw *ah);
  
  bool ath9k_hw_setpower(struct ath_hw *ah, enum ath9k_power_mode mode);
 +void ath9k_hw_update_diag(struct ath_hw *ah);
  
- #ifdef CPTCFG_ATH9K_DEBUGFS
- void ath9k_debug_sync_cause(struct ath_common *common, u32 sync_cause);
+ /* Generic hw timer primitives */
+ 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
 --- a/drivers/net/wireless/ath/ath9k/hw.c
 +++ b/drivers/net/wireless/ath/ath9k/hw.c
-@@ -1854,6 +1854,20 @@ fail:
+@@ -1822,6 +1822,20 @@ fail:
        return -EINVAL;
  }
  
        return -EINVAL;
  }
  
  int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,
                   struct ath9k_hw_cal_data *caldata, bool fastcc)
  {
  int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,
                   struct ath9k_hw_cal_data *caldata, bool fastcc)
  {
-@@ -2056,6 +2070,7 @@ int ath9k_hw_reset(struct ath_hw *ah, st
+@@ -2024,6 +2038,7 @@ int ath9k_hw_reset(struct ath_hw *ah, st
        }
  
        ath9k_hw_apply_gpio_override(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
                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
-@@ -574,6 +574,11 @@ irqreturn_t ath_isr(int irq, void *dev)
-       ath9k_hw_getisr(ah, &status);   /* NB: clears ISR too */
+@@ -576,6 +576,11 @@ irqreturn_t ath_isr(int irq, void *dev)
+       ath9k_debug_sync_cause(sc, sync_cause);
        status &= ah->imask;    /* discard unasked-for bits */
  
 +      if (test_bit(ATH_DIAG_TRIGGER_ERROR, &ah->diag)) {
        status &= ah->imask;    /* discard unasked-for bits */
  
 +      if (test_bit(ATH_DIAG_TRIGGER_ERROR, &ah->diag)) {
index 0e83822..a775ad9 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
        int (*external_reset)(void);
 --- a/drivers/net/wireless/ath/ath9k/hw.c
 +++ b/drivers/net/wireless/ath/ath9k/hw.c
-@@ -2441,17 +2441,25 @@ int ath9k_hw_fill_cap_info(struct ath_hw
+@@ -2409,17 +2409,25 @@ int ath9k_hw_fill_cap_info(struct ath_hw
        }
  
        eeval = ah->eep_ops->get_eeprom(ah, EEP_OP_MODE);
        }
  
        eeval = ah->eep_ops->get_eeprom(ah, EEP_OP_MODE);
@@ -47,7 +47,7 @@
            AR_SREV_9285(ah) ||
 --- a/drivers/net/wireless/ath/ath9k/hw.h
 +++ b/drivers/net/wireless/ath/ath9k/hw.h
            AR_SREV_9285(ah) ||
 --- a/drivers/net/wireless/ath/ath9k/hw.h
 +++ b/drivers/net/wireless/ath/ath9k/hw.h
-@@ -914,6 +914,8 @@ struct ath_hw {
+@@ -915,6 +915,8 @@ struct ath_hw {
        bool is_clk_25mhz;
        int (*get_mac_revision)(void);
        int (*external_reset)(void);
        bool is_clk_25mhz;
        int (*get_mac_revision)(void);
        int (*external_reset)(void);
@@ -58,7 +58,7 @@
  };
 --- a/drivers/net/wireless/ath/ath9k/init.c
 +++ b/drivers/net/wireless/ath/ath9k/init.c
  };
 --- a/drivers/net/wireless/ath/ath9k/init.c
 +++ b/drivers/net/wireless/ath/ath9k/init.c
-@@ -721,6 +721,8 @@ static int ath9k_init_softc(u16 devid, s
+@@ -719,6 +719,8 @@ static int ath9k_init_softc(u16 devid, s
                ah->is_clk_25mhz = pdata->is_clk_25mhz;
                ah->get_mac_revision = pdata->get_mac_revision;
                ah->external_reset = pdata->external_reset;
                ah->is_clk_25mhz = pdata->is_clk_25mhz;
                ah->get_mac_revision = pdata->get_mac_revision;
                ah->external_reset = pdata->external_reset;
index b8209a5..6cd09bd 100644 (file)
@@ -8,7 +8,7 @@
   * @spectral_scan_config: set parameters for spectral scan and enable/disable it
   * @spectral_scan_trigger: trigger a spectral scan run
   * @spectral_scan_wait: wait for a spectral scan run to finish
   * @spectral_scan_config: set parameters for spectral scan and enable/disable it
   * @spectral_scan_trigger: trigger a spectral scan run
   * @spectral_scan_wait: wait for a spectral scan run to finish
-@@ -683,6 +684,7 @@ struct ath_hw_ops {
+@@ -684,6 +685,7 @@ struct ath_hw_ops {
                        struct ath_hw_antcomb_conf *antconf);
        void (*antdiv_comb_conf_set)(struct ath_hw *ah,
                        struct ath_hw_antcomb_conf *antconf);
                        struct ath_hw_antcomb_conf *antconf);
        void (*antdiv_comb_conf_set)(struct ath_hw *ah,
                        struct ath_hw_antcomb_conf *antconf);
@@ -55,7 +55,7 @@
        ops->spectral_scan_config = ar9003_hw_spectral_scan_config;
 --- a/drivers/net/wireless/ath/ath9k/init.c
 +++ b/drivers/net/wireless/ath/ath9k/init.c
        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
-@@ -847,7 +847,8 @@ static void ath9k_init_txpower_limits(st
+@@ -845,7 +845,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);
  
        if (ah->caps.hw_caps & ATH9K_HW_CAP_5GHZ)
                ath9k_init_band_txpower(sc, IEEE80211_BAND_5GHZ);
  
@@ -65,7 +65,7 @@
  }
  
  void ath9k_reload_chainmask_settings(struct ath_softc *sc)
  }
  
  void ath9k_reload_chainmask_settings(struct ath_softc *sc)
-@@ -978,6 +979,18 @@ void ath9k_set_hw_capab(struct ath_softc
+@@ -976,6 +977,18 @@ static void ath9k_set_hw_capab(struct at
        SET_IEEE80211_PERM_ADDR(hw, common->macaddr);
  }
  
        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)
  {
  int ath9k_init_device(u16 devid, struct ath_softc *sc,
                    const struct ath_bus_ops *bus_ops)
  {
-@@ -1023,6 +1036,8 @@ int ath9k_init_device(u16 devid, struct 
+@@ -1021,6 +1034,8 @@ int ath9k_init_device(u16 devid, struct 
                ARRAY_SIZE(ath9k_tpt_blink));
  #endif
  
                ARRAY_SIZE(ath9k_tpt_blink));
  #endif
  
@@ -95,7 +95,7 @@
        if (error)
 --- a/drivers/net/wireless/ath/ath9k/hw-ops.h
 +++ b/drivers/net/wireless/ath/ath9k/hw-ops.h
        if (error)
 --- a/drivers/net/wireless/ath/ath9k/hw-ops.h
 +++ b/drivers/net/wireless/ath/ath9k/hw-ops.h
-@@ -94,6 +94,12 @@ static inline void ath9k_hw_tx99_set_txp
+@@ -95,6 +95,12 @@ static inline void ath9k_hw_tx99_set_txp
                ath9k_hw_ops(ah)->tx99_set_txpower(ah, power);
  }
  
                ath9k_hw_ops(ah)->tx99_set_txpower(ah, power);
  }