ath9k: merge another round of cleanups and fixes submitted to linux-wireless
authorFelix Fietkau <nbd@openwrt.org>
Sat, 14 Dec 2013 17:07:08 +0000 (17:07 +0000)
committerFelix Fietkau <nbd@openwrt.org>
Sat, 14 Dec 2013 17:07:08 +0000 (17:07 +0000)
Signed-off-by: Felix Fietkau <nbd@openwrt.org>
SVN-Revision: 39054

16 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/501-ath9k-eeprom_endianess.patch
package/kernel/mac80211/patches/510-ath9k_intr_mitigation_tweak.patch
package/kernel/mac80211/patches/513-ath9k_add_pci_ids.patch
package/kernel/mac80211/patches/521-ath9k_cur_txpower.patch
package/kernel/mac80211/patches/522-ath9k_per_chain_signal_strength.patch [deleted file]
package/kernel/mac80211/patches/522-mac80211_configure_antenna_gain.patch [new file with mode: 0644]
package/kernel/mac80211/patches/523-ath9k_use_configured_antenna_gain.patch [new file with mode: 0644]
package/kernel/mac80211/patches/523-mac80211_configure_antenna_gain.patch [deleted file]
package/kernel/mac80211/patches/524-ath9k_use_configured_antenna_gain.patch [deleted file]
package/kernel/mac80211/patches/530-ath9k_extra_leds.patch
package/kernel/mac80211/patches/541-ath9k_rx_dma_stop_check.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 7fd6225..f70ac79 100644 (file)
  
  /**********/
  /* BTCOEX */
-@@ -570,6 +571,34 @@ static inline void ath_fill_led_pin(stru
+@@ -476,20 +477,19 @@ enum bt_op_flags {
+ };
+ struct ath_btcoex {
+-      bool hw_timer_enabled;
+       spinlock_t btcoex_lock;
+       struct timer_list period_timer; /* Timer for BT period */
++      struct timer_list no_stomp_timer;
+       u32 bt_priority_cnt;
+       unsigned long bt_priority_time;
+       unsigned long op_flags;
+       int bt_stomp_type; /* Types of BT stomping */
+-      u32 btcoex_no_stomp; /* in usec */
++      u32 btcoex_no_stomp; /* in msec */
+       u32 btcoex_period; /* in msec */
+-      u32 btscan_no_stomp; /* in usec */
++      u32 btscan_no_stomp; /* in msec */
+       u32 duty_cycle;
+       u32 bt_wait_time;
+       int rssi_count;
+-      struct ath_gen_timer *no_stomp_timer; /* Timer for no BT stomping */
+       struct ath_mci_profile mci;
+       u8 stomp_audio;
+ };
+@@ -570,6 +570,34 @@ static inline void ath_fill_led_pin(stru
  }
  #endif
  
  /*******************************/
  /* Antenna diversity/combining */
  /*******************************/
-@@ -632,15 +661,16 @@ void ath_ant_comb_scan(struct ath_softc 
+@@ -632,15 +660,16 @@ void ath_ant_comb_scan(struct ath_softc 
  /* Main driver core */
  /********************/
  
  
  /*
   * Default cache line size, in bytes.
-@@ -723,6 +753,7 @@ struct ath_softc {
+@@ -723,6 +752,7 @@ struct ath_softc {
        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;
-@@ -759,6 +790,7 @@ struct ath_softc {
+@@ -759,6 +789,7 @@ struct ath_softc {
        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;
-@@ -783,7 +815,7 @@ struct ath_softc {
+@@ -783,7 +814,7 @@ struct ath_softc {
        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;
-@@ -946,10 +978,25 @@ struct fft_sample_ht20_40 {
+@@ -946,10 +977,25 @@ struct fft_sample_ht20_40 {
        u8 data[SPECTRAL_HT20_40_NUM_BINS];
  } __packed;
  
  
  void ath9k_tasklet(unsigned long data);
  int ath_cabq_update(struct ath_softc *);
-@@ -966,6 +1013,9 @@ extern bool is_ath9k_unloaded;
+@@ -966,6 +1012,9 @@ extern bool is_ath9k_unloaded;
  
  u8 ath9k_parse_mpdudensity(u8 mpdudensity);
  irqreturn_t ath_isr(int irq, void *dev);
  }
 --- a/drivers/net/wireless/ath/ath9k/hw.c
 +++ b/drivers/net/wireless/ath/ath9k/hw.c
-@@ -17,6 +17,7 @@
+@@ -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"
-@@ -454,7 +455,6 @@ static void ath9k_hw_init_config(struct 
-       }
+@@ -438,23 +440,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.pcie_clock_req = 0;
+       ah->config.analog_shiftreg = 1;
+-      for (i = 0; i < AR_EEPROM_MODAL_SPURS; i++) {
+-              ah->config.spurchans[i][0] = AR_NO_SPUR;
+-              ah->config.spurchans[i][1] = AR_NO_SPUR;
+-      }
+-
        ah->config.rx_intr_mitigation = true;
 -      ah->config.pcieSerDesWrite = true;
  
        /*
         * We need this for PCI devices only (Cardbus, PCI, miniPCI)
-@@ -549,11 +549,11 @@ static int ath9k_hw_post_init(struct ath
+@@ -486,7 +478,6 @@ static void ath9k_hw_init_defaults(struc
+       ah->hw_version.magic = AR5416_MAGIC;
+       ah->hw_version.subvendorid = 0;
+-      ah->atim_window = 0;
+       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
         * EEPROM needs to be initialized before we do this.
         * This is required for regulatory compliance.
         */
                }
        }
  
-@@ -1502,8 +1502,9 @@ static bool ath9k_hw_channel_change(stru
+@@ -1502,8 +1493,9 @@ static bool ath9k_hw_channel_change(stru
        int r;
  
        if (pCap->hw_caps & ATH9K_HW_CAP_FCC_BAND_SWITCH) {
        }
  
        for (qnum = 0; qnum < AR_NUM_QCU; qnum++) {
-@@ -1815,7 +1816,7 @@ static int ath9k_hw_do_fastcc(struct ath
+@@ -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) &&
                goto fail;
  
        if (!ath9k_hw_check_alive(ah))
-@@ -1856,10 +1857,12 @@ int ath9k_hw_reset(struct ath_hw *ah, st
+@@ -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);
        int r;
        bool start_mci_reset = false;
        bool save_fullsleep = ah->chip_fullsleep;
-@@ -1902,10 +1905,10 @@ int ath9k_hw_reset(struct ath_hw *ah, st
+@@ -1902,10 +1896,10 @@ int ath9k_hw_reset(struct ath_hw *ah, st
  
        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 |
-@@ -1938,8 +1941,9 @@ int ath9k_hw_reset(struct ath_hw *ah, st
+@@ -1938,8 +1932,9 @@ int ath9k_hw_reset(struct ath_hw *ah, st
        }
  
        /* Restore TSF */
  
        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 *
+       case NL80211_IFTYPE_ADHOC:
+               REG_SET_BIT(ah, AR_TXCFG,
+                           AR_TXCFG_ADHOC_BEACON_ATIM_TX_POLICY);
+-              REG_WRITE(ah, AR_NEXT_NDP_TIMER, next_beacon +
+-                        TU_TO_USEC(ah->atim_window ? ah->atim_window : 1));
+-              flags |= AR_NDP_TIMER_EN;
+       case NL80211_IFTYPE_MESH_POINT:
+       case NL80211_IFTYPE_AP:
+               REG_WRITE(ah, AR_NEXT_TBTT_TIMER, next_beacon);
+@@ -2284,7 +2276,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_NDP_PERIOD, beacon_period);
+       REGWRITE_BUFFER_FLUSH(ah);
+@@ -2301,12 +2292,9 @@ void ath9k_hw_set_sta_beacon_timers(stru
+       ENABLE_REGWRITE_BUFFER(ah);
+-      REG_WRITE(ah, AR_NEXT_TBTT_TIMER, TU_TO_USEC(bs->bs_nexttbtt));
+-
+-      REG_WRITE(ah, AR_BEACON_PERIOD,
+-                TU_TO_USEC(bs->bs_intval));
+-      REG_WRITE(ah, AR_DMA_BEACON_PERIOD,
+-                TU_TO_USEC(bs->bs_intval));
++      REG_WRITE(ah, AR_NEXT_TBTT_TIMER, bs->bs_nexttbtt);
++      REG_WRITE(ah, AR_BEACON_PERIOD, bs->bs_intval);
++      REG_WRITE(ah, AR_DMA_BEACON_PERIOD, bs->bs_intval);
+       REGWRITE_BUFFER_FLUSH(ah);
+@@ -2334,9 +2322,8 @@ void ath9k_hw_set_sta_beacon_timers(stru
+       ENABLE_REGWRITE_BUFFER(ah);
+-      REG_WRITE(ah, AR_NEXT_DTIM,
+-                TU_TO_USEC(bs->bs_nextdtim - SLEEP_SLOP));
+-      REG_WRITE(ah, AR_NEXT_TIM, TU_TO_USEC(nextTbtt - SLEEP_SLOP));
++      REG_WRITE(ah, AR_NEXT_DTIM, bs->bs_nextdtim - SLEEP_SLOP);
++      REG_WRITE(ah, AR_NEXT_TIM, nextTbtt - SLEEP_SLOP);
+       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
+       REG_WRITE(ah, AR_SLEEP2,
+                 SM(beacontimeout, AR_SLEEP2_BEACON_TIMEOUT));
+-      REG_WRITE(ah, AR_TIM_PERIOD, TU_TO_USEC(beaconintval));
+-      REG_WRITE(ah, AR_DTIM_PERIOD, TU_TO_USEC(dtimperiod));
++      REG_WRITE(ah, AR_TIM_PERIOD, beaconintval);
++      REG_WRITE(ah, AR_DTIM_PERIOD, dtimperiod);
+       REGWRITE_BUFFER_FLUSH(ah);
+@@ -2987,20 +2974,6 @@ static const struct ath_gen_timer_config
+ /* HW generic timer primitives */
+-/* compute and clear index of rightmost 1 */
+-static u32 rightmost_index(struct ath_gen_timer_table *timer_table, u32 *mask)
+-{
+-      u32 b;
+-
+-      b = *mask;
+-      b &= (0-b);
+-      *mask &= ~b;
+-      b *= debruijn32;
+-      b >>= 27;
+-
+-      return timer_table->gen_timer_index[b];
+-}
+-
+ 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
+       struct ath_gen_timer_table *timer_table = &ah->hw_gen_timers;
+       struct ath_gen_timer *timer;
++      if ((timer_index < AR_FIRST_NDP_TIMER) ||
++              (timer_index >= ATH_MAX_GEN_TIMER))
++              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);
+ void ath9k_hw_gen_timer_start(struct ath_hw *ah,
+                             struct ath_gen_timer *timer,
+-                            u32 trig_timeout,
++                            u32 timer_next,
+                             u32 timer_period)
+ {
+       struct ath_gen_timer_table *timer_table = &ah->hw_gen_timers;
+-      u32 tsf, timer_next;
+-
+-      BUG_ON(!timer_period);
+-
+-      set_bit(timer->index, &timer_table->timer_mask.timer_bits);
+-
+-      tsf = ath9k_hw_gettsf32(ah);
++      u32 mask = 0;
+-      timer_next = tsf + trig_timeout;
+-
+-      ath_dbg(ath9k_hw_common(ah), BTCOEX,
+-              "current tsf %x period %x timer_next %x\n",
+-              tsf, timer_period, timer_next);
++      timer_table->timer_mask |= BIT(timer->index);
+       /*
+        * Program generic timer registers
+@@ -3075,10 +3042,19 @@ void ath9k_hw_gen_timer_start(struct ath
+                                      (1 << timer->index));
+       }
+-      /* Enable both trigger and thresh interrupt masks */
+-      REG_SET_BIT(ah, AR_IMR_S5,
+-              (SM(AR_GENTMR_BIT(timer->index), AR_IMR_S5_GENTIMER_THRESH) |
+-              SM(AR_GENTMR_BIT(timer->index), AR_IMR_S5_GENTIMER_TRIG)));
++      if (timer->trigger)
++              mask |= SM(AR_GENTMR_BIT(timer->index),
++                         AR_IMR_S5_GENTIMER_TRIG);
++      if (timer->overflow)
++              mask |= SM(AR_GENTMR_BIT(timer->index),
++                         AR_IMR_S5_GENTIMER_THRESH);
++
++      REG_SET_BIT(ah, AR_IMR_S5, mask);
++
++      if ((ah->imask & ATH9K_INT_GENTIMER) == 0) {
++              ah->imask |= ATH9K_INT_GENTIMER;
++              ath9k_hw_set_interrupts(ah);
++      }
+ }
+ EXPORT_SYMBOL(ath9k_hw_gen_timer_start);
+@@ -3086,11 +3062,6 @@ void ath9k_hw_gen_timer_stop(struct ath_
+ {
+       struct ath_gen_timer_table *timer_table = &ah->hw_gen_timers;
+-      if ((timer->index < AR_FIRST_NDP_TIMER) ||
+-              (timer->index >= ATH_MAX_GEN_TIMER)) {
+-              return;
+-      }
+-
+       /* 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_
+               (SM(AR_GENTMR_BIT(timer->index), AR_IMR_S5_GENTIMER_THRESH) |
+               SM(AR_GENTMR_BIT(timer->index), AR_IMR_S5_GENTIMER_TRIG)));
+-      clear_bit(timer->index, &timer_table->timer_mask.timer_bits);
++      timer_table->timer_mask &= ~BIT(timer->index);
++
++      if (timer_table->timer_mask == 0) {
++              ah->imask &= ~ATH9K_INT_GENTIMER;
++              ath9k_hw_set_interrupts(ah);
++      }
+ }
+ EXPORT_SYMBOL(ath9k_hw_gen_timer_stop);
+@@ -3131,32 +3107,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_common *common = ath9k_hw_common(ah);
+-      u32 trigger_mask, thresh_mask, index;
++      unsigned long trigger_mask, thresh_mask;
++      unsigned int index;
+       /* get hardware generic timer interrupt status */
+       trigger_mask = ah->intr_gen_timer_trigger;
+       thresh_mask = ah->intr_gen_timer_thresh;
+-      trigger_mask &= timer_table->timer_mask.val;
+-      thresh_mask &= timer_table->timer_mask.val;
++      trigger_mask &= timer_table->timer_mask;
++      thresh_mask &= timer_table->timer_mask;
+       trigger_mask &= ~thresh_mask;
+-      while (thresh_mask) {
+-              index = rightmost_index(timer_table, &thresh_mask);
++      for_each_set_bit(index, &thresh_mask, ARRAY_SIZE(timer_table->timers)) {
+               timer = timer_table->timers[index];
+-              BUG_ON(!timer);
+-              ath_dbg(common, BTCOEX, "TSF overflow for Gen timer %d\n",
+-                      index);
++              if (!timer)
++                  continue;
++              if (!timer->overflow)
++                  continue;
+               timer->overflow(timer->arg);
+       }
+-      while (trigger_mask) {
+-              index = rightmost_index(timer_table, &trigger_mask);
++      for_each_set_bit(index, &trigger_mask, ARRAY_SIZE(timer_table->timers)) {
+               timer = timer_table->timers[index];
+-              BUG_ON(!timer);
+-              ath_dbg(common, BTCOEX,
+-                      "Gen timer[%d] trigger\n", index);
++              if (!timer)
++                  continue;
++              if (!timer->trigger)
++                  continue;
+               timer->trigger(timer->arg);
+       }
+ }
 --- a/drivers/net/wireless/ath/ath9k/hw.h
 +++ b/drivers/net/wireless/ath/ath9k/hw.h
-@@ -283,7 +283,6 @@ struct ath9k_ops_config {
-       int additional_swba_backoff;
+@@ -168,7 +168,7 @@
+ #define CAB_TIMEOUT_VAL             10
+ #define BEACON_TIMEOUT_VAL          10
+ #define MIN_BEACON_TIMEOUT_VAL      1
+-#define SLEEP_SLOP                  3
++#define SLEEP_SLOP                  TU_TO_USEC(3)
+ #define INIT_CONFIG_STATUS          0x00000000
+ #define INIT_RSSI_THR               0x00000700
+@@ -280,11 +280,8 @@ struct ath9k_hw_capabilities {
+ struct ath9k_ops_config {
+       int dma_beacon_response_time;
+       int sw_beacon_response_time;
+-      int additional_swba_backoff;
        int ack_6mb;
        u32 cwm_ignore_extcca;
 -      bool pcieSerDesWrite;
-       u8 pcie_clock_req;
+-      u8 pcie_clock_req;
        u32 pcie_waen;
        u8 analog_shiftreg;
-@@ -316,6 +315,8 @@ struct ath9k_ops_config {
+       u32 ofdm_trig_low;
+@@ -295,18 +292,11 @@ struct ath9k_ops_config {
+       int serialize_regmode;
+       bool rx_intr_mitigation;
+       bool tx_intr_mitigation;
+-#define SPUR_DISABLE          0
+-#define SPUR_ENABLE_IOCTL     1
+-#define SPUR_ENABLE_EEPROM    2
+-#define AR_SPUR_5413_1        1640
+-#define AR_SPUR_5413_2        1200
+ #define AR_NO_SPUR            0x8000
+ #define AR_BASE_FREQ_2GHZ     2300
+ #define AR_BASE_FREQ_5GHZ     4900
+ #define AR_SPUR_FEEQ_BOUND_HT40 19
+ #define AR_SPUR_FEEQ_BOUND_HT20 10
+-      int spurmode;
+-      u16 spurchans[AR_EEPROM_MODAL_SPURS][2];
+       u8 max_txtrig_level;
+       u16 ani_poll_interval; /* ANI poll interval in ms */
+@@ -316,6 +306,8 @@ struct ath9k_ops_config {
        u32 ant_ctrl_comm2g_switch_enable;
        bool xatten_margin_cfg;
        bool alt_mingainidx;
  };
  
  enum ath9k_int {
-@@ -864,6 +865,7 @@ struct ath_hw {
+@@ -459,10 +451,6 @@ struct ath9k_beacon_state {
+       u32 bs_intval;
+ #define ATH9K_TSFOOR_THRESHOLD    0x00004240 /* 16k us */
+       u32 bs_dtimperiod;
+-      u16 bs_cfpperiod;
+-      u16 bs_cfpmaxduration;
+-      u32 bs_cfpnext;
+-      u16 bs_timoffset;
+       u16 bs_bmissthreshold;
+       u32 bs_sleepduration;
+       u32 bs_tsfoor_threshold;
+@@ -498,12 +486,6 @@ struct ath9k_hw_version {
+ #define AR_GENTMR_BIT(_index) (1 << (_index))
+-/*
+- * Using de Bruijin sequence to look up 1's index in a 32 bit number
+- * debruijn32 = 0000 0111 0111 1100 1011 0101 0011 0001
+- */
+-#define debruijn32 0x077CB531U
+-
+ struct ath_gen_timer_configuration {
+       u32 next_addr;
+       u32 period_addr;
+@@ -519,12 +501,8 @@ struct ath_gen_timer {
+ };
+ struct ath_gen_timer_table {
+-      u32 gen_timer_index[32];
+       struct ath_gen_timer *timers[ATH_MAX_GEN_TIMER];
+-      union {
+-              unsigned long timer_bits;
+-              u16 val;
+-      } timer_mask;
++      u16 timer_mask;
+ };
+ struct ath_hw_antcomb_conf {
+@@ -785,7 +763,6 @@ struct ath_hw {
+       u32 txurn_interrupt_mask;
+       atomic_t intr_ref_cnt;
+       bool chip_fullsleep;
+-      u32 atim_window;
+       u32 modes_index;
+       /* Calibration */
+@@ -864,6 +841,7 @@ struct ath_hw {
        u32 gpio_mask;
        u32 gpio_val;
  
        struct ar5416IniArray iniModes;
        struct ar5416IniArray iniCommon;
        struct ar5416IniArray iniBB_RfGain;
-@@ -920,7 +922,7 @@ struct ath_hw {
+@@ -920,7 +898,7 @@ struct ath_hw {
        /* Enterprise mode cap */
        u32 ent_mode;
  
        u32 wow_event_mask;
  #endif
        bool is_clk_25mhz;
-@@ -1126,7 +1128,7 @@ ath9k_hw_get_btcoex_scheme(struct ath_hw
+@@ -1126,7 +1104,7 @@ ath9k_hw_get_btcoex_scheme(struct ath_hw
  #endif /* CPTCFG_ATH9K_BTCOEX_SUPPORT */
  
  
  {
        ieee80211_queue_delayed_work(sc->hw, &sc->tx_complete_work, 0);
  
-@@ -487,6 +504,8 @@ void ath9k_tasklet(unsigned long data)
+@@ -487,8 +504,13 @@ void ath9k_tasklet(unsigned long data)
                        ath_tx_edma_tasklet(sc);
                else
                        ath_tx_tasklet(sc);
 +              wake_up(&sc->tx_wait);
        }
  
++      if (status & ATH9K_INT_GENTIMER)
++              ath_gen_timer_isr(sc->sc_ah);
++
        ath9k_btcoex_handle_interrupt(sc, status);
-@@ -579,7 +598,8 @@ irqreturn_t ath_isr(int irq, void *dev)
+       /* re-enable hardware interrupt */
+@@ -579,7 +601,8 @@ irqreturn_t ath_isr(int irq, void *dev)
  
                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");
-@@ -588,6 +608,8 @@ irqreturn_t ath_isr(int irq, void *dev)
+@@ -588,6 +611,8 @@ irqreturn_t ath_isr(int irq, void *dev)
                }
        }
  #endif
        if (status & ATH9K_INT_SWBA)
                tasklet_schedule(&sc->bcon_tasklet);
  
-@@ -627,7 +649,7 @@ chip_reset:
+@@ -627,7 +652,7 @@ chip_reset:
  #undef SCHED_INTR
  }
  
  {
        int r;
  
-@@ -1817,13 +1839,31 @@ static void ath9k_set_coverage_class(str
+@@ -735,6 +760,8 @@ static int ath9k_start(struct ieee80211_
+        */
+       ath9k_cmn_init_crypto(sc->sc_ah);
++      ath9k_hw_reset_tsf(ah);
++
+       spin_unlock_bh(&sc->sc_pcu_lock);
+       mutex_unlock(&sc->mutex);
+@@ -1817,13 +1844,31 @@ static void ath9k_set_coverage_class(str
        mutex_unlock(&sc->mutex);
  }
  
        bool drain_txq;
  
        mutex_lock(&sc->mutex);
-@@ -1841,25 +1881,9 @@ static void ath9k_flush(struct ieee80211
+@@ -1841,25 +1886,9 @@ static void ath9k_flush(struct ieee80211
                return;
        }
  
  
        if (drop) {
                ath9k_ps_wakeup(sc);
-@@ -2021,333 +2045,6 @@ static int ath9k_get_antenna(struct ieee
+@@ -2021,333 +2050,6 @@ static int ath9k_get_antenna(struct ieee
        return 0;
  }
  
  static void ath9k_sw_scan_start(struct ieee80211_hw *hw)
  {
        struct ath_softc *sc = hw->priv;
-@@ -2373,134 +2070,6 @@ static void ath9k_channel_switch_beacon(
+@@ -2373,134 +2075,6 @@ static void ath9k_channel_switch_beacon(
        sc->csa_vif = vif;
  }
  
  struct ieee80211_ops ath9k_ops = {
        .tx                 = ath9k_tx,
        .start              = ath9k_start,
-@@ -2531,7 +2100,7 @@ struct ieee80211_ops ath9k_ops = {
+@@ -2531,7 +2105,7 @@ struct ieee80211_ops ath9k_ops = {
        .set_antenna        = ath9k_set_antenna,
        .get_antenna        = ath9k_get_antenna,
  
        }
  
        if (sync_cause) {
+--- 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 
+       struct ath_ant_comb *antcomb = &sc->ant_comb;
+       int alt_ratio = 0, alt_rssi_avg = 0, main_rssi_avg = 0, curr_alt_set;
+       int curr_main_set;
+-      int main_rssi = rs->rs_rssi_ctl0;
+-      int alt_rssi = rs->rs_rssi_ctl1;
++      int main_rssi = rs->rs_rssi_ctl[0];
++      int alt_rssi = rs->rs_rssi_ctl[1];
+       int rx_ant_conf,  main_ant_conf;
+       bool short_scan = false, ret;
+-      rx_ant_conf = (rs->rs_rssi_ctl2 >> ATH_ANT_RX_CURRENT_SHIFT) &
++      rx_ant_conf = (rs->rs_rssi_ctl[2] >> ATH_ANT_RX_CURRENT_SHIFT) &
+                      ATH_ANT_RX_MASK;
+-      main_ant_conf = (rs->rs_rssi_ctl2 >> ATH_ANT_RX_MAIN_SHIFT) &
++      main_ant_conf = (rs->rs_rssi_ctl[2] >> ATH_ANT_RX_MAIN_SHIFT) &
+                        ATH_ANT_RX_MASK;
+       if (alt_rssi >= antcomb->low_rssi_thresh) {
+--- a/drivers/net/wireless/ath/ath9k/ar9002_hw.c
++++ b/drivers/net/wireless/ath/ath9k/ar9002_hw.c
+@@ -32,12 +32,8 @@ static int ar9002_hw_init_mode_regs(stru
+               return 0;
+       }
+-      if (ah->config.pcie_clock_req)
+-              INIT_INI_ARRAY(&ah->iniPcieSerdes,
+-                         ar9280PciePhy_clkreq_off_L1_9280);
+-      else
+-              INIT_INI_ARRAY(&ah->iniPcieSerdes,
+-                         ar9280PciePhy_clkreq_always_on_L1_9280);
++      INIT_INI_ARRAY(&ah->iniPcieSerdes,
++                     ar9280PciePhy_clkreq_always_on_L1_9280);
+       if (AR_SREV_9287_11_OR_LATER(ah)) {
+               INIT_INI_ARRAY(&ah->iniModes, ar9287Modes_9287_1_1);
+--- a/drivers/net/wireless/ath/ath9k/ar9002_phy.c
++++ b/drivers/net/wireless/ath/ath9k/ar9002_phy.c
+@@ -201,7 +201,6 @@ static void ar9002_hw_spur_mitigate(stru
+       ath9k_hw_get_channel_centers(ah, chan, &centers);
+       freq = centers.synth_center;
+-      ah->config.spurmode = SPUR_ENABLE_EEPROM;
+       for (i = 0; i < AR_EEPROM_MODAL_SPURS; i++) {
+               cur_bb_spur = ah->eep_ops->get_spur_channel(ah, i, is2GHz);
+--- 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 
+       /* XXX: Keycache */
+       rxs->rs_rssi = MS(rxsp->status5, AR_RxRSSICombined);
+-      rxs->rs_rssi_ctl0 = MS(rxsp->status1, AR_RxRSSIAnt00);
+-      rxs->rs_rssi_ctl1 = MS(rxsp->status1, AR_RxRSSIAnt01);
+-      rxs->rs_rssi_ctl2 = MS(rxsp->status1, AR_RxRSSIAnt02);
+-      rxs->rs_rssi_ext0 = MS(rxsp->status5, AR_RxRSSIAnt10);
+-      rxs->rs_rssi_ext1 = MS(rxsp->status5, AR_RxRSSIAnt11);
+-      rxs->rs_rssi_ext2 = MS(rxsp->status5, AR_RxRSSIAnt12);
++      rxs->rs_rssi_ctl[0] = MS(rxsp->status1, AR_RxRSSIAnt00);
++      rxs->rs_rssi_ctl[1] = MS(rxsp->status1, AR_RxRSSIAnt01);
++      rxs->rs_rssi_ctl[2] = MS(rxsp->status1, AR_RxRSSIAnt02);
++      rxs->rs_rssi_ext[0] = MS(rxsp->status5, AR_RxRSSIAnt10);
++      rxs->rs_rssi_ext[1] = MS(rxsp->status5, AR_RxRSSIAnt11);
++      rxs->rs_rssi_ext[2] = MS(rxsp->status5, AR_RxRSSIAnt12);
+       if (rxsp->status11 & AR_RxKeyIdxValid)
+               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
+       ath9k_hw_enable_interrupts(ah);
+ }
++/* Calculate the modulo of a 64 bit TSF snapshot with a TU divisor */
++static u32 ath9k_mod_tsf64_tu(u64 tsf, u32 div_tu)
++{
++      u32 tsf_mod, tsf_hi, tsf_lo, mod_hi, mod_lo;
++
++      tsf_mod = tsf & (BIT(10) - 1);
++      tsf_hi = tsf >> 32;
++      tsf_lo = ((u32) tsf) >> 10;
++
++      mod_hi = tsf_hi % div_tu;
++      mod_lo = ((mod_hi << 22) + tsf_lo) % div_tu;
++
++      return (mod_lo << 10) | tsf_mod;
++}
++
++static u32 ath9k_get_next_tbtt(struct ath_softc *sc, u64 tsf,
++                             unsigned int interval)
++{
++      struct ath_hw *ah = sc->sc_ah;
++      unsigned int offset;
++
++      tsf += TU_TO_USEC(FUDGE + ah->config.sw_beacon_response_time);
++      offset = ath9k_mod_tsf64_tu(tsf, interval);
++
++      return (u32) tsf + TU_TO_USEC(interval) - offset;
++}
++
+ /*
+  * 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
+       /* NB: the beacon interval is kept internally in TU's */
+       intval = TU_TO_USEC(conf->beacon_interval);
+       intval /= ATH_BCBUF;
+-      nexttbtt = intval;
++      nexttbtt = ath9k_get_next_tbtt(sc, ath9k_hw_gettsf64(ah),
++                                     conf->beacon_interval);
+       if (conf->enable_beacon)
+               ah->imask |= ATH9K_INT_SWBA;
+@@ -458,7 +486,7 @@ static void ath9k_beacon_config_ap(struc
+               (conf->enable_beacon) ? "Enable" : "Disable",
+               nexttbtt, intval, conf->beacon_interval);
+-      ath9k_beacon_init(sc, nexttbtt, intval, true);
++      ath9k_beacon_init(sc, nexttbtt, intval, false);
+ }
+ /*
+@@ -475,11 +503,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;
+-      int dtimperiod, dtimcount, sleepduration;
+-      int cfpperiod, cfpcount;
+-      u32 nexttbtt = 0, intval, tsftu;
++      int dtim_intval, sleepduration;
++      u32 nexttbtt = 0, intval;
+       u64 tsf;
+-      int num_beacons, offset, dtim_dec_count, cfp_dec_count;
+       /* 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
+       intval = conf->beacon_interval;
+       /*
+-       * Setup dtim and cfp parameters according to
++       * Setup dtim parameters according to
+        * last beacon we received (which may be none).
+        */
+-      dtimperiod = conf->dtim_period;
+-      dtimcount = conf->dtim_count;
+-      if (dtimcount >= dtimperiod)    /* NB: sanity check */
+-              dtimcount = 0;
+-      cfpperiod = 1;                  /* NB: no PCF support yet */
+-      cfpcount = 0;
+-
++      dtim_intval = intval * conf->dtim_period;
+       sleepduration = conf->listen_interval * intval;
+       /*
+        * Pull nexttbtt forward to reflect the current
+-       * TSF and calculate dtim+cfp state for the result.
++       * TSF and calculate dtim state for the result.
+        */
+       tsf = ath9k_hw_gettsf64(ah);
+-      tsftu = TSF_TO_TU(tsf>>32, tsf) + FUDGE;
+-
+-      num_beacons = tsftu / intval + 1;
+-      offset = tsftu % intval;
+-      nexttbtt = tsftu - offset;
+-      if (offset)
+-              nexttbtt += intval;
+-
+-      /* DTIM Beacon every dtimperiod Beacon */
+-      dtim_dec_count = num_beacons % dtimperiod;
+-      /* CFP every cfpperiod DTIM Beacon */
+-      cfp_dec_count = (num_beacons / dtimperiod) % cfpperiod;
+-      if (dtim_dec_count)
+-              cfp_dec_count++;
+-
+-      dtimcount -= dtim_dec_count;
+-      if (dtimcount < 0)
+-              dtimcount += dtimperiod;
+-
+-      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_nexttbtt = nexttbtt;
+-      bs.bs_dtimperiod = dtimperiod*intval;
+-      bs.bs_nextdtim = bs.bs_nexttbtt + dtimcount*intval;
+-      bs.bs_cfpperiod = cfpperiod*bs.bs_dtimperiod;
+-      bs.bs_cfpnext = bs.bs_nextdtim + cfpcount*bs.bs_dtimperiod;
+-      bs.bs_cfpmaxduration = 0;
++      bs.bs_nextdtim = nexttbtt;
++      if (conf->dtim_period > 1)
++              bs.bs_nextdtim = ath9k_get_next_tbtt(sc, tsf, dtim_intval);
+       /*
+        * Calculate the number of consecutive beacons to miss* before taking
+@@ -566,18 +564,16 @@ static void ath9k_beacon_config_sta(stru
+        * XXX fixed at 100ms
+        */
+-      bs.bs_sleepduration = roundup(IEEE80211_MS_TO_TU(100), sleepduration);
++      bs.bs_sleepduration = TU_TO_USEC(roundup(IEEE80211_MS_TO_TU(100),
++                                               sleepduration));
+       if (bs.bs_sleepduration > bs.bs_dtimperiod)
+               bs.bs_sleepduration = bs.bs_dtimperiod;
+       /* TSF out of range threshold fixed at 1 second */
+       bs.bs_tsfoor_threshold = ATH9K_TSFOOR_THRESHOLD;
+-      ath_dbg(common, BEACON, "tsf: %llu tsftu: %u\n", tsf, tsftu);
+-      ath_dbg(common, BEACON,
+-              "bmiss: %u sleep: %u cfp-period: %u maxdur: %u next: %u\n",
+-              bs.bs_bmissthreshold, bs.bs_sleepduration,
+-              bs.bs_cfpperiod, bs.bs_cfpmaxduration, bs.bs_cfpnext);
++      ath_dbg(common, BEACON, "bmiss: %u sleep: %u\n",
++              bs.bs_bmissthreshold, bs.bs_sleepduration);
+       /* Set the computed STA beacon timers */
+@@ -600,25 +596,11 @@ static void ath9k_beacon_config_adhoc(st
+       intval = TU_TO_USEC(conf->beacon_interval);
+-      if (conf->ibss_creator) {
++      if (conf->ibss_creator)
+               nexttbtt = intval;
+-      } else {
+-              u32 tbtt, offset, tsftu;
+-              u64 tsf;
+-
+-              /*
+-               * Pull nexttbtt forward to reflect the current
+-               * sync'd TSF.
+-               */
+-              tsf = ath9k_hw_gettsf64(ah);
+-              tsftu = TSF_TO_TU(tsf >> 32, tsf) + FUDGE;
+-              offset = tsftu % conf->beacon_interval;
+-              tbtt = tsftu - offset;
+-              if (offset)
+-                      tbtt += conf->beacon_interval;
+-
+-              nexttbtt = TU_TO_USEC(tbtt);
+-      }
++      else
++              nexttbtt = ath9k_get_next_tbtt(sc, ath9k_hw_gettsf64(ah),
++                                             conf->beacon_interval);
+       if (conf->enable_beacon)
+               ah->imask |= ATH9K_INT_SWBA;
+--- 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_
+               .bt_first_slot_time = 5,
+               .bt_hold_rx_clear = true,
+       };
+-      u32 i, idx;
+       bool rxclear_polarity = ath_bt_config.bt_rxclear_polarity;
+       if (AR_SREV_9300_20_OR_LATER(ah))
+@@ -88,11 +87,6 @@ void ath9k_hw_init_btcoex_hw(struct ath_
+               SM(ath_bt_config.bt_hold_rx_clear, AR_BT_HOLD_RX_CLEAR) |
+               SM(ATH_BTCOEX_BMISS_THRESH, AR_BT_BCN_MISS_THRESH) |
+               AR_BT_DISABLE_BT_ANT;
+-
+-      for (i = 0; i < 32; i++) {
+-              idx = (debruijn32 << i) >> 27;
+-              ah->hw_gen_timers.gen_timer_index[idx] = i;
+-      }
+ }
+ EXPORT_SYMBOL(ath9k_hw_init_btcoex_hw);
+--- a/drivers/net/wireless/ath/ath9k/dfs.c
++++ b/drivers/net/wireless/ath/ath9k/dfs.c
+@@ -158,8 +158,8 @@ void ath9k_dfs_process_phyerr(struct ath
+               return;
+       }
+-      ard.rssi = rs->rs_rssi_ctl0;
+-      ard.ext_rssi = rs->rs_rssi_ext0;
++      ard.rssi = rs->rs_rssi_ctl[0];
++      ard.ext_rssi = rs->rs_rssi_ext[0];
+       /*
+        * hardware stores this as 8 bit signed value.
+--- a/drivers/net/wireless/ath/ath9k/eeprom_4k.c
++++ b/drivers/net/wireless/ath/ath9k/eeprom_4k.c
+@@ -1085,31 +1085,7 @@ static void ath9k_hw_4k_set_board_values
+ static u16 ath9k_hw_4k_get_spur_channel(struct ath_hw *ah, u16 i, bool is2GHz)
+ {
+-#define EEP_MAP4K_SPURCHAN \
+-      (ah->eeprom.map4k.modalHeader.spurChans[i].spurChan)
+-      struct ath_common *common = ath9k_hw_common(ah);
+-
+-      u16 spur_val = AR_NO_SPUR;
+-
+-      ath_dbg(common, ANI, "Getting spur idx:%d is2Ghz:%d val:%x\n",
+-              i, is2GHz, ah->config.spurchans[i][is2GHz]);
+-
+-      switch (ah->config.spurmode) {
+-      case SPUR_DISABLE:
+-              break;
+-      case SPUR_ENABLE_IOCTL:
+-              spur_val = ah->config.spurchans[i][is2GHz];
+-              ath_dbg(common, ANI, "Getting spur val from new loc. %d\n",
+-                      spur_val);
+-              break;
+-      case SPUR_ENABLE_EEPROM:
+-              spur_val = EEP_MAP4K_SPURCHAN;
+-              break;
+-      }
+-
+-      return spur_val;
+-
+-#undef EEP_MAP4K_SPURCHAN
++      return ah->eeprom.map4k.modalHeader.spurChans[i].spurChan;
+ }
+ const struct eeprom_ops eep_4k_ops = {
+--- a/drivers/net/wireless/ath/ath9k/eeprom_9287.c
++++ b/drivers/net/wireless/ath/ath9k/eeprom_9287.c
+@@ -1004,31 +1004,7 @@ static void ath9k_hw_ar9287_set_board_va
+ static u16 ath9k_hw_ar9287_get_spur_channel(struct ath_hw *ah,
+                                           u16 i, bool is2GHz)
+ {
+-#define EEP_MAP9287_SPURCHAN \
+-      (ah->eeprom.map9287.modalHeader.spurChans[i].spurChan)
+-
+-      struct ath_common *common = ath9k_hw_common(ah);
+-      u16 spur_val = AR_NO_SPUR;
+-
+-      ath_dbg(common, ANI, "Getting spur idx:%d is2Ghz:%d val:%x\n",
+-              i, is2GHz, ah->config.spurchans[i][is2GHz]);
+-
+-      switch (ah->config.spurmode) {
+-      case SPUR_DISABLE:
+-              break;
+-      case SPUR_ENABLE_IOCTL:
+-              spur_val = ah->config.spurchans[i][is2GHz];
+-              ath_dbg(common, ANI, "Getting spur val from new loc. %d\n",
+-                      spur_val);
+-              break;
+-      case SPUR_ENABLE_EEPROM:
+-              spur_val = EEP_MAP9287_SPURCHAN;
+-              break;
+-      }
+-
+-      return spur_val;
+-
+-#undef EEP_MAP9287_SPURCHAN
++      return ah->eeprom.map9287.modalHeader.spurChans[i].spurChan;
+ }
+ const struct eeprom_ops eep_ar9287_ops = {
+--- a/drivers/net/wireless/ath/ath9k/eeprom_def.c
++++ b/drivers/net/wireless/ath/ath9k/eeprom_def.c
+@@ -1348,31 +1348,7 @@ static void ath9k_hw_def_set_txpower(str
+ static u16 ath9k_hw_def_get_spur_channel(struct ath_hw *ah, u16 i, bool is2GHz)
+ {
+-#define EEP_DEF_SPURCHAN \
+-      (ah->eeprom.def.modalHeader[is2GHz].spurChans[i].spurChan)
+-      struct ath_common *common = ath9k_hw_common(ah);
+-
+-      u16 spur_val = AR_NO_SPUR;
+-
+-      ath_dbg(common, ANI, "Getting spur idx:%d is2Ghz:%d val:%x\n",
+-              i, is2GHz, ah->config.spurchans[i][is2GHz]);
+-
+-      switch (ah->config.spurmode) {
+-      case SPUR_DISABLE:
+-              break;
+-      case SPUR_ENABLE_IOCTL:
+-              spur_val = ah->config.spurchans[i][is2GHz];
+-              ath_dbg(common, ANI, "Getting spur val from new loc. %d\n",
+-                      spur_val);
+-              break;
+-      case SPUR_ENABLE_EEPROM:
+-              spur_val = EEP_DEF_SPURCHAN;
+-              break;
+-      }
+-
+-      return spur_val;
+-
+-#undef EEP_DEF_SPURCHAN
++      return ah->eeprom.def.modalHeader[is2GHz].spurChans[i].spurChan;
+ }
+ const struct eeprom_ops eep_def_ops = {
+--- a/drivers/net/wireless/ath/ath9k/gpio.c
++++ b/drivers/net/wireless/ath/ath9k/gpio.c
+@@ -157,36 +157,6 @@ static void ath_detect_bt_priority(struc
+       }
+ }
+-static void ath9k_gen_timer_start(struct ath_hw *ah,
+-                                struct ath_gen_timer *timer,
+-                                u32 trig_timeout,
+-                                u32 timer_period)
+-{
+-      ath9k_hw_gen_timer_start(ah, timer, trig_timeout, timer_period);
+-
+-      if ((ah->imask & ATH9K_INT_GENTIMER) == 0) {
+-              ath9k_hw_disable_interrupts(ah);
+-              ah->imask |= ATH9K_INT_GENTIMER;
+-              ath9k_hw_set_interrupts(ah);
+-              ath9k_hw_enable_interrupts(ah);
+-      }
+-}
+-
+-static void ath9k_gen_timer_stop(struct ath_hw *ah, struct ath_gen_timer *timer)
+-{
+-      struct ath_gen_timer_table *timer_table = &ah->hw_gen_timers;
+-
+-      ath9k_hw_gen_timer_stop(ah, timer);
+-
+-      /* if no timer is enabled, turn off interrupt mask */
+-      if (timer_table->timer_mask.val == 0) {
+-              ath9k_hw_disable_interrupts(ah);
+-              ah->imask &= ~ATH9K_INT_GENTIMER;
+-              ath9k_hw_set_interrupts(ah);
+-              ath9k_hw_enable_interrupts(ah);
+-      }
+-}
+-
+ static void ath_mci_ftp_adjust(struct ath_softc *sc)
+ {
+       struct ath_btcoex *btcoex = &sc->btcoex;
+@@ -257,19 +227,9 @@ static void ath_btcoex_period_timer(unsi
+       spin_unlock_bh(&btcoex->btcoex_lock);
+-      /*
+-       * btcoex_period is in msec while (btocex/btscan_)no_stomp are in usec,
+-       * ensure that we properly convert btcoex_period to usec
+-       * for any comparision with (btcoex/btscan_)no_stomp.
+-       */
+-      if (btcoex->btcoex_period * 1000 != btcoex->btcoex_no_stomp) {
+-              if (btcoex->hw_timer_enabled)
+-                      ath9k_gen_timer_stop(ah, btcoex->no_stomp_timer);
+-
+-              ath9k_gen_timer_start(ah, btcoex->no_stomp_timer, timer_period,
+-                                    timer_period * 10);
+-              btcoex->hw_timer_enabled = true;
+-      }
++      if (btcoex->btcoex_period != btcoex->btcoex_no_stomp)
++              mod_timer(&btcoex->no_stomp_timer,
++                       jiffies + msecs_to_jiffies(timer_period));
+       ath9k_ps_restore(sc);
+@@ -282,7 +242,7 @@ skip_hw_wakeup:
+  * Generic tsf based hw timer which configures weight
+  * registers to time slice between wlan and bt traffic
+  */
+-static void ath_btcoex_no_stomp_timer(void *arg)
++static void ath_btcoex_no_stomp_timer(unsigned long arg)
+ {
+       struct ath_softc *sc = (struct ath_softc *)arg;
+       struct ath_hw *ah = sc->sc_ah;
+@@ -311,24 +271,18 @@ static int ath_init_btcoex_timer(struct 
+       struct ath_btcoex *btcoex = &sc->btcoex;
+       btcoex->btcoex_period = ATH_BTCOEX_DEF_BT_PERIOD;
+-      btcoex->btcoex_no_stomp = (100 - ATH_BTCOEX_DEF_DUTY_CYCLE) * 1000 *
++      btcoex->btcoex_no_stomp = (100 - ATH_BTCOEX_DEF_DUTY_CYCLE) *
+               btcoex->btcoex_period / 100;
+-      btcoex->btscan_no_stomp = (100 - ATH_BTCOEX_BTSCAN_DUTY_CYCLE) * 1000 *
++      btcoex->btscan_no_stomp = (100 - ATH_BTCOEX_BTSCAN_DUTY_CYCLE) *
+                                  btcoex->btcoex_period / 100;
+       setup_timer(&btcoex->period_timer, ath_btcoex_period_timer,
+                       (unsigned long) sc);
++      setup_timer(&btcoex->no_stomp_timer, ath_btcoex_no_stomp_timer,
++                      (unsigned long) sc);
+       spin_lock_init(&btcoex->btcoex_lock);
+-      btcoex->no_stomp_timer = ath_gen_timer_alloc(sc->sc_ah,
+-                      ath_btcoex_no_stomp_timer,
+-                      ath_btcoex_no_stomp_timer,
+-                      (void *) sc, AR_FIRST_NDP_TIMER);
+-
+-      if (!btcoex->no_stomp_timer)
+-              return -ENOMEM;
+-
+       return 0;
+ }
+@@ -343,10 +297,7 @@ void ath9k_btcoex_timer_resume(struct at
+       ath_dbg(ath9k_hw_common(ah), BTCOEX, "Starting btcoex timers\n");
+       /* make sure duty cycle timer is also stopped when resuming */
+-      if (btcoex->hw_timer_enabled) {
+-              ath9k_gen_timer_stop(sc->sc_ah, btcoex->no_stomp_timer);
+-              btcoex->hw_timer_enabled = false;
+-      }
++      del_timer_sync(&btcoex->no_stomp_timer);
+       btcoex->bt_priority_cnt = 0;
+       btcoex->bt_priority_time = jiffies;
+@@ -363,24 +314,16 @@ void ath9k_btcoex_timer_resume(struct at
+ void ath9k_btcoex_timer_pause(struct ath_softc *sc)
+ {
+       struct ath_btcoex *btcoex = &sc->btcoex;
+-      struct ath_hw *ah = sc->sc_ah;
+       del_timer_sync(&btcoex->period_timer);
+-
+-      if (btcoex->hw_timer_enabled) {
+-              ath9k_gen_timer_stop(ah, btcoex->no_stomp_timer);
+-              btcoex->hw_timer_enabled = false;
+-      }
++      del_timer_sync(&btcoex->no_stomp_timer);
+ }
+ void ath9k_btcoex_stop_gen_timer(struct ath_softc *sc)
+ {
+       struct ath_btcoex *btcoex = &sc->btcoex;
+-      if (btcoex->hw_timer_enabled) {
+-              ath9k_gen_timer_stop(sc->sc_ah, btcoex->no_stomp_timer);
+-              btcoex->hw_timer_enabled = false;
+-      }
++      del_timer_sync(&btcoex->no_stomp_timer);
+ }
+ u16 ath9k_btcoex_aggr_limit(struct ath_softc *sc, u32 max_4ms_framelen)
+@@ -400,12 +343,6 @@ u16 ath9k_btcoex_aggr_limit(struct ath_s
+ void ath9k_btcoex_handle_interrupt(struct ath_softc *sc, u32 status)
+ {
+-      struct ath_hw *ah = sc->sc_ah;
+-
+-      if (ath9k_hw_get_btcoex_scheme(ah) == ATH_BTCOEX_CFG_3WIRE)
+-              if (status & ATH9K_INT_GENTIMER)
+-                      ath_gen_timer_isr(sc->sc_ah);
+-
+       if (status & ATH9K_INT_MCI)
+               ath_mci_intr(sc);
+ }
+@@ -447,10 +384,6 @@ void ath9k_deinit_btcoex(struct ath_soft
+ {
+       struct ath_hw *ah = sc->sc_ah;
+-        if ((sc->btcoex.no_stomp_timer) &&
+-          ath9k_hw_get_btcoex_scheme(sc->sc_ah) == ATH_BTCOEX_CFG_3WIRE)
+-              ath_gen_timer_free(sc->sc_ah, sc->btcoex.no_stomp_timer);
+-
+       if (ath9k_hw_mci_is_enabled(ah))
+               ath_mci_cleanup(sc);
+ }
+--- a/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c
++++ b/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c
+@@ -70,11 +70,11 @@ static void ath9k_htc_beacon_config_sta(
+       struct ath9k_beacon_state bs;
+       enum ath9k_int imask = 0;
+       int dtimperiod, dtimcount, sleepduration;
+-      int cfpperiod, cfpcount, bmiss_timeout;
++      int bmiss_timeout;
+       u32 nexttbtt = 0, intval, tsftu;
+       __be32 htc_imask = 0;
+       u64 tsf;
+-      int num_beacons, offset, dtim_dec_count, cfp_dec_count;
++      int num_beacons, offset, dtim_dec_count;
+       int ret __attribute__ ((unused));
+       u8 cmd_rsp;
+@@ -84,7 +84,7 @@ static void ath9k_htc_beacon_config_sta(
+       bmiss_timeout = (ATH_DEFAULT_BMISS_LIMIT * bss_conf->beacon_interval);
+       /*
+-       * Setup dtim and cfp parameters according to
++       * Setup dtim parameters according to
+        * last beacon we received (which may be none).
+        */
+       dtimperiod = bss_conf->dtim_period;
+@@ -93,8 +93,6 @@ static void ath9k_htc_beacon_config_sta(
+       dtimcount = 1;
+       if (dtimcount >= dtimperiod)    /* NB: sanity check */
+               dtimcount = 0;
+-      cfpperiod = 1;                  /* NB: no PCF support yet */
+-      cfpcount = 0;
+       sleepduration = intval;
+       if (sleepduration <= 0)
+@@ -102,7 +100,7 @@ static void ath9k_htc_beacon_config_sta(
+       /*
+        * Pull nexttbtt forward to reflect the current
+-       * TSF and calculate dtim+cfp state for the result.
++       * TSF and calculate dtim state for the result.
+        */
+       tsf = ath9k_hw_gettsf64(priv->ah);
+       tsftu = TSF_TO_TU(tsf>>32, tsf) + FUDGE;
+@@ -115,26 +113,14 @@ static void ath9k_htc_beacon_config_sta(
+       /* DTIM Beacon every dtimperiod Beacon */
+       dtim_dec_count = num_beacons % dtimperiod;
+-      /* CFP every cfpperiod DTIM Beacon */
+-      cfp_dec_count = (num_beacons / dtimperiod) % cfpperiod;
+-      if (dtim_dec_count)
+-              cfp_dec_count++;
+-
+       dtimcount -= dtim_dec_count;
+       if (dtimcount < 0)
+               dtimcount += dtimperiod;
+-      cfpcount -= cfp_dec_count;
+-      if (cfpcount < 0)
+-              cfpcount += cfpperiod;
+-
+-      bs.bs_intval = intval;
+-      bs.bs_nexttbtt = nexttbtt;
+-      bs.bs_dtimperiod = dtimperiod*intval;
+-      bs.bs_nextdtim = bs.bs_nexttbtt + dtimcount*intval;
+-      bs.bs_cfpperiod = cfpperiod*bs.bs_dtimperiod;
+-      bs.bs_cfpnext = bs.bs_nextdtim + cfpcount*bs.bs_dtimperiod;
+-      bs.bs_cfpmaxduration = 0;
++      bs.bs_intval = TU_TO_USEC(intval);
++      bs.bs_nexttbtt = TU_TO_USEC(nexttbtt);
++      bs.bs_dtimperiod = dtimperiod * bs.bs_intval;
++      bs.bs_nextdtim = bs.bs_nexttbtt + dtimcount * bs.bs_intval;
+       /*
+        * Calculate the number of consecutive beacons to miss* before taking
+@@ -161,7 +147,8 @@ static void ath9k_htc_beacon_config_sta(
+        * XXX fixed at 100ms
+        */
+-      bs.bs_sleepduration = roundup(IEEE80211_MS_TO_TU(100), sleepduration);
++      bs.bs_sleepduration = TU_TO_USEC(roundup(IEEE80211_MS_TO_TU(100),
++                                               sleepduration));
+       if (bs.bs_sleepduration > bs.bs_dtimperiod)
+               bs.bs_sleepduration = bs.bs_dtimperiod;
+@@ -170,10 +157,8 @@ static void ath9k_htc_beacon_config_sta(
+       ath_dbg(common, CONFIG, "intval: %u tsf: %llu tsftu: %u\n",
+               intval, tsf, tsftu);
+-      ath_dbg(common, CONFIG,
+-              "bmiss: %u sleep: %u cfp-period: %u maxdur: %u next: %u\n",
+-              bs.bs_bmissthreshold, bs.bs_sleepduration,
+-              bs.bs_cfpperiod, bs.bs_cfpmaxduration, bs.bs_cfpnext);
++      ath_dbg(common, CONFIG, "bmiss: %u sleep: %u\n",
++              bs.bs_bmissthreshold, bs.bs_sleepduration);
+       /* Set the computed STA beacon timers */
+--- a/drivers/net/wireless/ath/ath9k/mac.c
++++ b/drivers/net/wireless/ath/ath9k/mac.c
+@@ -481,8 +481,7 @@ bool ath9k_hw_resettxqueue(struct ath_hw
+                           | AR_Q_MISC_CBR_INCR_DIS0);
+               value = (qi->tqi_readyTime -
+                        (ah->config.sw_beacon_response_time -
+-                        ah->config.dma_beacon_response_time) -
+-                       ah->config.additional_swba_backoff) * 1024;
++                        ah->config.dma_beacon_response_time)) * 1024;
+               REG_WRITE(ah, AR_QRDYTIMECFG(q),
+                         value | AR_Q_RDYTIMECFG_EN);
+               REG_SET_BIT(ah, AR_DMISC(q),
+@@ -550,25 +549,25 @@ int ath9k_hw_rxprocdesc(struct ath_hw *a
+       if (ads.ds_rxstatus8 & AR_PostDelimCRCErr) {
+               rs->rs_rssi = ATH9K_RSSI_BAD;
+-              rs->rs_rssi_ctl0 = ATH9K_RSSI_BAD;
+-              rs->rs_rssi_ctl1 = ATH9K_RSSI_BAD;
+-              rs->rs_rssi_ctl2 = ATH9K_RSSI_BAD;
+-              rs->rs_rssi_ext0 = ATH9K_RSSI_BAD;
+-              rs->rs_rssi_ext1 = ATH9K_RSSI_BAD;
+-              rs->rs_rssi_ext2 = ATH9K_RSSI_BAD;
++              rs->rs_rssi_ctl[0] = ATH9K_RSSI_BAD;
++              rs->rs_rssi_ctl[1] = ATH9K_RSSI_BAD;
++              rs->rs_rssi_ctl[2] = ATH9K_RSSI_BAD;
++              rs->rs_rssi_ext[0] = ATH9K_RSSI_BAD;
++              rs->rs_rssi_ext[1] = ATH9K_RSSI_BAD;
++              rs->rs_rssi_ext[2] = ATH9K_RSSI_BAD;
+       } else {
+               rs->rs_rssi = MS(ads.ds_rxstatus4, AR_RxRSSICombined);
+-              rs->rs_rssi_ctl0 = MS(ads.ds_rxstatus0,
++              rs->rs_rssi_ctl[0] = MS(ads.ds_rxstatus0,
+                                               AR_RxRSSIAnt00);
+-              rs->rs_rssi_ctl1 = MS(ads.ds_rxstatus0,
++              rs->rs_rssi_ctl[1] = MS(ads.ds_rxstatus0,
+                                               AR_RxRSSIAnt01);
+-              rs->rs_rssi_ctl2 = MS(ads.ds_rxstatus0,
++              rs->rs_rssi_ctl[2] = MS(ads.ds_rxstatus0,
+                                               AR_RxRSSIAnt02);
+-              rs->rs_rssi_ext0 = MS(ads.ds_rxstatus4,
++              rs->rs_rssi_ext[0] = MS(ads.ds_rxstatus4,
+                                               AR_RxRSSIAnt10);
+-              rs->rs_rssi_ext1 = MS(ads.ds_rxstatus4,
++              rs->rs_rssi_ext[1] = MS(ads.ds_rxstatus4,
+                                               AR_RxRSSIAnt11);
+-              rs->rs_rssi_ext2 = MS(ads.ds_rxstatus4,
++              rs->rs_rssi_ext[2] = MS(ads.ds_rxstatus4,
+                                               AR_RxRSSIAnt12);
+       }
+       if (ads.ds_rxstatus8 & AR_RxKeyIdxValid)
+--- a/drivers/net/wireless/ath/ath9k/mac.h
++++ b/drivers/net/wireless/ath/ath9k/mac.h
+@@ -133,12 +133,8 @@ struct ath_rx_status {
+       u8 rs_rate;
+       u8 rs_antenna;
+       u8 rs_more;
+-      int8_t rs_rssi_ctl0;
+-      int8_t rs_rssi_ctl1;
+-      int8_t rs_rssi_ctl2;
+-      int8_t rs_rssi_ext0;
+-      int8_t rs_rssi_ext1;
+-      int8_t rs_rssi_ext2;
++      int8_t rs_rssi_ctl[3];
++      int8_t rs_rssi_ext[3];
+       u8 rs_isaggr;
+       u8 rs_firstaggr;
+       u8 rs_moreaggr;
+--- a/drivers/net/wireless/ath/ath9k/mci.c
++++ b/drivers/net/wireless/ath/ath9k/mci.c
+@@ -200,7 +200,7 @@ skip_tuning:
+       if (btcoex->duty_cycle > ATH_MCI_MAX_DUTY_CYCLE)
+               btcoex->duty_cycle = ATH_MCI_MAX_DUTY_CYCLE;
+-      btcoex->btcoex_no_stomp =  btcoex->btcoex_period * 1000 *
++      btcoex->btcoex_no_stomp =  btcoex->btcoex_period *
+               (100 - btcoex->duty_cycle) / 100;
+       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
+       struct ath_hw *ah = common->ah;
+       int last_rssi;
+       int rssi = rx_stats->rs_rssi;
++      int i, j;
+       /*
+        * RSSI is not available for subframes in an A-MPDU.
+@@ -924,6 +925,20 @@ static void ath9k_process_rssi(struct at
+               return;
+       }
++      for (i = 0, j = 0; i < ARRAY_SIZE(rx_stats->rs_rssi_ctl); i++) {
++              s8 rssi;
++
++              if (!(ah->rxchainmask & BIT(i)))
++                      continue;
++
++              rssi = rx_stats->rs_rssi_ctl[i];
++              if (rssi != ATH9K_RSSI_BAD) {
++                  rxs->chains |= BIT(j);
++                  rxs->chain_signal[j] = ah->noise + rssi;
++              }
++              j++;
++      }
++
+       /*
+        * 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;
+               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_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_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;
+@@ -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);
+-              fft_sample_20.rssi = fix_rssi_inv_only(rs->rs_rssi_ctl0);
++              fft_sample_20.rssi = fix_rssi_inv_only(rs->rs_rssi_ctl[0]);
+               fft_sample_20.noise = ah->noise;
+               mag_info = ((struct ath_ht20_mag_info *)radar_info) - 1;
index c803c1a..e900349 100644 (file)
@@ -1,14 +1,14 @@
 --- a/drivers/net/wireless/ath/ath9k/hw.c
 +++ b/drivers/net/wireless/ath/ath9k/hw.c
-@@ -18,6 +18,7 @@
- #include <linux/slab.h>
+@@ -19,6 +19,7 @@
  #include <linux/module.h>
  #include <linux/time.h>
+ #include <linux/bitops.h>
 +#include <linux/etherdevice.h>
  #include <asm/unaligned.h>
  
  #include "hw.h"
-@@ -513,8 +514,16 @@ static int ath9k_hw_init_macaddr(struct 
+@@ -504,8 +505,16 @@ static int ath9k_hw_init_macaddr(struct 
                common->macaddr[2 * i] = eeval >> 8;
                common->macaddr[2 * i + 1] = eeval & 0xff;
        }
index eb7f73a..4eca75a 100644 (file)
@@ -71,7 +71,7 @@
  
 --- a/drivers/net/wireless/ath/ath9k/hw.h
 +++ b/drivers/net/wireless/ath/ath9k/hw.h
-@@ -729,6 +729,7 @@ enum ath_cal_list {
+@@ -706,6 +706,7 @@ enum ath_cal_list {
  #define AH_USE_EEPROM   0x1
  #define AH_UNPLUGGED    0x2 /* The card has been physically removed. */
  #define AH_FASTCC       0x4
index 7f61c5c..647bde2 100644 (file)
@@ -1,6 +1,6 @@
 --- a/drivers/net/wireless/ath/ath9k/hw.c
 +++ b/drivers/net/wireless/ath/ath9k/hw.c
-@@ -2019,8 +2019,8 @@ int ath9k_hw_reset(struct ath_hw *ah, st
+@@ -2010,8 +2010,8 @@ int ath9k_hw_reset(struct ath_hw *ah, st
                REG_WRITE(ah, AR_OBS, 8);
  
        if (ah->config.rx_intr_mitigation) {
index 5f8ea68..70a333c 100644 (file)
@@ -1,6 +1,6 @@
 --- a/drivers/net/wireless/ath/ath9k/hw.c
 +++ b/drivers/net/wireless/ath/ath9k/hw.c
-@@ -733,6 +733,7 @@ int ath9k_hw_init(struct ath_hw *ah)
+@@ -724,6 +724,7 @@ int ath9k_hw_init(struct ath_hw *ah)
        case AR9300_DEVID_AR9462:
        case AR9485_DEVID_AR1111:
        case AR9300_DEVID_AR9565:
index ab59411..8e0c562 100644 (file)
@@ -14,7 +14,7 @@
  
  out:
        spin_unlock_bh(&sc->sc_pcu_lock);
-@@ -1340,6 +1344,7 @@ static int ath9k_config(struct ieee80211
+@@ -1345,6 +1349,7 @@ static int ath9k_config(struct ieee80211
                sc->config.txpowlimit = 2 * conf->power_level;
                ath9k_cmn_update_txpow(ah, sc->curtxpow,
                                       sc->config.txpowlimit, &sc->curtxpow);
diff --git a/package/kernel/mac80211/patches/522-ath9k_per_chain_signal_strength.patch b/package/kernel/mac80211/patches/522-ath9k_per_chain_signal_strength.patch
deleted file mode 100644 (file)
index 94e0154..0000000
+++ /dev/null
@@ -1,171 +0,0 @@
---- a/drivers/net/wireless/ath/ath9k/mac.h
-+++ b/drivers/net/wireless/ath/ath9k/mac.h
-@@ -133,12 +133,8 @@ struct ath_rx_status {
-       u8 rs_rate;
-       u8 rs_antenna;
-       u8 rs_more;
--      int8_t rs_rssi_ctl0;
--      int8_t rs_rssi_ctl1;
--      int8_t rs_rssi_ctl2;
--      int8_t rs_rssi_ext0;
--      int8_t rs_rssi_ext1;
--      int8_t rs_rssi_ext2;
-+      int8_t rs_rssi_ctl[3];
-+      int8_t rs_rssi_ext[3];
-       u8 rs_isaggr;
-       u8 rs_firstaggr;
-       u8 rs_moreaggr;
---- 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
-       struct ath_hw *ah = common->ah;
-       int last_rssi;
-       int rssi = rx_stats->rs_rssi;
-+      int i, j;
-       /*
-        * RSSI is not available for subframes in an A-MPDU.
-@@ -924,6 +925,20 @@ static void ath9k_process_rssi(struct at
-               return;
-       }
-+      for (i = 0, j = 0; i < ARRAY_SIZE(rx_stats->rs_rssi_ctl); i++) {
-+              s8 rssi;
-+
-+              if (!(ah->rxchainmask & BIT(i)))
-+                      continue;
-+
-+              rssi = rx_stats->rs_rssi_ctl[i];
-+              if (rssi != ATH9K_RSSI_BAD) {
-+                  rxs->chains |= BIT(j);
-+                  rxs->chain_signal[j] = ah->noise + rssi;
-+              }
-+              j++;
-+      }
-+
-       /*
-        * 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;
-               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_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_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;
-@@ -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);
--              fft_sample_20.rssi = fix_rssi_inv_only(rs->rs_rssi_ctl0);
-+              fft_sample_20.rssi = fix_rssi_inv_only(rs->rs_rssi_ctl[0]);
-               fft_sample_20.noise = ah->noise;
-               mag_info = ((struct ath_ht20_mag_info *)radar_info) - 1;
---- 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 
-       /* XXX: Keycache */
-       rxs->rs_rssi = MS(rxsp->status5, AR_RxRSSICombined);
--      rxs->rs_rssi_ctl0 = MS(rxsp->status1, AR_RxRSSIAnt00);
--      rxs->rs_rssi_ctl1 = MS(rxsp->status1, AR_RxRSSIAnt01);
--      rxs->rs_rssi_ctl2 = MS(rxsp->status1, AR_RxRSSIAnt02);
--      rxs->rs_rssi_ext0 = MS(rxsp->status5, AR_RxRSSIAnt10);
--      rxs->rs_rssi_ext1 = MS(rxsp->status5, AR_RxRSSIAnt11);
--      rxs->rs_rssi_ext2 = MS(rxsp->status5, AR_RxRSSIAnt12);
-+      rxs->rs_rssi_ctl[0] = MS(rxsp->status1, AR_RxRSSIAnt00);
-+      rxs->rs_rssi_ctl[1] = MS(rxsp->status1, AR_RxRSSIAnt01);
-+      rxs->rs_rssi_ctl[2] = MS(rxsp->status1, AR_RxRSSIAnt02);
-+      rxs->rs_rssi_ext[0] = MS(rxsp->status5, AR_RxRSSIAnt10);
-+      rxs->rs_rssi_ext[1] = MS(rxsp->status5, AR_RxRSSIAnt11);
-+      rxs->rs_rssi_ext[2] = MS(rxsp->status5, AR_RxRSSIAnt12);
-       if (rxsp->status11 & AR_RxKeyIdxValid)
-               rxs->rs_keyix = MS(rxsp->status11, AR_KeyIdx);
---- a/drivers/net/wireless/ath/ath9k/mac.c
-+++ b/drivers/net/wireless/ath/ath9k/mac.c
-@@ -550,25 +550,25 @@ int ath9k_hw_rxprocdesc(struct ath_hw *a
-       if (ads.ds_rxstatus8 & AR_PostDelimCRCErr) {
-               rs->rs_rssi = ATH9K_RSSI_BAD;
--              rs->rs_rssi_ctl0 = ATH9K_RSSI_BAD;
--              rs->rs_rssi_ctl1 = ATH9K_RSSI_BAD;
--              rs->rs_rssi_ctl2 = ATH9K_RSSI_BAD;
--              rs->rs_rssi_ext0 = ATH9K_RSSI_BAD;
--              rs->rs_rssi_ext1 = ATH9K_RSSI_BAD;
--              rs->rs_rssi_ext2 = ATH9K_RSSI_BAD;
-+              rs->rs_rssi_ctl[0] = ATH9K_RSSI_BAD;
-+              rs->rs_rssi_ctl[1] = ATH9K_RSSI_BAD;
-+              rs->rs_rssi_ctl[2] = ATH9K_RSSI_BAD;
-+              rs->rs_rssi_ext[0] = ATH9K_RSSI_BAD;
-+              rs->rs_rssi_ext[1] = ATH9K_RSSI_BAD;
-+              rs->rs_rssi_ext[2] = ATH9K_RSSI_BAD;
-       } else {
-               rs->rs_rssi = MS(ads.ds_rxstatus4, AR_RxRSSICombined);
--              rs->rs_rssi_ctl0 = MS(ads.ds_rxstatus0,
-+              rs->rs_rssi_ctl[0] = MS(ads.ds_rxstatus0,
-                                               AR_RxRSSIAnt00);
--              rs->rs_rssi_ctl1 = MS(ads.ds_rxstatus0,
-+              rs->rs_rssi_ctl[1] = MS(ads.ds_rxstatus0,
-                                               AR_RxRSSIAnt01);
--              rs->rs_rssi_ctl2 = MS(ads.ds_rxstatus0,
-+              rs->rs_rssi_ctl[2] = MS(ads.ds_rxstatus0,
-                                               AR_RxRSSIAnt02);
--              rs->rs_rssi_ext0 = MS(ads.ds_rxstatus4,
-+              rs->rs_rssi_ext[0] = MS(ads.ds_rxstatus4,
-                                               AR_RxRSSIAnt10);
--              rs->rs_rssi_ext1 = MS(ads.ds_rxstatus4,
-+              rs->rs_rssi_ext[1] = MS(ads.ds_rxstatus4,
-                                               AR_RxRSSIAnt11);
--              rs->rs_rssi_ext2 = MS(ads.ds_rxstatus4,
-+              rs->rs_rssi_ext[2] = MS(ads.ds_rxstatus4,
-                                               AR_RxRSSIAnt12);
-       }
-       if (ads.ds_rxstatus8 & AR_RxKeyIdxValid)
---- a/drivers/net/wireless/ath/ath9k/dfs.c
-+++ b/drivers/net/wireless/ath/ath9k/dfs.c
-@@ -158,8 +158,8 @@ void ath9k_dfs_process_phyerr(struct ath
-               return;
-       }
--      ard.rssi = rs->rs_rssi_ctl0;
--      ard.ext_rssi = rs->rs_rssi_ext0;
-+      ard.rssi = rs->rs_rssi_ctl[0];
-+      ard.ext_rssi = rs->rs_rssi_ext[0];
-       /*
-        * hardware stores this as 8 bit signed value.
---- 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 
-       struct ath_ant_comb *antcomb = &sc->ant_comb;
-       int alt_ratio = 0, alt_rssi_avg = 0, main_rssi_avg = 0, curr_alt_set;
-       int curr_main_set;
--      int main_rssi = rs->rs_rssi_ctl0;
--      int alt_rssi = rs->rs_rssi_ctl1;
-+      int main_rssi = rs->rs_rssi_ctl[0];
-+      int alt_rssi = rs->rs_rssi_ctl[1];
-       int rx_ant_conf,  main_ant_conf;
-       bool short_scan = false, ret;
--      rx_ant_conf = (rs->rs_rssi_ctl2 >> ATH_ANT_RX_CURRENT_SHIFT) &
-+      rx_ant_conf = (rs->rs_rssi_ctl[2] >> ATH_ANT_RX_CURRENT_SHIFT) &
-                      ATH_ANT_RX_MASK;
--      main_ant_conf = (rs->rs_rssi_ctl2 >> ATH_ANT_RX_MAIN_SHIFT) &
-+      main_ant_conf = (rs->rs_rssi_ctl[2] >> ATH_ANT_RX_MAIN_SHIFT) &
-                        ATH_ANT_RX_MASK;
-       if (alt_rssi >= antcomb->low_rssi_thresh) {
diff --git a/package/kernel/mac80211/patches/522-mac80211_configure_antenna_gain.patch b/package/kernel/mac80211/patches/522-mac80211_configure_antenna_gain.patch
new file mode 100644 (file)
index 0000000..00265e9
--- /dev/null
@@ -0,0 +1,172 @@
+--- a/include/net/cfg80211.h
++++ b/include/net/cfg80211.h
+@@ -2081,6 +2081,7 @@ struct cfg80211_update_ft_ies_params {
+  *    (as advertised by the nl80211 feature flag.)
+  * @get_tx_power: store the current TX power into the dbm variable;
+  *    return 0 if successful
++ * @set_antenna_gain: set antenna gain to reduce maximum tx power if necessary
+  *
+  * @set_wds_peer: set the WDS peer for a WDS interface
+  *
+@@ -2303,6 +2304,7 @@ struct cfg80211_ops {
+                               enum nl80211_tx_power_setting type, int mbm);
+       int     (*get_tx_power)(struct wiphy *wiphy, struct wireless_dev *wdev,
+                               int *dbm);
++      int     (*set_antenna_gain)(struct wiphy *wiphy, int dbi);
+       int     (*set_wds_peer)(struct wiphy *wiphy, struct net_device *dev,
+                               const u8 *addr);
+--- a/include/net/mac80211.h
++++ b/include/net/mac80211.h
+@@ -1029,6 +1029,7 @@ enum ieee80211_smps_mode {
+  *
+  * @power_level: requested transmit power (in dBm), backward compatibility
+  *    value only that is set to the minimum of all interfaces
++ * @max_antenna_gain: maximum antenna gain adjusted by user config (in dBi)
+  *
+  * @chandef: the channel definition to tune to
+  * @radar_enabled: whether radar detection is enabled
+@@ -1050,6 +1051,7 @@ struct ieee80211_conf {
+       u32 flags;
+       int power_level, dynamic_ps_timeout;
+       int max_sleep_period;
++      int max_antenna_gain;
+       u16 listen_interval;
+       u8 ps_dtim_period;
+--- a/include/uapi/linux/nl80211.h
++++ b/include/uapi/linux/nl80211.h
+@@ -1514,6 +1514,9 @@ enum nl80211_commands {
+  * @NL80211_ATTR_SUPPORT_10_MHZ: A flag indicating that the device supports
+  *    10 MHz channel bandwidth.
+  *
++ * @NL80211_ATTR_WIPHY_ANTENNA_GAIN: Configured antenna gain. Used to reduce
++ *    transmit power to stay within regulatory limits. u32, dBi.
++ *
+  * @NL80211_ATTR_MAX: highest attribute number currently defined
+  * @__NL80211_ATTR_AFTER_LAST: internal use
+  */
+@@ -1833,6 +1836,8 @@ enum nl80211_attrs {
+       NL80211_ATTR_SUPPORT_5_MHZ,
+       NL80211_ATTR_SUPPORT_10_MHZ,
++      NL80211_ATTR_WIPHY_ANTENNA_GAIN,
++
+       /* add attributes here, update the policy in nl80211.c */
+       __NL80211_ATTR_AFTER_LAST,
+--- a/net/mac80211/cfg.c
++++ b/net/mac80211/cfg.c
+@@ -2308,6 +2308,19 @@ static int ieee80211_get_tx_power(struct
+       return 0;
+ }
++static int ieee80211_set_antenna_gain(struct wiphy *wiphy, int dbi)
++{
++      struct ieee80211_local *local = wiphy_priv(wiphy);
++
++      if (dbi < 0)
++              return -EINVAL;
++
++      local->user_antenna_gain = dbi;
++      ieee80211_hw_config(local, 0);
++
++      return 0;
++}
++
+ static int ieee80211_set_wds_peer(struct wiphy *wiphy, struct net_device *dev,
+                                 const u8 *addr)
+ {
+@@ -3861,6 +3874,7 @@ struct cfg80211_ops mac80211_config_ops 
+       .set_wiphy_params = ieee80211_set_wiphy_params,
+       .set_tx_power = ieee80211_set_tx_power,
+       .get_tx_power = ieee80211_get_tx_power,
++      .set_antenna_gain = ieee80211_set_antenna_gain,
+       .set_wds_peer = ieee80211_set_wds_peer,
+       .rfkill_poll = ieee80211_rfkill_poll,
+       CFG80211_TESTMODE_CMD(ieee80211_testmode_cmd)
+--- a/net/mac80211/ieee80211_i.h
++++ b/net/mac80211/ieee80211_i.h
+@@ -1185,6 +1185,7 @@ struct ieee80211_local {
+       int dynamic_ps_forced_timeout;
+       int user_power_level; /* in dBm, for all interfaces */
++      int user_antenna_gain; /* in dBi */
+       enum ieee80211_smps_mode smps_mode;
+--- a/net/mac80211/main.c
++++ b/net/mac80211/main.c
+@@ -101,7 +101,7 @@ static u32 ieee80211_hw_conf_chan(struct
+       struct ieee80211_sub_if_data *sdata;
+       struct cfg80211_chan_def chandef = {};
+       u32 changed = 0;
+-      int power;
++      int power, ant_gain, max_power;
+       u32 offchannel_flag;
+       offchannel_flag = local->hw.conf.flags & IEEE80211_CONF_OFFCHANNEL;
+@@ -156,8 +156,21 @@ static u32 ieee80211_hw_conf_chan(struct
+       }
+       rcu_read_unlock();
+-      if (local->hw.conf.power_level != power) {
++      max_power = chandef.chan->max_reg_power;
++      ant_gain = chandef.chan->max_antenna_gain;
++      if (local->user_antenna_gain > 0) {
++              if (local->user_antenna_gain > ant_gain) {
++                      max_power -= local->user_antenna_gain - ant_gain;
++                      ant_gain = 0;
++              } else
++                      ant_gain -= local->user_antenna_gain;
++              power = min(power, max_power);
++      }
++
++      if (local->hw.conf.power_level != power ||
++          local->hw.conf.max_antenna_gain != ant_gain) {
+               changed |= IEEE80211_CONF_CHANGE_POWER;
++              local->hw.conf.max_antenna_gain = ant_gain;
+               local->hw.cur_power_level = power;
+               local->hw.conf.power_level = power;
+       }
+@@ -588,6 +601,7 @@ struct ieee80211_hw *ieee80211_alloc_hw(
+                                        IEEE80211_RADIOTAP_MCS_HAVE_BW;
+       local->hw.radiotap_vht_details = IEEE80211_RADIOTAP_VHT_KNOWN_GI |
+                                        IEEE80211_RADIOTAP_VHT_KNOWN_BANDWIDTH;
++      local->user_antenna_gain = 0;
+       local->hw.uapsd_queues = IEEE80211_DEFAULT_UAPSD_QUEUES;
+       local->hw.uapsd_max_sp_len = IEEE80211_DEFAULT_MAX_SP_LEN;
+       local->user_power_level = IEEE80211_UNSET_POWER_LEVEL;
+--- a/net/wireless/nl80211.c
++++ b/net/wireless/nl80211.c
+@@ -357,6 +357,7 @@ static const struct nla_policy nl80211_p
+       [NL80211_ATTR_STA_SUPPORTED_CHANNELS] = { .type = NLA_BINARY },
+       [NL80211_ATTR_STA_SUPPORTED_OPER_CLASSES] = { .type = NLA_BINARY },
+       [NL80211_ATTR_HANDLE_DFS] = { .type = NLA_FLAG },
++      [NL80211_ATTR_WIPHY_ANTENNA_GAIN] = { .type = NLA_U32 },
+ };
+ /* policy for the key attributes */
+@@ -2039,6 +2040,22 @@ static int nl80211_set_wiphy(struct sk_b
+                       goto bad_res;
+       }
++      if (info->attrs[NL80211_ATTR_WIPHY_ANTENNA_GAIN]) {
++              int idx, dbi = 0;
++
++              if (!rdev->ops->set_antenna_gain) {
++                      result = -EOPNOTSUPP;
++                      goto bad_res;
++              }
++
++              idx = NL80211_ATTR_WIPHY_ANTENNA_GAIN;
++              dbi = nla_get_u32(info->attrs[idx]);
++
++              result = rdev->ops->set_antenna_gain(&rdev->wiphy, dbi);
++              if (result)
++                      goto bad_res;
++      }
++
+       if (info->attrs[NL80211_ATTR_WIPHY_ANTENNA_TX] &&
+           info->attrs[NL80211_ATTR_WIPHY_ANTENNA_RX]) {
+               u32 tx_ant, rx_ant;
diff --git a/package/kernel/mac80211/patches/523-ath9k_use_configured_antenna_gain.patch b/package/kernel/mac80211/patches/523-ath9k_use_configured_antenna_gain.patch
new file mode 100644 (file)
index 0000000..afc5ba6
--- /dev/null
@@ -0,0 +1,34 @@
+--- a/drivers/net/wireless/ath/ath.h
++++ b/drivers/net/wireless/ath/ath.h
+@@ -73,6 +73,7 @@ struct ath_regulatory {
+       u16 max_power_level;
+       u16 current_rd;
+       int16_t power_limit;
++      int16_t max_antenna_gain;
+       struct reg_dmn_pair_mapping *regpair;
+ };
+--- 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
+       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);
+-      max_gain = chan_pwr - new_pwr + channel->max_antenna_gain * 2;
++      max_gain = chan_pwr - new_pwr + reg->max_antenna_gain * 2;
+       ant_gain = get_antenna_gain(ah, chan);
+       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
+       }
+       if (changed & IEEE80211_CONF_CHANGE_POWER) {
++              struct ath_regulatory *reg = ath9k_hw_regulatory(ah);
++
+               ath_dbg(common, CONFIG, "Set power: %d\n", conf->power_level);
++              reg->max_antenna_gain = conf->max_antenna_gain;
+               sc->config.txpowlimit = 2 * conf->power_level;
+               ath9k_cmn_update_txpow(ah, sc->curtxpow,
+                                      sc->config.txpowlimit, &sc->curtxpow);
diff --git a/package/kernel/mac80211/patches/523-mac80211_configure_antenna_gain.patch b/package/kernel/mac80211/patches/523-mac80211_configure_antenna_gain.patch
deleted file mode 100644 (file)
index 00265e9..0000000
+++ /dev/null
@@ -1,172 +0,0 @@
---- a/include/net/cfg80211.h
-+++ b/include/net/cfg80211.h
-@@ -2081,6 +2081,7 @@ struct cfg80211_update_ft_ies_params {
-  *    (as advertised by the nl80211 feature flag.)
-  * @get_tx_power: store the current TX power into the dbm variable;
-  *    return 0 if successful
-+ * @set_antenna_gain: set antenna gain to reduce maximum tx power if necessary
-  *
-  * @set_wds_peer: set the WDS peer for a WDS interface
-  *
-@@ -2303,6 +2304,7 @@ struct cfg80211_ops {
-                               enum nl80211_tx_power_setting type, int mbm);
-       int     (*get_tx_power)(struct wiphy *wiphy, struct wireless_dev *wdev,
-                               int *dbm);
-+      int     (*set_antenna_gain)(struct wiphy *wiphy, int dbi);
-       int     (*set_wds_peer)(struct wiphy *wiphy, struct net_device *dev,
-                               const u8 *addr);
---- a/include/net/mac80211.h
-+++ b/include/net/mac80211.h
-@@ -1029,6 +1029,7 @@ enum ieee80211_smps_mode {
-  *
-  * @power_level: requested transmit power (in dBm), backward compatibility
-  *    value only that is set to the minimum of all interfaces
-+ * @max_antenna_gain: maximum antenna gain adjusted by user config (in dBi)
-  *
-  * @chandef: the channel definition to tune to
-  * @radar_enabled: whether radar detection is enabled
-@@ -1050,6 +1051,7 @@ struct ieee80211_conf {
-       u32 flags;
-       int power_level, dynamic_ps_timeout;
-       int max_sleep_period;
-+      int max_antenna_gain;
-       u16 listen_interval;
-       u8 ps_dtim_period;
---- a/include/uapi/linux/nl80211.h
-+++ b/include/uapi/linux/nl80211.h
-@@ -1514,6 +1514,9 @@ enum nl80211_commands {
-  * @NL80211_ATTR_SUPPORT_10_MHZ: A flag indicating that the device supports
-  *    10 MHz channel bandwidth.
-  *
-+ * @NL80211_ATTR_WIPHY_ANTENNA_GAIN: Configured antenna gain. Used to reduce
-+ *    transmit power to stay within regulatory limits. u32, dBi.
-+ *
-  * @NL80211_ATTR_MAX: highest attribute number currently defined
-  * @__NL80211_ATTR_AFTER_LAST: internal use
-  */
-@@ -1833,6 +1836,8 @@ enum nl80211_attrs {
-       NL80211_ATTR_SUPPORT_5_MHZ,
-       NL80211_ATTR_SUPPORT_10_MHZ,
-+      NL80211_ATTR_WIPHY_ANTENNA_GAIN,
-+
-       /* add attributes here, update the policy in nl80211.c */
-       __NL80211_ATTR_AFTER_LAST,
---- a/net/mac80211/cfg.c
-+++ b/net/mac80211/cfg.c
-@@ -2308,6 +2308,19 @@ static int ieee80211_get_tx_power(struct
-       return 0;
- }
-+static int ieee80211_set_antenna_gain(struct wiphy *wiphy, int dbi)
-+{
-+      struct ieee80211_local *local = wiphy_priv(wiphy);
-+
-+      if (dbi < 0)
-+              return -EINVAL;
-+
-+      local->user_antenna_gain = dbi;
-+      ieee80211_hw_config(local, 0);
-+
-+      return 0;
-+}
-+
- static int ieee80211_set_wds_peer(struct wiphy *wiphy, struct net_device *dev,
-                                 const u8 *addr)
- {
-@@ -3861,6 +3874,7 @@ struct cfg80211_ops mac80211_config_ops 
-       .set_wiphy_params = ieee80211_set_wiphy_params,
-       .set_tx_power = ieee80211_set_tx_power,
-       .get_tx_power = ieee80211_get_tx_power,
-+      .set_antenna_gain = ieee80211_set_antenna_gain,
-       .set_wds_peer = ieee80211_set_wds_peer,
-       .rfkill_poll = ieee80211_rfkill_poll,
-       CFG80211_TESTMODE_CMD(ieee80211_testmode_cmd)
---- a/net/mac80211/ieee80211_i.h
-+++ b/net/mac80211/ieee80211_i.h
-@@ -1185,6 +1185,7 @@ struct ieee80211_local {
-       int dynamic_ps_forced_timeout;
-       int user_power_level; /* in dBm, for all interfaces */
-+      int user_antenna_gain; /* in dBi */
-       enum ieee80211_smps_mode smps_mode;
---- a/net/mac80211/main.c
-+++ b/net/mac80211/main.c
-@@ -101,7 +101,7 @@ static u32 ieee80211_hw_conf_chan(struct
-       struct ieee80211_sub_if_data *sdata;
-       struct cfg80211_chan_def chandef = {};
-       u32 changed = 0;
--      int power;
-+      int power, ant_gain, max_power;
-       u32 offchannel_flag;
-       offchannel_flag = local->hw.conf.flags & IEEE80211_CONF_OFFCHANNEL;
-@@ -156,8 +156,21 @@ static u32 ieee80211_hw_conf_chan(struct
-       }
-       rcu_read_unlock();
--      if (local->hw.conf.power_level != power) {
-+      max_power = chandef.chan->max_reg_power;
-+      ant_gain = chandef.chan->max_antenna_gain;
-+      if (local->user_antenna_gain > 0) {
-+              if (local->user_antenna_gain > ant_gain) {
-+                      max_power -= local->user_antenna_gain - ant_gain;
-+                      ant_gain = 0;
-+              } else
-+                      ant_gain -= local->user_antenna_gain;
-+              power = min(power, max_power);
-+      }
-+
-+      if (local->hw.conf.power_level != power ||
-+          local->hw.conf.max_antenna_gain != ant_gain) {
-               changed |= IEEE80211_CONF_CHANGE_POWER;
-+              local->hw.conf.max_antenna_gain = ant_gain;
-               local->hw.cur_power_level = power;
-               local->hw.conf.power_level = power;
-       }
-@@ -588,6 +601,7 @@ struct ieee80211_hw *ieee80211_alloc_hw(
-                                        IEEE80211_RADIOTAP_MCS_HAVE_BW;
-       local->hw.radiotap_vht_details = IEEE80211_RADIOTAP_VHT_KNOWN_GI |
-                                        IEEE80211_RADIOTAP_VHT_KNOWN_BANDWIDTH;
-+      local->user_antenna_gain = 0;
-       local->hw.uapsd_queues = IEEE80211_DEFAULT_UAPSD_QUEUES;
-       local->hw.uapsd_max_sp_len = IEEE80211_DEFAULT_MAX_SP_LEN;
-       local->user_power_level = IEEE80211_UNSET_POWER_LEVEL;
---- a/net/wireless/nl80211.c
-+++ b/net/wireless/nl80211.c
-@@ -357,6 +357,7 @@ static const struct nla_policy nl80211_p
-       [NL80211_ATTR_STA_SUPPORTED_CHANNELS] = { .type = NLA_BINARY },
-       [NL80211_ATTR_STA_SUPPORTED_OPER_CLASSES] = { .type = NLA_BINARY },
-       [NL80211_ATTR_HANDLE_DFS] = { .type = NLA_FLAG },
-+      [NL80211_ATTR_WIPHY_ANTENNA_GAIN] = { .type = NLA_U32 },
- };
- /* policy for the key attributes */
-@@ -2039,6 +2040,22 @@ static int nl80211_set_wiphy(struct sk_b
-                       goto bad_res;
-       }
-+      if (info->attrs[NL80211_ATTR_WIPHY_ANTENNA_GAIN]) {
-+              int idx, dbi = 0;
-+
-+              if (!rdev->ops->set_antenna_gain) {
-+                      result = -EOPNOTSUPP;
-+                      goto bad_res;
-+              }
-+
-+              idx = NL80211_ATTR_WIPHY_ANTENNA_GAIN;
-+              dbi = nla_get_u32(info->attrs[idx]);
-+
-+              result = rdev->ops->set_antenna_gain(&rdev->wiphy, dbi);
-+              if (result)
-+                      goto bad_res;
-+      }
-+
-       if (info->attrs[NL80211_ATTR_WIPHY_ANTENNA_TX] &&
-           info->attrs[NL80211_ATTR_WIPHY_ANTENNA_RX]) {
-               u32 tx_ant, rx_ant;
diff --git a/package/kernel/mac80211/patches/524-ath9k_use_configured_antenna_gain.patch b/package/kernel/mac80211/patches/524-ath9k_use_configured_antenna_gain.patch
deleted file mode 100644 (file)
index 3614b4a..0000000
+++ /dev/null
@@ -1,34 +0,0 @@
---- a/drivers/net/wireless/ath/ath.h
-+++ b/drivers/net/wireless/ath/ath.h
-@@ -73,6 +73,7 @@ struct ath_regulatory {
-       u16 max_power_level;
-       u16 current_rd;
-       int16_t power_limit;
-+      int16_t max_antenna_gain;
-       struct reg_dmn_pair_mapping *regpair;
- };
---- a/drivers/net/wireless/ath/ath9k/hw.c
-+++ b/drivers/net/wireless/ath/ath9k/hw.c
-@@ -2858,7 +2858,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);
--      max_gain = chan_pwr - new_pwr + channel->max_antenna_gain * 2;
-+      max_gain = chan_pwr - new_pwr + reg->max_antenna_gain * 2;
-       ant_gain = get_antenna_gain(ah, chan);
-       if (ant_gain > max_gain)
---- a/drivers/net/wireless/ath/ath9k/main.c
-+++ b/drivers/net/wireless/ath/ath9k/main.c
-@@ -1340,7 +1340,10 @@ static int ath9k_config(struct ieee80211
-       }
-       if (changed & IEEE80211_CONF_CHANGE_POWER) {
-+              struct ath_regulatory *reg = ath9k_hw_regulatory(ah);
-+
-               ath_dbg(common, CONFIG, "Set power: %d\n", conf->power_level);
-+              reg->max_antenna_gain = conf->max_antenna_gain;
-               sc->config.txpowlimit = 2 * conf->power_level;
-               ath9k_cmn_update_txpow(ah, sc->curtxpow,
-                                      sc->config.txpowlimit, &sc->curtxpow);
index 41081dc..4557c27 100644 (file)
@@ -1,6 +1,6 @@
 --- a/drivers/net/wireless/ath/ath9k/ath9k.h
 +++ b/drivers/net/wireless/ath/ath9k/ath9k.h
-@@ -558,6 +558,9 @@ struct ath9k_wow_pattern {
+@@ -557,6 +557,9 @@ struct ath9k_wow_pattern {
  void ath_init_leds(struct ath_softc *sc);
  void ath_deinit_leds(struct ath_softc *sc);
  void ath_fill_led_pin(struct ath_softc *sc);
@@ -10,7 +10,7 @@
  #else
  static inline void ath_init_leds(struct ath_softc *sc)
  {
-@@ -733,6 +736,13 @@ enum spectral_mode {
+@@ -732,6 +735,13 @@ enum spectral_mode {
        SPECTRAL_CHANSCAN,
  };
  
@@ -24,7 +24,7 @@
  struct ath_softc {
        struct ieee80211_hw *hw;
        struct device *dev;
-@@ -775,9 +785,8 @@ struct ath_softc {
+@@ -774,9 +784,8 @@ struct ath_softc {
        struct ieee80211_supported_band sbands[IEEE80211_NUM_BANDS];
  
  #ifdef CPTCFG_MAC80211_LEDS
index accf8ee..a521525 100644 (file)
@@ -1,6 +1,6 @@
 --- a/drivers/net/wireless/ath/ath9k/mac.c
 +++ b/drivers/net/wireless/ath/ath9k/mac.c
-@@ -701,7 +701,7 @@ bool ath9k_hw_stopdmarecv(struct ath_hw 
+@@ -700,7 +700,7 @@ bool ath9k_hw_stopdmarecv(struct ath_hw 
  {
  #define AH_RX_STOP_DMA_TIMEOUT 10000   /* usec */
        struct ath_common *common = ath9k_hw_common(ah);
@@ -9,7 +9,7 @@
        int i;
  
        /* Enable access to the DMA observation bus */
-@@ -731,6 +731,16 @@ bool ath9k_hw_stopdmarecv(struct ath_hw 
+@@ -730,6 +730,16 @@ bool ath9k_hw_stopdmarecv(struct ath_hw 
        }
  
        if (i == 0) {
index 0a43af1..cf5bbbe 100644 (file)
@@ -62,7 +62,7 @@
        debugfs_create_file("interrupt", S_IRUSR, sc->debug.debugfs_phy, sc,
 --- a/drivers/net/wireless/ath/ath9k/hw.h
 +++ b/drivers/net/wireless/ath/ath9k/hw.h
-@@ -482,6 +482,12 @@ enum {
+@@ -469,6 +469,12 @@ enum {
        ATH9K_RESET_COLD,
  };
  
@@ -75,7 +75,7 @@
  struct ath9k_hw_version {
        u32 magic;
        u16 devid;
-@@ -767,6 +773,8 @@ struct ath_hw {
+@@ -744,6 +750,8 @@ struct ath_hw {
        u32 rfkill_polarity;
        u32 ah_flags;
  
@@ -84,7 +84,7 @@
        bool reset_power_on;
        bool htc_reset_init;
  
-@@ -1019,6 +1027,7 @@ void ath9k_hw_check_nav(struct ath_hw *a
+@@ -995,6 +1003,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);
@@ -94,7 +94,7 @@
  void ath9k_debug_sync_cause(struct ath_common *common, u32 sync_cause);
 --- a/drivers/net/wireless/ath/ath9k/hw.c
 +++ b/drivers/net/wireless/ath/ath9k/hw.c
-@@ -1863,6 +1863,20 @@ fail:
+@@ -1854,6 +1854,20 @@ fail:
        return -EINVAL;
  }
  
  int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,
                   struct ath9k_hw_cal_data *caldata, bool fastcc)
  {
-@@ -2065,6 +2079,7 @@ int ath9k_hw_reset(struct ath_hw *ah, st
+@@ -2056,6 +2070,7 @@ int ath9k_hw_reset(struct ath_hw *ah, st
        }
  
        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
-@@ -571,6 +571,11 @@ irqreturn_t ath_isr(int irq, void *dev)
+@@ -574,6 +574,11 @@ irqreturn_t ath_isr(int irq, void *dev)
        ath9k_hw_getisr(ah, &status);   /* NB: clears ISR too */
        status &= ah->imask;    /* discard unasked-for bits */
  
index f33ff92..0e83822 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
-@@ -2458,17 +2458,25 @@ int ath9k_hw_fill_cap_info(struct ath_hw
+@@ -2441,17 +2441,25 @@ int ath9k_hw_fill_cap_info(struct ath_hw
        }
  
        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
-@@ -938,6 +938,8 @@ struct ath_hw {
+@@ -914,6 +914,8 @@ struct ath_hw {
        bool is_clk_25mhz;
        int (*get_mac_revision)(void);
        int (*external_reset)(void);
index f264062..b8209a5 100644 (file)
@@ -1,6 +1,6 @@
 --- a/drivers/net/wireless/ath/ath9k/hw.h
 +++ b/drivers/net/wireless/ath/ath9k/hw.h
-@@ -684,6 +684,7 @@ struct ath_spec_scan {
+@@ -661,6 +661,7 @@ struct ath_spec_scan {
   * @config_pci_powersave:
   * @calibrate: periodic calibration for NF, ANI, IQ, ADC gain, ADC-DC
   *
@@ -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
-@@ -706,6 +707,7 @@ struct ath_hw_ops {
+@@ -683,6 +684,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);