+--- 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;