/**********/
/* 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, ¢ers);
+ 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;