aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorFelix Fietkau <nbd@openwrt.org>2011-10-08 14:06:20 -0400
committerJohn W. Linville <linville@tuxdriver.com>2011-10-11 16:41:26 -0400
commitca2c68cc7bc80fc4504fb420df04cce99c9ee6ec (patch)
tree999cd166f17b1d47226961267c1dd93ae9c8a4fd /drivers
parent72d874c67c3cdf21ca95045baabac6a5843222d8 (diff)
ath9k_hw: clean up tx power handling
The code for handling various restrictions concerning regulatory limits, antenna gain, etc. is very convoluted and duplicated across various EEPROM parsing implementations, making it hard to review. This patch partially cleans up the mess by unifying regulatory limit handling in one function and simplifying handling of antenna gain. It also removes unused transmit power scaling arrays from the EEPROM code, which belonged to an unimplemented API that isn't supposed to be in the driver anyway. Signed-off-by: Felix Fietkau <nbd@openwrt.org> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/net/wireless/ath/ath.h1
-rw-r--r--drivers/net/wireless/ath/ath9k/ar5008_phy.c11
-rw-r--r--drivers/net/wireless/ath/ath9k/ar9003_eeprom.c39
-rw-r--r--drivers/net/wireless/ath/ath9k/ar9003_paprd.c9
-rw-r--r--drivers/net/wireless/ath/ath9k/ar9003_phy.c11
-rw-r--r--drivers/net/wireless/ath/ath9k/common.c6
-rw-r--r--drivers/net/wireless/ath/ath9k/eeprom.h7
-rw-r--r--drivers/net/wireless/ath/ath9k/eeprom_4k.c27
-rw-r--r--drivers/net/wireless/ath/ath9k/eeprom_9287.c33
-rw-r--r--drivers/net/wireless/ath/ath9k/eeprom_def.c43
-rw-r--r--drivers/net/wireless/ath/ath9k/hw.c63
-rw-r--r--drivers/net/wireless/ath/ath9k/hw.h9
-rw-r--r--drivers/net/wireless/ath/ath9k/init.c2
13 files changed, 85 insertions, 176 deletions
diff --git a/drivers/net/wireless/ath/ath.h b/drivers/net/wireless/ath/ath.h
index 4ed7f248a57..bb71b4f27a9 100644
--- a/drivers/net/wireless/ath/ath.h
+++ b/drivers/net/wireless/ath/ath.h
@@ -71,7 +71,6 @@ struct ath_regulatory {
71 char alpha2[2]; 71 char alpha2[2];
72 u16 country_code; 72 u16 country_code;
73 u16 max_power_level; 73 u16 max_power_level;
74 u32 tp_scale;
75 u16 current_rd; 74 u16 current_rd;
76 u16 current_rd_ext; 75 u16 current_rd_ext;
77 int16_t power_limit; 76 int16_t power_limit;
diff --git a/drivers/net/wireless/ath/ath9k/ar5008_phy.c b/drivers/net/wireless/ath/ath9k/ar5008_phy.c
index 0a749c8fa63..f199e9e2514 100644
--- 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(struct ath_hw *ah,
763static int ar5008_hw_process_ini(struct ath_hw *ah, 763static int ar5008_hw_process_ini(struct ath_hw *ah,
764 struct ath9k_channel *chan) 764 struct ath9k_channel *chan)
765{ 765{
766 struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah);
767 struct ath_common *common = ath9k_hw_common(ah); 766 struct ath_common *common = ath9k_hw_common(ah);
768 int i, regWrites = 0; 767 int i, regWrites = 0;
769 struct ieee80211_channel *channel = chan->chan;
770 u32 modesIndex, freqIndex; 768 u32 modesIndex, freqIndex;
771 769
772 switch (chan->chanmode) { 770 switch (chan->chanmode) {
@@ -903,14 +901,7 @@ static int ar5008_hw_process_ini(struct ath_hw *ah,
903 ar5008_hw_set_channel_regs(ah, chan); 901 ar5008_hw_set_channel_regs(ah, chan);
904 ar5008_hw_init_chain_masks(ah); 902 ar5008_hw_init_chain_masks(ah);
905 ath9k_olc_init(ah); 903 ath9k_olc_init(ah);
906 904 ath9k_hw_apply_txpower(ah, chan);
907 /* Set TX power */
908 ah->eep_ops->set_txpower(ah, chan,
909 ath9k_regd_get_ctl(regulatory, chan),
910 channel->max_antenna_gain * 2,
911 channel->max_power * 2,
912 min((u32) MAX_RATE_POWER,
913 (u32) regulatory->power_limit), false);
914 905
915 /* Write analog registers */ 906 /* Write analog registers */
916 if (!ath9k_hw_set_rf_regs(ah, chan, freqIndex)) { 907 if (!ath9k_hw_set_rf_regs(ah, chan, freqIndex)) {
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c
index 51398f0063e..d7a5ca72254 100644
--- a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c
+++ b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c
@@ -3021,6 +3021,10 @@ static u32 ath9k_hw_ar9300_get_eeprom(struct ath_hw *ah,
3021 return (pBase->miscConfiguration >> 0x3) & 0x1; 3021 return (pBase->miscConfiguration >> 0x3) & 0x1;
3022 case EEP_ANT_DIV_CTL1: 3022 case EEP_ANT_DIV_CTL1:
3023 return eep->base_ext1.ant_div_control; 3023 return eep->base_ext1.ant_div_control;
3024 case EEP_ANTENNA_GAIN_5G:
3025 return eep->modalHeader5G.antennaGain;
3026 case EEP_ANTENNA_GAIN_2G:
3027 return eep->modalHeader2G.antennaGain;
3024 default: 3028 default:
3025 return 0; 3029 return 0;
3026 } 3030 }
@@ -4764,20 +4768,14 @@ static u16 ar9003_hw_get_max_edge_power(struct ar9300_eeprom *eep,
4764static void ar9003_hw_set_power_per_rate_table(struct ath_hw *ah, 4768static void ar9003_hw_set_power_per_rate_table(struct ath_hw *ah,
4765 struct ath9k_channel *chan, 4769 struct ath9k_channel *chan,
4766 u8 *pPwrArray, u16 cfgCtl, 4770 u8 *pPwrArray, u16 cfgCtl,
4767 u8 twiceAntennaReduction, 4771 u8 antenna_reduction,
4768 u8 twiceMaxRegulatoryPower,
4769 u16 powerLimit) 4772 u16 powerLimit)
4770{ 4773{
4771 struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah);
4772 struct ath_common *common = ath9k_hw_common(ah); 4774 struct ath_common *common = ath9k_hw_common(ah);
4773 struct ar9300_eeprom *pEepData = &ah->eeprom.ar9300_eep; 4775 struct ar9300_eeprom *pEepData = &ah->eeprom.ar9300_eep;
4774 u16 twiceMaxEdgePower = MAX_RATE_POWER; 4776 u16 twiceMaxEdgePower = MAX_RATE_POWER;
4775 static const u16 tpScaleReductionTable[5] = {
4776 0, 3, 6, 9, MAX_RATE_POWER
4777 };
4778 int i; 4777 int i;
4779 int16_t twiceLargestAntenna; 4778 u16 scaledPower = 0, minCtlPower;
4780 u16 scaledPower = 0, minCtlPower, maxRegAllowedPower;
4781 static const u16 ctlModesFor11a[] = { 4779 static const u16 ctlModesFor11a[] = {
4782 CTL_11A, CTL_5GHT20, CTL_11A_EXT, CTL_5GHT40 4780 CTL_11A, CTL_5GHT20, CTL_11A_EXT, CTL_5GHT40
4783 }; 4781 };
@@ -4795,28 +4793,7 @@ static void ar9003_hw_set_power_per_rate_table(struct ath_hw *ah,
4795 bool is2ghz = IS_CHAN_2GHZ(chan); 4793 bool is2ghz = IS_CHAN_2GHZ(chan);
4796 4794
4797 ath9k_hw_get_channel_centers(ah, chan, &centers); 4795 ath9k_hw_get_channel_centers(ah, chan, &centers);
4798 4796 scaledPower = powerLimit - antenna_reduction;
4799 /* Compute TxPower reduction due to Antenna Gain */
4800 if (is2ghz)
4801 twiceLargestAntenna = pEepData->modalHeader2G.antennaGain;
4802 else
4803 twiceLargestAntenna = pEepData->modalHeader5G.antennaGain;
4804
4805 twiceLargestAntenna = (int16_t)min((twiceAntennaReduction) -
4806 twiceLargestAntenna, 0);
4807
4808 /*
4809 * scaledPower is the minimum of the user input power level
4810 * and the regulatory allowed power level
4811 */
4812 maxRegAllowedPower = twiceMaxRegulatoryPower + twiceLargestAntenna;
4813
4814 if (regulatory->tp_scale != ATH9K_TP_SCALE_MAX) {
4815 maxRegAllowedPower -=
4816 (tpScaleReductionTable[(regulatory->tp_scale)] * 2);
4817 }
4818
4819 scaledPower = min(powerLimit, maxRegAllowedPower);
4820 4797
4821 /* 4798 /*
4822 * Reduce scaled Power by number of chains active to get 4799 * Reduce scaled Power by number of chains active to get
@@ -5003,7 +4980,6 @@ static inline u8 mcsidx_to_tgtpwridx(unsigned int mcs_idx, u8 base_pwridx)
5003static void ath9k_hw_ar9300_set_txpower(struct ath_hw *ah, 4980static void ath9k_hw_ar9300_set_txpower(struct ath_hw *ah,
5004 struct ath9k_channel *chan, u16 cfgCtl, 4981 struct ath9k_channel *chan, u16 cfgCtl,
5005 u8 twiceAntennaReduction, 4982 u8 twiceAntennaReduction,
5006 u8 twiceMaxRegulatoryPower,
5007 u8 powerLimit, bool test) 4983 u8 powerLimit, bool test)
5008{ 4984{
5009 struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah); 4985 struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah);
@@ -5056,7 +5032,6 @@ static void ath9k_hw_ar9300_set_txpower(struct ath_hw *ah,
5056 ar9003_hw_set_power_per_rate_table(ah, chan, 5032 ar9003_hw_set_power_per_rate_table(ah, chan,
5057 targetPowerValT2, cfgCtl, 5033 targetPowerValT2, cfgCtl,
5058 twiceAntennaReduction, 5034 twiceAntennaReduction,
5059 twiceMaxRegulatoryPower,
5060 powerLimit); 5035 powerLimit);
5061 5036
5062 if (ah->eep_ops->get_eeprom(ah, EEP_PAPRD)) { 5037 if (ah->eep_ops->get_eeprom(ah, EEP_PAPRD)) {
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_paprd.c b/drivers/net/wireless/ath/ath9k/ar9003_paprd.c
index 609acb2b504..a1a08b31b33 100644
--- a/drivers/net/wireless/ath/ath9k/ar9003_paprd.c
+++ b/drivers/net/wireless/ath/ath9k/ar9003_paprd.c
@@ -19,7 +19,6 @@
19 19
20void ar9003_paprd_enable(struct ath_hw *ah, bool val) 20void ar9003_paprd_enable(struct ath_hw *ah, bool val)
21{ 21{
22 struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah);
23 struct ath9k_channel *chan = ah->curchan; 22 struct ath9k_channel *chan = ah->curchan;
24 struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep; 23 struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep;
25 24
@@ -54,13 +53,7 @@ void ar9003_paprd_enable(struct ath_hw *ah, bool val)
54 53
55 if (val) { 54 if (val) {
56 ah->paprd_table_write_done = true; 55 ah->paprd_table_write_done = true;
57 56 ath9k_hw_apply_txpower(ah, chan);
58 ah->eep_ops->set_txpower(ah, chan,
59 ath9k_regd_get_ctl(regulatory, chan),
60 chan->chan->max_antenna_gain * 2,
61 chan->chan->max_power * 2,
62 min((u32) MAX_RATE_POWER,
63 (u32) regulatory->power_limit), false);
64 } 57 }
65 58
66 REG_RMW_FIELD(ah, AR_PHY_PAPRD_CTRL0_B0, 59 REG_RMW_FIELD(ah, AR_PHY_PAPRD_CTRL0_B0,
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_phy.c b/drivers/net/wireless/ath/ath9k/ar9003_phy.c
index 7db6e8647a0..779f407222e 100644
--- a/drivers/net/wireless/ath/ath9k/ar9003_phy.c
+++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.c
@@ -631,9 +631,7 @@ static void ar9003_hw_prog_ini(struct ath_hw *ah,
631static int ar9003_hw_process_ini(struct ath_hw *ah, 631static int ar9003_hw_process_ini(struct ath_hw *ah,
632 struct ath9k_channel *chan) 632 struct ath9k_channel *chan)
633{ 633{
634 struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah);
635 unsigned int regWrites = 0, i; 634 unsigned int regWrites = 0, i;
636 struct ieee80211_channel *channel = chan->chan;
637 u32 modesIndex; 635 u32 modesIndex;
638 636
639 switch (chan->chanmode) { 637 switch (chan->chanmode) {
@@ -693,14 +691,7 @@ static int ar9003_hw_process_ini(struct ath_hw *ah,
693 ar9003_hw_override_ini(ah); 691 ar9003_hw_override_ini(ah);
694 ar9003_hw_set_channel_regs(ah, chan); 692 ar9003_hw_set_channel_regs(ah, chan);
695 ar9003_hw_set_chain_masks(ah, ah->rxchainmask, ah->txchainmask); 693 ar9003_hw_set_chain_masks(ah, ah->rxchainmask, ah->txchainmask);
696 694 ath9k_hw_apply_txpower(ah, chan);
697 /* Set TX power */
698 ah->eep_ops->set_txpower(ah, chan,
699 ath9k_regd_get_ctl(regulatory, chan),
700 channel->max_antenna_gain * 2,
701 channel->max_power * 2,
702 min((u32) MAX_RATE_POWER,
703 (u32) regulatory->power_limit), false);
704 695
705 return 0; 696 return 0;
706} 697}
diff --git a/drivers/net/wireless/ath/ath9k/common.c b/drivers/net/wireless/ath/ath9k/common.c
index dc705a22495..905f1b31396 100644
--- 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);
161void ath9k_cmn_update_txpow(struct ath_hw *ah, u16 cur_txpow, 161void ath9k_cmn_update_txpow(struct ath_hw *ah, u16 cur_txpow,
162 u16 new_txpow, u16 *txpower) 162 u16 new_txpow, u16 *txpower)
163{ 163{
164 if (cur_txpow != new_txpow) { 164 struct ath_regulatory *reg = ath9k_hw_regulatory(ah);
165
166 if (reg->power_limit != new_txpow) {
165 ath9k_hw_set_txpowerlimit(ah, new_txpow, false); 167 ath9k_hw_set_txpowerlimit(ah, new_txpow, false);
166 /* read back in case value is clamped */ 168 /* read back in case value is clamped */
167 *txpower = ath9k_hw_regulatory(ah)->power_limit; 169 *txpower = reg->max_power_level;
168 } 170 }
169} 171}
170EXPORT_SYMBOL(ath9k_cmn_update_txpow); 172EXPORT_SYMBOL(ath9k_cmn_update_txpow);
diff --git a/drivers/net/wireless/ath/ath9k/eeprom.h b/drivers/net/wireless/ath/ath9k/eeprom.h
index 5d92f96980e..909a224fb65 100644
--- a/drivers/net/wireless/ath/ath9k/eeprom.h
+++ b/drivers/net/wireless/ath/ath9k/eeprom.h
@@ -248,7 +248,9 @@ enum eeprom_param {
248 EEP_PAPRD, 248 EEP_PAPRD,
249 EEP_MODAL_VER, 249 EEP_MODAL_VER,
250 EEP_ANT_DIV_CTL1, 250 EEP_ANT_DIV_CTL1,
251 EEP_CHAIN_MASK_REDUCE 251 EEP_CHAIN_MASK_REDUCE,
252 EEP_ANTENNA_GAIN_2G,
253 EEP_ANTENNA_GAIN_5G
252}; 254};
253 255
254enum ar5416_rates { 256enum ar5416_rates {
@@ -652,8 +654,7 @@ struct eeprom_ops {
652 void (*set_addac)(struct ath_hw *hw, struct ath9k_channel *chan); 654 void (*set_addac)(struct ath_hw *hw, struct ath9k_channel *chan);
653 void (*set_txpower)(struct ath_hw *hw, struct ath9k_channel *chan, 655 void (*set_txpower)(struct ath_hw *hw, struct ath9k_channel *chan,
654 u16 cfgCtl, u8 twiceAntennaReduction, 656 u16 cfgCtl, u8 twiceAntennaReduction,
655 u8 twiceMaxRegulatoryPower, u8 powerLimit, 657 u8 powerLimit, bool test);
656 bool test);
657 u16 (*get_spur_channel)(struct ath_hw *ah, u16 i, bool is2GHz); 658 u16 (*get_spur_channel)(struct ath_hw *ah, u16 i, bool is2GHz);
658}; 659};
659 660
diff --git a/drivers/net/wireless/ath/ath9k/eeprom_4k.c b/drivers/net/wireless/ath/ath9k/eeprom_4k.c
index 303560e49ac..ab6811dc5de 100644
--- 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 ath_hw *ah,
350 return pModal->antdiv_ctl1; 350 return pModal->antdiv_ctl1;
351 case EEP_TXGAIN_TYPE: 351 case EEP_TXGAIN_TYPE:
352 return pBase->txGainType; 352 return pBase->txGainType;
353 case EEP_ANTENNA_GAIN_2G:
354 return pModal->antennaGainCh[0];
353 default: 355 default:
354 return 0; 356 return 0;
355 } 357 }
@@ -462,8 +464,7 @@ static void ath9k_hw_set_4k_power_per_rate_table(struct ath_hw *ah,
462 struct ath9k_channel *chan, 464 struct ath9k_channel *chan,
463 int16_t *ratesArray, 465 int16_t *ratesArray,
464 u16 cfgCtl, 466 u16 cfgCtl,
465 u16 AntennaReduction, 467 u16 antenna_reduction,
466 u16 twiceMaxRegulatoryPower,
467 u16 powerLimit) 468 u16 powerLimit)
468{ 469{
469#define CMP_TEST_GRP \ 470#define CMP_TEST_GRP \
@@ -472,20 +473,16 @@ static void ath9k_hw_set_4k_power_per_rate_table(struct ath_hw *ah,
472 || (((cfgCtl & ~CTL_MODE_M) | (pCtlMode[ctlMode] & CTL_MODE_M)) == \ 473 || (((cfgCtl & ~CTL_MODE_M) | (pCtlMode[ctlMode] & CTL_MODE_M)) == \
473 ((pEepData->ctlIndex[i] & CTL_MODE_M) | SD_NO_CTL)) 474 ((pEepData->ctlIndex[i] & CTL_MODE_M) | SD_NO_CTL))
474 475
475 struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah);
476 int i; 476 int i;
477 int16_t twiceLargestAntenna;
478 u16 twiceMinEdgePower; 477 u16 twiceMinEdgePower;
479 u16 twiceMaxEdgePower = MAX_RATE_POWER; 478 u16 twiceMaxEdgePower = MAX_RATE_POWER;
480 u16 scaledPower = 0, minCtlPower, maxRegAllowedPower; 479 u16 scaledPower = 0, minCtlPower;
481 u16 numCtlModes; 480 u16 numCtlModes;
482 const u16 *pCtlMode; 481 const u16 *pCtlMode;
483 u16 ctlMode, freq; 482 u16 ctlMode, freq;
484 struct chan_centers centers; 483 struct chan_centers centers;
485 struct cal_ctl_data_4k *rep; 484 struct cal_ctl_data_4k *rep;
486 struct ar5416_eeprom_4k *pEepData = &ah->eeprom.map4k; 485 struct ar5416_eeprom_4k *pEepData = &ah->eeprom.map4k;
487 static const u16 tpScaleReductionTable[5] =
488 { 0, 3, 6, 9, MAX_RATE_POWER };
489 struct cal_target_power_leg targetPowerOfdm, targetPowerCck = { 486 struct cal_target_power_leg targetPowerOfdm, targetPowerCck = {
490 0, { 0, 0, 0, 0} 487 0, { 0, 0, 0, 0}
491 }; 488 };
@@ -503,19 +500,7 @@ static void ath9k_hw_set_4k_power_per_rate_table(struct ath_hw *ah,
503 500
504 ath9k_hw_get_channel_centers(ah, chan, &centers); 501 ath9k_hw_get_channel_centers(ah, chan, &centers);
505 502
506 twiceLargestAntenna = pEepData->modalHeader.antennaGainCh[0]; 503 scaledPower = powerLimit - antenna_reduction;
507 twiceLargestAntenna = (int16_t)min(AntennaReduction -
508 twiceLargestAntenna, 0);
509
510 maxRegAllowedPower = twiceMaxRegulatoryPower + twiceLargestAntenna;
511 if (regulatory->tp_scale != ATH9K_TP_SCALE_MAX) {
512 maxRegAllowedPower -=
513 (tpScaleReductionTable[(regulatory->tp_scale)] * 2);
514 }
515
516 scaledPower = min(powerLimit, maxRegAllowedPower);
517 scaledPower = max((u16)0, scaledPower);
518
519 numCtlModes = ARRAY_SIZE(ctlModesFor11g) - SUB_NUM_CTL_MODES_AT_2G_40; 504 numCtlModes = ARRAY_SIZE(ctlModesFor11g) - SUB_NUM_CTL_MODES_AT_2G_40;
520 pCtlMode = ctlModesFor11g; 505 pCtlMode = ctlModesFor11g;
521 506
@@ -671,7 +656,6 @@ static void ath9k_hw_4k_set_txpower(struct ath_hw *ah,
671 struct ath9k_channel *chan, 656 struct ath9k_channel *chan,
672 u16 cfgCtl, 657 u16 cfgCtl,
673 u8 twiceAntennaReduction, 658 u8 twiceAntennaReduction,
674 u8 twiceMaxRegulatoryPower,
675 u8 powerLimit, bool test) 659 u8 powerLimit, bool test)
676{ 660{
677 struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah); 661 struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah);
@@ -691,7 +675,6 @@ static void ath9k_hw_4k_set_txpower(struct ath_hw *ah,
691 ath9k_hw_set_4k_power_per_rate_table(ah, chan, 675 ath9k_hw_set_4k_power_per_rate_table(ah, chan,
692 &ratesArray[0], cfgCtl, 676 &ratesArray[0], cfgCtl,
693 twiceAntennaReduction, 677 twiceAntennaReduction,
694 twiceMaxRegulatoryPower,
695 powerLimit); 678 powerLimit);
696 679
697 ath9k_hw_set_4k_power_cal_table(ah, chan); 680 ath9k_hw_set_4k_power_cal_table(ah, chan);
diff --git a/drivers/net/wireless/ath/ath9k/eeprom_9287.c b/drivers/net/wireless/ath/ath9k/eeprom_9287.c
index 6698b722b60..90d771fa2de 100644
--- 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(struct ath_hw *ah,
336 return pBase->tempSensSlopePalOn; 336 return pBase->tempSensSlopePalOn;
337 else 337 else
338 return 0; 338 return 0;
339 case EEP_ANTENNA_GAIN_2G:
340 return max_t(u8, pModal->antennaGainCh[0],
341 pModal->antennaGainCh[1]);
339 default: 342 default:
340 return 0; 343 return 0;
341 } 344 }
@@ -554,8 +557,7 @@ static void ath9k_hw_set_ar9287_power_per_rate_table(struct ath_hw *ah,
554 struct ath9k_channel *chan, 557 struct ath9k_channel *chan,
555 int16_t *ratesArray, 558 int16_t *ratesArray,
556 u16 cfgCtl, 559 u16 cfgCtl,
557 u16 AntennaReduction, 560 u16 antenna_reduction,
558 u16 twiceMaxRegulatoryPower,
559 u16 powerLimit) 561 u16 powerLimit)
560{ 562{
561#define CMP_CTL \ 563#define CMP_CTL \
@@ -569,12 +571,8 @@ static void ath9k_hw_set_ar9287_power_per_rate_table(struct ath_hw *ah,
569#define REDUCE_SCALED_POWER_BY_TWO_CHAIN 6 571#define REDUCE_SCALED_POWER_BY_TWO_CHAIN 6
570#define REDUCE_SCALED_POWER_BY_THREE_CHAIN 10 572#define REDUCE_SCALED_POWER_BY_THREE_CHAIN 10
571 573
572 struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah);
573 u16 twiceMaxEdgePower = MAX_RATE_POWER; 574 u16 twiceMaxEdgePower = MAX_RATE_POWER;
574 static const u16 tpScaleReductionTable[5] =
575 { 0, 3, 6, 9, MAX_RATE_POWER };
576 int i; 575 int i;
577 int16_t twiceLargestAntenna;
578 struct cal_ctl_data_ar9287 *rep; 576 struct cal_ctl_data_ar9287 *rep;
579 struct cal_target_power_leg targetPowerOfdm = {0, {0, 0, 0, 0} }, 577 struct cal_target_power_leg targetPowerOfdm = {0, {0, 0, 0, 0} },
580 targetPowerCck = {0, {0, 0, 0, 0} }; 578 targetPowerCck = {0, {0, 0, 0, 0} };
@@ -582,7 +580,7 @@ static void ath9k_hw_set_ar9287_power_per_rate_table(struct ath_hw *ah,
582 targetPowerCckExt = {0, {0, 0, 0, 0} }; 580 targetPowerCckExt = {0, {0, 0, 0, 0} };
583 struct cal_target_power_ht targetPowerHt20, 581 struct cal_target_power_ht targetPowerHt20,
584 targetPowerHt40 = {0, {0, 0, 0, 0} }; 582 targetPowerHt40 = {0, {0, 0, 0, 0} };
585 u16 scaledPower = 0, minCtlPower, maxRegAllowedPower; 583 u16 scaledPower = 0, minCtlPower;
586 static const u16 ctlModesFor11g[] = { 584 static const u16 ctlModesFor11g[] = {
587 CTL_11B, CTL_11G, CTL_2GHT20, 585 CTL_11B, CTL_11G, CTL_2GHT20,
588 CTL_11B_EXT, CTL_11G_EXT, CTL_2GHT40 586 CTL_11B_EXT, CTL_11G_EXT, CTL_2GHT40
@@ -597,24 +595,7 @@ static void ath9k_hw_set_ar9287_power_per_rate_table(struct ath_hw *ah,
597 tx_chainmask = ah->txchainmask; 595 tx_chainmask = ah->txchainmask;
598 596
599 ath9k_hw_get_channel_centers(ah, chan, &centers); 597 ath9k_hw_get_channel_centers(ah, chan, &centers);
600 598 scaledPower = powerLimit - antenna_reduction;
601 /* Compute TxPower reduction due to Antenna Gain */
602 twiceLargestAntenna = max(pEepData->modalHeader.antennaGainCh[0],
603 pEepData->modalHeader.antennaGainCh[1]);
604 twiceLargestAntenna = (int16_t)min((AntennaReduction) -
605 twiceLargestAntenna, 0);
606
607 /*
608 * scaledPower is the minimum of the user input power level
609 * and the regulatory allowed power level.
610 */
611 maxRegAllowedPower = twiceMaxRegulatoryPower + twiceLargestAntenna;
612
613 if (regulatory->tp_scale != ATH9K_TP_SCALE_MAX)
614 maxRegAllowedPower -=
615 (tpScaleReductionTable[(regulatory->tp_scale)] * 2);
616
617 scaledPower = min(powerLimit, maxRegAllowedPower);
618 599
619 /* 600 /*
620 * Reduce scaled Power by number of chains active 601 * Reduce scaled Power by number of chains active
@@ -815,7 +796,6 @@ static void ath9k_hw_set_ar9287_power_per_rate_table(struct ath_hw *ah,
815static void ath9k_hw_ar9287_set_txpower(struct ath_hw *ah, 796static void ath9k_hw_ar9287_set_txpower(struct ath_hw *ah,
816 struct ath9k_channel *chan, u16 cfgCtl, 797 struct ath9k_channel *chan, u16 cfgCtl,
817 u8 twiceAntennaReduction, 798 u8 twiceAntennaReduction,
818 u8 twiceMaxRegulatoryPower,
819 u8 powerLimit, bool test) 799 u8 powerLimit, bool test)
820{ 800{
821 struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah); 801 struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah);
@@ -834,7 +814,6 @@ static void ath9k_hw_ar9287_set_txpower(struct ath_hw *ah,
834 ath9k_hw_set_ar9287_power_per_rate_table(ah, chan, 814 ath9k_hw_set_ar9287_power_per_rate_table(ah, chan,
835 &ratesArray[0], cfgCtl, 815 &ratesArray[0], cfgCtl,
836 twiceAntennaReduction, 816 twiceAntennaReduction,
837 twiceMaxRegulatoryPower,
838 powerLimit); 817 powerLimit);
839 818
840 ath9k_hw_set_ar9287_power_cal_table(ah, chan); 819 ath9k_hw_set_ar9287_power_cal_table(ah, chan);
diff --git a/drivers/net/wireless/ath/ath9k/eeprom_def.c b/drivers/net/wireless/ath/ath9k/eeprom_def.c
index eda681fc7ba..e175e2078a3 100644
--- 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(struct ath_hw *ah,
400 struct ar5416_eeprom_def *eep = &ah->eeprom.def; 400 struct ar5416_eeprom_def *eep = &ah->eeprom.def;
401 struct modal_eep_header *pModal = eep->modalHeader; 401 struct modal_eep_header *pModal = eep->modalHeader;
402 struct base_eep_header *pBase = &eep->baseEepHeader; 402 struct base_eep_header *pBase = &eep->baseEepHeader;
403 int band = 0;
403 404
404 switch (param) { 405 switch (param) {
405 case EEP_NFTHRESH_5: 406 case EEP_NFTHRESH_5:
@@ -467,6 +468,14 @@ static u32 ath9k_hw_def_get_eeprom(struct ath_hw *ah,
467 return pBase->pwr_table_offset; 468 return pBase->pwr_table_offset;
468 else 469 else
469 return AR5416_PWR_TABLE_OFFSET_DB; 470 return AR5416_PWR_TABLE_OFFSET_DB;
471 case EEP_ANTENNA_GAIN_2G:
472 band = 1;
473 /* fall through */
474 case EEP_ANTENNA_GAIN_5G:
475 return max_t(u8, max_t(u8,
476 pModal[band].antennaGainCh[0],
477 pModal[band].antennaGainCh[1]),
478 pModal[band].antennaGainCh[2]);
470 default: 479 default:
471 return 0; 480 return 0;
472 } 481 }
@@ -986,21 +995,15 @@ static void ath9k_hw_set_def_power_per_rate_table(struct ath_hw *ah,
986 struct ath9k_channel *chan, 995 struct ath9k_channel *chan,
987 int16_t *ratesArray, 996 int16_t *ratesArray,
988 u16 cfgCtl, 997 u16 cfgCtl,
989 u16 AntennaReduction, 998 u16 antenna_reduction,
990 u16 twiceMaxRegulatoryPower,
991 u16 powerLimit) 999 u16 powerLimit)
992{ 1000{
993#define REDUCE_SCALED_POWER_BY_TWO_CHAIN 6 /* 10*log10(2)*2 */ 1001#define REDUCE_SCALED_POWER_BY_TWO_CHAIN 6 /* 10*log10(2)*2 */
994#define REDUCE_SCALED_POWER_BY_THREE_CHAIN 9 /* 10*log10(3)*2 */ 1002#define REDUCE_SCALED_POWER_BY_THREE_CHAIN 9 /* 10*log10(3)*2 */
995 1003
996 struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah);
997 struct ar5416_eeprom_def *pEepData = &ah->eeprom.def; 1004 struct ar5416_eeprom_def *pEepData = &ah->eeprom.def;
998 u16 twiceMaxEdgePower = MAX_RATE_POWER; 1005 u16 twiceMaxEdgePower = MAX_RATE_POWER;
999 static const u16 tpScaleReductionTable[5] =
1000 { 0, 3, 6, 9, MAX_RATE_POWER };
1001
1002 int i; 1006 int i;
1003 int16_t twiceLargestAntenna;
1004 struct cal_ctl_data *rep; 1007 struct cal_ctl_data *rep;
1005 struct cal_target_power_leg targetPowerOfdm, targetPowerCck = { 1008 struct cal_target_power_leg targetPowerOfdm, targetPowerCck = {
1006 0, { 0, 0, 0, 0} 1009 0, { 0, 0, 0, 0}
@@ -1012,7 +1015,7 @@ static void ath9k_hw_set_def_power_per_rate_table(struct ath_hw *ah,
1012 struct cal_target_power_ht targetPowerHt20, targetPowerHt40 = { 1015 struct cal_target_power_ht targetPowerHt20, targetPowerHt40 = {
1013 0, {0, 0, 0, 0} 1016 0, {0, 0, 0, 0}
1014 }; 1017 };
1015 u16 scaledPower = 0, minCtlPower, maxRegAllowedPower; 1018 u16 scaledPower = 0, minCtlPower;
1016 static const u16 ctlModesFor11a[] = { 1019 static const u16 ctlModesFor11a[] = {
1017 CTL_11A, CTL_5GHT20, CTL_11A_EXT, CTL_5GHT40 1020 CTL_11A, CTL_5GHT20, CTL_11A_EXT, CTL_5GHT40
1018 }; 1021 };
@@ -1031,27 +1034,7 @@ static void ath9k_hw_set_def_power_per_rate_table(struct ath_hw *ah,
1031 1034
1032 ath9k_hw_get_channel_centers(ah, chan, &centers); 1035 ath9k_hw_get_channel_centers(ah, chan, &centers);
1033 1036
1034 twiceLargestAntenna = max( 1037 scaledPower = powerLimit - antenna_reduction;
1035 pEepData->modalHeader
1036 [IS_CHAN_2GHZ(chan)].antennaGainCh[0],
1037 pEepData->modalHeader
1038 [IS_CHAN_2GHZ(chan)].antennaGainCh[1]);
1039
1040 twiceLargestAntenna = max((u8)twiceLargestAntenna,
1041 pEepData->modalHeader
1042 [IS_CHAN_2GHZ(chan)].antennaGainCh[2]);
1043
1044 twiceLargestAntenna = (int16_t)min(AntennaReduction -
1045 twiceLargestAntenna, 0);
1046
1047 maxRegAllowedPower = twiceMaxRegulatoryPower + twiceLargestAntenna;
1048
1049 if (regulatory->tp_scale != ATH9K_TP_SCALE_MAX) {
1050 maxRegAllowedPower -=
1051 (tpScaleReductionTable[(regulatory->tp_scale)] * 2);
1052 }
1053
1054 scaledPower = min(powerLimit, maxRegAllowedPower);
1055 1038
1056 switch (ar5416_get_ntxchains(tx_chainmask)) { 1039 switch (ar5416_get_ntxchains(tx_chainmask)) {
1057 case 1: 1040 case 1:
@@ -1256,7 +1239,6 @@ static void ath9k_hw_def_set_txpower(struct ath_hw *ah,
1256 struct ath9k_channel *chan, 1239 struct ath9k_channel *chan,
1257 u16 cfgCtl, 1240 u16 cfgCtl,
1258 u8 twiceAntennaReduction, 1241 u8 twiceAntennaReduction,
1259 u8 twiceMaxRegulatoryPower,
1260 u8 powerLimit, bool test) 1242 u8 powerLimit, bool test)
1261{ 1243{
1262#define RT_AR_DELTA(x) (ratesArray[x] - cck_ofdm_delta) 1244#define RT_AR_DELTA(x) (ratesArray[x] - cck_ofdm_delta)
@@ -1278,7 +1260,6 @@ static void ath9k_hw_def_set_txpower(struct ath_hw *ah,
1278 ath9k_hw_set_def_power_per_rate_table(ah, chan, 1260 ath9k_hw_set_def_power_per_rate_table(ah, chan,
1279 &ratesArray[0], cfgCtl, 1261 &ratesArray[0], cfgCtl,
1280 twiceAntennaReduction, 1262 twiceAntennaReduction,
1281 twiceMaxRegulatoryPower,
1282 powerLimit); 1263 powerLimit);
1283 1264
1284 ath9k_hw_set_def_power_cal_table(ah, chan); 1265 ath9k_hw_set_def_power_cal_table(ah, chan);
diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c
index 42ebe8fb053..949656d928d 100644
--- a/drivers/net/wireless/ath/ath9k/hw.c
+++ b/drivers/net/wireless/ath/ath9k/hw.c
@@ -433,7 +433,6 @@ static void ath9k_hw_init_defaults(struct ath_hw *ah)
433 433
434 regulatory->country_code = CTRY_DEFAULT; 434 regulatory->country_code = CTRY_DEFAULT;
435 regulatory->power_limit = MAX_RATE_POWER; 435 regulatory->power_limit = MAX_RATE_POWER;
436 regulatory->tp_scale = ATH9K_TP_SCALE_MAX;
437 436
438 ah->hw_version.magic = AR5416_MAGIC; 437 ah->hw_version.magic = AR5416_MAGIC;
439 ah->hw_version.subvendorid = 0; 438 ah->hw_version.subvendorid = 0;
@@ -1389,9 +1388,7 @@ static bool ath9k_hw_chip_reset(struct ath_hw *ah,
1389static bool ath9k_hw_channel_change(struct ath_hw *ah, 1388static bool ath9k_hw_channel_change(struct ath_hw *ah,
1390 struct ath9k_channel *chan) 1389 struct ath9k_channel *chan)
1391{ 1390{
1392 struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah);
1393 struct ath_common *common = ath9k_hw_common(ah); 1391 struct ath_common *common = ath9k_hw_common(ah);
1394 struct ieee80211_channel *channel = chan->chan;
1395 u32 qnum; 1392 u32 qnum;
1396 int r; 1393 int r;
1397 1394
@@ -1416,14 +1413,7 @@ static bool ath9k_hw_channel_change(struct ath_hw *ah,
1416 return false; 1413 return false;
1417 } 1414 }
1418 ath9k_hw_set_clockrate(ah); 1415 ath9k_hw_set_clockrate(ah);
1419 1416 ath9k_hw_apply_txpower(ah, chan);
1420 ah->eep_ops->set_txpower(ah, chan,
1421 ath9k_regd_get_ctl(regulatory, chan),
1422 channel->max_antenna_gain * 2,
1423 channel->max_power * 2,
1424 min((u32) MAX_RATE_POWER,
1425 (u32) regulatory->power_limit), false);
1426
1427 ath9k_hw_rfbus_done(ah); 1417 ath9k_hw_rfbus_done(ah);
1428 1418
1429 if (IS_CHAN_OFDM(chan) || IS_CHAN_HT(chan)) 1419 if (IS_CHAN_OFDM(chan) || IS_CHAN_HT(chan))
@@ -2498,23 +2488,56 @@ bool ath9k_hw_disable(struct ath_hw *ah)
2498} 2488}
2499EXPORT_SYMBOL(ath9k_hw_disable); 2489EXPORT_SYMBOL(ath9k_hw_disable);
2500 2490
2491static int get_antenna_gain(struct ath_hw *ah, struct ath9k_channel *chan)
2492{
2493 enum eeprom_param gain_param;
2494
2495 if (IS_CHAN_2GHZ(chan))
2496 gain_param = EEP_ANTENNA_GAIN_2G;
2497 else
2498 gain_param = EEP_ANTENNA_GAIN_5G;
2499
2500 return ah->eep_ops->get_eeprom(ah, gain_param);
2501}
2502
2503void ath9k_hw_apply_txpower(struct ath_hw *ah, struct ath9k_channel *chan)
2504{
2505 struct ath_regulatory *reg = ath9k_hw_regulatory(ah);
2506 struct ieee80211_channel *channel;
2507 int chan_pwr, new_pwr, max_gain;
2508 int ant_gain, ant_reduction = 0;
2509
2510 if (!chan)
2511 return;
2512
2513 channel = chan->chan;
2514 chan_pwr = min_t(int, channel->max_power * 2, MAX_RATE_POWER);
2515 new_pwr = min_t(int, chan_pwr, reg->power_limit);
2516 max_gain = chan_pwr - new_pwr + channel->max_antenna_gain * 2;
2517
2518 ant_gain = get_antenna_gain(ah, chan);
2519 if (ant_gain > max_gain)
2520 ant_reduction = ant_gain - max_gain;
2521
2522 ah->eep_ops->set_txpower(ah, chan,
2523 ath9k_regd_get_ctl(reg, chan),
2524 ant_reduction, new_pwr, false);
2525}
2526
2501void ath9k_hw_set_txpowerlimit(struct ath_hw *ah, u32 limit, bool test) 2527void ath9k_hw_set_txpowerlimit(struct ath_hw *ah, u32 limit, bool test)
2502{ 2528{
2503 struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah); 2529 struct ath_regulatory *reg = ath9k_hw_regulatory(ah);
2504 struct ath9k_channel *chan = ah->curchan; 2530 struct ath9k_channel *chan = ah->curchan;
2505 struct ieee80211_channel *channel = chan->chan; 2531 struct ieee80211_channel *channel = chan->chan;
2506 int reg_pwr = min_t(int, MAX_RATE_POWER, limit);
2507 int chan_pwr = channel->max_power * 2;
2508 2532
2533 reg->power_limit = min_t(int, limit, MAX_RATE_POWER);
2509 if (test) 2534 if (test)
2510 reg_pwr = chan_pwr = MAX_RATE_POWER; 2535 channel->max_power = MAX_RATE_POWER / 2;
2511 2536
2512 regulatory->power_limit = reg_pwr; 2537 ath9k_hw_apply_txpower(ah, chan);
2513 2538
2514 ah->eep_ops->set_txpower(ah, chan, 2539 if (test)
2515 ath9k_regd_get_ctl(regulatory, chan), 2540 channel->max_power = DIV_ROUND_UP(reg->max_power_level, 2);
2516 channel->max_antenna_gain * 2,
2517 chan_pwr, reg_pwr, test);
2518} 2541}
2519EXPORT_SYMBOL(ath9k_hw_set_txpowerlimit); 2542EXPORT_SYMBOL(ath9k_hw_set_txpowerlimit);
2520 2543
diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h
index 24889f78a05..684c33c4897 100644
--- a/drivers/net/wireless/ath/ath9k/hw.h
+++ b/drivers/net/wireless/ath/ath9k/hw.h
@@ -390,14 +390,6 @@ enum ath9k_power_mode {
390 ATH9K_PM_UNDEFINED 390 ATH9K_PM_UNDEFINED
391}; 391};
392 392
393enum ath9k_tp_scale {
394 ATH9K_TP_SCALE_MAX = 0,
395 ATH9K_TP_SCALE_50,
396 ATH9K_TP_SCALE_25,
397 ATH9K_TP_SCALE_12,
398 ATH9K_TP_SCALE_MIN
399};
400
401enum ser_reg_mode { 393enum ser_reg_mode {
402 SER_REG_MODE_OFF = 0, 394 SER_REG_MODE_OFF = 0,
403 SER_REG_MODE_ON = 1, 395 SER_REG_MODE_ON = 1,
@@ -968,6 +960,7 @@ void ath9k_hw_htc_resetinit(struct ath_hw *ah);
968/* PHY */ 960/* PHY */
969void ath9k_hw_get_delta_slope_vals(struct ath_hw *ah, u32 coef_scaled, 961void ath9k_hw_get_delta_slope_vals(struct ath_hw *ah, u32 coef_scaled,
970 u32 *coef_mantissa, u32 *coef_exponent); 962 u32 *coef_mantissa, u32 *coef_exponent);
963void ath9k_hw_apply_txpower(struct ath_hw *ah, struct ath9k_channel *chan);
971 964
972/* 965/*
973 * Code Specific to AR5008, AR9001 or AR9002, 966 * Code Specific to AR5008, AR9001 or AR9002,
diff --git a/drivers/net/wireless/ath/ath9k/init.c b/drivers/net/wireless/ath/ath9k/init.c
index 39514de044e..af1b3254953 100644
--- 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(struct ath_softc *sc, int band)
626 struct ieee80211_supported_band *sband; 626 struct ieee80211_supported_band *sband;
627 struct ieee80211_channel *chan; 627 struct ieee80211_channel *chan;
628 struct ath_hw *ah = sc->sc_ah; 628 struct ath_hw *ah = sc->sc_ah;
629 struct ath_regulatory *reg = ath9k_hw_regulatory(ah);
630 int i; 629 int i;
631 630
632 sband = &sc->sbands[band]; 631 sband = &sc->sbands[band];
@@ -635,7 +634,6 @@ static void ath9k_init_band_txpower(struct ath_softc *sc, int band)
635 ah->curchan = &ah->channels[chan->hw_value]; 634 ah->curchan = &ah->channels[chan->hw_value];
636 ath9k_cmn_update_ichannel(ah->curchan, chan, NL80211_CHAN_HT20); 635 ath9k_cmn_update_ichannel(ah->curchan, chan, NL80211_CHAN_HT20);
637 ath9k_hw_set_txpowerlimit(ah, MAX_RATE_POWER, true); 636 ath9k_hw_set_txpowerlimit(ah, MAX_RATE_POWER, true);
638 chan->max_power = reg->max_power_level / 2;
639 } 637 }
640} 638}
641 639