diff options
author | Felix Fietkau <nbd@openwrt.org> | 2013-12-14 17:07:08 +0000 |
---|---|---|
committer | Felix Fietkau <nbd@openwrt.org> | 2013-12-14 17:07:08 +0000 |
commit | 43122f092ee5588d9f826d9ea470be8929b5be35 (patch) | |
tree | dcc6a45966b84db519841a242ff46181ef8943fa /package/kernel/mac80211/patches/300-pending_work.patch | |
parent | c411d7e762f2bd12685e86e0b162b88ec7432759 (diff) | |
download | master-187ad058-43122f092ee5588d9f826d9ea470be8929b5be35.tar.gz master-187ad058-43122f092ee5588d9f826d9ea470be8929b5be35.tar.bz2 master-187ad058-43122f092ee5588d9f826d9ea470be8929b5be35.zip |
ath9k: merge another round of cleanups and fixes submitted to linux-wireless
Signed-off-by: Felix Fietkau <nbd@openwrt.org>
git-svn-id: svn://svn.openwrt.org/openwrt/trunk@39054 3c298f89-4303-0410-b956-a3cf2f4a3e73
Diffstat (limited to 'package/kernel/mac80211/patches/300-pending_work.patch')
-rw-r--r-- | package/kernel/mac80211/patches/300-pending_work.patch | 1209 |
1 files changed, 1177 insertions, 32 deletions
diff --git a/package/kernel/mac80211/patches/300-pending_work.patch b/package/kernel/mac80211/patches/300-pending_work.patch index 7fd622546f..f70ac79104 100644 --- a/package/kernel/mac80211/patches/300-pending_work.patch +++ b/package/kernel/mac80211/patches/300-pending_work.patch @@ -856,7 +856,31 @@ /**********/ /* 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 @@ -891,7 +915,7 @@ /*******************************/ /* 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 */ /********************/ @@ -917,7 +941,7 @@ /* * 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; @@ -925,7 +949,7 @@ 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; @@ -933,7 +957,7 @@ #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; @@ -942,7 +966,7 @@ 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; @@ -970,7 +994,7 @@ 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); @@ -1120,23 +1144,48 @@ } --- 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. */ @@ -1151,7 +1200,7 @@ } } -@@ -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) { @@ -1163,7 +1212,7 @@ } 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) && @@ -1172,7 +1221,7 @@ 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); @@ -1185,7 +1234,7 @@ 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; @@ -1200,7 +1249,7 @@ 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 */ @@ -1212,17 +1261,262 @@ 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; @@ -1231,7 +1525,53 @@ }; 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; @@ -1239,7 +1579,7 @@ 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; @@ -1248,7 +1588,7 @@ 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 */ @@ -1496,7 +1836,7 @@ { 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); @@ -1504,8 +1844,13 @@ + 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; } @@ -1515,7 +1860,7 @@ 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 @@ -1524,7 +1869,7 @@ 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 } @@ -1533,7 +1878,16 @@ { 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); } @@ -1567,7 +1921,7 @@ 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; } @@ -1596,7 +1950,7 @@ 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; } @@ -1930,7 +2284,7 @@ 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; } @@ -2065,7 +2419,7 @@ 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, @@ -11533,3 +11887,794 @@ } 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; |