Просмотр исходного кода

ath9k: merge another round of cleanups and fixes submitted to linux-wireless

Signed-off-by: Felix Fietkau <[email protected]>

SVN-Revision: 39054
Felix Fietkau 12 лет назад
Родитель
Сommit
a55649082a

+ 1177 - 32
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, &centers);
+ 	freq = centers.synth_center;
+ 
+-	ah->config.spurmode = SPUR_ENABLE_EEPROM;
+ 	for (i = 0; i < AR_EEPROM_MODAL_SPURS; i++) {
+ 		cur_bb_spur = ah->eep_ops->get_spur_channel(ah, i, is2GHz);
+ 
+--- a/drivers/net/wireless/ath/ath9k/ar9003_mac.c
++++ b/drivers/net/wireless/ath/ath9k/ar9003_mac.c
+@@ -476,12 +476,12 @@ int ath9k_hw_process_rxdesc_edma(struct 
+ 
+ 	/* XXX: Keycache */
+ 	rxs->rs_rssi = MS(rxsp->status5, AR_RxRSSICombined);
+-	rxs->rs_rssi_ctl0 = MS(rxsp->status1, AR_RxRSSIAnt00);
+-	rxs->rs_rssi_ctl1 = MS(rxsp->status1, AR_RxRSSIAnt01);
+-	rxs->rs_rssi_ctl2 = MS(rxsp->status1, AR_RxRSSIAnt02);
+-	rxs->rs_rssi_ext0 = MS(rxsp->status5, AR_RxRSSIAnt10);
+-	rxs->rs_rssi_ext1 = MS(rxsp->status5, AR_RxRSSIAnt11);
+-	rxs->rs_rssi_ext2 = MS(rxsp->status5, AR_RxRSSIAnt12);
++	rxs->rs_rssi_ctl[0] = MS(rxsp->status1, AR_RxRSSIAnt00);
++	rxs->rs_rssi_ctl[1] = MS(rxsp->status1, AR_RxRSSIAnt01);
++	rxs->rs_rssi_ctl[2] = MS(rxsp->status1, AR_RxRSSIAnt02);
++	rxs->rs_rssi_ext[0] = MS(rxsp->status5, AR_RxRSSIAnt10);
++	rxs->rs_rssi_ext[1] = MS(rxsp->status5, AR_RxRSSIAnt11);
++	rxs->rs_rssi_ext[2] = MS(rxsp->status5, AR_RxRSSIAnt12);
+ 
+ 	if (rxsp->status11 & AR_RxKeyIdxValid)
+ 		rxs->rs_keyix = MS(rxsp->status11, AR_KeyIdx);
+--- a/drivers/net/wireless/ath/ath9k/beacon.c
++++ b/drivers/net/wireless/ath/ath9k/beacon.c
+@@ -431,6 +431,33 @@ static void ath9k_beacon_init(struct ath
+ 	ath9k_hw_enable_interrupts(ah);
+ }
+ 
++/* Calculate the modulo of a 64 bit TSF snapshot with a TU divisor */
++static u32 ath9k_mod_tsf64_tu(u64 tsf, u32 div_tu)
++{
++	u32 tsf_mod, tsf_hi, tsf_lo, mod_hi, mod_lo;
++
++	tsf_mod = tsf & (BIT(10) - 1);
++	tsf_hi = tsf >> 32;
++	tsf_lo = ((u32) tsf) >> 10;
++
++	mod_hi = tsf_hi % div_tu;
++	mod_lo = ((mod_hi << 22) + tsf_lo) % div_tu;
++
++	return (mod_lo << 10) | tsf_mod;
++}
++
++static u32 ath9k_get_next_tbtt(struct ath_softc *sc, u64 tsf,
++			       unsigned int interval)
++{
++	struct ath_hw *ah = sc->sc_ah;
++	unsigned int offset;
++
++	tsf += TU_TO_USEC(FUDGE + ah->config.sw_beacon_response_time);
++	offset = ath9k_mod_tsf64_tu(tsf, interval);
++
++	return (u32) tsf + TU_TO_USEC(interval) - offset;
++}
++
+ /*
+  * For multi-bss ap support beacons are either staggered evenly over N slots or
+  * burst together.  For the former arrange for the SWBA to be delivered for each
+@@ -446,7 +473,8 @@ static void ath9k_beacon_config_ap(struc
+ 	/* NB: the beacon interval is kept internally in TU's */
+ 	intval = TU_TO_USEC(conf->beacon_interval);
+ 	intval /= ATH_BCBUF;
+-	nexttbtt = intval;
++	nexttbtt = ath9k_get_next_tbtt(sc, ath9k_hw_gettsf64(ah),
++				       conf->beacon_interval);
+ 
+ 	if (conf->enable_beacon)
+ 		ah->imask |= ATH9K_INT_SWBA;
+@@ -458,7 +486,7 @@ static void ath9k_beacon_config_ap(struc
+ 		(conf->enable_beacon) ? "Enable" : "Disable",
+ 		nexttbtt, intval, conf->beacon_interval);
+ 
+-	ath9k_beacon_init(sc, nexttbtt, intval, true);
++	ath9k_beacon_init(sc, nexttbtt, intval, false);
+ }
+ 
+ /*
+@@ -475,11 +503,9 @@ static void ath9k_beacon_config_sta(stru
+ 	struct ath_hw *ah = sc->sc_ah;
+ 	struct ath_common *common = ath9k_hw_common(ah);
+ 	struct ath9k_beacon_state bs;
+-	int dtimperiod, dtimcount, sleepduration;
+-	int cfpperiod, cfpcount;
+-	u32 nexttbtt = 0, intval, tsftu;
++	int dtim_intval, sleepduration;
++	u32 nexttbtt = 0, intval;
+ 	u64 tsf;
+-	int num_beacons, offset, dtim_dec_count, cfp_dec_count;
+ 
+ 	/* No need to configure beacon if we are not associated */
+ 	if (!test_bit(SC_OP_PRIM_STA_VIF, &sc->sc_flags)) {
+@@ -492,53 +518,25 @@ static void ath9k_beacon_config_sta(stru
+ 	intval = conf->beacon_interval;
+ 
+ 	/*
+-	 * Setup dtim and cfp parameters according to
++	 * Setup dtim parameters according to
+ 	 * last beacon we received (which may be none).
+ 	 */
+-	dtimperiod = conf->dtim_period;
+-	dtimcount = conf->dtim_count;
+-	if (dtimcount >= dtimperiod)	/* NB: sanity check */
+-		dtimcount = 0;
+-	cfpperiod = 1;			/* NB: no PCF support yet */
+-	cfpcount = 0;
+-
++	dtim_intval = intval * conf->dtim_period;
+ 	sleepduration = conf->listen_interval * intval;
+ 
+ 	/*
+ 	 * Pull nexttbtt forward to reflect the current
+-	 * TSF and calculate dtim+cfp state for the result.
++	 * TSF and calculate dtim state for the result.
+ 	 */
+ 	tsf = ath9k_hw_gettsf64(ah);
+-	tsftu = TSF_TO_TU(tsf>>32, tsf) + FUDGE;
+-
+-	num_beacons = tsftu / intval + 1;
+-	offset = tsftu % intval;
+-	nexttbtt = tsftu - offset;
+-	if (offset)
+-		nexttbtt += intval;
+-
+-	/* DTIM Beacon every dtimperiod Beacon */
+-	dtim_dec_count = num_beacons % dtimperiod;
+-	/* CFP every cfpperiod DTIM Beacon */
+-	cfp_dec_count = (num_beacons / dtimperiod) % cfpperiod;
+-	if (dtim_dec_count)
+-		cfp_dec_count++;
+-
+-	dtimcount -= dtim_dec_count;
+-	if (dtimcount < 0)
+-		dtimcount += dtimperiod;
+-
+-	cfpcount -= cfp_dec_count;
+-	if (cfpcount < 0)
+-		cfpcount += cfpperiod;
++	nexttbtt = ath9k_get_next_tbtt(sc, tsf, intval);
+ 
+-	bs.bs_intval = intval;
++	bs.bs_intval = TU_TO_USEC(intval);
++	bs.bs_dtimperiod = conf->dtim_period * bs.bs_intval;
+ 	bs.bs_nexttbtt = nexttbtt;
+-	bs.bs_dtimperiod = dtimperiod*intval;
+-	bs.bs_nextdtim = bs.bs_nexttbtt + dtimcount*intval;
+-	bs.bs_cfpperiod = cfpperiod*bs.bs_dtimperiod;
+-	bs.bs_cfpnext = bs.bs_nextdtim + cfpcount*bs.bs_dtimperiod;
+-	bs.bs_cfpmaxduration = 0;
++	bs.bs_nextdtim = nexttbtt;
++	if (conf->dtim_period > 1)
++		bs.bs_nextdtim = ath9k_get_next_tbtt(sc, tsf, dtim_intval);
+ 
+ 	/*
+ 	 * Calculate the number of consecutive beacons to miss* before taking
+@@ -566,18 +564,16 @@ static void ath9k_beacon_config_sta(stru
+ 	 * XXX fixed at 100ms
+ 	 */
+ 
+-	bs.bs_sleepduration = roundup(IEEE80211_MS_TO_TU(100), sleepduration);
++	bs.bs_sleepduration = TU_TO_USEC(roundup(IEEE80211_MS_TO_TU(100),
++						 sleepduration));
+ 	if (bs.bs_sleepduration > bs.bs_dtimperiod)
+ 		bs.bs_sleepduration = bs.bs_dtimperiod;
+ 
+ 	/* TSF out of range threshold fixed at 1 second */
+ 	bs.bs_tsfoor_threshold = ATH9K_TSFOOR_THRESHOLD;
+ 
+-	ath_dbg(common, BEACON, "tsf: %llu tsftu: %u\n", tsf, tsftu);
+-	ath_dbg(common, BEACON,
+-		"bmiss: %u sleep: %u cfp-period: %u maxdur: %u next: %u\n",
+-		bs.bs_bmissthreshold, bs.bs_sleepduration,
+-		bs.bs_cfpperiod, bs.bs_cfpmaxduration, bs.bs_cfpnext);
++	ath_dbg(common, BEACON, "bmiss: %u sleep: %u\n",
++		bs.bs_bmissthreshold, bs.bs_sleepduration);
+ 
+ 	/* Set the computed STA beacon timers */
+ 
+@@ -600,25 +596,11 @@ static void ath9k_beacon_config_adhoc(st
+ 
+ 	intval = TU_TO_USEC(conf->beacon_interval);
+ 
+-	if (conf->ibss_creator) {
++	if (conf->ibss_creator)
+ 		nexttbtt = intval;
+-	} else {
+-		u32 tbtt, offset, tsftu;
+-		u64 tsf;
+-
+-		/*
+-		 * Pull nexttbtt forward to reflect the current
+-		 * sync'd TSF.
+-		 */
+-		tsf = ath9k_hw_gettsf64(ah);
+-		tsftu = TSF_TO_TU(tsf >> 32, tsf) + FUDGE;
+-		offset = tsftu % conf->beacon_interval;
+-		tbtt = tsftu - offset;
+-		if (offset)
+-			tbtt += conf->beacon_interval;
+-
+-		nexttbtt = TU_TO_USEC(tbtt);
+-	}
++	else
++		nexttbtt = ath9k_get_next_tbtt(sc, ath9k_hw_gettsf64(ah),
++					       conf->beacon_interval);
+ 
+ 	if (conf->enable_beacon)
+ 		ah->imask |= ATH9K_INT_SWBA;
+--- a/drivers/net/wireless/ath/ath9k/btcoex.c
++++ b/drivers/net/wireless/ath/ath9k/btcoex.c
+@@ -66,7 +66,6 @@ void ath9k_hw_init_btcoex_hw(struct ath_
+ 		.bt_first_slot_time = 5,
+ 		.bt_hold_rx_clear = true,
+ 	};
+-	u32 i, idx;
+ 	bool rxclear_polarity = ath_bt_config.bt_rxclear_polarity;
+ 
+ 	if (AR_SREV_9300_20_OR_LATER(ah))
+@@ -88,11 +87,6 @@ void ath9k_hw_init_btcoex_hw(struct ath_
+ 		SM(ath_bt_config.bt_hold_rx_clear, AR_BT_HOLD_RX_CLEAR) |
+ 		SM(ATH_BTCOEX_BMISS_THRESH, AR_BT_BCN_MISS_THRESH) |
+ 		AR_BT_DISABLE_BT_ANT;
+-
+-	for (i = 0; i < 32; i++) {
+-		idx = (debruijn32 << i) >> 27;
+-		ah->hw_gen_timers.gen_timer_index[idx] = i;
+-	}
+ }
+ EXPORT_SYMBOL(ath9k_hw_init_btcoex_hw);
+ 
+--- a/drivers/net/wireless/ath/ath9k/dfs.c
++++ b/drivers/net/wireless/ath/ath9k/dfs.c
+@@ -158,8 +158,8 @@ void ath9k_dfs_process_phyerr(struct ath
+ 		return;
+ 	}
+ 
+-	ard.rssi = rs->rs_rssi_ctl0;
+-	ard.ext_rssi = rs->rs_rssi_ext0;
++	ard.rssi = rs->rs_rssi_ctl[0];
++	ard.ext_rssi = rs->rs_rssi_ext[0];
+ 
+ 	/*
+ 	 * hardware stores this as 8 bit signed value.
+--- a/drivers/net/wireless/ath/ath9k/eeprom_4k.c
++++ b/drivers/net/wireless/ath/ath9k/eeprom_4k.c
+@@ -1085,31 +1085,7 @@ static void ath9k_hw_4k_set_board_values
+ 
+ static u16 ath9k_hw_4k_get_spur_channel(struct ath_hw *ah, u16 i, bool is2GHz)
+ {
+-#define EEP_MAP4K_SPURCHAN \
+-	(ah->eeprom.map4k.modalHeader.spurChans[i].spurChan)
+-	struct ath_common *common = ath9k_hw_common(ah);
+-
+-	u16 spur_val = AR_NO_SPUR;
+-
+-	ath_dbg(common, ANI, "Getting spur idx:%d is2Ghz:%d val:%x\n",
+-		i, is2GHz, ah->config.spurchans[i][is2GHz]);
+-
+-	switch (ah->config.spurmode) {
+-	case SPUR_DISABLE:
+-		break;
+-	case SPUR_ENABLE_IOCTL:
+-		spur_val = ah->config.spurchans[i][is2GHz];
+-		ath_dbg(common, ANI, "Getting spur val from new loc. %d\n",
+-			spur_val);
+-		break;
+-	case SPUR_ENABLE_EEPROM:
+-		spur_val = EEP_MAP4K_SPURCHAN;
+-		break;
+-	}
+-
+-	return spur_val;
+-
+-#undef EEP_MAP4K_SPURCHAN
++	return ah->eeprom.map4k.modalHeader.spurChans[i].spurChan;
+ }
+ 
+ const struct eeprom_ops eep_4k_ops = {
+--- a/drivers/net/wireless/ath/ath9k/eeprom_9287.c
++++ b/drivers/net/wireless/ath/ath9k/eeprom_9287.c
+@@ -1004,31 +1004,7 @@ static void ath9k_hw_ar9287_set_board_va
+ static u16 ath9k_hw_ar9287_get_spur_channel(struct ath_hw *ah,
+ 					    u16 i, bool is2GHz)
+ {
+-#define EEP_MAP9287_SPURCHAN \
+-	(ah->eeprom.map9287.modalHeader.spurChans[i].spurChan)
+-
+-	struct ath_common *common = ath9k_hw_common(ah);
+-	u16 spur_val = AR_NO_SPUR;
+-
+-	ath_dbg(common, ANI, "Getting spur idx:%d is2Ghz:%d val:%x\n",
+-		i, is2GHz, ah->config.spurchans[i][is2GHz]);
+-
+-	switch (ah->config.spurmode) {
+-	case SPUR_DISABLE:
+-		break;
+-	case SPUR_ENABLE_IOCTL:
+-		spur_val = ah->config.spurchans[i][is2GHz];
+-		ath_dbg(common, ANI, "Getting spur val from new loc. %d\n",
+-			spur_val);
+-		break;
+-	case SPUR_ENABLE_EEPROM:
+-		spur_val = EEP_MAP9287_SPURCHAN;
+-		break;
+-	}
+-
+-	return spur_val;
+-
+-#undef EEP_MAP9287_SPURCHAN
++	return ah->eeprom.map9287.modalHeader.spurChans[i].spurChan;
+ }
+ 
+ const struct eeprom_ops eep_ar9287_ops = {
+--- a/drivers/net/wireless/ath/ath9k/eeprom_def.c
++++ b/drivers/net/wireless/ath/ath9k/eeprom_def.c
+@@ -1348,31 +1348,7 @@ static void ath9k_hw_def_set_txpower(str
+ 
+ static u16 ath9k_hw_def_get_spur_channel(struct ath_hw *ah, u16 i, bool is2GHz)
+ {
+-#define EEP_DEF_SPURCHAN \
+-	(ah->eeprom.def.modalHeader[is2GHz].spurChans[i].spurChan)
+-	struct ath_common *common = ath9k_hw_common(ah);
+-
+-	u16 spur_val = AR_NO_SPUR;
+-
+-	ath_dbg(common, ANI, "Getting spur idx:%d is2Ghz:%d val:%x\n",
+-		i, is2GHz, ah->config.spurchans[i][is2GHz]);
+-
+-	switch (ah->config.spurmode) {
+-	case SPUR_DISABLE:
+-		break;
+-	case SPUR_ENABLE_IOCTL:
+-		spur_val = ah->config.spurchans[i][is2GHz];
+-		ath_dbg(common, ANI, "Getting spur val from new loc. %d\n",
+-			spur_val);
+-		break;
+-	case SPUR_ENABLE_EEPROM:
+-		spur_val = EEP_DEF_SPURCHAN;
+-		break;
+-	}
+-
+-	return spur_val;
+-
+-#undef EEP_DEF_SPURCHAN
++	return ah->eeprom.def.modalHeader[is2GHz].spurChans[i].spurChan;
+ }
+ 
+ const struct eeprom_ops eep_def_ops = {
+--- a/drivers/net/wireless/ath/ath9k/gpio.c
++++ b/drivers/net/wireless/ath/ath9k/gpio.c
+@@ -157,36 +157,6 @@ static void ath_detect_bt_priority(struc
+ 	}
+ }
+ 
+-static void ath9k_gen_timer_start(struct ath_hw *ah,
+-				  struct ath_gen_timer *timer,
+-				  u32 trig_timeout,
+-				  u32 timer_period)
+-{
+-	ath9k_hw_gen_timer_start(ah, timer, trig_timeout, timer_period);
+-
+-	if ((ah->imask & ATH9K_INT_GENTIMER) == 0) {
+-		ath9k_hw_disable_interrupts(ah);
+-		ah->imask |= ATH9K_INT_GENTIMER;
+-		ath9k_hw_set_interrupts(ah);
+-		ath9k_hw_enable_interrupts(ah);
+-	}
+-}
+-
+-static void ath9k_gen_timer_stop(struct ath_hw *ah, struct ath_gen_timer *timer)
+-{
+-	struct ath_gen_timer_table *timer_table = &ah->hw_gen_timers;
+-
+-	ath9k_hw_gen_timer_stop(ah, timer);
+-
+-	/* if no timer is enabled, turn off interrupt mask */
+-	if (timer_table->timer_mask.val == 0) {
+-		ath9k_hw_disable_interrupts(ah);
+-		ah->imask &= ~ATH9K_INT_GENTIMER;
+-		ath9k_hw_set_interrupts(ah);
+-		ath9k_hw_enable_interrupts(ah);
+-	}
+-}
+-
+ static void ath_mci_ftp_adjust(struct ath_softc *sc)
+ {
+ 	struct ath_btcoex *btcoex = &sc->btcoex;
+@@ -257,19 +227,9 @@ static void ath_btcoex_period_timer(unsi
+ 
+ 	spin_unlock_bh(&btcoex->btcoex_lock);
+ 
+-	/*
+-	 * btcoex_period is in msec while (btocex/btscan_)no_stomp are in usec,
+-	 * ensure that we properly convert btcoex_period to usec
+-	 * for any comparision with (btcoex/btscan_)no_stomp.
+-	 */
+-	if (btcoex->btcoex_period * 1000 != btcoex->btcoex_no_stomp) {
+-		if (btcoex->hw_timer_enabled)
+-			ath9k_gen_timer_stop(ah, btcoex->no_stomp_timer);
+-
+-		ath9k_gen_timer_start(ah, btcoex->no_stomp_timer, timer_period,
+-				      timer_period * 10);
+-		btcoex->hw_timer_enabled = true;
+-	}
++	if (btcoex->btcoex_period != btcoex->btcoex_no_stomp)
++		mod_timer(&btcoex->no_stomp_timer,
++			 jiffies + msecs_to_jiffies(timer_period));
+ 
+ 	ath9k_ps_restore(sc);
+ 
+@@ -282,7 +242,7 @@ skip_hw_wakeup:
+  * Generic tsf based hw timer which configures weight
+  * registers to time slice between wlan and bt traffic
+  */
+-static void ath_btcoex_no_stomp_timer(void *arg)
++static void ath_btcoex_no_stomp_timer(unsigned long arg)
+ {
+ 	struct ath_softc *sc = (struct ath_softc *)arg;
+ 	struct ath_hw *ah = sc->sc_ah;
+@@ -311,24 +271,18 @@ static int ath_init_btcoex_timer(struct 
+ 	struct ath_btcoex *btcoex = &sc->btcoex;
+ 
+ 	btcoex->btcoex_period = ATH_BTCOEX_DEF_BT_PERIOD;
+-	btcoex->btcoex_no_stomp = (100 - ATH_BTCOEX_DEF_DUTY_CYCLE) * 1000 *
++	btcoex->btcoex_no_stomp = (100 - ATH_BTCOEX_DEF_DUTY_CYCLE) *
+ 		btcoex->btcoex_period / 100;
+-	btcoex->btscan_no_stomp = (100 - ATH_BTCOEX_BTSCAN_DUTY_CYCLE) * 1000 *
++	btcoex->btscan_no_stomp = (100 - ATH_BTCOEX_BTSCAN_DUTY_CYCLE) *
+ 				   btcoex->btcoex_period / 100;
+ 
+ 	setup_timer(&btcoex->period_timer, ath_btcoex_period_timer,
+ 			(unsigned long) sc);
++	setup_timer(&btcoex->no_stomp_timer, ath_btcoex_no_stomp_timer,
++			(unsigned long) sc);
+ 
+ 	spin_lock_init(&btcoex->btcoex_lock);
+ 
+-	btcoex->no_stomp_timer = ath_gen_timer_alloc(sc->sc_ah,
+-			ath_btcoex_no_stomp_timer,
+-			ath_btcoex_no_stomp_timer,
+-			(void *) sc, AR_FIRST_NDP_TIMER);
+-
+-	if (!btcoex->no_stomp_timer)
+-		return -ENOMEM;
+-
+ 	return 0;
+ }
+ 
+@@ -343,10 +297,7 @@ void ath9k_btcoex_timer_resume(struct at
+ 	ath_dbg(ath9k_hw_common(ah), BTCOEX, "Starting btcoex timers\n");
+ 
+ 	/* make sure duty cycle timer is also stopped when resuming */
+-	if (btcoex->hw_timer_enabled) {
+-		ath9k_gen_timer_stop(sc->sc_ah, btcoex->no_stomp_timer);
+-		btcoex->hw_timer_enabled = false;
+-	}
++	del_timer_sync(&btcoex->no_stomp_timer);
+ 
+ 	btcoex->bt_priority_cnt = 0;
+ 	btcoex->bt_priority_time = jiffies;
+@@ -363,24 +314,16 @@ void ath9k_btcoex_timer_resume(struct at
+ void ath9k_btcoex_timer_pause(struct ath_softc *sc)
+ {
+ 	struct ath_btcoex *btcoex = &sc->btcoex;
+-	struct ath_hw *ah = sc->sc_ah;
+ 
+ 	del_timer_sync(&btcoex->period_timer);
+-
+-	if (btcoex->hw_timer_enabled) {
+-		ath9k_gen_timer_stop(ah, btcoex->no_stomp_timer);
+-		btcoex->hw_timer_enabled = false;
+-	}
++	del_timer_sync(&btcoex->no_stomp_timer);
+ }
+ 
+ void ath9k_btcoex_stop_gen_timer(struct ath_softc *sc)
+ {
+ 	struct ath_btcoex *btcoex = &sc->btcoex;
+ 
+-	if (btcoex->hw_timer_enabled) {
+-		ath9k_gen_timer_stop(sc->sc_ah, btcoex->no_stomp_timer);
+-		btcoex->hw_timer_enabled = false;
+-	}
++	del_timer_sync(&btcoex->no_stomp_timer);
+ }
+ 
+ u16 ath9k_btcoex_aggr_limit(struct ath_softc *sc, u32 max_4ms_framelen)
+@@ -400,12 +343,6 @@ u16 ath9k_btcoex_aggr_limit(struct ath_s
+ 
+ void ath9k_btcoex_handle_interrupt(struct ath_softc *sc, u32 status)
+ {
+-	struct ath_hw *ah = sc->sc_ah;
+-
+-	if (ath9k_hw_get_btcoex_scheme(ah) == ATH_BTCOEX_CFG_3WIRE)
+-		if (status & ATH9K_INT_GENTIMER)
+-			ath_gen_timer_isr(sc->sc_ah);
+-
+ 	if (status & ATH9K_INT_MCI)
+ 		ath_mci_intr(sc);
+ }
+@@ -447,10 +384,6 @@ void ath9k_deinit_btcoex(struct ath_soft
+ {
+ 	struct ath_hw *ah = sc->sc_ah;
+ 
+-        if ((sc->btcoex.no_stomp_timer) &&
+-	    ath9k_hw_get_btcoex_scheme(sc->sc_ah) == ATH_BTCOEX_CFG_3WIRE)
+-		ath_gen_timer_free(sc->sc_ah, sc->btcoex.no_stomp_timer);
+-
+ 	if (ath9k_hw_mci_is_enabled(ah))
+ 		ath_mci_cleanup(sc);
+ }
+--- a/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c
++++ b/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c
+@@ -70,11 +70,11 @@ static void ath9k_htc_beacon_config_sta(
+ 	struct ath9k_beacon_state bs;
+ 	enum ath9k_int imask = 0;
+ 	int dtimperiod, dtimcount, sleepduration;
+-	int cfpperiod, cfpcount, bmiss_timeout;
++	int bmiss_timeout;
+ 	u32 nexttbtt = 0, intval, tsftu;
+ 	__be32 htc_imask = 0;
+ 	u64 tsf;
+-	int num_beacons, offset, dtim_dec_count, cfp_dec_count;
++	int num_beacons, offset, dtim_dec_count;
+ 	int ret __attribute__ ((unused));
+ 	u8 cmd_rsp;
+ 
+@@ -84,7 +84,7 @@ static void ath9k_htc_beacon_config_sta(
+ 	bmiss_timeout = (ATH_DEFAULT_BMISS_LIMIT * bss_conf->beacon_interval);
+ 
+ 	/*
+-	 * Setup dtim and cfp parameters according to
++	 * Setup dtim parameters according to
+ 	 * last beacon we received (which may be none).
+ 	 */
+ 	dtimperiod = bss_conf->dtim_period;
+@@ -93,8 +93,6 @@ static void ath9k_htc_beacon_config_sta(
+ 	dtimcount = 1;
+ 	if (dtimcount >= dtimperiod)	/* NB: sanity check */
+ 		dtimcount = 0;
+-	cfpperiod = 1;			/* NB: no PCF support yet */
+-	cfpcount = 0;
+ 
+ 	sleepduration = intval;
+ 	if (sleepduration <= 0)
+@@ -102,7 +100,7 @@ static void ath9k_htc_beacon_config_sta(
+ 
+ 	/*
+ 	 * Pull nexttbtt forward to reflect the current
+-	 * TSF and calculate dtim+cfp state for the result.
++	 * TSF and calculate dtim state for the result.
+ 	 */
+ 	tsf = ath9k_hw_gettsf64(priv->ah);
+ 	tsftu = TSF_TO_TU(tsf>>32, tsf) + FUDGE;
+@@ -115,26 +113,14 @@ static void ath9k_htc_beacon_config_sta(
+ 
+ 	/* DTIM Beacon every dtimperiod Beacon */
+ 	dtim_dec_count = num_beacons % dtimperiod;
+-	/* CFP every cfpperiod DTIM Beacon */
+-	cfp_dec_count = (num_beacons / dtimperiod) % cfpperiod;
+-	if (dtim_dec_count)
+-		cfp_dec_count++;
+-
+ 	dtimcount -= dtim_dec_count;
+ 	if (dtimcount < 0)
+ 		dtimcount += dtimperiod;
+ 
+-	cfpcount -= cfp_dec_count;
+-	if (cfpcount < 0)
+-		cfpcount += cfpperiod;
+-
+-	bs.bs_intval = intval;
+-	bs.bs_nexttbtt = nexttbtt;
+-	bs.bs_dtimperiod = dtimperiod*intval;
+-	bs.bs_nextdtim = bs.bs_nexttbtt + dtimcount*intval;
+-	bs.bs_cfpperiod = cfpperiod*bs.bs_dtimperiod;
+-	bs.bs_cfpnext = bs.bs_nextdtim + cfpcount*bs.bs_dtimperiod;
+-	bs.bs_cfpmaxduration = 0;
++	bs.bs_intval = TU_TO_USEC(intval);
++	bs.bs_nexttbtt = TU_TO_USEC(nexttbtt);
++	bs.bs_dtimperiod = dtimperiod * bs.bs_intval;
++	bs.bs_nextdtim = bs.bs_nexttbtt + dtimcount * bs.bs_intval;
+ 
+ 	/*
+ 	 * Calculate the number of consecutive beacons to miss* before taking
+@@ -161,7 +147,8 @@ static void ath9k_htc_beacon_config_sta(
+ 	 * XXX fixed at 100ms
+ 	 */
+ 
+-	bs.bs_sleepduration = roundup(IEEE80211_MS_TO_TU(100), sleepduration);
++	bs.bs_sleepduration = TU_TO_USEC(roundup(IEEE80211_MS_TO_TU(100),
++						 sleepduration));
+ 	if (bs.bs_sleepduration > bs.bs_dtimperiod)
+ 		bs.bs_sleepduration = bs.bs_dtimperiod;
+ 
+@@ -170,10 +157,8 @@ static void ath9k_htc_beacon_config_sta(
+ 
+ 	ath_dbg(common, CONFIG, "intval: %u tsf: %llu tsftu: %u\n",
+ 		intval, tsf, tsftu);
+-	ath_dbg(common, CONFIG,
+-		"bmiss: %u sleep: %u cfp-period: %u maxdur: %u next: %u\n",
+-		bs.bs_bmissthreshold, bs.bs_sleepduration,
+-		bs.bs_cfpperiod, bs.bs_cfpmaxduration, bs.bs_cfpnext);
++	ath_dbg(common, CONFIG, "bmiss: %u sleep: %u\n",
++		bs.bs_bmissthreshold, bs.bs_sleepduration);
+ 
+ 	/* Set the computed STA beacon timers */
+ 
+--- a/drivers/net/wireless/ath/ath9k/mac.c
++++ b/drivers/net/wireless/ath/ath9k/mac.c
+@@ -481,8 +481,7 @@ bool ath9k_hw_resettxqueue(struct ath_hw
+ 			    | AR_Q_MISC_CBR_INCR_DIS0);
+ 		value = (qi->tqi_readyTime -
+ 			 (ah->config.sw_beacon_response_time -
+-			  ah->config.dma_beacon_response_time) -
+-			 ah->config.additional_swba_backoff) * 1024;
++			  ah->config.dma_beacon_response_time)) * 1024;
+ 		REG_WRITE(ah, AR_QRDYTIMECFG(q),
+ 			  value | AR_Q_RDYTIMECFG_EN);
+ 		REG_SET_BIT(ah, AR_DMISC(q),
+@@ -550,25 +549,25 @@ int ath9k_hw_rxprocdesc(struct ath_hw *a
+ 
+ 	if (ads.ds_rxstatus8 & AR_PostDelimCRCErr) {
+ 		rs->rs_rssi = ATH9K_RSSI_BAD;
+-		rs->rs_rssi_ctl0 = ATH9K_RSSI_BAD;
+-		rs->rs_rssi_ctl1 = ATH9K_RSSI_BAD;
+-		rs->rs_rssi_ctl2 = ATH9K_RSSI_BAD;
+-		rs->rs_rssi_ext0 = ATH9K_RSSI_BAD;
+-		rs->rs_rssi_ext1 = ATH9K_RSSI_BAD;
+-		rs->rs_rssi_ext2 = ATH9K_RSSI_BAD;
++		rs->rs_rssi_ctl[0] = ATH9K_RSSI_BAD;
++		rs->rs_rssi_ctl[1] = ATH9K_RSSI_BAD;
++		rs->rs_rssi_ctl[2] = ATH9K_RSSI_BAD;
++		rs->rs_rssi_ext[0] = ATH9K_RSSI_BAD;
++		rs->rs_rssi_ext[1] = ATH9K_RSSI_BAD;
++		rs->rs_rssi_ext[2] = ATH9K_RSSI_BAD;
+ 	} else {
+ 		rs->rs_rssi = MS(ads.ds_rxstatus4, AR_RxRSSICombined);
+-		rs->rs_rssi_ctl0 = MS(ads.ds_rxstatus0,
++		rs->rs_rssi_ctl[0] = MS(ads.ds_rxstatus0,
+ 						AR_RxRSSIAnt00);
+-		rs->rs_rssi_ctl1 = MS(ads.ds_rxstatus0,
++		rs->rs_rssi_ctl[1] = MS(ads.ds_rxstatus0,
+ 						AR_RxRSSIAnt01);
+-		rs->rs_rssi_ctl2 = MS(ads.ds_rxstatus0,
++		rs->rs_rssi_ctl[2] = MS(ads.ds_rxstatus0,
+ 						AR_RxRSSIAnt02);
+-		rs->rs_rssi_ext0 = MS(ads.ds_rxstatus4,
++		rs->rs_rssi_ext[0] = MS(ads.ds_rxstatus4,
+ 						AR_RxRSSIAnt10);
+-		rs->rs_rssi_ext1 = MS(ads.ds_rxstatus4,
++		rs->rs_rssi_ext[1] = MS(ads.ds_rxstatus4,
+ 						AR_RxRSSIAnt11);
+-		rs->rs_rssi_ext2 = MS(ads.ds_rxstatus4,
++		rs->rs_rssi_ext[2] = MS(ads.ds_rxstatus4,
+ 						AR_RxRSSIAnt12);
+ 	}
+ 	if (ads.ds_rxstatus8 & AR_RxKeyIdxValid)
+--- a/drivers/net/wireless/ath/ath9k/mac.h
++++ b/drivers/net/wireless/ath/ath9k/mac.h
+@@ -133,12 +133,8 @@ struct ath_rx_status {
+ 	u8 rs_rate;
+ 	u8 rs_antenna;
+ 	u8 rs_more;
+-	int8_t rs_rssi_ctl0;
+-	int8_t rs_rssi_ctl1;
+-	int8_t rs_rssi_ctl2;
+-	int8_t rs_rssi_ext0;
+-	int8_t rs_rssi_ext1;
+-	int8_t rs_rssi_ext2;
++	int8_t rs_rssi_ctl[3];
++	int8_t rs_rssi_ext[3];
+ 	u8 rs_isaggr;
+ 	u8 rs_firstaggr;
+ 	u8 rs_moreaggr;
+--- a/drivers/net/wireless/ath/ath9k/mci.c
++++ b/drivers/net/wireless/ath/ath9k/mci.c
+@@ -200,7 +200,7 @@ skip_tuning:
+ 	if (btcoex->duty_cycle > ATH_MCI_MAX_DUTY_CYCLE)
+ 		btcoex->duty_cycle = ATH_MCI_MAX_DUTY_CYCLE;
+ 
+-	btcoex->btcoex_no_stomp =  btcoex->btcoex_period * 1000 *
++	btcoex->btcoex_no_stomp =  btcoex->btcoex_period *
+ 		(100 - btcoex->duty_cycle) / 100;
+ 
+ 	ath9k_hw_btcoex_enable(sc->sc_ah);
+--- a/drivers/net/wireless/ath/ath9k/recv.c
++++ b/drivers/net/wireless/ath/ath9k/recv.c
+@@ -906,6 +906,7 @@ static void ath9k_process_rssi(struct at
+ 	struct ath_hw *ah = common->ah;
+ 	int last_rssi;
+ 	int rssi = rx_stats->rs_rssi;
++	int i, j;
+ 
+ 	/*
+ 	 * RSSI is not available for subframes in an A-MPDU.
+@@ -924,6 +925,20 @@ static void ath9k_process_rssi(struct at
+ 		return;
+ 	}
+ 
++	for (i = 0, j = 0; i < ARRAY_SIZE(rx_stats->rs_rssi_ctl); i++) {
++		s8 rssi;
++
++		if (!(ah->rxchainmask & BIT(i)))
++			continue;
++
++		rssi = rx_stats->rs_rssi_ctl[i];
++		if (rssi != ATH9K_RSSI_BAD) {
++		    rxs->chains |= BIT(j);
++		    rxs->chain_signal[j] = ah->noise + rssi;
++		}
++		j++;
++	}
++
+ 	/*
+ 	 * Update Beacon RSSI, this is used by ANI.
+ 	 */
+@@ -1073,14 +1088,14 @@ static int ath_process_fft(struct ath_so
+ 		fft_sample_40.channel_type = chan_type;
+ 
+ 		if (chan_type == NL80211_CHAN_HT40PLUS) {
+-			lower_rssi = fix_rssi_inv_only(rs->rs_rssi_ctl0);
+-			upper_rssi = fix_rssi_inv_only(rs->rs_rssi_ext0);
++			lower_rssi = fix_rssi_inv_only(rs->rs_rssi_ctl[0]);
++			upper_rssi = fix_rssi_inv_only(rs->rs_rssi_ext[0]);
+ 
+ 			fft_sample_40.lower_noise = ah->noise;
+ 			fft_sample_40.upper_noise = ext_nf;
+ 		} else {
+-			lower_rssi = fix_rssi_inv_only(rs->rs_rssi_ext0);
+-			upper_rssi = fix_rssi_inv_only(rs->rs_rssi_ctl0);
++			lower_rssi = fix_rssi_inv_only(rs->rs_rssi_ext[0]);
++			upper_rssi = fix_rssi_inv_only(rs->rs_rssi_ctl[0]);
+ 
+ 			fft_sample_40.lower_noise = ext_nf;
+ 			fft_sample_40.upper_noise = ah->noise;
+@@ -1116,7 +1131,7 @@ static int ath_process_fft(struct ath_so
+ 		fft_sample_20.tlv.length = __cpu_to_be16(length);
+ 		fft_sample_20.freq = __cpu_to_be16(freq);
+ 
+-		fft_sample_20.rssi = fix_rssi_inv_only(rs->rs_rssi_ctl0);
++		fft_sample_20.rssi = fix_rssi_inv_only(rs->rs_rssi_ctl[0]);
+ 		fft_sample_20.noise = ah->noise;
+ 
+ 		mag_info = ((struct ath_ht20_mag_info *)radar_info) - 1;

+ 3 - 3
package/kernel/mac80211/patches/402-ath9k-fix-invalid-mac-address-handling.patch

@@ -1,14 +1,14 @@
 --- a/drivers/net/wireless/ath/ath9k/hw.c
 +++ b/drivers/net/wireless/ath/ath9k/hw.c
-@@ -18,6 +18,7 @@
- #include <linux/slab.h>
+@@ -19,6 +19,7 @@
  #include <linux/module.h>
  #include <linux/time.h>
+ #include <linux/bitops.h>
 +#include <linux/etherdevice.h>
  #include <asm/unaligned.h>
  
  #include "hw.h"
-@@ -513,8 +514,16 @@ static int ath9k_hw_init_macaddr(struct 
+@@ -504,8 +505,16 @@ static int ath9k_hw_init_macaddr(struct 
  		common->macaddr[2 * i] = eeval >> 8;
  		common->macaddr[2 * i + 1] = eeval & 0xff;
  	}

+ 1 - 1
package/kernel/mac80211/patches/501-ath9k-eeprom_endianess.patch

@@ -71,7 +71,7 @@
  
 --- a/drivers/net/wireless/ath/ath9k/hw.h
 +++ b/drivers/net/wireless/ath/ath9k/hw.h
-@@ -729,6 +729,7 @@ enum ath_cal_list {
+@@ -706,6 +706,7 @@ enum ath_cal_list {
  #define AH_USE_EEPROM   0x1
  #define AH_UNPLUGGED    0x2 /* The card has been physically removed. */
  #define AH_FASTCC       0x4

+ 1 - 1
package/kernel/mac80211/patches/510-ath9k_intr_mitigation_tweak.patch

@@ -1,6 +1,6 @@
 --- a/drivers/net/wireless/ath/ath9k/hw.c
 +++ b/drivers/net/wireless/ath/ath9k/hw.c
-@@ -2019,8 +2019,8 @@ int ath9k_hw_reset(struct ath_hw *ah, st
+@@ -2010,8 +2010,8 @@ int ath9k_hw_reset(struct ath_hw *ah, st
  		REG_WRITE(ah, AR_OBS, 8);
  
  	if (ah->config.rx_intr_mitigation) {

+ 1 - 1
package/kernel/mac80211/patches/513-ath9k_add_pci_ids.patch

@@ -1,6 +1,6 @@
 --- a/drivers/net/wireless/ath/ath9k/hw.c
 +++ b/drivers/net/wireless/ath/ath9k/hw.c
-@@ -733,6 +733,7 @@ int ath9k_hw_init(struct ath_hw *ah)
+@@ -724,6 +724,7 @@ int ath9k_hw_init(struct ath_hw *ah)
  	case AR9300_DEVID_AR9462:
  	case AR9485_DEVID_AR1111:
  	case AR9300_DEVID_AR9565:

+ 1 - 1
package/kernel/mac80211/patches/521-ath9k_cur_txpower.patch

@@ -14,7 +14,7 @@
  
  out:
  	spin_unlock_bh(&sc->sc_pcu_lock);
-@@ -1340,6 +1344,7 @@ static int ath9k_config(struct ieee80211
+@@ -1345,6 +1349,7 @@ static int ath9k_config(struct ieee80211
  		sc->config.txpowlimit = 2 * conf->power_level;
  		ath9k_cmn_update_txpow(ah, sc->curtxpow,
  				       sc->config.txpowlimit, &sc->curtxpow);

+ 0 - 171
package/kernel/mac80211/patches/522-ath9k_per_chain_signal_strength.patch

@@ -1,171 +0,0 @@
---- a/drivers/net/wireless/ath/ath9k/mac.h
-+++ b/drivers/net/wireless/ath/ath9k/mac.h
-@@ -133,12 +133,8 @@ struct ath_rx_status {
- 	u8 rs_rate;
- 	u8 rs_antenna;
- 	u8 rs_more;
--	int8_t rs_rssi_ctl0;
--	int8_t rs_rssi_ctl1;
--	int8_t rs_rssi_ctl2;
--	int8_t rs_rssi_ext0;
--	int8_t rs_rssi_ext1;
--	int8_t rs_rssi_ext2;
-+	int8_t rs_rssi_ctl[3];
-+	int8_t rs_rssi_ext[3];
- 	u8 rs_isaggr;
- 	u8 rs_firstaggr;
- 	u8 rs_moreaggr;
---- a/drivers/net/wireless/ath/ath9k/recv.c
-+++ b/drivers/net/wireless/ath/ath9k/recv.c
-@@ -906,6 +906,7 @@ static void ath9k_process_rssi(struct at
- 	struct ath_hw *ah = common->ah;
- 	int last_rssi;
- 	int rssi = rx_stats->rs_rssi;
-+	int i, j;
- 
- 	/*
- 	 * RSSI is not available for subframes in an A-MPDU.
-@@ -924,6 +925,20 @@ static void ath9k_process_rssi(struct at
- 		return;
- 	}
- 
-+	for (i = 0, j = 0; i < ARRAY_SIZE(rx_stats->rs_rssi_ctl); i++) {
-+		s8 rssi;
-+
-+		if (!(ah->rxchainmask & BIT(i)))
-+			continue;
-+
-+		rssi = rx_stats->rs_rssi_ctl[i];
-+		if (rssi != ATH9K_RSSI_BAD) {
-+		    rxs->chains |= BIT(j);
-+		    rxs->chain_signal[j] = ah->noise + rssi;
-+		}
-+		j++;
-+	}
-+
- 	/*
- 	 * Update Beacon RSSI, this is used by ANI.
- 	 */
-@@ -1073,14 +1088,14 @@ static int ath_process_fft(struct ath_so
- 		fft_sample_40.channel_type = chan_type;
- 
- 		if (chan_type == NL80211_CHAN_HT40PLUS) {
--			lower_rssi = fix_rssi_inv_only(rs->rs_rssi_ctl0);
--			upper_rssi = fix_rssi_inv_only(rs->rs_rssi_ext0);
-+			lower_rssi = fix_rssi_inv_only(rs->rs_rssi_ctl[0]);
-+			upper_rssi = fix_rssi_inv_only(rs->rs_rssi_ext[0]);
- 
- 			fft_sample_40.lower_noise = ah->noise;
- 			fft_sample_40.upper_noise = ext_nf;
- 		} else {
--			lower_rssi = fix_rssi_inv_only(rs->rs_rssi_ext0);
--			upper_rssi = fix_rssi_inv_only(rs->rs_rssi_ctl0);
-+			lower_rssi = fix_rssi_inv_only(rs->rs_rssi_ext[0]);
-+			upper_rssi = fix_rssi_inv_only(rs->rs_rssi_ctl[0]);
- 
- 			fft_sample_40.lower_noise = ext_nf;
- 			fft_sample_40.upper_noise = ah->noise;
-@@ -1116,7 +1131,7 @@ static int ath_process_fft(struct ath_so
- 		fft_sample_20.tlv.length = __cpu_to_be16(length);
- 		fft_sample_20.freq = __cpu_to_be16(freq);
- 
--		fft_sample_20.rssi = fix_rssi_inv_only(rs->rs_rssi_ctl0);
-+		fft_sample_20.rssi = fix_rssi_inv_only(rs->rs_rssi_ctl[0]);
- 		fft_sample_20.noise = ah->noise;
- 
- 		mag_info = ((struct ath_ht20_mag_info *)radar_info) - 1;
---- a/drivers/net/wireless/ath/ath9k/ar9003_mac.c
-+++ b/drivers/net/wireless/ath/ath9k/ar9003_mac.c
-@@ -476,12 +476,12 @@ int ath9k_hw_process_rxdesc_edma(struct 
- 
- 	/* XXX: Keycache */
- 	rxs->rs_rssi = MS(rxsp->status5, AR_RxRSSICombined);
--	rxs->rs_rssi_ctl0 = MS(rxsp->status1, AR_RxRSSIAnt00);
--	rxs->rs_rssi_ctl1 = MS(rxsp->status1, AR_RxRSSIAnt01);
--	rxs->rs_rssi_ctl2 = MS(rxsp->status1, AR_RxRSSIAnt02);
--	rxs->rs_rssi_ext0 = MS(rxsp->status5, AR_RxRSSIAnt10);
--	rxs->rs_rssi_ext1 = MS(rxsp->status5, AR_RxRSSIAnt11);
--	rxs->rs_rssi_ext2 = MS(rxsp->status5, AR_RxRSSIAnt12);
-+	rxs->rs_rssi_ctl[0] = MS(rxsp->status1, AR_RxRSSIAnt00);
-+	rxs->rs_rssi_ctl[1] = MS(rxsp->status1, AR_RxRSSIAnt01);
-+	rxs->rs_rssi_ctl[2] = MS(rxsp->status1, AR_RxRSSIAnt02);
-+	rxs->rs_rssi_ext[0] = MS(rxsp->status5, AR_RxRSSIAnt10);
-+	rxs->rs_rssi_ext[1] = MS(rxsp->status5, AR_RxRSSIAnt11);
-+	rxs->rs_rssi_ext[2] = MS(rxsp->status5, AR_RxRSSIAnt12);
- 
- 	if (rxsp->status11 & AR_RxKeyIdxValid)
- 		rxs->rs_keyix = MS(rxsp->status11, AR_KeyIdx);
---- a/drivers/net/wireless/ath/ath9k/mac.c
-+++ b/drivers/net/wireless/ath/ath9k/mac.c
-@@ -550,25 +550,25 @@ int ath9k_hw_rxprocdesc(struct ath_hw *a
- 
- 	if (ads.ds_rxstatus8 & AR_PostDelimCRCErr) {
- 		rs->rs_rssi = ATH9K_RSSI_BAD;
--		rs->rs_rssi_ctl0 = ATH9K_RSSI_BAD;
--		rs->rs_rssi_ctl1 = ATH9K_RSSI_BAD;
--		rs->rs_rssi_ctl2 = ATH9K_RSSI_BAD;
--		rs->rs_rssi_ext0 = ATH9K_RSSI_BAD;
--		rs->rs_rssi_ext1 = ATH9K_RSSI_BAD;
--		rs->rs_rssi_ext2 = ATH9K_RSSI_BAD;
-+		rs->rs_rssi_ctl[0] = ATH9K_RSSI_BAD;
-+		rs->rs_rssi_ctl[1] = ATH9K_RSSI_BAD;
-+		rs->rs_rssi_ctl[2] = ATH9K_RSSI_BAD;
-+		rs->rs_rssi_ext[0] = ATH9K_RSSI_BAD;
-+		rs->rs_rssi_ext[1] = ATH9K_RSSI_BAD;
-+		rs->rs_rssi_ext[2] = ATH9K_RSSI_BAD;
- 	} else {
- 		rs->rs_rssi = MS(ads.ds_rxstatus4, AR_RxRSSICombined);
--		rs->rs_rssi_ctl0 = MS(ads.ds_rxstatus0,
-+		rs->rs_rssi_ctl[0] = MS(ads.ds_rxstatus0,
- 						AR_RxRSSIAnt00);
--		rs->rs_rssi_ctl1 = MS(ads.ds_rxstatus0,
-+		rs->rs_rssi_ctl[1] = MS(ads.ds_rxstatus0,
- 						AR_RxRSSIAnt01);
--		rs->rs_rssi_ctl2 = MS(ads.ds_rxstatus0,
-+		rs->rs_rssi_ctl[2] = MS(ads.ds_rxstatus0,
- 						AR_RxRSSIAnt02);
--		rs->rs_rssi_ext0 = MS(ads.ds_rxstatus4,
-+		rs->rs_rssi_ext[0] = MS(ads.ds_rxstatus4,
- 						AR_RxRSSIAnt10);
--		rs->rs_rssi_ext1 = MS(ads.ds_rxstatus4,
-+		rs->rs_rssi_ext[1] = MS(ads.ds_rxstatus4,
- 						AR_RxRSSIAnt11);
--		rs->rs_rssi_ext2 = MS(ads.ds_rxstatus4,
-+		rs->rs_rssi_ext[2] = MS(ads.ds_rxstatus4,
- 						AR_RxRSSIAnt12);
- 	}
- 	if (ads.ds_rxstatus8 & AR_RxKeyIdxValid)
---- a/drivers/net/wireless/ath/ath9k/dfs.c
-+++ b/drivers/net/wireless/ath/ath9k/dfs.c
-@@ -158,8 +158,8 @@ void ath9k_dfs_process_phyerr(struct ath
- 		return;
- 	}
- 
--	ard.rssi = rs->rs_rssi_ctl0;
--	ard.ext_rssi = rs->rs_rssi_ext0;
-+	ard.rssi = rs->rs_rssi_ctl[0];
-+	ard.ext_rssi = rs->rs_rssi_ext[0];
- 
- 	/*
- 	 * hardware stores this as 8 bit signed value.
---- a/drivers/net/wireless/ath/ath9k/antenna.c
-+++ b/drivers/net/wireless/ath/ath9k/antenna.c
-@@ -724,14 +724,14 @@ void ath_ant_comb_scan(struct ath_softc 
- 	struct ath_ant_comb *antcomb = &sc->ant_comb;
- 	int alt_ratio = 0, alt_rssi_avg = 0, main_rssi_avg = 0, curr_alt_set;
- 	int curr_main_set;
--	int main_rssi = rs->rs_rssi_ctl0;
--	int alt_rssi = rs->rs_rssi_ctl1;
-+	int main_rssi = rs->rs_rssi_ctl[0];
-+	int alt_rssi = rs->rs_rssi_ctl[1];
- 	int rx_ant_conf,  main_ant_conf;
- 	bool short_scan = false, ret;
- 
--	rx_ant_conf = (rs->rs_rssi_ctl2 >> ATH_ANT_RX_CURRENT_SHIFT) &
-+	rx_ant_conf = (rs->rs_rssi_ctl[2] >> ATH_ANT_RX_CURRENT_SHIFT) &
- 		       ATH_ANT_RX_MASK;
--	main_ant_conf = (rs->rs_rssi_ctl2 >> ATH_ANT_RX_MAIN_SHIFT) &
-+	main_ant_conf = (rs->rs_rssi_ctl[2] >> ATH_ANT_RX_MAIN_SHIFT) &
- 			 ATH_ANT_RX_MASK;
- 
- 	if (alt_rssi >= antcomb->low_rssi_thresh) {

+ 0 - 0
package/kernel/mac80211/patches/523-mac80211_configure_antenna_gain.patch → package/kernel/mac80211/patches/522-mac80211_configure_antenna_gain.patch


+ 2 - 2
package/kernel/mac80211/patches/524-ath9k_use_configured_antenna_gain.patch → package/kernel/mac80211/patches/523-ath9k_use_configured_antenna_gain.patch

@@ -10,7 +10,7 @@
  
 --- a/drivers/net/wireless/ath/ath9k/hw.c
 +++ b/drivers/net/wireless/ath/ath9k/hw.c
-@@ -2858,7 +2858,7 @@ void ath9k_hw_apply_txpower(struct ath_h
+@@ -2841,7 +2841,7 @@ void ath9k_hw_apply_txpower(struct ath_h
  	channel = chan->chan;
  	chan_pwr = min_t(int, channel->max_power * 2, MAX_RATE_POWER);
  	new_pwr = min_t(int, chan_pwr, reg->power_limit);
@@ -21,7 +21,7 @@
  	if (ant_gain > max_gain)
 --- a/drivers/net/wireless/ath/ath9k/main.c
 +++ b/drivers/net/wireless/ath/ath9k/main.c
-@@ -1340,7 +1340,10 @@ static int ath9k_config(struct ieee80211
+@@ -1345,7 +1345,10 @@ static int ath9k_config(struct ieee80211
  	}
  
  	if (changed & IEEE80211_CONF_CHANGE_POWER) {

+ 3 - 3
package/kernel/mac80211/patches/530-ath9k_extra_leds.patch

@@ -1,6 +1,6 @@
 --- a/drivers/net/wireless/ath/ath9k/ath9k.h
 +++ b/drivers/net/wireless/ath/ath9k/ath9k.h
-@@ -558,6 +558,9 @@ struct ath9k_wow_pattern {
+@@ -557,6 +557,9 @@ struct ath9k_wow_pattern {
  void ath_init_leds(struct ath_softc *sc);
  void ath_deinit_leds(struct ath_softc *sc);
  void ath_fill_led_pin(struct ath_softc *sc);
@@ -10,7 +10,7 @@
  #else
  static inline void ath_init_leds(struct ath_softc *sc)
  {
-@@ -733,6 +736,13 @@ enum spectral_mode {
+@@ -732,6 +735,13 @@ enum spectral_mode {
  	SPECTRAL_CHANSCAN,
  };
  
@@ -24,7 +24,7 @@
  struct ath_softc {
  	struct ieee80211_hw *hw;
  	struct device *dev;
-@@ -775,9 +785,8 @@ struct ath_softc {
+@@ -774,9 +784,8 @@ struct ath_softc {
  	struct ieee80211_supported_band sbands[IEEE80211_NUM_BANDS];
  
  #ifdef CPTCFG_MAC80211_LEDS

+ 2 - 2
package/kernel/mac80211/patches/541-ath9k_rx_dma_stop_check.patch

@@ -1,6 +1,6 @@
 --- a/drivers/net/wireless/ath/ath9k/mac.c
 +++ b/drivers/net/wireless/ath/ath9k/mac.c
-@@ -701,7 +701,7 @@ bool ath9k_hw_stopdmarecv(struct ath_hw 
+@@ -700,7 +700,7 @@ bool ath9k_hw_stopdmarecv(struct ath_hw 
  {
  #define AH_RX_STOP_DMA_TIMEOUT 10000   /* usec */
  	struct ath_common *common = ath9k_hw_common(ah);
@@ -9,7 +9,7 @@
  	int i;
  
  	/* Enable access to the DMA observation bus */
-@@ -731,6 +731,16 @@ bool ath9k_hw_stopdmarecv(struct ath_hw 
+@@ -730,6 +730,16 @@ bool ath9k_hw_stopdmarecv(struct ath_hw 
  	}
  
  	if (i == 0) {

+ 6 - 6
package/kernel/mac80211/patches/542-ath9k_debugfs_diag.patch

@@ -62,7 +62,7 @@
  	debugfs_create_file("interrupt", S_IRUSR, sc->debug.debugfs_phy, sc,
 --- a/drivers/net/wireless/ath/ath9k/hw.h
 +++ b/drivers/net/wireless/ath/ath9k/hw.h
-@@ -482,6 +482,12 @@ enum {
+@@ -469,6 +469,12 @@ enum {
  	ATH9K_RESET_COLD,
  };
  
@@ -75,7 +75,7 @@
  struct ath9k_hw_version {
  	u32 magic;
  	u16 devid;
-@@ -767,6 +773,8 @@ struct ath_hw {
+@@ -744,6 +750,8 @@ struct ath_hw {
  	u32 rfkill_polarity;
  	u32 ah_flags;
  
@@ -84,7 +84,7 @@
  	bool reset_power_on;
  	bool htc_reset_init;
  
-@@ -1019,6 +1027,7 @@ void ath9k_hw_check_nav(struct ath_hw *a
+@@ -995,6 +1003,7 @@ void ath9k_hw_check_nav(struct ath_hw *a
  bool ath9k_hw_check_alive(struct ath_hw *ah);
  
  bool ath9k_hw_setpower(struct ath_hw *ah, enum ath9k_power_mode mode);
@@ -94,7 +94,7 @@
  void ath9k_debug_sync_cause(struct ath_common *common, u32 sync_cause);
 --- a/drivers/net/wireless/ath/ath9k/hw.c
 +++ b/drivers/net/wireless/ath/ath9k/hw.c
-@@ -1863,6 +1863,20 @@ fail:
+@@ -1854,6 +1854,20 @@ fail:
  	return -EINVAL;
  }
  
@@ -115,7 +115,7 @@
  int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,
  		   struct ath9k_hw_cal_data *caldata, bool fastcc)
  {
-@@ -2065,6 +2079,7 @@ int ath9k_hw_reset(struct ath_hw *ah, st
+@@ -2056,6 +2070,7 @@ int ath9k_hw_reset(struct ath_hw *ah, st
  	}
  
  	ath9k_hw_apply_gpio_override(ah);
@@ -125,7 +125,7 @@
  		REG_SET_BIT(ah, AR_BTCOEX_WL_LNADIV, AR_BTCOEX_WL_LNADIV_FORCE_ON);
 --- a/drivers/net/wireless/ath/ath9k/main.c
 +++ b/drivers/net/wireless/ath/ath9k/main.c
-@@ -571,6 +571,11 @@ irqreturn_t ath_isr(int irq, void *dev)
+@@ -574,6 +574,11 @@ irqreturn_t ath_isr(int irq, void *dev)
  	ath9k_hw_getisr(ah, &status);	/* NB: clears ISR too */
  	status &= ah->imask;	/* discard unasked-for bits */
  

+ 2 - 2
package/kernel/mac80211/patches/543-ath9k-allow-to-disable-bands-via-platform-data.patch

@@ -11,7 +11,7 @@
  	int (*external_reset)(void);
 --- a/drivers/net/wireless/ath/ath9k/hw.c
 +++ b/drivers/net/wireless/ath/ath9k/hw.c
-@@ -2458,17 +2458,25 @@ int ath9k_hw_fill_cap_info(struct ath_hw
+@@ -2441,17 +2441,25 @@ int ath9k_hw_fill_cap_info(struct ath_hw
  	}
  
  	eeval = ah->eep_ops->get_eeprom(ah, EEP_OP_MODE);
@@ -47,7 +47,7 @@
  	    AR_SREV_9285(ah) ||
 --- a/drivers/net/wireless/ath/ath9k/hw.h
 +++ b/drivers/net/wireless/ath/ath9k/hw.h
-@@ -938,6 +938,8 @@ struct ath_hw {
+@@ -914,6 +914,8 @@ struct ath_hw {
  	bool is_clk_25mhz;
  	int (*get_mac_revision)(void);
  	int (*external_reset)(void);

+ 2 - 2
package/kernel/mac80211/patches/550-ath9k_entropy_from_adc.patch

@@ -1,6 +1,6 @@
 --- a/drivers/net/wireless/ath/ath9k/hw.h
 +++ b/drivers/net/wireless/ath/ath9k/hw.h
-@@ -684,6 +684,7 @@ struct ath_spec_scan {
+@@ -661,6 +661,7 @@ struct ath_spec_scan {
   * @config_pci_powersave:
   * @calibrate: periodic calibration for NF, ANI, IQ, ADC gain, ADC-DC
   *
@@ -8,7 +8,7 @@
   * @spectral_scan_config: set parameters for spectral scan and enable/disable it
   * @spectral_scan_trigger: trigger a spectral scan run
   * @spectral_scan_wait: wait for a spectral scan run to finish
-@@ -706,6 +707,7 @@ struct ath_hw_ops {
+@@ -683,6 +684,7 @@ struct ath_hw_ops {
  			struct ath_hw_antcomb_conf *antconf);
  	void (*antdiv_comb_conf_set)(struct ath_hw *ah,
  			struct ath_hw_antcomb_conf *antconf);