From 0dfebf47a27cd17710ba0254f4ae2ac25ee3549b Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Tue, 26 Jul 2011 20:59:12 +0000 Subject: [PATCH] ath9k: rework tx power handling - display the correct *current* tx power, and also fix tx power limits with ATH_USER_REGD set (backport of r27788) SVN-Revision: 27789 --- .../patches/590-mac80211_cur_txpower.patch | 32 +++++ .../591-ath9k_initialize_chainmask.patch | 13 ++ .../592-ath9k_remove_tx_indexoffset.patch | 125 ++++++++++++++++++ .../patches/593-ath9k_fix_rate_power.patch | 83 ++++++++++++ .../patches/594-ath9k_test_txpower.patch | 25 ++++ .../patches/595-ath9k_cur_txpower.patch | 35 +++++ 6 files changed, 313 insertions(+) create mode 100644 package/mac80211/patches/590-mac80211_cur_txpower.patch create mode 100644 package/mac80211/patches/591-ath9k_initialize_chainmask.patch create mode 100644 package/mac80211/patches/592-ath9k_remove_tx_indexoffset.patch create mode 100644 package/mac80211/patches/593-ath9k_fix_rate_power.patch create mode 100644 package/mac80211/patches/594-ath9k_test_txpower.patch create mode 100644 package/mac80211/patches/595-ath9k_cur_txpower.patch diff --git a/package/mac80211/patches/590-mac80211_cur_txpower.patch b/package/mac80211/patches/590-mac80211_cur_txpower.patch new file mode 100644 index 0000000000..8e729c1a44 --- /dev/null +++ b/package/mac80211/patches/590-mac80211_cur_txpower.patch @@ -0,0 +1,32 @@ +--- a/include/net/mac80211.h ++++ b/include/net/mac80211.h +@@ -779,7 +779,7 @@ enum ieee80211_smps_mode { + */ + struct ieee80211_conf { + u32 flags; +- int power_level, dynamic_ps_timeout; ++ int cur_power_level, power_level, dynamic_ps_timeout; + int max_sleep_period; + + u16 listen_interval; +--- a/net/mac80211/cfg.c ++++ b/net/mac80211/cfg.c +@@ -1524,7 +1524,7 @@ static int ieee80211_get_tx_power(struct + { + struct ieee80211_local *local = wiphy_priv(wiphy); + +- *dbm = local->hw.conf.power_level; ++ *dbm = local->hw.conf.cur_power_level; + + return 0; + } +--- a/net/mac80211/main.c ++++ b/net/mac80211/main.c +@@ -210,6 +210,7 @@ int ieee80211_hw_config(struct ieee80211 + + if (local->hw.conf.power_level != power) { + changed |= IEEE80211_CONF_CHANGE_POWER; ++ local->hw.conf.cur_power_level = power; + local->hw.conf.power_level = power; + } + diff --git a/package/mac80211/patches/591-ath9k_initialize_chainmask.patch b/package/mac80211/patches/591-ath9k_initialize_chainmask.patch new file mode 100644 index 0000000000..03f7c36a35 --- /dev/null +++ b/package/mac80211/patches/591-ath9k_initialize_chainmask.patch @@ -0,0 +1,13 @@ +--- a/drivers/net/wireless/ath/ath9k/init.c ++++ b/drivers/net/wireless/ath/ath9k/init.c +@@ -667,8 +667,10 @@ static void ath9k_init_band_txpower(stru + static void ath9k_init_txpower_limits(struct ath_softc *sc) + { + struct ath_hw *ah = sc->sc_ah; ++ struct ath_common *common = ath9k_hw_common(sc->sc_ah); + struct ath9k_channel *curchan = ah->curchan; + ++ ah->txchainmask = common->tx_chainmask; + 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) diff --git a/package/mac80211/patches/592-ath9k_remove_tx_indexoffset.patch b/package/mac80211/patches/592-ath9k_remove_tx_indexoffset.patch new file mode 100644 index 0000000000..c8e2640eec --- /dev/null +++ b/package/mac80211/patches/592-ath9k_remove_tx_indexoffset.patch @@ -0,0 +1,125 @@ +--- a/drivers/net/wireless/ath/ath9k/eeprom_4k.c ++++ b/drivers/net/wireless/ath/ath9k/eeprom_4k.c +@@ -247,8 +247,7 @@ static u32 ath9k_hw_4k_get_eeprom(struct + } + + static void ath9k_hw_set_4k_power_cal_table(struct ath_hw *ah, +- struct ath9k_channel *chan, +- int16_t *pTxPowerIndexOffset) ++ struct ath9k_channel *chan) + { + struct ath_common *common = ath9k_hw_common(ah); + struct ar5416_eeprom_4k *pEepData = &ah->eeprom.map4k; +@@ -358,8 +357,6 @@ static void ath9k_hw_set_4k_power_cal_ta + REGWRITE_BUFFER_FLUSH(ah); + } + } +- +- *pTxPowerIndexOffset = 0; + } + + static void ath9k_hw_set_4k_power_per_rate_table(struct ath_hw *ah, +@@ -582,7 +579,6 @@ static void ath9k_hw_4k_set_txpower(stru + struct ar5416_eeprom_4k *pEepData = &ah->eeprom.map4k; + struct modal_eep_4k_header *pModal = &pEepData->modalHeader; + int16_t ratesArray[Ar5416RateSize]; +- int16_t txPowerIndexOffset = 0; + u8 ht40PowerIncForPdadc = 2; + int i; + +@@ -599,11 +595,10 @@ static void ath9k_hw_4k_set_txpower(stru + twiceMaxRegulatoryPower, + powerLimit); + +- ath9k_hw_set_4k_power_cal_table(ah, chan, &txPowerIndexOffset); ++ ath9k_hw_set_4k_power_cal_table(ah, chan); + + regulatory->max_power_level = 0; + for (i = 0; i < ARRAY_SIZE(ratesArray); i++) { +- ratesArray[i] = (int16_t)(txPowerIndexOffset + ratesArray[i]); + if (ratesArray[i] > MAX_RATE_POWER) + ratesArray[i] = MAX_RATE_POWER; + +--- a/drivers/net/wireless/ath/ath9k/eeprom_9287.c ++++ b/drivers/net/wireless/ath/ath9k/eeprom_9287.c +@@ -306,8 +306,7 @@ static void ar9287_eeprom_olpc_set_pdadc + } + + static void ath9k_hw_set_ar9287_power_cal_table(struct ath_hw *ah, +- struct ath9k_channel *chan, +- int16_t *pTxPowerIndexOffset) ++ struct ath9k_channel *chan) + { + struct cal_data_per_freq_ar9287 *pRawDataset; + struct cal_data_op_loop_ar9287 *pRawDatasetOpenLoop; +@@ -446,8 +445,6 @@ static void ath9k_hw_set_ar9287_power_ca + REGWRITE_BUFFER_FLUSH(ah); + } + } +- +- *pTxPowerIndexOffset = 0; + } + + static void ath9k_hw_set_ar9287_power_per_rate_table(struct ath_hw *ah, +@@ -722,7 +719,6 @@ static void ath9k_hw_ar9287_set_txpower( + struct ar9287_eeprom *pEepData = &ah->eeprom.map9287; + struct modal_eep_ar9287_header *pModal = &pEepData->modalHeader; + int16_t ratesArray[Ar5416RateSize]; +- int16_t txPowerIndexOffset = 0; + u8 ht40PowerIncForPdadc = 2; + int i; + +@@ -738,11 +734,10 @@ static void ath9k_hw_ar9287_set_txpower( + twiceMaxRegulatoryPower, + powerLimit); + +- ath9k_hw_set_ar9287_power_cal_table(ah, chan, &txPowerIndexOffset); ++ ath9k_hw_set_ar9287_power_cal_table(ah, chan); + + regulatory->max_power_level = 0; + for (i = 0; i < ARRAY_SIZE(ratesArray); i++) { +- ratesArray[i] = (int16_t)(txPowerIndexOffset + ratesArray[i]); + if (ratesArray[i] > MAX_RATE_POWER) + ratesArray[i] = MAX_RATE_POWER; + +--- a/drivers/net/wireless/ath/ath9k/eeprom_def.c ++++ b/drivers/net/wireless/ath/ath9k/eeprom_def.c +@@ -692,8 +692,7 @@ static void ath9k_adjust_pdadc_values(st + } + + static void ath9k_hw_set_def_power_cal_table(struct ath_hw *ah, +- struct ath9k_channel *chan, +- int16_t *pTxPowerIndexOffset) ++ struct ath9k_channel *chan) + { + #define SM_PD_GAIN(x) SM(0x38, AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_##x) + #define SM_PDGAIN_B(x, y) \ +@@ -857,7 +856,6 @@ static void ath9k_hw_set_def_power_cal_t + } + } + +- *pTxPowerIndexOffset = 0; + #undef SM_PD_GAIN + #undef SM_PDGAIN_B + } +@@ -1145,7 +1143,6 @@ static void ath9k_hw_def_set_txpower(str + struct modal_eep_header *pModal = + &(pEepData->modalHeader[IS_CHAN_2GHZ(chan)]); + int16_t ratesArray[Ar5416RateSize]; +- int16_t txPowerIndexOffset = 0; + u8 ht40PowerIncForPdadc = 2; + int i, cck_ofdm_delta = 0; + +@@ -1162,11 +1159,10 @@ static void ath9k_hw_def_set_txpower(str + twiceMaxRegulatoryPower, + powerLimit); + +- ath9k_hw_set_def_power_cal_table(ah, chan, &txPowerIndexOffset); ++ ath9k_hw_set_def_power_cal_table(ah, chan); + + regulatory->max_power_level = 0; + for (i = 0; i < ARRAY_SIZE(ratesArray); i++) { +- ratesArray[i] = (int16_t)(txPowerIndexOffset + ratesArray[i]); + if (ratesArray[i] > MAX_RATE_POWER) + ratesArray[i] = MAX_RATE_POWER; + if (ratesArray[i] > regulatory->max_power_level) diff --git a/package/mac80211/patches/593-ath9k_fix_rate_power.patch b/package/mac80211/patches/593-ath9k_fix_rate_power.patch new file mode 100644 index 0000000000..fc79d5f9e2 --- /dev/null +++ b/package/mac80211/patches/593-ath9k_fix_rate_power.patch @@ -0,0 +1,83 @@ +--- a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c ++++ b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c +@@ -4922,25 +4922,7 @@ static void ath9k_hw_ar9300_set_txpower( + "TPC[%02d] 0x%08x\n", i, targetPowerValT2[i]); + } + +- /* +- * This is the TX power we send back to driver core, +- * and it can use to pass to userspace to display our +- * currently configured TX power setting. +- * +- * Since power is rate dependent, use one of the indices +- * from the AR9300_Rates enum to select an entry from +- * targetPowerValT2[] to report. Currently returns the +- * power for HT40 MCS 0, HT20 MCS 0, or OFDM 6 Mbps +- * as CCK power is less interesting (?). +- */ +- i = ALL_TARGET_LEGACY_6_24; /* legacy */ +- if (IS_CHAN_HT40(chan)) +- i = ALL_TARGET_HT40_0_8_16; /* ht40 */ +- else if (IS_CHAN_HT20(chan)) +- i = ALL_TARGET_HT20_0_8_16; /* ht20 */ +- +- ah->txpower_limit = targetPowerValT2[i]; +- regulatory->max_power_level = targetPowerValT2[i]; ++ ah->txpower_limit = regulatory->max_power_level; + + /* Write target power array to registers */ + ar9003_hw_tx_power_regwrite(ah, targetPowerValT2); +--- a/drivers/net/wireless/ath/ath9k/eeprom_4k.c ++++ b/drivers/net/wireless/ath/ath9k/eeprom_4k.c +@@ -609,15 +609,6 @@ static void ath9k_hw_4k_set_txpower(stru + if (test) + return; + +- /* Update regulatory */ +- 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]; +- + 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 +@@ -748,13 +748,6 @@ static void ath9k_hw_ar9287_set_txpower( + if (test) + return; + +- if (IS_CHAN_2GHZ(chan)) +- i = rate1l; +- else +- i = rate6mb; +- +- regulatory->max_power_level = ratesArray[i]; +- + if (AR_SREV_9280_20_OR_LATER(ah)) { + for (i = 0; i < Ar5416RateSize; i++) + ratesArray[i] -= AR9287_PWR_TABLE_OFFSET_DB * 2; +--- a/drivers/net/wireless/ath/ath9k/eeprom_def.c ++++ b/drivers/net/wireless/ath/ath9k/eeprom_def.c +@@ -1169,17 +1169,6 @@ static void ath9k_hw_def_set_txpower(str + regulatory->max_power_level = ratesArray[i]; + } + +- if (!test) { +- 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; diff --git a/package/mac80211/patches/594-ath9k_test_txpower.patch b/package/mac80211/patches/594-ath9k_test_txpower.patch new file mode 100644 index 0000000000..45a51be61e --- /dev/null +++ b/package/mac80211/patches/594-ath9k_test_txpower.patch @@ -0,0 +1,25 @@ +--- a/drivers/net/wireless/ath/ath9k/hw.c ++++ b/drivers/net/wireless/ath/ath9k/hw.c +@@ -2442,15 +2442,18 @@ void ath9k_hw_set_txpowerlimit(struct at + struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah); + struct ath9k_channel *chan = ah->curchan; + struct ieee80211_channel *channel = chan->chan; ++ int reg_pwr = min_t(int, MAX_RATE_POWER, regulatory->power_limit); ++ int chan_pwr = channel->max_power * 2; ++ ++ if (test) ++ reg_pwr = chan_pwr = MAX_RATE_POWER; + + regulatory->power_limit = min(limit, (u32) MAX_RATE_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), test); ++ chan_pwr, reg_pwr, test); + } + EXPORT_SYMBOL(ath9k_hw_set_txpowerlimit); + + diff --git a/package/mac80211/patches/595-ath9k_cur_txpower.patch b/package/mac80211/patches/595-ath9k_cur_txpower.patch new file mode 100644 index 0000000000..29ed81aba3 --- /dev/null +++ b/package/mac80211/patches/595-ath9k_cur_txpower.patch @@ -0,0 +1,35 @@ +--- a/drivers/net/wireless/ath/ath9k/main.c ++++ b/drivers/net/wireless/ath/ath9k/main.c +@@ -1724,6 +1724,8 @@ static int ath9k_config(struct ieee80211 + return -EINVAL; + } + ++ conf->cur_power_level = sc->curtxpow / 2; ++ + /* + * The most recent snapshot of channel->noisefloor for the old + * channel is only available after the hardware reset. Copy it to +@@ -1741,6 +1743,7 @@ static int ath9k_config(struct ieee80211 + ath9k_cmn_update_txpow(ah, sc->curtxpow, + sc->config.txpowlimit, &sc->curtxpow); + ath9k_ps_restore(sc); ++ conf->cur_power_level = sc->curtxpow / 2; + } + + if (disable_radio) { +--- 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); + void ath9k_cmn_update_txpow(struct ath_hw *ah, u16 cur_txpow, + u16 new_txpow, u16 *txpower) + { ++ struct ath_regulatory *reg = ath9k_hw_regulatory(ah); ++ + if (cur_txpow != 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 = min_t(u16, reg->power_limit, reg->max_power_level); + } + } + EXPORT_SYMBOL(ath9k_cmn_update_txpow); -- 2.30.2