Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

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
Loading
Loading
Loading
Loading
+0 −1
Original line number Original line Diff line number Diff line
@@ -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;
+1 −10
Original line number Original line Diff line number Diff line
@@ -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,
	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)) {
+7 −32
Original line number Original line Diff line number Diff line
@@ -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,
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,
	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)
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,
	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)) {
+1 −8
Original line number Original line Diff line number Diff line
@@ -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)


	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,
+1 −10
Original line number Original line Diff line number Diff line
@@ -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,
	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;
}
}
Loading