Commit ca2c68cc authored by Felix Fietkau's avatar Felix Fietkau Committed by John W. Linville

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: default avatarFelix Fietkau <nbd@openwrt.org>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent 72d874c6
...@@ -71,7 +71,6 @@ struct ath_regulatory { ...@@ -71,7 +71,6 @@ struct ath_regulatory {
char alpha2[2]; char alpha2[2];
u16 country_code; u16 country_code;
u16 max_power_level; u16 max_power_level;
u32 tp_scale;
u16 current_rd; u16 current_rd;
u16 current_rd_ext; u16 current_rd_ext;
int16_t power_limit; int16_t power_limit;
......
...@@ -763,10 +763,8 @@ static void ar5008_hw_set_channel_regs(struct ath_hw *ah, ...@@ -763,10 +763,8 @@ static void ar5008_hw_set_channel_regs(struct ath_hw *ah,
static int ar5008_hw_process_ini(struct ath_hw *ah, static int ar5008_hw_process_ini(struct ath_hw *ah,
struct ath9k_channel *chan) struct ath9k_channel *chan)
{ {
struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah);
struct ath_common *common = ath9k_hw_common(ah); struct ath_common *common = ath9k_hw_common(ah);
int i, regWrites = 0; int i, regWrites = 0;
struct ieee80211_channel *channel = chan->chan;
u32 modesIndex, freqIndex; u32 modesIndex, freqIndex;
switch (chan->chanmode) { switch (chan->chanmode) {
...@@ -903,14 +901,7 @@ static int ar5008_hw_process_ini(struct ath_hw *ah, ...@@ -903,14 +901,7 @@ static int ar5008_hw_process_ini(struct ath_hw *ah,
ar5008_hw_set_channel_regs(ah, chan); ar5008_hw_set_channel_regs(ah, chan);
ar5008_hw_init_chain_masks(ah); ar5008_hw_init_chain_masks(ah);
ath9k_olc_init(ah); ath9k_olc_init(ah);
ath9k_hw_apply_txpower(ah, chan);
/* 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);
/* Write analog registers */ /* Write analog registers */
if (!ath9k_hw_set_rf_regs(ah, chan, freqIndex)) { if (!ath9k_hw_set_rf_regs(ah, chan, freqIndex)) {
......
...@@ -3021,6 +3021,10 @@ static u32 ath9k_hw_ar9300_get_eeprom(struct ath_hw *ah, ...@@ -3021,6 +3021,10 @@ static u32 ath9k_hw_ar9300_get_eeprom(struct ath_hw *ah,
return (pBase->miscConfiguration >> 0x3) & 0x1; return (pBase->miscConfiguration >> 0x3) & 0x1;
case EEP_ANT_DIV_CTL1: case EEP_ANT_DIV_CTL1:
return eep->base_ext1.ant_div_control; 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: default:
return 0; return 0;
} }
...@@ -4764,20 +4768,14 @@ static u16 ar9003_hw_get_max_edge_power(struct ar9300_eeprom *eep, ...@@ -4764,20 +4768,14 @@ static u16 ar9003_hw_get_max_edge_power(struct ar9300_eeprom *eep,
static void ar9003_hw_set_power_per_rate_table(struct ath_hw *ah, static void ar9003_hw_set_power_per_rate_table(struct ath_hw *ah,
struct ath9k_channel *chan, struct ath9k_channel *chan,
u8 *pPwrArray, u16 cfgCtl, u8 *pPwrArray, u16 cfgCtl,
u8 twiceAntennaReduction, u8 antenna_reduction,
u8 twiceMaxRegulatoryPower,
u16 powerLimit) u16 powerLimit)
{ {
struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah);
struct ath_common *common = ath9k_hw_common(ah); struct ath_common *common = ath9k_hw_common(ah);
struct ar9300_eeprom *pEepData = &ah->eeprom.ar9300_eep; struct ar9300_eeprom *pEepData = &ah->eeprom.ar9300_eep;
u16 twiceMaxEdgePower = MAX_RATE_POWER; u16 twiceMaxEdgePower = MAX_RATE_POWER;
static const u16 tpScaleReductionTable[5] = {
0, 3, 6, 9, MAX_RATE_POWER
};
int i; int i;
int16_t twiceLargestAntenna; u16 scaledPower = 0, minCtlPower;
u16 scaledPower = 0, minCtlPower, maxRegAllowedPower;
static const u16 ctlModesFor11a[] = { static const u16 ctlModesFor11a[] = {
CTL_11A, CTL_5GHT20, CTL_11A_EXT, CTL_5GHT40 CTL_11A, CTL_5GHT20, CTL_11A_EXT, CTL_5GHT40
}; };
...@@ -4795,28 +4793,7 @@ static void ar9003_hw_set_power_per_rate_table(struct ath_hw *ah, ...@@ -4795,28 +4793,7 @@ static void ar9003_hw_set_power_per_rate_table(struct ath_hw *ah,
bool is2ghz = IS_CHAN_2GHZ(chan); bool is2ghz = IS_CHAN_2GHZ(chan);
ath9k_hw_get_channel_centers(ah, chan, &centers); ath9k_hw_get_channel_centers(ah, chan, &centers);
scaledPower = powerLimit - antenna_reduction;
/* 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);
/* /*
* Reduce scaled Power by number of chains active to get * 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) ...@@ -5003,7 +4980,6 @@ static inline u8 mcsidx_to_tgtpwridx(unsigned int mcs_idx, u8 base_pwridx)
static void ath9k_hw_ar9300_set_txpower(struct ath_hw *ah, static void ath9k_hw_ar9300_set_txpower(struct ath_hw *ah,
struct ath9k_channel *chan, u16 cfgCtl, struct ath9k_channel *chan, u16 cfgCtl,
u8 twiceAntennaReduction, u8 twiceAntennaReduction,
u8 twiceMaxRegulatoryPower,
u8 powerLimit, bool test) u8 powerLimit, bool test)
{ {
struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah); struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah);
...@@ -5056,7 +5032,6 @@ static void ath9k_hw_ar9300_set_txpower(struct ath_hw *ah, ...@@ -5056,7 +5032,6 @@ static void ath9k_hw_ar9300_set_txpower(struct ath_hw *ah,
ar9003_hw_set_power_per_rate_table(ah, chan, ar9003_hw_set_power_per_rate_table(ah, chan,
targetPowerValT2, cfgCtl, targetPowerValT2, cfgCtl,
twiceAntennaReduction, twiceAntennaReduction,
twiceMaxRegulatoryPower,
powerLimit); powerLimit);
if (ah->eep_ops->get_eeprom(ah, EEP_PAPRD)) { if (ah->eep_ops->get_eeprom(ah, EEP_PAPRD)) {
......
...@@ -19,7 +19,6 @@ ...@@ -19,7 +19,6 @@
void ar9003_paprd_enable(struct ath_hw *ah, bool val) 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 ath9k_channel *chan = ah->curchan;
struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep; struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep;
...@@ -54,13 +53,7 @@ void ar9003_paprd_enable(struct ath_hw *ah, bool val) ...@@ -54,13 +53,7 @@ void ar9003_paprd_enable(struct ath_hw *ah, bool val)
if (val) { if (val) {
ah->paprd_table_write_done = true; ah->paprd_table_write_done = true;
ath9k_hw_apply_txpower(ah, chan);
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);
} }
REG_RMW_FIELD(ah, AR_PHY_PAPRD_CTRL0_B0, REG_RMW_FIELD(ah, AR_PHY_PAPRD_CTRL0_B0,
......
...@@ -631,9 +631,7 @@ static void ar9003_hw_prog_ini(struct ath_hw *ah, ...@@ -631,9 +631,7 @@ static void ar9003_hw_prog_ini(struct ath_hw *ah,
static int ar9003_hw_process_ini(struct ath_hw *ah, static int ar9003_hw_process_ini(struct ath_hw *ah,
struct ath9k_channel *chan) struct ath9k_channel *chan)
{ {
struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah);
unsigned int regWrites = 0, i; unsigned int regWrites = 0, i;
struct ieee80211_channel *channel = chan->chan;
u32 modesIndex; u32 modesIndex;
switch (chan->chanmode) { switch (chan->chanmode) {
...@@ -693,14 +691,7 @@ static int ar9003_hw_process_ini(struct ath_hw *ah, ...@@ -693,14 +691,7 @@ static int ar9003_hw_process_ini(struct ath_hw *ah,
ar9003_hw_override_ini(ah); ar9003_hw_override_ini(ah);
ar9003_hw_set_channel_regs(ah, chan); ar9003_hw_set_channel_regs(ah, chan);
ar9003_hw_set_chain_masks(ah, ah->rxchainmask, ah->txchainmask); ar9003_hw_set_chain_masks(ah, ah->rxchainmask, ah->txchainmask);
ath9k_hw_apply_txpower(ah, chan);
/* 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);
return 0; return 0;
} }
......
...@@ -161,10 +161,12 @@ EXPORT_SYMBOL(ath9k_cmn_count_streams); ...@@ -161,10 +161,12 @@ EXPORT_SYMBOL(ath9k_cmn_count_streams);
void ath9k_cmn_update_txpow(struct ath_hw *ah, u16 cur_txpow, void ath9k_cmn_update_txpow(struct ath_hw *ah, u16 cur_txpow,
u16 new_txpow, u16 *txpower) 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); ath9k_hw_set_txpowerlimit(ah, new_txpow, false);
/* read back in case value is clamped */ /* 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); EXPORT_SYMBOL(ath9k_cmn_update_txpow);
......
...@@ -248,7 +248,9 @@ enum eeprom_param { ...@@ -248,7 +248,9 @@ enum eeprom_param {
EEP_PAPRD, EEP_PAPRD,
EEP_MODAL_VER, EEP_MODAL_VER,
EEP_ANT_DIV_CTL1, EEP_ANT_DIV_CTL1,
EEP_CHAIN_MASK_REDUCE EEP_CHAIN_MASK_REDUCE,
EEP_ANTENNA_GAIN_2G,
EEP_ANTENNA_GAIN_5G
}; };
enum ar5416_rates { enum ar5416_rates {
...@@ -652,8 +654,7 @@ struct eeprom_ops { ...@@ -652,8 +654,7 @@ struct eeprom_ops {
void (*set_addac)(struct ath_hw *hw, struct ath9k_channel *chan); void (*set_addac)(struct ath_hw *hw, struct ath9k_channel *chan);
void (*set_txpower)(struct ath_hw *hw, struct ath9k_channel *chan, void (*set_txpower)(struct ath_hw *hw, struct ath9k_channel *chan,
u16 cfgCtl, u8 twiceAntennaReduction, u16 cfgCtl, u8 twiceAntennaReduction,
u8 twiceMaxRegulatoryPower, u8 powerLimit, u8 powerLimit, bool test);
bool test);
u16 (*get_spur_channel)(struct ath_hw *ah, u16 i, bool is2GHz); u16 (*get_spur_channel)(struct ath_hw *ah, u16 i, bool is2GHz);
}; };
......
...@@ -350,6 +350,8 @@ static u32 ath9k_hw_4k_get_eeprom(struct ath_hw *ah, ...@@ -350,6 +350,8 @@ static u32 ath9k_hw_4k_get_eeprom(struct ath_hw *ah,
return pModal->antdiv_ctl1; return pModal->antdiv_ctl1;
case EEP_TXGAIN_TYPE: case EEP_TXGAIN_TYPE:
return pBase->txGainType; return pBase->txGainType;
case EEP_ANTENNA_GAIN_2G:
return pModal->antennaGainCh[0];
default: default:
return 0; return 0;
} }
...@@ -462,8 +464,7 @@ static void ath9k_hw_set_4k_power_per_rate_table(struct ath_hw *ah, ...@@ -462,8 +464,7 @@ static void ath9k_hw_set_4k_power_per_rate_table(struct ath_hw *ah,
struct ath9k_channel *chan, struct ath9k_channel *chan,
int16_t *ratesArray, int16_t *ratesArray,
u16 cfgCtl, u16 cfgCtl,
u16 AntennaReduction, u16 antenna_reduction,
u16 twiceMaxRegulatoryPower,
u16 powerLimit) u16 powerLimit)
{ {
#define CMP_TEST_GRP \ #define CMP_TEST_GRP \
...@@ -472,20 +473,16 @@ static void ath9k_hw_set_4k_power_per_rate_table(struct ath_hw *ah, ...@@ -472,20 +473,16 @@ static void ath9k_hw_set_4k_power_per_rate_table(struct ath_hw *ah,
|| (((cfgCtl & ~CTL_MODE_M) | (pCtlMode[ctlMode] & CTL_MODE_M)) == \ || (((cfgCtl & ~CTL_MODE_M) | (pCtlMode[ctlMode] & CTL_MODE_M)) == \
((pEepData->ctlIndex[i] & CTL_MODE_M) | SD_NO_CTL)) ((pEepData->ctlIndex[i] & CTL_MODE_M) | SD_NO_CTL))
struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah);
int i; int i;
int16_t twiceLargestAntenna;
u16 twiceMinEdgePower; u16 twiceMinEdgePower;
u16 twiceMaxEdgePower = MAX_RATE_POWER; u16 twiceMaxEdgePower = MAX_RATE_POWER;
u16 scaledPower = 0, minCtlPower, maxRegAllowedPower; u16 scaledPower = 0, minCtlPower;
u16 numCtlModes; u16 numCtlModes;
const u16 *pCtlMode; const u16 *pCtlMode;
u16 ctlMode, freq; u16 ctlMode, freq;
struct chan_centers centers; struct chan_centers centers;
struct cal_ctl_data_4k *rep; struct cal_ctl_data_4k *rep;
struct ar5416_eeprom_4k *pEepData = &ah->eeprom.map4k; 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 = { struct cal_target_power_leg targetPowerOfdm, targetPowerCck = {
0, { 0, 0, 0, 0} 0, { 0, 0, 0, 0}
}; };
...@@ -503,19 +500,7 @@ static void ath9k_hw_set_4k_power_per_rate_table(struct ath_hw *ah, ...@@ -503,19 +500,7 @@ static void ath9k_hw_set_4k_power_per_rate_table(struct ath_hw *ah,
ath9k_hw_get_channel_centers(ah, chan, &centers); ath9k_hw_get_channel_centers(ah, chan, &centers);
twiceLargestAntenna = pEepData->modalHeader.antennaGainCh[0]; scaledPower = powerLimit - antenna_reduction;
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);
numCtlModes = ARRAY_SIZE(ctlModesFor11g) - SUB_NUM_CTL_MODES_AT_2G_40; numCtlModes = ARRAY_SIZE(ctlModesFor11g) - SUB_NUM_CTL_MODES_AT_2G_40;
pCtlMode = ctlModesFor11g; pCtlMode = ctlModesFor11g;
...@@ -671,7 +656,6 @@ static void ath9k_hw_4k_set_txpower(struct ath_hw *ah, ...@@ -671,7 +656,6 @@ static void ath9k_hw_4k_set_txpower(struct ath_hw *ah,
struct ath9k_channel *chan, struct ath9k_channel *chan,
u16 cfgCtl, u16 cfgCtl,
u8 twiceAntennaReduction, u8 twiceAntennaReduction,
u8 twiceMaxRegulatoryPower,
u8 powerLimit, bool test) u8 powerLimit, bool test)
{ {
struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah); struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah);
...@@ -691,7 +675,6 @@ static void ath9k_hw_4k_set_txpower(struct ath_hw *ah, ...@@ -691,7 +675,6 @@ static void ath9k_hw_4k_set_txpower(struct ath_hw *ah,
ath9k_hw_set_4k_power_per_rate_table(ah, chan, ath9k_hw_set_4k_power_per_rate_table(ah, chan,
&ratesArray[0], cfgCtl, &ratesArray[0], cfgCtl,
twiceAntennaReduction, twiceAntennaReduction,
twiceMaxRegulatoryPower,
powerLimit); powerLimit);
ath9k_hw_set_4k_power_cal_table(ah, chan); ath9k_hw_set_4k_power_cal_table(ah, chan);
......
...@@ -336,6 +336,9 @@ static u32 ath9k_hw_ar9287_get_eeprom(struct ath_hw *ah, ...@@ -336,6 +336,9 @@ static u32 ath9k_hw_ar9287_get_eeprom(struct ath_hw *ah,
return pBase->tempSensSlopePalOn; return pBase->tempSensSlopePalOn;
else else
return 0; return 0;
case EEP_ANTENNA_GAIN_2G:
return max_t(u8, pModal->antennaGainCh[0],
pModal->antennaGainCh[1]);
default: default:
return 0; return 0;
} }
...@@ -554,8 +557,7 @@ static void ath9k_hw_set_ar9287_power_per_rate_table(struct ath_hw *ah, ...@@ -554,8 +557,7 @@ static void ath9k_hw_set_ar9287_power_per_rate_table(struct ath_hw *ah,
struct ath9k_channel *chan, struct ath9k_channel *chan,
int16_t *ratesArray, int16_t *ratesArray,
u16 cfgCtl, u16 cfgCtl,
u16 AntennaReduction, u16 antenna_reduction,
u16 twiceMaxRegulatoryPower,
u16 powerLimit) u16 powerLimit)
{ {
#define CMP_CTL \ #define CMP_CTL \
...@@ -569,12 +571,8 @@ static void ath9k_hw_set_ar9287_power_per_rate_table(struct ath_hw *ah, ...@@ -569,12 +571,8 @@ static void ath9k_hw_set_ar9287_power_per_rate_table(struct ath_hw *ah,
#define REDUCE_SCALED_POWER_BY_TWO_CHAIN 6 #define REDUCE_SCALED_POWER_BY_TWO_CHAIN 6
#define REDUCE_SCALED_POWER_BY_THREE_CHAIN 10 #define REDUCE_SCALED_POWER_BY_THREE_CHAIN 10
struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah);
u16 twiceMaxEdgePower = MAX_RATE_POWER; u16 twiceMaxEdgePower = MAX_RATE_POWER;
static const u16 tpScaleReductionTable[5] =
{ 0, 3, 6, 9, MAX_RATE_POWER };
int i; int i;
int16_t twiceLargestAntenna;
struct cal_ctl_data_ar9287 *rep; struct cal_ctl_data_ar9287 *rep;
struct cal_target_power_leg targetPowerOfdm = {0, {0, 0, 0, 0} }, struct cal_target_power_leg targetPowerOfdm = {0, {0, 0, 0, 0} },
targetPowerCck = {0, {0, 0, 0, 0} }; 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,7 +580,7 @@ static void ath9k_hw_set_ar9287_power_per_rate_table(struct ath_hw *ah,
targetPowerCckExt = {0, {0, 0, 0, 0} }; targetPowerCckExt = {0, {0, 0, 0, 0} };
struct cal_target_power_ht targetPowerHt20, struct cal_target_power_ht targetPowerHt20,
targetPowerHt40 = {0, {0, 0, 0, 0} }; targetPowerHt40 = {0, {0, 0, 0, 0} };
u16 scaledPower = 0, minCtlPower, maxRegAllowedPower; u16 scaledPower = 0, minCtlPower;
static const u16 ctlModesFor11g[] = { static const u16 ctlModesFor11g[] = {
CTL_11B, CTL_11G, CTL_2GHT20, CTL_11B, CTL_11G, CTL_2GHT20,
CTL_11B_EXT, CTL_11G_EXT, CTL_2GHT40 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,24 +595,7 @@ static void ath9k_hw_set_ar9287_power_per_rate_table(struct ath_hw *ah,
tx_chainmask = ah->txchainmask; tx_chainmask = ah->txchainmask;
ath9k_hw_get_channel_centers(ah, chan, &centers); ath9k_hw_get_channel_centers(ah, chan, &centers);
scaledPower = powerLimit - antenna_reduction;
/* 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);
/* /*
* Reduce scaled Power by number of chains active * 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, ...@@ -815,7 +796,6 @@ static void ath9k_hw_set_ar9287_power_per_rate_table(struct ath_hw *ah,
static void ath9k_hw_ar9287_set_txpower(struct ath_hw *ah, static void ath9k_hw_ar9287_set_txpower(struct ath_hw *ah,
struct ath9k_channel *chan, u16 cfgCtl, struct ath9k_channel *chan, u16 cfgCtl,
u8 twiceAntennaReduction, u8 twiceAntennaReduction,
u8 twiceMaxRegulatoryPower,
u8 powerLimit, bool test) u8 powerLimit, bool test)
{ {
struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah); struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah);
...@@ -834,7 +814,6 @@ static void ath9k_hw_ar9287_set_txpower(struct ath_hw *ah, ...@@ -834,7 +814,6 @@ static void ath9k_hw_ar9287_set_txpower(struct ath_hw *ah,
ath9k_hw_set_ar9287_power_per_rate_table(ah, chan, ath9k_hw_set_ar9287_power_per_rate_table(ah, chan,
&ratesArray[0], cfgCtl, &ratesArray[0], cfgCtl,
twiceAntennaReduction, twiceAntennaReduction,
twiceMaxRegulatoryPower,
powerLimit); powerLimit);
ath9k_hw_set_ar9287_power_cal_table(ah, chan); ath9k_hw_set_ar9287_power_cal_table(ah, chan);
......
...@@ -400,6 +400,7 @@ static u32 ath9k_hw_def_get_eeprom(struct ath_hw *ah, ...@@ -400,6 +400,7 @@ static u32 ath9k_hw_def_get_eeprom(struct ath_hw *ah,
struct ar5416_eeprom_def *eep = &ah->eeprom.def; struct ar5416_eeprom_def *eep = &ah->eeprom.def;
struct modal_eep_header *pModal = eep->modalHeader; struct modal_eep_header *pModal = eep->modalHeader;
struct base_eep_header *pBase = &eep->baseEepHeader; struct base_eep_header *pBase = &eep->baseEepHeader;
int band = 0;
switch (param) { switch (param) {
case EEP_NFTHRESH_5: case EEP_NFTHRESH_5:
...@@ -467,6 +468,14 @@ static u32 ath9k_hw_def_get_eeprom(struct ath_hw *ah, ...@@ -467,6 +468,14 @@ static u32 ath9k_hw_def_get_eeprom(struct ath_hw *ah,
return pBase->pwr_table_offset; return pBase->pwr_table_offset;
else else
return AR5416_PWR_TABLE_OFFSET_DB; 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: default:
return 0; return 0;
} }
...@@ -986,21 +995,15 @@ static void ath9k_hw_set_def_power_per_rate_table(struct ath_hw *ah, ...@@ -986,21 +995,15 @@ static void ath9k_hw_set_def_power_per_rate_table(struct ath_hw *ah,
struct ath9k_channel *chan, struct ath9k_channel *chan,
int16_t *ratesArray, int16_t *ratesArray,
u16 cfgCtl, u16 cfgCtl,
u16 AntennaReduction, u16 antenna_reduction,
u16 twiceMaxRegulatoryPower,
u16 powerLimit) u16 powerLimit)
{ {
#define REDUCE_SCALED_POWER_BY_TWO_CHAIN 6 /* 10*log10(2)*2 */ #define REDUCE_SCALED_POWER_BY_TWO_CHAIN 6 /* 10*log10(2)*2 */
#define REDUCE_SCALED_POWER_BY_THREE_CHAIN 9 /* 10*log10(3)*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; struct ar5416_eeprom_def *pEepData = &ah->eeprom.def;
u16 twiceMaxEdgePower = MAX_RATE_POWER; u16 twiceMaxEdgePower = MAX_RATE_POWER;
static const u16 tpScaleReductionTable[5] =
{ 0, 3, 6, 9, MAX_RATE_POWER };
int i; int i;
int16_t twiceLargestAntenna;
struct cal_ctl_data *rep; struct cal_ctl_data *rep;
struct cal_target_power_leg targetPowerOfdm, targetPowerCck = { struct cal_target_power_leg targetPowerOfdm, targetPowerCck = {
0, { 0, 0, 0, 0} 0, { 0, 0, 0, 0}
...@@ -1012,7 +1015,7 @@ static void ath9k_hw_set_def_power_per_rate_table(struct ath_hw *ah, ...@@ -1012,7 +1015,7 @@ static void ath9k_hw_set_def_power_per_rate_table(struct ath_hw *ah,
struct cal_target_power_ht targetPowerHt20, targetPowerHt40 = { struct cal_target_power_ht targetPowerHt20, targetPowerHt40 = {
0, {0, 0, 0, 0} 0, {0, 0, 0, 0}
}; };
u16 scaledPower = 0, minCtlPower, maxRegAllowedPower; u16 scaledPower = 0, minCtlPower;
static const u16 ctlModesFor11a[] = { static const u16 ctlModesFor11a[] = {
CTL_11A, CTL_5GHT20, CTL_11A_EXT, CTL_5GHT40 CTL_11A, CTL_5GHT20, CTL_11A_EXT, CTL_5GHT40
}; };
...@@ -1031,27 +1034,7 @@ static void ath9k_hw_set_def_power_per_rate_table(struct ath_hw *ah, ...@@ -1031,27 +1034,7 @@ static void ath9k_hw_set_def_power_per_rate_table(struct ath_hw *ah,
ath9k_hw_get_channel_centers(ah, chan, &centers); ath9k_hw_get_channel_centers(ah, chan, &centers);
twiceLargestAntenna = max( scaledPower = powerLimit - antenna_reduction;
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);
switch (ar5416_get_ntxchains(tx_chainmask)) { switch (ar5416_get_ntxchains(tx_chainmask)) {
case 1: case 1:
...@@ -1256,7 +1239,6 @@ static void ath9k_hw_def_set_txpower(struct ath_hw *ah, ...@@ -1256,7 +1239,6 @@ static void ath9k_hw_def_set_txpower(struct ath_hw *ah,
struct ath9k_channel *chan, struct ath9k_channel *chan,
u16 cfgCtl, u16 cfgCtl,
u8 twiceAntennaReduction, u8 twiceAntennaReduction,
u8 twiceMaxRegulatoryPower,
u8 powerLimit, bool test) u8 powerLimit, bool test)
{ {
#define RT_AR_DELTA(x) (ratesArray[x] - cck_ofdm_delta) #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,7 +1260,6 @@ static void ath9k_hw_def_set_txpower(struct ath_hw *ah,
ath9k_hw_set_def_power_per_rate_table(ah, chan, ath9k_hw_set_def_power_per_rate_table(ah, chan,
&ratesArray[0], cfgCtl, &ratesArray[0], cfgCtl,
twiceAntennaReduction, twiceAntennaReduction,
twiceMaxRegulatoryPower,
powerLimit); powerLimit);
ath9k_hw_set_def_power_cal_table(ah, chan); ath9k_hw_set_def_power_cal_table(ah, chan);
......
...@@ -433,7 +433,6 @@ static void ath9k_hw_init_defaults(struct ath_hw *ah) ...@@ -433,7 +433,6 @@ static void ath9k_hw_init_defaults(struct ath_hw *ah)
regulatory->country_code = CTRY_DEFAULT; regulatory->country_code = CTRY_DEFAULT;
regulatory->power_limit = MAX_RATE_POWER; regulatory->power_limit = MAX_RATE_POWER;
regulatory->tp_scale = ATH9K_TP_SCALE_MAX;
ah->hw_version.magic = AR5416_MAGIC; ah->hw_version.magic = AR5416_MAGIC;
ah->hw_version.subvendorid = 0; ah->hw_version.subvendorid = 0;
...@@ -1389,9 +1388,7 @@ static bool ath9k_hw_chip_reset(struct ath_hw *ah, ...@@ -1389,9 +1388,7 @@ static bool ath9k_hw_chip_reset(struct ath_hw *ah,
static bool ath9k_hw_channel_change(struct ath_hw *ah, static bool ath9k_hw_channel_change(struct ath_hw *ah,
struct ath9k_channel *chan) struct ath9k_channel *chan)
{ {
struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah);
struct ath_common *common = ath9k_hw_common(ah); struct ath_common *common = ath9k_hw_common(ah);
struct ieee80211_channel *channel = chan->chan;
u32 qnum; u32 qnum;
int r; int r;
...@@ -1416,14 +1413,7 @@ static bool ath9k_hw_channel_change(struct ath_hw *ah, ...@@ -1416,14 +1413,7 @@ static bool ath9k_hw_channel_change(struct ath_hw *ah,
return false; return false;
} }
ath9k_hw_set_clockrate(ah); ath9k_hw_set_clockrate(ah);
ath9k_hw_apply_txpower(ah, chan);
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_rfbus_done(ah); ath9k_hw_rfbus_done(ah);
if (IS_CHAN_OFDM(chan) || IS_CHAN_HT(chan)) if (IS_CHAN_OFDM(chan) || IS_CHAN_HT(chan))
...@@ -2498,23 +2488,56 @@ bool ath9k_hw_disable(struct ath_hw *ah) ...@@ -2498,23 +2488,56 @@ bool ath9k_hw_disable(struct ath_hw *ah)
} }
EXPORT_SYMBOL(ath9k_hw_disable); 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 = chan_pwr - new_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) 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 ath9k_channel *chan = ah->curchan;
struct ieee80211_channel *channel = chan->chan; 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) 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, if (test)
ath9k_regd_get_ctl(regulatory, chan), channel->max_power = DIV_ROUND_UP(reg->max_power_level, 2);
channel->max_antenna_gain * 2,
chan_pwr, reg_pwr, test);
} }
EXPORT_SYMBOL(ath9k_hw_set_txpowerlimit); EXPORT_SYMBOL(ath9k_hw_set_txpowerlimit);
......
...@@ -390,14 +390,6 @@ enum ath9k_power_mode { ...@@ -390,14 +390,6 @@ enum ath9k_power_mode {
ATH9K_PM_UNDEFINED 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 { enum ser_reg_mode {
SER_REG_MODE_OFF = 0, SER_REG_MODE_OFF = 0,
SER_REG_MODE_ON = 1, SER_REG_MODE_ON = 1,
...@@ -968,6 +960,7 @@ void ath9k_hw_htc_resetinit(struct ath_hw *ah); ...@@ -968,6 +960,7 @@ void ath9k_hw_htc_resetinit(struct ath_hw *ah);
/* PHY */ /* PHY */
void ath9k_hw_get_delta_slope_vals(struct ath_hw *ah, u32 coef_scaled, void ath9k_hw_get_delta_slope_vals(struct ath_hw *ah, u32 coef_scaled,
u32 *coef_mantissa, u32 *coef_exponent); 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, * Code Specific to AR5008, AR9001 or AR9002,
......
...@@ -626,7 +626,6 @@ static void ath9k_init_band_txpower(struct ath_softc *sc, int band) ...@@ -626,7 +626,6 @@ static void ath9k_init_band_txpower(struct ath_softc *sc, int band)
struct ieee80211_supported_band *sband; struct ieee80211_supported_band *sband;
struct ieee80211_channel *chan; struct ieee80211_channel *chan;
struct ath_hw *ah = sc->sc_ah; struct ath_hw *ah = sc->sc_ah;
struct ath_regulatory *reg = ath9k_hw_regulatory(ah);
int i; int i;
sband = &sc->sbands[band]; sband = &sc->sbands[band];
...@@ -635,7 +634,6 @@ static void ath9k_init_band_txpower(struct ath_softc *sc, int band) ...@@ -635,7 +634,6 @@ static void ath9k_init_band_txpower(struct ath_softc *sc, int band)
ah->curchan = &ah->channels[chan->hw_value]; ah->curchan = &ah->channels[chan->hw_value];
ath9k_cmn_update_ichannel(ah->curchan, chan, NL80211_CHAN_HT20); ath9k_cmn_update_ichannel(ah->curchan, chan, NL80211_CHAN_HT20);
ath9k_hw_set_txpowerlimit(ah, MAX_RATE_POWER, true); ath9k_hw_set_txpowerlimit(ah, MAX_RATE_POWER, true);
chan->max_power = reg->max_power_level / 2;
} }
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment