Skip to content

Commit

Permalink
ath9k_hw: clean up tx power handling
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Felix Fietkau authored and John W. Linville committed Oct 11, 2011
1 parent 72d874c commit ca2c68c
Show file tree
Hide file tree
Showing 13 changed files with 85 additions and 176 deletions.
1 change: 0 additions & 1 deletion drivers/net/wireless/ath/ath.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
11 changes: 1 addition & 10 deletions drivers/net/wireless/ath/ath9k/ar5008_phy.c
Original file line number Diff line number Diff line change
Expand Up @@ -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,
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) {
Expand Down Expand Up @@ -903,14 +901,7 @@ static int ar5008_hw_process_ini(struct ath_hw *ah,
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)) {
Expand Down
39 changes: 7 additions & 32 deletions drivers/net/wireless/ath/ath9k/ar9003_eeprom.c
Original file line number Diff line number Diff line change
Expand Up @@ -3021,6 +3021,10 @@ static u32 ath9k_hw_ar9300_get_eeprom(struct ath_hw *ah,
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;
}
Expand Down Expand Up @@ -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,
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
};
Expand All @@ -4795,28 +4793,7 @@ static void ar9003_hw_set_power_per_rate_table(struct ath_hw *ah,
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
Expand Down Expand Up @@ -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,
struct ath9k_channel *chan, u16 cfgCtl,
u8 twiceAntennaReduction,
u8 twiceMaxRegulatoryPower,
u8 powerLimit, bool test)
{
struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah);
Expand Down Expand Up @@ -5056,7 +5032,6 @@ static void ath9k_hw_ar9300_set_txpower(struct ath_hw *ah,
ar9003_hw_set_power_per_rate_table(ah, chan,
targetPowerValT2, cfgCtl,
twiceAntennaReduction,
twiceMaxRegulatoryPower,
powerLimit);

if (ah->eep_ops->get_eeprom(ah, EEP_PAPRD)) {
Expand Down
9 changes: 1 addition & 8 deletions drivers/net/wireless/ath/ath9k/ar9003_paprd.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -54,13 +53,7 @@ void ar9003_paprd_enable(struct ath_hw *ah, bool val)

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,
Expand Down
11 changes: 1 addition & 10 deletions drivers/net/wireless/ath/ath9k/ar9003_phy.c
Original file line number Diff line number Diff line change
Expand Up @@ -631,9 +631,7 @@ static void ar9003_hw_prog_ini(struct ath_hw *ah,
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) {
Expand Down Expand Up @@ -693,14 +691,7 @@ static int ar9003_hw_process_ini(struct ath_hw *ah,
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;
}
Expand Down
6 changes: 4 additions & 2 deletions drivers/net/wireless/ath/ath9k/common.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
7 changes: 4 additions & 3 deletions drivers/net/wireless/ath/ath9k/eeprom.h
Original file line number Diff line number Diff line change
Expand Up @@ -248,7 +248,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 {
Expand Down Expand Up @@ -652,8 +654,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);
};

Expand Down
27 changes: 5 additions & 22 deletions drivers/net/wireless/ath/ath9k/eeprom_4k.c
Original file line number Diff line number Diff line change
Expand Up @@ -350,6 +350,8 @@ static u32 ath9k_hw_4k_get_eeprom(struct ath_hw *ah,
return pModal->antdiv_ctl1;
case EEP_TXGAIN_TYPE:
return pBase->txGainType;
case EEP_ANTENNA_GAIN_2G:
return pModal->antennaGainCh[0];
default:
return 0;
}
Expand Down Expand Up @@ -462,8 +464,7 @@ static void ath9k_hw_set_4k_power_per_rate_table(struct ath_hw *ah,
struct ath9k_channel *chan,
int16_t *ratesArray,
u16 cfgCtl,
u16 AntennaReduction,
u16 twiceMaxRegulatoryPower,
u16 antenna_reduction,
u16 powerLimit)
{
#define CMP_TEST_GRP \
Expand All @@ -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)) == \
((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}
};
Expand All @@ -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);

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;

Expand Down Expand Up @@ -671,7 +656,6 @@ static void ath9k_hw_4k_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);
Expand All @@ -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,
&ratesArray[0], cfgCtl,
twiceAntennaReduction,
twiceMaxRegulatoryPower,
powerLimit);

ath9k_hw_set_4k_power_cal_table(ah, chan);
Expand Down
33 changes: 6 additions & 27 deletions drivers/net/wireless/ath/ath9k/eeprom_9287.c
Original file line number Diff line number Diff line change
Expand Up @@ -336,6 +336,9 @@ static u32 ath9k_hw_ar9287_get_eeprom(struct ath_hw *ah,
return pBase->tempSensSlopePalOn;
else
return 0;
case EEP_ANTENNA_GAIN_2G:
return max_t(u8, pModal->antennaGainCh[0],
pModal->antennaGainCh[1]);
default:
return 0;
}
Expand Down Expand Up @@ -554,8 +557,7 @@ static void ath9k_hw_set_ar9287_power_per_rate_table(struct ath_hw *ah,
struct ath9k_channel *chan,
int16_t *ratesArray,
u16 cfgCtl,
u16 AntennaReduction,
u16 twiceMaxRegulatoryPower,
u16 antenna_reduction,
u16 powerLimit)
{
#define CMP_CTL \
Expand All @@ -569,20 +571,16 @@ 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_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} };
struct cal_target_power_leg targetPowerOfdmExt = {0, {0, 0, 0, 0} },
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
Expand All @@ -597,24 +595,7 @@ static void ath9k_hw_set_ar9287_power_per_rate_table(struct ath_hw *ah,
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
Expand Down Expand Up @@ -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,
struct ath9k_channel *chan, u16 cfgCtl,
u8 twiceAntennaReduction,
u8 twiceMaxRegulatoryPower,
u8 powerLimit, bool test)
{
struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah);
Expand All @@ -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,
&ratesArray[0], cfgCtl,
twiceAntennaReduction,
twiceMaxRegulatoryPower,
powerLimit);

ath9k_hw_set_ar9287_power_cal_table(ah, chan);
Expand Down
Loading

0 comments on commit ca2c68c

Please sign in to comment.