From b81588bd0866017338b35434afa0232fd9df6ba7 Mon Sep 17 00:00:00 2001
From: Felix Fietkau <nbd@openwrt.org>
Date: Sat, 17 Sep 2011 16:02:56 +0000
Subject: ath9k: add some cleanup patches and rework tx power handling

SVN-Revision: 28253
---
 .../mac80211/patches/531-ath9k_cur_txpower.patch   |  16 -
 .../patches/580-ath9k_cleanup_set_interrupt.patch  | 155 +++++
 .../581-ath9k_cleanup_txpower_handling.patch       | 627 +++++++++++++++++++++
 .../patches/582-ath9k_remove_current_rd_ext.patch  |  34 ++
 .../patches/583-ath9k_remove_eep_reg_1.patch       |  54 ++
 5 files changed, 870 insertions(+), 16 deletions(-)
 create mode 100644 package/mac80211/patches/580-ath9k_cleanup_set_interrupt.patch
 create mode 100644 package/mac80211/patches/581-ath9k_cleanup_txpower_handling.patch
 create mode 100644 package/mac80211/patches/582-ath9k_remove_current_rd_ext.patch
 create mode 100644 package/mac80211/patches/583-ath9k_remove_eep_reg_1.patch

(limited to 'package')

diff --git a/package/mac80211/patches/531-ath9k_cur_txpower.patch b/package/mac80211/patches/531-ath9k_cur_txpower.patch
index 9a2ce9e43a..894d780420 100644
--- a/package/mac80211/patches/531-ath9k_cur_txpower.patch
+++ b/package/mac80211/patches/531-ath9k_cur_txpower.patch
@@ -17,19 +17,3 @@
  	}
  
  	if (disable_radio) {
---- a/drivers/net/wireless/ath/ath9k/common.c
-+++ b/drivers/net/wireless/ath/ath9k/common.c
-@@ -161,10 +161,12 @@ EXPORT_SYMBOL(ath9k_cmn_count_streams);
- void ath9k_cmn_update_txpow(struct ath_hw *ah, u16 cur_txpow,
- 			    u16 new_txpow, u16 *txpower)
- {
-+	struct ath_regulatory *reg = ath9k_hw_regulatory(ah);
-+
- 	if (cur_txpow != new_txpow) {
- 		ath9k_hw_set_txpowerlimit(ah, new_txpow, false);
- 		/* read back in case value is clamped */
--		*txpower = ath9k_hw_regulatory(ah)->power_limit;
-+		*txpower = min_t(u16, reg->power_limit, reg->max_power_level);
- 	}
- }
- EXPORT_SYMBOL(ath9k_cmn_update_txpow);
diff --git a/package/mac80211/patches/580-ath9k_cleanup_set_interrupt.patch b/package/mac80211/patches/580-ath9k_cleanup_set_interrupt.patch
new file mode 100644
index 0000000000..8723e50410
--- /dev/null
+++ b/package/mac80211/patches/580-ath9k_cleanup_set_interrupt.patch
@@ -0,0 +1,155 @@
+--- a/drivers/net/wireless/ath/ath9k/beacon.c
++++ b/drivers/net/wireless/ath/ath9k/beacon.c
+@@ -515,7 +515,7 @@ static void ath_beacon_config_ap(struct 
+ 	sc->sc_flags |= SC_OP_TSF_RESET;
+ 	ath9k_beacon_init(sc, nexttbtt, intval);
+ 	sc->beacon.bmisscnt = 0;
+-	ath9k_hw_set_interrupts(ah, ah->imask);
++	ath9k_hw_set_interrupts(ah);
+ 	ath9k_hw_enable_interrupts(ah);
+ }
+ 
+@@ -643,7 +643,7 @@ static void ath_beacon_config_sta(struct
+ 	ath9k_hw_set_sta_beacon_timers(ah, &bs);
+ 	ah->imask |= ATH9K_INT_BMISS;
+ 
+-	ath9k_hw_set_interrupts(ah, ah->imask);
++	ath9k_hw_set_interrupts(ah);
+ 	ath9k_hw_enable_interrupts(ah);
+ }
+ 
+@@ -679,7 +679,7 @@ static void ath_beacon_config_adhoc(stru
+ 	ath9k_beacon_init(sc, nexttbtt, intval);
+ 	sc->beacon.bmisscnt = 0;
+ 
+-	ath9k_hw_set_interrupts(ah, ah->imask);
++	ath9k_hw_set_interrupts(ah);
+ 	ath9k_hw_enable_interrupts(ah);
+ }
+ 
+@@ -821,11 +821,11 @@ void ath9k_set_beaconing_status(struct a
+ 	if (status) {
+ 		/* Re-enable beaconing */
+ 		ah->imask |= ATH9K_INT_SWBA;
+-		ath9k_hw_set_interrupts(ah, ah->imask);
++		ath9k_hw_set_interrupts(ah);
+ 	} else {
+ 		/* Disable SWBA interrupt */
+ 		ah->imask &= ~ATH9K_INT_SWBA;
+-		ath9k_hw_set_interrupts(ah, ah->imask);
++		ath9k_hw_set_interrupts(ah);
+ 		tasklet_kill(&sc->bcon_tasklet);
+ 		ath9k_hw_stop_dma_queue(ah, sc->beacon.beaconq);
+ 	}
+--- a/drivers/net/wireless/ath/ath9k/gpio.c
++++ b/drivers/net/wireless/ath/ath9k/gpio.c
+@@ -151,7 +151,7 @@ static void ath9k_gen_timer_start(struct
+ 	if ((ah->imask & ATH9K_INT_GENTIMER) == 0) {
+ 		ath9k_hw_disable_interrupts(ah);
+ 		ah->imask |= ATH9K_INT_GENTIMER;
+-		ath9k_hw_set_interrupts(ah, ah->imask);
++		ath9k_hw_set_interrupts(ah);
+ 		ath9k_hw_enable_interrupts(ah);
+ 	}
+ }
+@@ -166,7 +166,7 @@ static void ath9k_gen_timer_stop(struct 
+ 	if (timer_table->timer_mask.val == 0) {
+ 		ath9k_hw_disable_interrupts(ah);
+ 		ah->imask &= ~ATH9K_INT_GENTIMER;
+-		ath9k_hw_set_interrupts(ah, ah->imask);
++		ath9k_hw_set_interrupts(ah);
+ 		ath9k_hw_enable_interrupts(ah);
+ 	}
+ }
+--- a/drivers/net/wireless/ath/ath9k/main.c
++++ b/drivers/net/wireless/ath/ath9k/main.c
+@@ -273,7 +273,7 @@ static bool ath_complete_reset(struct at
+ 
+ 	ath9k_cmn_update_txpow(ah, sc->curtxpow,
+ 			       sc->config.txpowlimit, &sc->curtxpow);
+-	ath9k_hw_set_interrupts(ah, ah->imask);
++	ath9k_hw_set_interrupts(ah);
+ 	ath9k_hw_enable_interrupts(ah);
+ 
+ 	if (!(sc->sc_flags & (SC_OP_OFFCHANNEL)) && start) {
+@@ -833,7 +833,7 @@ irqreturn_t ath_isr(int irq, void *dev)
+ 
+ 	if (status & ATH9K_INT_RXEOL) {
+ 		ah->imask &= ~(ATH9K_INT_RXEOL | ATH9K_INT_RXORN);
+-		ath9k_hw_set_interrupts(ah, ah->imask);
++		ath9k_hw_set_interrupts(ah);
+ 	}
+ 
+ 	if (status & ATH9K_INT_MIB) {
+@@ -1409,7 +1409,7 @@ static void ath9k_calculate_summary_stat
+ 		ah->imask &= ~ATH9K_INT_TSFOOR;
+ 	}
+ 
+-	ath9k_hw_set_interrupts(ah, ah->imask);
++	ath9k_hw_set_interrupts(ah);
+ 
+ 	/* Set up ANI */
+ 	if (iter_data.naps > 0) {
+@@ -1566,7 +1566,7 @@ static void ath9k_enable_ps(struct ath_s
+ 	if (!(ah->caps.hw_caps & ATH9K_HW_CAP_AUTOSLEEP)) {
+ 		if ((ah->imask & ATH9K_INT_TIM_TIMER) == 0) {
+ 			ah->imask |= ATH9K_INT_TIM_TIMER;
+-			ath9k_hw_set_interrupts(ah, ah->imask);
++			ath9k_hw_set_interrupts(ah);
+ 		}
+ 		ath9k_hw_setrxabort(ah, 1);
+ 	}
+@@ -1586,7 +1586,7 @@ static void ath9k_disable_ps(struct ath_
+ 				  PS_WAIT_FOR_TX_ACK);
+ 		if (ah->imask & ATH9K_INT_TIM_TIMER) {
+ 			ah->imask &= ~ATH9K_INT_TIM_TIMER;
+-			ath9k_hw_set_interrupts(ah, ah->imask);
++			ath9k_hw_set_interrupts(ah);
+ 		}
+ 	}
+ 
+--- a/drivers/net/wireless/ath/ath9k/recv.c
++++ b/drivers/net/wireless/ath/ath9k/recv.c
+@@ -1977,7 +1977,7 @@ requeue:
+ 
+ 	if (!(ah->imask & ATH9K_INT_RXEOL)) {
+ 		ah->imask |= (ATH9K_INT_RXEOL | ATH9K_INT_RXORN);
+-		ath9k_hw_set_interrupts(ah, ah->imask);
++		ath9k_hw_set_interrupts(ah);
+ 	}
+ 
+ 	return 0;
+--- a/drivers/net/wireless/ath/ath9k/mac.c
++++ b/drivers/net/wireless/ath/ath9k/mac.c
+@@ -827,9 +827,9 @@ void ath9k_hw_enable_interrupts(struct a
+ }
+ EXPORT_SYMBOL(ath9k_hw_enable_interrupts);
+ 
+-void ath9k_hw_set_interrupts(struct ath_hw *ah, enum ath9k_int ints)
++void ath9k_hw_set_interrupts(struct ath_hw *ah)
+ {
+-	enum ath9k_int omask = ah->imask;
++	enum ath9k_int ints = ah->imask;
+ 	u32 mask, mask2;
+ 	struct ath9k_hw_capabilities *pCap = &ah->caps;
+ 	struct ath_common *common = ath9k_hw_common(ah);
+@@ -837,7 +837,7 @@ void ath9k_hw_set_interrupts(struct ath_
+ 	if (!(ints & ATH9K_INT_GLOBAL))
+ 		ath9k_hw_disable_interrupts(ah);
+ 
+-	ath_dbg(common, ATH_DBG_INTERRUPT, "0x%x => 0x%x\n", omask, ints);
++	ath_dbg(common, ATH_DBG_INTERRUPT, "New interrupt mask 0x%x\n", ints);
+ 
+ 	mask = ints & ATH9K_INT_COMMON;
+ 	mask2 = 0;
+--- a/drivers/net/wireless/ath/ath9k/mac.h
++++ b/drivers/net/wireless/ath/ath9k/mac.h
+@@ -734,7 +734,7 @@ int ath9k_hw_beaconq_setup(struct ath_hw
+ 
+ /* Interrupt Handling */
+ bool ath9k_hw_intrpend(struct ath_hw *ah);
+-void ath9k_hw_set_interrupts(struct ath_hw *ah, enum ath9k_int ints);
++void ath9k_hw_set_interrupts(struct ath_hw *ah);
+ void ath9k_hw_enable_interrupts(struct ath_hw *ah);
+ void ath9k_hw_disable_interrupts(struct ath_hw *ah);
+ 
diff --git a/package/mac80211/patches/581-ath9k_cleanup_txpower_handling.patch b/package/mac80211/patches/581-ath9k_cleanup_txpower_handling.patch
new file mode 100644
index 0000000000..9d92aba8b2
--- /dev/null
+++ b/package/mac80211/patches/581-ath9k_cleanup_txpower_handling.patch
@@ -0,0 +1,627 @@
+--- a/drivers/net/wireless/ath/ath.h
++++ b/drivers/net/wireless/ath/ath.h
+@@ -71,7 +71,6 @@ struct ath_regulatory {
+ 	char alpha2[2];
+ 	u16 country_code;
+ 	u16 max_power_level;
+-	u32 tp_scale;
+ 	u16 current_rd;
+ 	u16 current_rd_ext;
+ 	int16_t power_limit;
+--- a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c
++++ b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c
+@@ -3040,6 +3040,10 @@ static u32 ath9k_hw_ar9300_get_eeprom(st
+ 		return (pBase->miscConfiguration >> 0x3) & 0x1;
+ 	case EEP_ANT_DIV_CTL1:
+ 		return eep->base_ext1.ant_div_control;
++	case EEP_ANTENNA_GAIN_5G:
++		return eep->modalHeader5G.antennaGain;
++	case EEP_ANTENNA_GAIN_2G:
++		return eep->modalHeader2G.antennaGain;
+ 	default:
+ 		return 0;
+ 	}
+@@ -4727,20 +4731,14 @@ static u16 ar9003_hw_get_max_edge_power(
+ static void ar9003_hw_set_power_per_rate_table(struct ath_hw *ah,
+ 					       struct ath9k_channel *chan,
+ 					       u8 *pPwrArray, u16 cfgCtl,
+-					       u8 twiceAntennaReduction,
+-					       u8 twiceMaxRegulatoryPower,
++					       u8 antenna_reduction,
+ 					       u16 powerLimit)
+ {
+-	struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah);
+ 	struct ath_common *common = ath9k_hw_common(ah);
+ 	struct ar9300_eeprom *pEepData = &ah->eeprom.ar9300_eep;
+ 	u16 twiceMaxEdgePower = MAX_RATE_POWER;
+-	static const u16 tpScaleReductionTable[5] = {
+-		0, 3, 6, 9, MAX_RATE_POWER
+-	};
+ 	int i;
+-	int16_t  twiceLargestAntenna;
+-	u16 scaledPower = 0, minCtlPower, maxRegAllowedPower;
++	u16 scaledPower = 0, minCtlPower;
+ 	static const u16 ctlModesFor11a[] = {
+ 		CTL_11A, CTL_5GHT20, CTL_11A_EXT, CTL_5GHT40
+ 	};
+@@ -4758,28 +4756,7 @@ static void ar9003_hw_set_power_per_rate
+ 	bool is2ghz = IS_CHAN_2GHZ(chan);
+ 
+ 	ath9k_hw_get_channel_centers(ah, chan, &centers);
+-
+-	/* Compute TxPower reduction due to Antenna Gain */
+-	if (is2ghz)
+-		twiceLargestAntenna = pEepData->modalHeader2G.antennaGain;
+-	else
+-		twiceLargestAntenna = pEepData->modalHeader5G.antennaGain;
+-
+-	twiceLargestAntenna = (int16_t)min((twiceAntennaReduction) -
+-				twiceLargestAntenna, 0);
+-
+-	/*
+-	 * scaledPower is the minimum of the user input power level
+-	 * and the regulatory allowed power level
+-	 */
+-	maxRegAllowedPower = twiceMaxRegulatoryPower + twiceLargestAntenna;
+-
+-	if (regulatory->tp_scale != ATH9K_TP_SCALE_MAX) {
+-		maxRegAllowedPower -=
+-			(tpScaleReductionTable[(regulatory->tp_scale)] * 2);
+-	}
+-
+-	scaledPower = min(powerLimit, maxRegAllowedPower);
++	scaledPower = powerLimit - antenna_reduction;
+ 
+ 	/*
+ 	 * Reduce scaled Power by number of chains active to get
+@@ -4966,7 +4943,6 @@ static inline u8 mcsidx_to_tgtpwridx(uns
+ static void ath9k_hw_ar9300_set_txpower(struct ath_hw *ah,
+ 					struct ath9k_channel *chan, u16 cfgCtl,
+ 					u8 twiceAntennaReduction,
+-					u8 twiceMaxRegulatoryPower,
+ 					u8 powerLimit, bool test)
+ {
+ 	struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah);
+@@ -5019,7 +4995,6 @@ static void ath9k_hw_ar9300_set_txpower(
+ 	ar9003_hw_set_power_per_rate_table(ah, chan,
+ 					   targetPowerValT2, cfgCtl,
+ 					   twiceAntennaReduction,
+-					   twiceMaxRegulatoryPower,
+ 					   powerLimit);
+ 
+ 	if (ah->eep_ops->get_eeprom(ah, EEP_PAPRD)) {
+--- a/drivers/net/wireless/ath/ath9k/hw.c
++++ b/drivers/net/wireless/ath/ath9k/hw.c
+@@ -429,7 +429,6 @@ static void ath9k_hw_init_defaults(struc
+ 
+ 	regulatory->country_code = CTRY_DEFAULT;
+ 	regulatory->power_limit = MAX_RATE_POWER;
+-	regulatory->tp_scale = ATH9K_TP_SCALE_MAX;
+ 
+ 	ah->hw_version.magic = AR5416_MAGIC;
+ 	ah->hw_version.subvendorid = 0;
+@@ -1396,9 +1395,7 @@ static bool ath9k_hw_chip_reset(struct a
+ static bool ath9k_hw_channel_change(struct ath_hw *ah,
+ 				    struct ath9k_channel *chan)
+ {
+-	struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah);
+ 	struct ath_common *common = ath9k_hw_common(ah);
+-	struct ieee80211_channel *channel = chan->chan;
+ 	u32 qnum;
+ 	int r;
+ 
+@@ -1423,14 +1420,7 @@ static bool ath9k_hw_channel_change(stru
+ 		return false;
+ 	}
+ 	ath9k_hw_set_clockrate(ah);
+-
+-	ah->eep_ops->set_txpower(ah, chan,
+-			     ath9k_regd_get_ctl(regulatory, chan),
+-			     channel->max_antenna_gain * 2,
+-			     channel->max_power * 2,
+-			     min((u32) MAX_RATE_POWER,
+-			     (u32) regulatory->power_limit), false);
+-
++	ath9k_hw_apply_txpower(ah, chan);
+ 	ath9k_hw_rfbus_done(ah);
+ 
+ 	if (IS_CHAN_OFDM(chan) || IS_CHAN_HT(chan))
+@@ -2466,23 +2456,56 @@ bool ath9k_hw_disable(struct ath_hw *ah)
+ }
+ EXPORT_SYMBOL(ath9k_hw_disable);
+ 
++static int get_antenna_gain(struct ath_hw *ah, struct ath9k_channel *chan)
++{
++	enum eeprom_param gain_param;
++
++	if (IS_CHAN_2GHZ(chan))
++		gain_param = EEP_ANTENNA_GAIN_2G;
++	else
++		gain_param = EEP_ANTENNA_GAIN_5G;
++
++	return ah->eep_ops->get_eeprom(ah, gain_param);
++}
++
++void ath9k_hw_apply_txpower(struct ath_hw *ah, struct ath9k_channel *chan)
++{
++	struct ath_regulatory *reg = ath9k_hw_regulatory(ah);
++	struct ieee80211_channel *channel;
++	int chan_pwr, new_pwr, max_gain;
++	int ant_gain, ant_reduction = 0;
++
++	if (!chan)
++		return;
++
++	channel = chan->chan;
++	chan_pwr = min_t(int, channel->max_power * 2, MAX_RATE_POWER);
++	new_pwr = min_t(int, chan_pwr, reg->power_limit);
++	max_gain = new_pwr - chan_pwr + channel->max_antenna_gain * 2;
++
++	ant_gain = get_antenna_gain(ah, chan);
++	if (ant_gain > max_gain)
++		ant_reduction = ant_gain - max_gain;
++
++	ah->eep_ops->set_txpower(ah, chan,
++				 ath9k_regd_get_ctl(reg, chan),
++				 ant_reduction, new_pwr, false);
++}
++
+ void ath9k_hw_set_txpowerlimit(struct ath_hw *ah, u32 limit, bool test)
+ {
+-	struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah);
++	struct ath_regulatory *reg = ath9k_hw_regulatory(ah);
+ 	struct ath9k_channel *chan = ah->curchan;
+ 	struct ieee80211_channel *channel = chan->chan;
+-	int reg_pwr = min_t(int, MAX_RATE_POWER, limit);
+-	int chan_pwr = channel->max_power * 2;
+ 
++	reg->power_limit = min_t(int, limit, MAX_RATE_POWER);
+ 	if (test)
+-		reg_pwr = chan_pwr = MAX_RATE_POWER;
++		channel->max_power = MAX_RATE_POWER / 2;
+ 
+-	regulatory->power_limit = reg_pwr;
++	ath9k_hw_apply_txpower(ah, chan);
+ 
+-	ah->eep_ops->set_txpower(ah, chan,
+-				 ath9k_regd_get_ctl(regulatory, chan),
+-				 channel->max_antenna_gain * 2,
+-				 chan_pwr, reg_pwr, test);
++	if (test)
++		channel->max_power = DIV_ROUND_UP(reg->max_power_level, 2);
+ }
+ EXPORT_SYMBOL(ath9k_hw_set_txpowerlimit);
+ 
+--- a/drivers/net/wireless/ath/ath9k/hw.h
++++ b/drivers/net/wireless/ath/ath9k/hw.h
+@@ -389,14 +389,6 @@ enum ath9k_power_mode {
+ 	ATH9K_PM_UNDEFINED
+ };
+ 
+-enum ath9k_tp_scale {
+-	ATH9K_TP_SCALE_MAX = 0,
+-	ATH9K_TP_SCALE_50,
+-	ATH9K_TP_SCALE_25,
+-	ATH9K_TP_SCALE_12,
+-	ATH9K_TP_SCALE_MIN
+-};
+-
+ enum ser_reg_mode {
+ 	SER_REG_MODE_OFF = 0,
+ 	SER_REG_MODE_ON = 1,
+@@ -964,6 +956,7 @@ void ath9k_hw_htc_resetinit(struct ath_h
+ /* PHY */
+ void ath9k_hw_get_delta_slope_vals(struct ath_hw *ah, u32 coef_scaled,
+ 				   u32 *coef_mantissa, u32 *coef_exponent);
++void ath9k_hw_apply_txpower(struct ath_hw *ah, struct ath9k_channel *chan);
+ 
+ /*
+  * Code Specific to AR5008, AR9001 or AR9002,
+--- a/drivers/net/wireless/ath/ath9k/eeprom_4k.c
++++ b/drivers/net/wireless/ath/ath9k/eeprom_4k.c
+@@ -350,6 +350,8 @@ static u32 ath9k_hw_4k_get_eeprom(struct
+ 		return pModal->antdiv_ctl1;
+ 	case EEP_TXGAIN_TYPE:
+ 		return pBase->txGainType;
++	case EEP_ANTENNA_GAIN_2G:
++		return pModal->antennaGainCh[0];
+ 	default:
+ 		return 0;
+ 	}
+@@ -462,8 +464,7 @@ static void ath9k_hw_set_4k_power_per_ra
+ 						 struct ath9k_channel *chan,
+ 						 int16_t *ratesArray,
+ 						 u16 cfgCtl,
+-						 u16 AntennaReduction,
+-						 u16 twiceMaxRegulatoryPower,
++						 u16 antenna_reduction,
+ 						 u16 powerLimit)
+ {
+ #define CMP_TEST_GRP \
+@@ -472,20 +473,16 @@ static void ath9k_hw_set_4k_power_per_ra
+ 	|| (((cfgCtl & ~CTL_MODE_M) | (pCtlMode[ctlMode] & CTL_MODE_M)) == \
+ 	    ((pEepData->ctlIndex[i] & CTL_MODE_M) | SD_NO_CTL))
+ 
+-	struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah);
+ 	int i;
+-	int16_t twiceLargestAntenna;
+ 	u16 twiceMinEdgePower;
+ 	u16 twiceMaxEdgePower = MAX_RATE_POWER;
+-	u16 scaledPower = 0, minCtlPower, maxRegAllowedPower;
++	u16 scaledPower = 0, minCtlPower;
+ 	u16 numCtlModes;
+ 	const u16 *pCtlMode;
+ 	u16 ctlMode, freq;
+ 	struct chan_centers centers;
+ 	struct cal_ctl_data_4k *rep;
+ 	struct ar5416_eeprom_4k *pEepData = &ah->eeprom.map4k;
+-	static const u16 tpScaleReductionTable[5] =
+-		{ 0, 3, 6, 9, MAX_RATE_POWER };
+ 	struct cal_target_power_leg targetPowerOfdm, targetPowerCck = {
+ 		0, { 0, 0, 0, 0}
+ 	};
+@@ -503,19 +500,7 @@ static void ath9k_hw_set_4k_power_per_ra
+ 
+ 	ath9k_hw_get_channel_centers(ah, chan, &centers);
+ 
+-	twiceLargestAntenna = pEepData->modalHeader.antennaGainCh[0];
+-	twiceLargestAntenna = (int16_t)min(AntennaReduction -
+-					   twiceLargestAntenna, 0);
+-
+-	maxRegAllowedPower = twiceMaxRegulatoryPower + twiceLargestAntenna;
+-	if (regulatory->tp_scale != ATH9K_TP_SCALE_MAX) {
+-		maxRegAllowedPower -=
+-			(tpScaleReductionTable[(regulatory->tp_scale)] * 2);
+-	}
+-
+-	scaledPower = min(powerLimit, maxRegAllowedPower);
+-	scaledPower = max((u16)0, scaledPower);
+-
++	scaledPower = powerLimit - antenna_reduction;
+ 	numCtlModes = ARRAY_SIZE(ctlModesFor11g) - SUB_NUM_CTL_MODES_AT_2G_40;
+ 	pCtlMode = ctlModesFor11g;
+ 
+@@ -671,7 +656,6 @@ static void ath9k_hw_4k_set_txpower(stru
+ 				    struct ath9k_channel *chan,
+ 				    u16 cfgCtl,
+ 				    u8 twiceAntennaReduction,
+-				    u8 twiceMaxRegulatoryPower,
+ 				    u8 powerLimit, bool test)
+ {
+ 	struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah);
+@@ -691,7 +675,6 @@ static void ath9k_hw_4k_set_txpower(stru
+ 	ath9k_hw_set_4k_power_per_rate_table(ah, chan,
+ 					     &ratesArray[0], cfgCtl,
+ 					     twiceAntennaReduction,
+-					     twiceMaxRegulatoryPower,
+ 					     powerLimit);
+ 
+ 	ath9k_hw_set_4k_power_cal_table(ah, chan);
+--- a/drivers/net/wireless/ath/ath9k/eeprom_9287.c
++++ b/drivers/net/wireless/ath/ath9k/eeprom_9287.c
+@@ -336,6 +336,9 @@ static u32 ath9k_hw_ar9287_get_eeprom(st
+ 			return pBase->tempSensSlopePalOn;
+ 		else
+ 			return 0;
++	case EEP_ANTENNA_GAIN_2G:
++		return max_t(u8, pModal->antennaGainCh[0],
++				 pModal->antennaGainCh[1]);
+ 	default:
+ 		return 0;
+ 	}
+@@ -554,8 +557,7 @@ static void ath9k_hw_set_ar9287_power_pe
+ 						     struct ath9k_channel *chan,
+ 						     int16_t *ratesArray,
+ 						     u16 cfgCtl,
+-						     u16 AntennaReduction,
+-						     u16 twiceMaxRegulatoryPower,
++						     u16 antenna_reduction,
+ 						     u16 powerLimit)
+ {
+ #define CMP_CTL \
+@@ -569,12 +571,8 @@ static void ath9k_hw_set_ar9287_power_pe
+ #define REDUCE_SCALED_POWER_BY_TWO_CHAIN     6
+ #define REDUCE_SCALED_POWER_BY_THREE_CHAIN   10
+ 
+-	struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah);
+ 	u16 twiceMaxEdgePower = MAX_RATE_POWER;
+-	static const u16 tpScaleReductionTable[5] =
+-		{ 0, 3, 6, 9, MAX_RATE_POWER };
+ 	int i;
+-	int16_t twiceLargestAntenna;
+ 	struct cal_ctl_data_ar9287 *rep;
+ 	struct cal_target_power_leg targetPowerOfdm = {0, {0, 0, 0, 0} },
+ 				    targetPowerCck = {0, {0, 0, 0, 0} };
+@@ -582,7 +580,7 @@ static void ath9k_hw_set_ar9287_power_pe
+ 				    targetPowerCckExt = {0, {0, 0, 0, 0} };
+ 	struct cal_target_power_ht targetPowerHt20,
+ 				    targetPowerHt40 = {0, {0, 0, 0, 0} };
+-	u16 scaledPower = 0, minCtlPower, maxRegAllowedPower;
++	u16 scaledPower = 0, minCtlPower;
+ 	static const u16 ctlModesFor11g[] = {
+ 		CTL_11B, CTL_11G, CTL_2GHT20,
+ 		CTL_11B_EXT, CTL_11G_EXT, CTL_2GHT40
+@@ -597,24 +595,7 @@ static void ath9k_hw_set_ar9287_power_pe
+ 	tx_chainmask = ah->txchainmask;
+ 
+ 	ath9k_hw_get_channel_centers(ah, chan, &centers);
+-
+-	/* Compute TxPower reduction due to Antenna Gain */
+-	twiceLargestAntenna = max(pEepData->modalHeader.antennaGainCh[0],
+-				  pEepData->modalHeader.antennaGainCh[1]);
+-	twiceLargestAntenna = (int16_t)min((AntennaReduction) -
+-					   twiceLargestAntenna, 0);
+-
+-	/*
+-	 * scaledPower is the minimum of the user input power level
+-	 * and the regulatory allowed power level.
+-	 */
+-	maxRegAllowedPower = twiceMaxRegulatoryPower + twiceLargestAntenna;
+-
+-	if (regulatory->tp_scale != ATH9K_TP_SCALE_MAX)
+-		maxRegAllowedPower -=
+-			(tpScaleReductionTable[(regulatory->tp_scale)] * 2);
+-
+-	scaledPower = min(powerLimit, maxRegAllowedPower);
++	scaledPower = powerLimit - antenna_reduction;
+ 
+ 	/*
+ 	 * Reduce scaled Power by number of chains active
+@@ -815,7 +796,6 @@ static void ath9k_hw_set_ar9287_power_pe
+ static void ath9k_hw_ar9287_set_txpower(struct ath_hw *ah,
+ 					struct ath9k_channel *chan, u16 cfgCtl,
+ 					u8 twiceAntennaReduction,
+-					u8 twiceMaxRegulatoryPower,
+ 					u8 powerLimit, bool test)
+ {
+ 	struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah);
+@@ -834,7 +814,6 @@ static void ath9k_hw_ar9287_set_txpower(
+ 	ath9k_hw_set_ar9287_power_per_rate_table(ah, chan,
+ 						 &ratesArray[0], cfgCtl,
+ 						 twiceAntennaReduction,
+-						 twiceMaxRegulatoryPower,
+ 						 powerLimit);
+ 
+ 	ath9k_hw_set_ar9287_power_cal_table(ah, chan);
+--- a/drivers/net/wireless/ath/ath9k/eeprom_def.c
++++ b/drivers/net/wireless/ath/ath9k/eeprom_def.c
+@@ -400,6 +400,7 @@ static u32 ath9k_hw_def_get_eeprom(struc
+ 	struct ar5416_eeprom_def *eep = &ah->eeprom.def;
+ 	struct modal_eep_header *pModal = eep->modalHeader;
+ 	struct base_eep_header *pBase = &eep->baseEepHeader;
++	int band = 0;
+ 
+ 	switch (param) {
+ 	case EEP_NFTHRESH_5:
+@@ -467,6 +468,14 @@ static u32 ath9k_hw_def_get_eeprom(struc
+ 			return pBase->pwr_table_offset;
+ 		else
+ 			return AR5416_PWR_TABLE_OFFSET_DB;
++	case EEP_ANTENNA_GAIN_2G:
++		band = 1;
++		/* fall through */
++	case EEP_ANTENNA_GAIN_5G:
++		return max_t(u8, max_t(u8,
++			pModal[band].antennaGainCh[0],
++			pModal[band].antennaGainCh[1]),
++			pModal[band].antennaGainCh[2]);
+ 	default:
+ 		return 0;
+ 	}
+@@ -986,21 +995,15 @@ static void ath9k_hw_set_def_power_per_r
+ 						  struct ath9k_channel *chan,
+ 						  int16_t *ratesArray,
+ 						  u16 cfgCtl,
+-						  u16 AntennaReduction,
+-						  u16 twiceMaxRegulatoryPower,
++						  u16 antenna_reduction,
+ 						  u16 powerLimit)
+ {
+ #define REDUCE_SCALED_POWER_BY_TWO_CHAIN     6  /* 10*log10(2)*2 */
+ #define REDUCE_SCALED_POWER_BY_THREE_CHAIN   9 /* 10*log10(3)*2 */
+ 
+-	struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah);
+ 	struct ar5416_eeprom_def *pEepData = &ah->eeprom.def;
+ 	u16 twiceMaxEdgePower = MAX_RATE_POWER;
+-	static const u16 tpScaleReductionTable[5] =
+-		{ 0, 3, 6, 9, MAX_RATE_POWER };
+-
+ 	int i;
+-	int16_t twiceLargestAntenna;
+ 	struct cal_ctl_data *rep;
+ 	struct cal_target_power_leg targetPowerOfdm, targetPowerCck = {
+ 		0, { 0, 0, 0, 0}
+@@ -1012,7 +1015,7 @@ static void ath9k_hw_set_def_power_per_r
+ 	struct cal_target_power_ht targetPowerHt20, targetPowerHt40 = {
+ 		0, {0, 0, 0, 0}
+ 	};
+-	u16 scaledPower = 0, minCtlPower, maxRegAllowedPower;
++	u16 scaledPower = 0, minCtlPower;
+ 	static const u16 ctlModesFor11a[] = {
+ 		CTL_11A, CTL_5GHT20, CTL_11A_EXT, CTL_5GHT40
+ 	};
+@@ -1031,27 +1034,7 @@ static void ath9k_hw_set_def_power_per_r
+ 
+ 	ath9k_hw_get_channel_centers(ah, chan, &centers);
+ 
+-	twiceLargestAntenna = max(
+-		pEepData->modalHeader
+-			[IS_CHAN_2GHZ(chan)].antennaGainCh[0],
+-		pEepData->modalHeader
+-			[IS_CHAN_2GHZ(chan)].antennaGainCh[1]);
+-
+-	twiceLargestAntenna = max((u8)twiceLargestAntenna,
+-				  pEepData->modalHeader
+-				  [IS_CHAN_2GHZ(chan)].antennaGainCh[2]);
+-
+-	twiceLargestAntenna = (int16_t)min(AntennaReduction -
+-					   twiceLargestAntenna, 0);
+-
+-	maxRegAllowedPower = twiceMaxRegulatoryPower + twiceLargestAntenna;
+-
+-	if (regulatory->tp_scale != ATH9K_TP_SCALE_MAX) {
+-		maxRegAllowedPower -=
+-			(tpScaleReductionTable[(regulatory->tp_scale)] * 2);
+-	}
+-
+-	scaledPower = min(powerLimit, maxRegAllowedPower);
++	scaledPower = powerLimit - antenna_reduction;
+ 
+ 	switch (ar5416_get_ntxchains(tx_chainmask)) {
+ 	case 1:
+@@ -1256,7 +1239,6 @@ static void ath9k_hw_def_set_txpower(str
+ 				    struct ath9k_channel *chan,
+ 				    u16 cfgCtl,
+ 				    u8 twiceAntennaReduction,
+-				    u8 twiceMaxRegulatoryPower,
+ 				    u8 powerLimit, bool test)
+ {
+ #define RT_AR_DELTA(x) (ratesArray[x] - cck_ofdm_delta)
+@@ -1278,7 +1260,6 @@ static void ath9k_hw_def_set_txpower(str
+ 	ath9k_hw_set_def_power_per_rate_table(ah, chan,
+ 					       &ratesArray[0], cfgCtl,
+ 					       twiceAntennaReduction,
+-					       twiceMaxRegulatoryPower,
+ 					       powerLimit);
+ 
+ 	ath9k_hw_set_def_power_cal_table(ah, chan);
+--- a/drivers/net/wireless/ath/ath9k/ar5008_phy.c
++++ b/drivers/net/wireless/ath/ath9k/ar5008_phy.c
+@@ -763,10 +763,8 @@ static void ar5008_hw_set_channel_regs(s
+ static int ar5008_hw_process_ini(struct ath_hw *ah,
+ 				 struct ath9k_channel *chan)
+ {
+-	struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah);
+ 	struct ath_common *common = ath9k_hw_common(ah);
+ 	int i, regWrites = 0;
+-	struct ieee80211_channel *channel = chan->chan;
+ 	u32 modesIndex, freqIndex;
+ 
+ 	switch (chan->chanmode) {
+@@ -903,14 +901,7 @@ static int ar5008_hw_process_ini(struct 
+ 	ar5008_hw_set_channel_regs(ah, chan);
+ 	ar5008_hw_init_chain_masks(ah);
+ 	ath9k_olc_init(ah);
+-
+-	/* Set TX power */
+-	ah->eep_ops->set_txpower(ah, chan,
+-				 ath9k_regd_get_ctl(regulatory, chan),
+-				 channel->max_antenna_gain * 2,
+-				 channel->max_power * 2,
+-				 min((u32) MAX_RATE_POWER,
+-				 (u32) regulatory->power_limit), false);
++	ath9k_hw_apply_txpower(ah, chan);
+ 
+ 	/* Write analog registers */
+ 	if (!ath9k_hw_set_rf_regs(ah, chan, freqIndex)) {
+--- a/drivers/net/wireless/ath/ath9k/ar9003_paprd.c
++++ b/drivers/net/wireless/ath/ath9k/ar9003_paprd.c
+@@ -19,7 +19,6 @@
+ 
+ void ar9003_paprd_enable(struct ath_hw *ah, bool val)
+ {
+-	struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah);
+ 	struct ath9k_channel *chan = ah->curchan;
+ 	struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep;
+ 
+@@ -54,13 +53,7 @@ void ar9003_paprd_enable(struct ath_hw *
+ 
+ 	if (val) {
+ 		ah->paprd_table_write_done = true;
+-
+-		ah->eep_ops->set_txpower(ah, chan,
+-				ath9k_regd_get_ctl(regulatory, chan),
+-				chan->chan->max_antenna_gain * 2,
+-				chan->chan->max_power * 2,
+-				min((u32) MAX_RATE_POWER,
+-				(u32) regulatory->power_limit), false);
++		ath9k_hw_apply_txpower(ah, chan);
+ 	}
+ 
+ 	REG_RMW_FIELD(ah, AR_PHY_PAPRD_CTRL0_B0,
+--- a/drivers/net/wireless/ath/ath9k/ar9003_phy.c
++++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.c
+@@ -628,9 +628,7 @@ static void ar9003_hw_prog_ini(struct at
+ static int ar9003_hw_process_ini(struct ath_hw *ah,
+ 				 struct ath9k_channel *chan)
+ {
+-	struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah);
+ 	unsigned int regWrites = 0, i;
+-	struct ieee80211_channel *channel = chan->chan;
+ 	u32 modesIndex;
+ 
+ 	switch (chan->chanmode) {
+@@ -683,14 +681,7 @@ static int ar9003_hw_process_ini(struct 
+ 	ar9003_hw_override_ini(ah);
+ 	ar9003_hw_set_channel_regs(ah, chan);
+ 	ar9003_hw_set_chain_masks(ah, ah->rxchainmask, ah->txchainmask);
+-
+-	/* Set TX power */
+-	ah->eep_ops->set_txpower(ah, chan,
+-				 ath9k_regd_get_ctl(regulatory, chan),
+-				 channel->max_antenna_gain * 2,
+-				 channel->max_power * 2,
+-				 min((u32) MAX_RATE_POWER,
+-				 (u32) regulatory->power_limit), false);
++	ath9k_hw_apply_txpower(ah, chan);
+ 
+ 	return 0;
+ }
+--- a/drivers/net/wireless/ath/ath9k/common.c
++++ b/drivers/net/wireless/ath/ath9k/common.c
+@@ -161,10 +161,12 @@ EXPORT_SYMBOL(ath9k_cmn_count_streams);
+ void ath9k_cmn_update_txpow(struct ath_hw *ah, u16 cur_txpow,
+ 			    u16 new_txpow, u16 *txpower)
+ {
+-	if (cur_txpow != new_txpow) {
++	struct ath_regulatory *reg = ath9k_hw_regulatory(ah);
++
++	if (reg->power_limit != new_txpow) {
+ 		ath9k_hw_set_txpowerlimit(ah, new_txpow, false);
+ 		/* read back in case value is clamped */
+-		*txpower = ath9k_hw_regulatory(ah)->power_limit;
++		*txpower = reg->max_power_level;
+ 	}
+ }
+ EXPORT_SYMBOL(ath9k_cmn_update_txpow);
+--- a/drivers/net/wireless/ath/ath9k/eeprom.h
++++ b/drivers/net/wireless/ath/ath9k/eeprom.h
+@@ -253,7 +253,9 @@ enum eeprom_param {
+ 	EEP_PAPRD,
+ 	EEP_MODAL_VER,
+ 	EEP_ANT_DIV_CTL1,
+-	EEP_CHAIN_MASK_REDUCE
++	EEP_CHAIN_MASK_REDUCE,
++	EEP_ANTENNA_GAIN_2G,
++	EEP_ANTENNA_GAIN_5G
+ };
+ 
+ enum ar5416_rates {
+@@ -657,8 +659,7 @@ struct eeprom_ops {
+ 	void (*set_addac)(struct ath_hw *hw, struct ath9k_channel *chan);
+ 	void (*set_txpower)(struct ath_hw *hw, struct ath9k_channel *chan,
+ 			   u16 cfgCtl, u8 twiceAntennaReduction,
+-			   u8 twiceMaxRegulatoryPower, u8 powerLimit,
+-			   bool test);
++			   u8 powerLimit, bool test);
+ 	u16 (*get_spur_channel)(struct ath_hw *ah, u16 i, bool is2GHz);
+ };
+ 
+--- a/drivers/net/wireless/ath/ath9k/init.c
++++ b/drivers/net/wireless/ath/ath9k/init.c
+@@ -626,7 +626,6 @@ static void ath9k_init_band_txpower(stru
+ 	struct ieee80211_supported_band *sband;
+ 	struct ieee80211_channel *chan;
+ 	struct ath_hw *ah = sc->sc_ah;
+-	struct ath_regulatory *reg = ath9k_hw_regulatory(ah);
+ 	int i;
+ 
+ 	sband = &sc->sbands[band];
+@@ -635,7 +634,6 @@ static void ath9k_init_band_txpower(stru
+ 		ah->curchan = &ah->channels[chan->hw_value];
+ 		ath9k_cmn_update_ichannel(ah->curchan, chan, NL80211_CHAN_HT20);
+ 		ath9k_hw_set_txpowerlimit(ah, MAX_RATE_POWER, true);
+-		chan->max_power = reg->max_power_level / 2;
+ 	}
+ }
+ 
diff --git a/package/mac80211/patches/582-ath9k_remove_current_rd_ext.patch b/package/mac80211/patches/582-ath9k_remove_current_rd_ext.patch
new file mode 100644
index 0000000000..c2f61c2582
--- /dev/null
+++ b/package/mac80211/patches/582-ath9k_remove_current_rd_ext.patch
@@ -0,0 +1,34 @@
+--- a/drivers/net/wireless/ath/ath.h
++++ b/drivers/net/wireless/ath/ath.h
+@@ -72,7 +72,6 @@ struct ath_regulatory {
+ 	u16 country_code;
+ 	u16 max_power_level;
+ 	u16 current_rd;
+-	u16 current_rd_ext;
+ 	int16_t power_limit;
+ 	struct reg_dmn_pair_mapping *regpair;
+ };
+--- a/drivers/net/wireless/ath/ath9k/hw.c
++++ b/drivers/net/wireless/ath/ath9k/hw.c
+@@ -2047,11 +2047,6 @@ int ath9k_hw_fill_cap_info(struct ath_hw
+ 	eeval = ah->eep_ops->get_eeprom(ah, EEP_REG_0);
+ 	regulatory->current_rd = eeval;
+ 
+-	eeval = ah->eep_ops->get_eeprom(ah, EEP_REG_1);
+-	if (AR_SREV_9285_12_OR_LATER(ah))
+-		eeval |= AR9285_RDEXT_DEFAULT;
+-	regulatory->current_rd_ext = eeval;
+-
+ 	if (ah->opmode != NL80211_IFTYPE_AP &&
+ 	    ah->hw_version.subvendorid == AR_SUBVENDOR_ID_NEW_A) {
+ 		if (regulatory->current_rd == 0x64 ||
+--- a/drivers/net/wireless/ath/carl9170/main.c
++++ b/drivers/net/wireless/ath/carl9170/main.c
+@@ -1912,7 +1912,6 @@ static int carl9170_parse_eeprom(struct 
+ 		ar->hw->channel_change_time = 80 * 1000;
+ 
+ 	regulatory->current_rd = le16_to_cpu(ar->eeprom.reg_domain[0]);
+-	regulatory->current_rd_ext = le16_to_cpu(ar->eeprom.reg_domain[1]);
+ 
+ 	/* second part of wiphy init */
+ 	SET_IEEE80211_PERM_ADDR(ar->hw, ar->eeprom.mac_address);
diff --git a/package/mac80211/patches/583-ath9k_remove_eep_reg_1.patch b/package/mac80211/patches/583-ath9k_remove_eep_reg_1.patch
new file mode 100644
index 0000000000..feaa30d934
--- /dev/null
+++ b/package/mac80211/patches/583-ath9k_remove_eep_reg_1.patch
@@ -0,0 +1,54 @@
+--- a/drivers/net/wireless/ath/ath9k/eeprom_def.c
++++ b/drivers/net/wireless/ath/ath9k/eeprom_def.c
+@@ -415,8 +415,6 @@ static u32 ath9k_hw_def_get_eeprom(struc
+ 		return get_unaligned_be16(pBase->macAddr + 4);
+ 	case EEP_REG_0:
+ 		return pBase->regDmn[0];
+-	case EEP_REG_1:
+-		return pBase->regDmn[1];
+ 	case EEP_OP_CAP:
+ 		return pBase->deviceCap;
+ 	case EEP_OP_MODE:
+--- a/drivers/net/wireless/ath/ath9k/eeprom_4k.c
++++ b/drivers/net/wireless/ath/ath9k/eeprom_4k.c
+@@ -322,8 +322,6 @@ static u32 ath9k_hw_4k_get_eeprom(struct
+ 		return get_unaligned_be16(pBase->macAddr + 4);
+ 	case EEP_REG_0:
+ 		return pBase->regDmn[0];
+-	case EEP_REG_1:
+-		return pBase->regDmn[1];
+ 	case EEP_OP_CAP:
+ 		return pBase->deviceCap;
+ 	case EEP_OP_MODE:
+--- a/drivers/net/wireless/ath/ath9k/eeprom_9287.c
++++ b/drivers/net/wireless/ath/ath9k/eeprom_9287.c
+@@ -308,8 +308,6 @@ static u32 ath9k_hw_ar9287_get_eeprom(st
+ 		return get_unaligned_be16(pBase->macAddr + 4);
+ 	case EEP_REG_0:
+ 		return pBase->regDmn[0];
+-	case EEP_REG_1:
+-		return pBase->regDmn[1];
+ 	case EEP_OP_CAP:
+ 		return pBase->deviceCap;
+ 	case EEP_OP_MODE:
+--- a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c
++++ b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c
+@@ -3014,8 +3014,6 @@ static u32 ath9k_hw_ar9300_get_eeprom(st
+ 		return get_unaligned_be16(eep->macAddr + 4);
+ 	case EEP_REG_0:
+ 		return le16_to_cpu(pBase->regDmn[0]);
+-	case EEP_REG_1:
+-		return le16_to_cpu(pBase->regDmn[1]);
+ 	case EEP_OP_CAP:
+ 		return pBase->deviceCap;
+ 	case EEP_OP_MODE:
+--- a/drivers/net/wireless/ath/ath9k/eeprom.h
++++ b/drivers/net/wireless/ath/ath9k/eeprom.h
+@@ -225,7 +225,6 @@ enum eeprom_param {
+ 	EEP_MAC_MID,
+ 	EEP_MAC_LSW,
+ 	EEP_REG_0,
+-	EEP_REG_1,
+ 	EEP_OP_CAP,
+ 	EEP_OP_MODE,
+ 	EEP_RF_SILENT,
-- 
cgit v1.2.3