ath9k_hw: extend ath9k_hw_set_txpowerlimit to test channel txpower
authorFelix Fietkau <nbd@openwrt.org>
Wed, 20 Oct 2010 01:08:53 +0000 (03:08 +0200)
committerJohn W. Linville <linville@tuxdriver.com>
Mon, 15 Nov 2010 18:23:14 +0000 (13:23 -0500)
ath9k_hw_set_txpowerlimit gets an extra boolean parameter that - if set -
causes the rate txpower table and the regulatory limit to be calculated
and stored, without changing hardware registers.

Signed-off-by: Felix Fietkau <nbd@openwrt.org>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
drivers/net/wireless/ath/ath9k/ar5008_phy.c
drivers/net/wireless/ath/ath9k/ar9003_eeprom.c
drivers/net/wireless/ath/ath9k/ar9003_phy.c
drivers/net/wireless/ath/ath9k/eeprom.h
drivers/net/wireless/ath/ath9k/eeprom_4k.c
drivers/net/wireless/ath/ath9k/eeprom_9287.c
drivers/net/wireless/ath/ath9k/eeprom_def.c
drivers/net/wireless/ath/ath9k/htc_drv_main.c
drivers/net/wireless/ath/ath9k/hw.c
drivers/net/wireless/ath/ath9k/hw.h
drivers/net/wireless/ath/ath9k/main.c

index ea9f4497f58c79bd491d84181a605e7b251f4b91..777a602176f244ba41800c99dd406e38c38f26b2 100644 (file)
@@ -873,7 +873,7 @@ static int ar5008_hw_process_ini(struct ath_hw *ah,
                                 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)) {
index 92cfef22547785fe4a5707eb87b3c62cf48d8b15..a88fe0d6142fe4ea5a5eb69f2e6b1d023cb1eebb 100644 (file)
@@ -2131,7 +2131,7 @@ static void ath9k_hw_ar9300_set_txpower(struct ath_hw *ah,
                                        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);
@@ -2145,7 +2145,16 @@ static void ath9k_hw_ar9300_set_txpower(struct ath_hw *ah,
                                           twiceMaxRegulatoryPower,
                                           powerLimit);
 
-       while (i < ar9300RateSize) {
+       regulatory->max_power_level = 0;
+       for (i = 0; i < ar9300RateSize; i++) {
+               if (targetPowerValT2[i] > regulatory->max_power_level)
+                       regulatory->max_power_level = targetPowerValT2[i];
+       }
+
+       if (test)
+               return;
+
+       for (i = 0; i < ar9300RateSize; i++) {
                ath_print(common, ATH_DBG_EEPROM,
                          "TPC[%02d] 0x%08x ", i, targetPowerValT2[i]);
                i++;
@@ -2160,9 +2169,6 @@ static void ath9k_hw_ar9300_set_txpower(struct ath_hw *ah,
                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 +2187,10 @@ static void ath9k_hw_ar9300_set_txpower(struct ath_hw *ah,
                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];
 
+       /* Write target power array to registers */
+       ar9003_hw_tx_power_regwrite(ah, targetPowerValT2);
        ar9003_hw_calibration_apply(ah, chan->channel);
 }
 
index 669b777729b314161a99987812ed1b93ef16c168..06a9c4cd2f444bbc9304827f6debd7d3e6fa1869 100644 (file)
@@ -614,7 +614,7 @@ static int ar9003_hw_process_ini(struct ath_hw *ah,
                                 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;
 }
index dacb45e1b9063b620736475b6116975fcb60cf4d..3c99830dab0c2b385725075e5d36afa05d7d44b6 100644 (file)
@@ -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);
 };
 
index 4fa4d8e28c64236ffa5d7547ad5d5234565658bc..c40c534c66622eb8bfb1a9c8459aea75d648198e 100644 (file)
@@ -726,7 +726,7 @@ static void ath9k_hw_4k_set_txpower(struct ath_hw *ah,
                                    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;
@@ -751,15 +751,20 @@ static void ath9k_hw_4k_set_txpower(struct ath_hw *ah,
 
        ath9k_hw_set_4k_power_cal_table(ah, chan, &txPowerIndexOffset);
 
+       regulatory->max_power_level = 0;
        for (i = 0; i < ARRAY_SIZE(ratesArray); i++) {
                ratesArray[i] = (int16_t)(txPowerIndexOffset + ratesArray[i]);
                if (ratesArray[i] > AR5416_MAX_RATE_POWER)
                        ratesArray[i] = AR5416_MAX_RATE_POWER;
+
+               if (ratesArray[i] > regulatory->max_power_level)
+                       regulatory->max_power_level = ratesArray[i];
        }
 
+       if (test)
+           return;
 
        /* Update regulatory */
-
        i = rate6mb;
        if (IS_CHAN_HT40(chan))
                i = rateHt40_0;
index 966b9496a9dd4b51cf5c1f850fc987ea4b6ffff2..ebf7a89f547cafacfa64ae3c227e94716422f7a2 100644 (file)
@@ -853,7 +853,7 @@ static void ath9k_hw_ar9287_set_txpower(struct ath_hw *ah,
                                        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;
@@ -877,12 +877,26 @@ static void ath9k_hw_ar9287_set_txpower(struct ath_hw *ah,
 
        ath9k_hw_set_ar9287_power_cal_table(ah, chan, &txPowerIndexOffset);
 
+       regulatory->max_power_level = 0;
        for (i = 0; i < ARRAY_SIZE(ratesArray); i++) {
                ratesArray[i] = (int16_t)(txPowerIndexOffset + ratesArray[i]);
                if (ratesArray[i] > AR9287_MAX_RATE_POWER)
                        ratesArray[i] = AR9287_MAX_RATE_POWER;
+
+               if (ratesArray[i] > regulatory->max_power_level)
+                       regulatory->max_power_level = ratesArray[i];
        }
 
+       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;
@@ -971,17 +985,6 @@ static void ath9k_hw_ar9287_set_txpower(struct ath_hw *ah,
                          | 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,
index 76b4d65472dd2b37dbf98ff69b57646e53443c61..a819ddc9fdbccde8fa12debc95c86f6b2c3eda58 100644 (file)
@@ -1258,7 +1258,7 @@ static void ath9k_hw_def_set_txpower(struct ath_hw *ah,
                                    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);
@@ -1285,12 +1285,44 @@ static void ath9k_hw_def_set_txpower(struct ath_hw *ah,
 
        ath9k_hw_set_def_power_cal_table(ah, chan, &txPowerIndexOffset);
 
+       regulatory->max_power_level = 0;
        for (i = 0; i < ARRAY_SIZE(ratesArray); i++) {
                ratesArray[i] = (int16_t)(txPowerIndexOffset + ratesArray[i]);
                if (ratesArray[i] > AR5416_MAX_RATE_POWER)
                        ratesArray[i] = AR5416_MAX_RATE_POWER;
+               if (ratesArray[i] > regulatory->max_power_level)
+                       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;
+       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 +1419,6 @@ static void ath9k_hw_def_set_txpower(struct ath_hw *ah,
        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,
index 9a3be8da755d2f7181ada323e5ec9054b58a0a9e..26b9a16ce33fb7c1db99434409972dc38ace6a51 100644 (file)
@@ -29,7 +29,7 @@ static void ath_update_txpow(struct ath9k_htc_priv *priv)
        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;
        }
index d37a8ad03d745e15f66da29af5e6020694f338ad..e75d8e8cf4d2ddcf505bfdec8cc06ed4037372b2 100644 (file)
@@ -1166,7 +1166,7 @@ static bool ath9k_hw_channel_change(struct ath_hw *ah,
                             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);
 
@@ -2165,7 +2165,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;
@@ -2178,7 +2178,7 @@ void ath9k_hw_set_txpowerlimit(struct ath_hw *ah, u32 limit)
                                 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);
 
index e68204ae899c7dc7e382760d80c307354ccb0505..366f088dc15dd5a86186e2e5436411553f0be4b9 100644 (file)
@@ -860,7 +860,7 @@ u32 ath9k_hw_getrxfilter(struct ath_hw *ah);
 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);
index 7185ef3a3bff87860ac0c00152cfadb577109b2e..92ed5bb71196752d90c2cab851774b602cd4adee 100644 (file)
@@ -23,7 +23,7 @@ static void ath_update_txpow(struct ath_softc *sc)
        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;
        }