ath9k: fix tx power display
authorFelix Fietkau <nbd@openwrt.org>
Wed, 20 Oct 2010 00:08:17 +0000 (00:08 +0000)
committerFelix Fietkau <nbd@openwrt.org>
Wed, 20 Oct 2010 00:08:17 +0000 (00:08 +0000)
SVN-Revision: 23541

package/mac80211/patches/520-ath9k_ar9003_regulatory_power.patch [new file with mode: 0644]
package/mac80211/patches/521-ath9k_hw_tx_power.patch [new file with mode: 0644]
package/mac80211/patches/522-ath9k_tx_power_init.patch [new file with mode: 0644]

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 (file)
index 0000000..6d0ecef
--- /dev/null
@@ -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 (file)
index 0000000..b220750
--- /dev/null
@@ -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 (file)
index 0000000..b8138af
--- /dev/null
@@ -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,