From d430237b28a6b2b5701f817ebfbfec1d22fdaaa6 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Wed, 20 Oct 2010 00:08:17 +0000 Subject: [PATCH] ath9k: fix tx power display SVN-Revision: 23541 --- .../520-ath9k_ar9003_regulatory_power.patch | 18 ++ .../patches/521-ath9k_hw_tx_power.patch | 279 ++++++++++++++++++ .../patches/522-ath9k_tx_power_init.patch | 115 ++++++++ 3 files changed, 412 insertions(+) create mode 100644 package/mac80211/patches/520-ath9k_ar9003_regulatory_power.patch create mode 100644 package/mac80211/patches/521-ath9k_hw_tx_power.patch create mode 100644 package/mac80211/patches/522-ath9k_tx_power_init.patch diff --git a/package/mac80211/patches/520-ath9k_ar9003_regulatory_power.patch b/package/mac80211/patches/520-ath9k_ar9003_regulatory_power.patch new file mode 100644 index 000000000000..6d0ecef8660f --- /dev/null +++ b/package/mac80211/patches/520-ath9k_ar9003_regulatory_power.patch @@ -0,0 +1,18 @@ +--- a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c ++++ b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c +@@ -2133,6 +2133,7 @@ static void ath9k_hw_ar9300_set_txpower( + u8 twiceMaxRegulatoryPower, + u8 powerLimit) + { ++ struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah); + struct ath_common *common = ath9k_hw_common(ah); + u8 targetPowerValT2[ar9300RateSize]; + unsigned int i = 0; +@@ -2180,6 +2181,7 @@ static void ath9k_hw_ar9300_set_txpower( + i = ALL_TARGET_HT20_0_8_16; /* ht20 */ + + ah->txpower_limit = targetPowerValT2[i]; ++ regulatory->max_power_level = ratesArray[i]; + + ar9003_hw_calibration_apply(ah, chan->channel); + } diff --git a/package/mac80211/patches/521-ath9k_hw_tx_power.patch b/package/mac80211/patches/521-ath9k_hw_tx_power.patch new file mode 100644 index 000000000000..b220750c3122 --- /dev/null +++ b/package/mac80211/patches/521-ath9k_hw_tx_power.patch @@ -0,0 +1,279 @@ +--- a/drivers/net/wireless/ath/ath9k/eeprom.h ++++ b/drivers/net/wireless/ath/ath9k/eeprom.h +@@ -680,7 +680,8 @@ 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); ++ u8 twiceMaxRegulatoryPower, u8 powerLimit, ++ bool test); + u16 (*get_spur_channel)(struct ath_hw *ah, u16 i, bool is2GHz); + }; + +--- a/drivers/net/wireless/ath/ath9k/eeprom_4k.c ++++ b/drivers/net/wireless/ath/ath9k/eeprom_4k.c +@@ -726,7 +726,7 @@ static void ath9k_hw_4k_set_txpower(stru + u16 cfgCtl, + u8 twiceAntennaReduction, + u8 twiceMaxRegulatoryPower, +- u8 powerLimit) ++ u8 powerLimit, bool test) + { + struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah); + struct ar5416_eeprom_4k *pEepData = &ah->eeprom.map4k; +@@ -768,6 +768,9 @@ static void ath9k_hw_4k_set_txpower(stru + + regulatory->max_power_level = ratesArray[i]; + ++ if (test) ++ return; ++ + if (AR_SREV_9280_20_OR_LATER(ah)) { + for (i = 0; i < Ar5416RateSize; i++) + ratesArray[i] -= AR5416_PWR_TABLE_OFFSET_DB * 2; +--- a/drivers/net/wireless/ath/ath9k/eeprom_9287.c ++++ b/drivers/net/wireless/ath/ath9k/eeprom_9287.c +@@ -853,7 +853,7 @@ static void ath9k_hw_ar9287_set_txpower( + struct ath9k_channel *chan, u16 cfgCtl, + u8 twiceAntennaReduction, + u8 twiceMaxRegulatoryPower, +- u8 powerLimit) ++ u8 powerLimit, bool test) + { + struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah); + struct ar9287_eeprom *pEepData = &ah->eeprom.map9287; +@@ -883,6 +883,16 @@ static void ath9k_hw_ar9287_set_txpower( + ratesArray[i] = AR9287_MAX_RATE_POWER; + } + ++ if (IS_CHAN_2GHZ(chan)) ++ i = rate1l; ++ else ++ i = rate6mb; ++ ++ regulatory->max_power_level = ratesArray[i]; ++ ++ if (test) ++ return; ++ + if (AR_SREV_9280_20_OR_LATER(ah)) { + for (i = 0; i < Ar5416RateSize; i++) + ratesArray[i] -= AR9287_PWR_TABLE_OFFSET_DB * 2; +@@ -971,17 +981,6 @@ static void ath9k_hw_ar9287_set_txpower( + | ATH9K_POW_SM(ratesArray[rateDupOfdm], 8) + | ATH9K_POW_SM(ratesArray[rateDupCck], 0)); + } +- +- if (IS_CHAN_2GHZ(chan)) +- i = rate1l; +- else +- i = rate6mb; +- +- if (AR_SREV_9280_20_OR_LATER(ah)) +- regulatory->max_power_level = +- ratesArray[i] + AR9287_PWR_TABLE_OFFSET_DB * 2; +- else +- regulatory->max_power_level = ratesArray[i]; + } + + static void ath9k_hw_ar9287_set_addac(struct ath_hw *ah, +--- a/drivers/net/wireless/ath/ath9k/eeprom_def.c ++++ b/drivers/net/wireless/ath/ath9k/eeprom_def.c +@@ -1258,7 +1258,7 @@ static void ath9k_hw_def_set_txpower(str + u16 cfgCtl, + u8 twiceAntennaReduction, + u8 twiceMaxRegulatoryPower, +- u8 powerLimit) ++ u8 powerLimit, bool test) + { + #define RT_AR_DELTA(x) (ratesArray[x] - cck_ofdm_delta) + struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah); +@@ -1291,6 +1291,33 @@ static void ath9k_hw_def_set_txpower(str + ratesArray[i] = AR5416_MAX_RATE_POWER; + } + ++ i = rate6mb; ++ ++ if (IS_CHAN_HT40(chan)) ++ i = rateHt40_0; ++ else if (IS_CHAN_HT20(chan)) ++ i = rateHt20_0; ++ ++ regulatory->max_power_level = ratesArray[i]; ++ ++ switch(ar5416_get_ntxchains(ah->txchainmask)) { ++ case 1: ++ break; ++ case 2: ++ regulatory->max_power_level += INCREASE_MAXPOW_BY_TWO_CHAIN; ++ break; ++ case 3: ++ regulatory->max_power_level += INCREASE_MAXPOW_BY_THREE_CHAIN; ++ break; ++ default: ++ ath_print(ath9k_hw_common(ah), ATH_DBG_EEPROM, ++ "Invalid chainmask configuration\n"); ++ break; ++ } ++ ++ if (test) ++ return; ++ + if (AR_SREV_9280_20_OR_LATER(ah)) { + for (i = 0; i < Ar5416RateSize; i++) { + int8_t pwr_table_offset; +@@ -1387,34 +1414,6 @@ static void ath9k_hw_def_set_txpower(str + REG_WRITE(ah, AR_PHY_POWER_TX_SUB, + ATH9K_POW_SM(pModal->pwrDecreaseFor3Chain, 6) + | ATH9K_POW_SM(pModal->pwrDecreaseFor2Chain, 0)); +- +- i = rate6mb; +- +- if (IS_CHAN_HT40(chan)) +- i = rateHt40_0; +- else if (IS_CHAN_HT20(chan)) +- i = rateHt20_0; +- +- if (AR_SREV_9280_20_OR_LATER(ah)) +- regulatory->max_power_level = +- ratesArray[i] + AR5416_PWR_TABLE_OFFSET_DB * 2; +- else +- regulatory->max_power_level = ratesArray[i]; +- +- switch(ar5416_get_ntxchains(ah->txchainmask)) { +- case 1: +- break; +- case 2: +- regulatory->max_power_level += INCREASE_MAXPOW_BY_TWO_CHAIN; +- break; +- case 3: +- regulatory->max_power_level += INCREASE_MAXPOW_BY_THREE_CHAIN; +- break; +- default: +- ath_print(ath9k_hw_common(ah), ATH_DBG_EEPROM, +- "Invalid chainmask configuration\n"); +- break; +- } + } + + static u8 ath9k_hw_def_get_num_ant_config(struct ath_hw *ah, +--- a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c ++++ b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c +@@ -2131,7 +2131,7 @@ static void ath9k_hw_ar9300_set_txpower( + struct ath9k_channel *chan, u16 cfgCtl, + u8 twiceAntennaReduction, + u8 twiceMaxRegulatoryPower, +- u8 powerLimit) ++ u8 powerLimit, bool test) + { + struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah); + struct ath_common *common = ath9k_hw_common(ah); +@@ -2160,9 +2160,6 @@ static void ath9k_hw_ar9300_set_txpower( + i++; + } + +- /* Write target power array to registers */ +- ar9003_hw_tx_power_regwrite(ah, targetPowerValT2); +- + /* + * This is the TX power we send back to driver core, + * and it can use to pass to userspace to display our +@@ -2181,8 +2178,13 @@ static void ath9k_hw_ar9300_set_txpower( + i = ALL_TARGET_HT20_0_8_16; /* ht20 */ + + ah->txpower_limit = targetPowerValT2[i]; +- regulatory->max_power_level = ratesArray[i]; ++ regulatory->max_power_level = targetPowerValT2[i]; + ++ if (test) ++ return; ++ ++ /* Write target power array to registers */ ++ ar9003_hw_tx_power_regwrite(ah, targetPowerValT2); + ar9003_hw_calibration_apply(ah, chan->channel); + } + +--- a/drivers/net/wireless/ath/ath9k/hw.c ++++ b/drivers/net/wireless/ath/ath9k/hw.c +@@ -1178,7 +1178,7 @@ static bool ath9k_hw_channel_change(stru + channel->max_antenna_gain * 2, + channel->max_power * 2, + min((u32) MAX_RATE_POWER, +- (u32) regulatory->power_limit)); ++ (u32) regulatory->power_limit), false); + + ath9k_hw_rfbus_done(ah); + +@@ -2177,7 +2177,7 @@ bool ath9k_hw_disable(struct ath_hw *ah) + } + EXPORT_SYMBOL(ath9k_hw_disable); + +-void ath9k_hw_set_txpowerlimit(struct ath_hw *ah, u32 limit) ++void ath9k_hw_set_txpowerlimit(struct ath_hw *ah, u32 limit, bool test) + { + struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah); + struct ath9k_channel *chan = ah->curchan; +@@ -2190,7 +2190,7 @@ void ath9k_hw_set_txpowerlimit(struct at + channel->max_antenna_gain * 2, + channel->max_power * 2, + min((u32) MAX_RATE_POWER, +- (u32) regulatory->power_limit)); ++ (u32) regulatory->power_limit), test); + } + EXPORT_SYMBOL(ath9k_hw_set_txpowerlimit); + +--- a/drivers/net/wireless/ath/ath9k/hw.h ++++ b/drivers/net/wireless/ath/ath9k/hw.h +@@ -860,7 +860,7 @@ u32 ath9k_hw_getrxfilter(struct ath_hw * + void ath9k_hw_setrxfilter(struct ath_hw *ah, u32 bits); + bool ath9k_hw_phy_disable(struct ath_hw *ah); + bool ath9k_hw_disable(struct ath_hw *ah); +-void ath9k_hw_set_txpowerlimit(struct ath_hw *ah, u32 limit); ++void ath9k_hw_set_txpowerlimit(struct ath_hw *ah, u32 limit, bool test); + void ath9k_hw_setopmode(struct ath_hw *ah); + void ath9k_hw_setmcastfilter(struct ath_hw *ah, u32 filter0, u32 filter1); + void ath9k_hw_setbssidmask(struct ath_hw *ah); +--- a/drivers/net/wireless/ath/ath9k/main.c ++++ b/drivers/net/wireless/ath/ath9k/main.c +@@ -24,7 +24,7 @@ static void ath_update_txpow(struct ath_ + struct ath_hw *ah = sc->sc_ah; + + if (sc->curtxpow != sc->config.txpowlimit) { +- ath9k_hw_set_txpowerlimit(ah, sc->config.txpowlimit); ++ ath9k_hw_set_txpowerlimit(ah, sc->config.txpowlimit, false); + /* read back in case value is clamped */ + sc->curtxpow = ath9k_hw_regulatory(ah)->power_limit; + } +--- a/drivers/net/wireless/ath/ath9k/ar9003_phy.c ++++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.c +@@ -614,7 +614,7 @@ static int ar9003_hw_process_ini(struct + channel->max_antenna_gain * 2, + channel->max_power * 2, + min((u32) MAX_RATE_POWER, +- (u32) regulatory->power_limit)); ++ (u32) regulatory->power_limit), false); + + return 0; + } +--- a/drivers/net/wireless/ath/ath9k/ar5008_phy.c ++++ b/drivers/net/wireless/ath/ath9k/ar5008_phy.c +@@ -875,7 +875,7 @@ static int ar5008_hw_process_ini(struct + channel->max_antenna_gain * 2, + channel->max_power * 2, + min((u32) MAX_RATE_POWER, +- (u32) regulatory->power_limit)); ++ (u32) regulatory->power_limit), false); + + /* Write analog registers */ + if (!ath9k_hw_set_rf_regs(ah, chan, freqIndex)) { +--- a/drivers/net/wireless/ath/ath9k/htc_drv_main.c ++++ b/drivers/net/wireless/ath/ath9k/htc_drv_main.c +@@ -29,7 +29,7 @@ static void ath_update_txpow(struct ath9 + struct ath_hw *ah = priv->ah; + + if (priv->curtxpow != priv->txpowlimit) { +- ath9k_hw_set_txpowerlimit(ah, priv->txpowlimit); ++ ath9k_hw_set_txpowerlimit(ah, priv->txpowlimit, false); + /* read back in case value is clamped */ + priv->curtxpow = ath9k_hw_regulatory(ah)->power_limit; + } diff --git a/package/mac80211/patches/522-ath9k_tx_power_init.patch b/package/mac80211/patches/522-ath9k_tx_power_init.patch new file mode 100644 index 000000000000..b8138af255ec --- /dev/null +++ b/package/mac80211/patches/522-ath9k_tx_power_init.patch @@ -0,0 +1,115 @@ +--- a/drivers/net/wireless/ath/ath9k/init.c ++++ b/drivers/net/wireless/ath/ath9k/init.c +@@ -650,6 +650,37 @@ err_hw: + return ret; + } + ++static void ath9k_init_band_txpower(struct ath_softc *sc, int band) ++{ ++ 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]; ++ for (i = 0; i < sband->n_channels; i++) { ++ chan = &sband->channels[i]; ++ 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; ++ } ++} ++ ++static void ath9k_init_txpower_limits(struct ath_softc *sc) ++{ ++ struct ath_hw *ah = sc->sc_ah; ++ struct ath9k_channel *curchan = ah->curchan; ++ ++ if (ah->caps.hw_caps & ATH9K_HW_CAP_2GHZ) ++ ath9k_init_band_txpower(sc, IEEE80211_BAND_2GHZ); ++ if (ah->caps.hw_caps & ATH9K_HW_CAP_5GHZ) ++ ath9k_init_band_txpower(sc, IEEE80211_BAND_5GHZ); ++ ++ ah->curchan = curchan; ++} ++ + void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw) + { + struct ath_common *common = ath9k_hw_common(sc->sc_ah); +@@ -765,6 +796,8 @@ int ath9k_init_device(u16 devid, struct + if (error != 0) + goto error_rx; + ++ ath9k_init_txpower_limits(sc); ++ + /* Register with mac80211 */ + error = ieee80211_register_hw(hw); + if (error) +--- a/drivers/net/wireless/ath/ath9k/common.c ++++ b/drivers/net/wireless/ath/ath9k/common.c +@@ -107,12 +107,10 @@ static u32 ath9k_get_extchanmode(struct + /* + * Update internal channel flags. + */ +-void ath9k_cmn_update_ichannel(struct ieee80211_hw *hw, +- struct ath9k_channel *ichan) ++void ath9k_cmn_update_ichannel(struct ath9k_channel *ichan, ++ struct ieee80211_channel *chan, ++ enum nl80211_channel_type channel_type) + { +- struct ieee80211_channel *chan = hw->conf.channel; +- struct ieee80211_conf *conf = &hw->conf; +- + ichan->channel = chan->center_freq; + ichan->chan = chan; + +@@ -124,9 +122,8 @@ void ath9k_cmn_update_ichannel(struct ie + ichan->channelFlags = CHANNEL_5GHZ | CHANNEL_OFDM; + } + +- if (conf_is_ht(conf)) +- ichan->chanmode = ath9k_get_extchanmode(chan, +- conf->channel_type); ++ if (channel_type != NL80211_CHAN_NO_HT) ++ ichan->chanmode = ath9k_get_extchanmode(chan, channel_type); + } + EXPORT_SYMBOL(ath9k_cmn_update_ichannel); + +@@ -142,7 +139,7 @@ struct ath9k_channel *ath9k_cmn_get_curc + + chan_idx = curchan->hw_value; + channel = &ah->channels[chan_idx]; +- ath9k_cmn_update_ichannel(hw, channel); ++ ath9k_cmn_update_ichannel(channel, curchan, hw->conf.channel_type); + + return channel; + } +--- a/drivers/net/wireless/ath/ath9k/common.h ++++ b/drivers/net/wireless/ath/ath9k/common.h +@@ -62,8 +62,9 @@ enum ath_stomp_type { + + int ath9k_cmn_padpos(__le16 frame_control); + int ath9k_cmn_get_hw_crypto_keytype(struct sk_buff *skb); +-void ath9k_cmn_update_ichannel(struct ieee80211_hw *hw, +- struct ath9k_channel *ichan); ++void ath9k_cmn_update_ichannel(struct ath9k_channel *ichan, ++ struct ieee80211_channel *chan, ++ enum nl80211_channel_type channel_type); + struct ath9k_channel *ath9k_cmn_get_curchannel(struct ieee80211_hw *hw, + struct ath_hw *ah); + int ath9k_cmn_count_streams(unsigned int chainmask, int max); +--- a/drivers/net/wireless/ath/ath9k/htc_drv_main.c ++++ b/drivers/net/wireless/ath/ath9k/htc_drv_main.c +@@ -1405,7 +1405,9 @@ static int ath9k_htc_config(struct ieee8 + ath_print(common, ATH_DBG_CONFIG, "Set channel: %d MHz\n", + curchan->center_freq); + +- ath9k_cmn_update_ichannel(hw, &priv->ah->channels[pos]); ++ ath9k_cmn_update_ichannel(&priv->ah->channels[pos], ++ hw->conf.channel, ++ hw->conf.channel_type); + + if (ath9k_htc_set_channel(priv, hw, &priv->ah->channels[pos]) < 0) { + ath_print(common, ATH_DBG_FATAL, -- 2.30.2