ath9k_hw: clean up tx power handling
authorFelix Fietkau <nbd@openwrt.org>
Sat, 8 Oct 2011 18:06:20 +0000 (20:06 +0200)
committerJohn W. Linville <linville@tuxdriver.com>
Tue, 11 Oct 2011 20:41:26 +0000 (16:41 -0400)
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: Felix Fietkau <nbd@openwrt.org>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
13 files changed:
drivers/net/wireless/ath/ath.h
drivers/net/wireless/ath/ath9k/ar5008_phy.c
drivers/net/wireless/ath/ath9k/ar9003_eeprom.c
drivers/net/wireless/ath/ath9k/ar9003_paprd.c
drivers/net/wireless/ath/ath9k/ar9003_phy.c
drivers/net/wireless/ath/ath9k/common.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/hw.c
drivers/net/wireless/ath/ath9k/hw.h
drivers/net/wireless/ath/ath9k/init.c

index 4ed7f248a577a25ac198a8ad5a1dc50846b49457..bb71b4f27a9b8a839e73b62d3c13d108777e4f1f 100644 (file)
@@ -71,7 +71,6 @@ struct ath_regulatory {
        char alpha2[2];
        u16 country_code;
        u16 max_power_level;
-       u32 tp_scale;
        u16 current_rd;
        u16 current_rd_ext;
        int16_t power_limit;
index 0a749c8fa634830cbb90239e13ebc7ed8a343685..f199e9e2514950757e27dcba7da906571dad954b 100644 (file)
@@ -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,
                                 struct ath9k_channel *chan)
 {
-       struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah);
        struct ath_common *common = ath9k_hw_common(ah);
        int i, regWrites = 0;
-       struct ieee80211_channel *channel = chan->chan;
        u32 modesIndex, freqIndex;
 
        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_init_chain_masks(ah);
        ath9k_olc_init(ah);
-
-       /* 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);
+       ath9k_hw_apply_txpower(ah, chan);
 
        /* Write analog registers */
        if (!ath9k_hw_set_rf_regs(ah, chan, freqIndex)) {
index 51398f0063e21c16edced8a93d30f1d081f6f5c8..d7a5ca7225485dd91fbc0cea30362db572de866a 100644 (file)
@@ -3021,6 +3021,10 @@ static u32 ath9k_hw_ar9300_get_eeprom(struct ath_hw *ah,
                return (pBase->miscConfiguration >> 0x3) & 0x1;
        case EEP_ANT_DIV_CTL1:
                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:
                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,
                                               struct ath9k_channel *chan,
                                               u8 *pPwrArray, u16 cfgCtl,
-                                              u8 twiceAntennaReduction,
-                                              u8 twiceMaxRegulatoryPower,
+                                              u8 antenna_reduction,
                                               u16 powerLimit)
 {
-       struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah);
        struct ath_common *common = ath9k_hw_common(ah);
        struct ar9300_eeprom *pEepData = &ah->eeprom.ar9300_eep;
        u16 twiceMaxEdgePower = MAX_RATE_POWER;
-       static const u16 tpScaleReductionTable[5] = {
-               0, 3, 6, 9, MAX_RATE_POWER
-       };
        int i;
-       int16_t  twiceLargestAntenna;
-       u16 scaledPower = 0, minCtlPower, maxRegAllowedPower;
+       u16 scaledPower = 0, minCtlPower;
        static const u16 ctlModesFor11a[] = {
                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);
 
        ath9k_hw_get_channel_centers(ah, chan, &centers);
-
-       /* 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);
+       scaledPower = powerLimit - antenna_reduction;
 
        /*
         * 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,
                                        struct ath9k_channel *chan, u16 cfgCtl,
                                        u8 twiceAntennaReduction,
-                                       u8 twiceMaxRegulatoryPower,
                                        u8 powerLimit, bool test)
 {
        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,
                                           targetPowerValT2, cfgCtl,
                                           twiceAntennaReduction,
-                                          twiceMaxRegulatoryPower,
                                           powerLimit);
 
        if (ah->eep_ops->get_eeprom(ah, EEP_PAPRD)) {
index 609acb2b504f301d91611b603556ffa76a5dc108..a1a08b31b33ddca2025eba9405b467f376c6d27d 100644 (file)
@@ -19,7 +19,6 @@
 
 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 ar9300_eeprom *eep = &ah->eeprom.ar9300_eep;
 
@@ -54,13 +53,7 @@ void ar9003_paprd_enable(struct ath_hw *ah, bool val)
 
        if (val) {
                ah->paprd_table_write_done = true;
-
-               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);
+               ath9k_hw_apply_txpower(ah, chan);
        }
 
        REG_RMW_FIELD(ah, AR_PHY_PAPRD_CTRL0_B0,
index 7db6e8647a01ffc2bfb952ba34eedb5bb0008f5f..779f407222ed1b3171e75b91cb5b35d1a7626507 100644 (file)
@@ -631,9 +631,7 @@ static void ar9003_hw_prog_ini(struct ath_hw *ah,
 static int ar9003_hw_process_ini(struct ath_hw *ah,
                                 struct ath9k_channel *chan)
 {
-       struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah);
        unsigned int regWrites = 0, i;
-       struct ieee80211_channel *channel = chan->chan;
        u32 modesIndex;
 
        switch (chan->chanmode) {
@@ -693,14 +691,7 @@ static int ar9003_hw_process_ini(struct ath_hw *ah,
        ar9003_hw_override_ini(ah);
        ar9003_hw_set_channel_regs(ah, chan);
        ar9003_hw_set_chain_masks(ah, ah->rxchainmask, ah->txchainmask);
-
-       /* 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);
+       ath9k_hw_apply_txpower(ah, chan);
 
        return 0;
 }
index dc705a224952658ecc9202b65e8d39b1748ef0da..905f1b313961914ef3faf81aa6ed210248846196 100644 (file)
@@ -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)
 {
-       if (cur_txpow != new_txpow) {
+       struct ath_regulatory *reg = ath9k_hw_regulatory(ah);
+
+       if (reg->power_limit != 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 = reg->max_power_level;
        }
 }
 EXPORT_SYMBOL(ath9k_cmn_update_txpow);
index 5d92f96980e650fc68f1c14b338dc714f711a79b..909a224fb6502127e00ee9779a81189efc78f48e 100644 (file)
@@ -248,7 +248,9 @@ enum eeprom_param {
        EEP_PAPRD,
        EEP_MODAL_VER,
        EEP_ANT_DIV_CTL1,
-       EEP_CHAIN_MASK_REDUCE
+       EEP_CHAIN_MASK_REDUCE,
+       EEP_ANTENNA_GAIN_2G,
+       EEP_ANTENNA_GAIN_5G
 };
 
 enum ar5416_rates {
@@ -652,8 +654,7 @@ 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,
-                          bool test);
+                          u8 powerLimit, bool test);
        u16 (*get_spur_channel)(struct ath_hw *ah, u16 i, bool is2GHz);
 };
 
index 303560e49ac88f399f4a25f197bc7609d9e7065e..ab6811dc5debbea9dfa561935e9f5a2dede38a57 100644 (file)
@@ -350,6 +350,8 @@ static u32 ath9k_hw_4k_get_eeprom(struct ath_hw *ah,
                return pModal->antdiv_ctl1;
        case EEP_TXGAIN_TYPE:
                return pBase->txGainType;
+       case EEP_ANTENNA_GAIN_2G:
+               return pModal->antennaGainCh[0];
        default:
                return 0;
        }
@@ -462,8 +464,7 @@ static void ath9k_hw_set_4k_power_per_rate_table(struct ath_hw *ah,
                                                 struct ath9k_channel *chan,
                                                 int16_t *ratesArray,
                                                 u16 cfgCtl,
-                                                u16 AntennaReduction,
-                                                u16 twiceMaxRegulatoryPower,
+                                                u16 antenna_reduction,
                                                 u16 powerLimit)
 {
 #define CMP_TEST_GRP \
@@ -472,20 +473,16 @@ static void ath9k_hw_set_4k_power_per_rate_table(struct ath_hw *ah,
        || (((cfgCtl & ~CTL_MODE_M) | (pCtlMode[ctlMode] & CTL_MODE_M)) == \
            ((pEepData->ctlIndex[i] & CTL_MODE_M) | SD_NO_CTL))
 
-       struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah);
        int i;
-       int16_t twiceLargestAntenna;
        u16 twiceMinEdgePower;
        u16 twiceMaxEdgePower = MAX_RATE_POWER;
-       u16 scaledPower = 0, minCtlPower, maxRegAllowedPower;
+       u16 scaledPower = 0, minCtlPower;
        u16 numCtlModes;
        const u16 *pCtlMode;
        u16 ctlMode, freq;
        struct chan_centers centers;
        struct cal_ctl_data_4k *rep;
        struct ar5416_eeprom_4k *pEepData = &ah->eeprom.map4k;
-       static const u16 tpScaleReductionTable[5] =
-               { 0, 3, 6, 9, MAX_RATE_POWER };
        struct cal_target_power_leg targetPowerOfdm, targetPowerCck = {
                0, { 0, 0, 0, 0}
        };
@@ -503,19 +500,7 @@ static void ath9k_hw_set_4k_power_per_rate_table(struct ath_hw *ah,
 
        ath9k_hw_get_channel_centers(ah, chan, &centers);
 
-       twiceLargestAntenna = pEepData->modalHeader.antennaGainCh[0];
-       twiceLargestAntenna = (int16_t)min(AntennaReduction -
-                                          twiceLargestAntenna, 0);
-
-       maxRegAllowedPower = twiceMaxRegulatoryPower + twiceLargestAntenna;
-       if (regulatory->tp_scale != ATH9K_TP_SCALE_MAX) {
-               maxRegAllowedPower -=
-                       (tpScaleReductionTable[(regulatory->tp_scale)] * 2);
-       }
-
-       scaledPower = min(powerLimit, maxRegAllowedPower);
-       scaledPower = max((u16)0, scaledPower);
-
+       scaledPower = powerLimit - antenna_reduction;
        numCtlModes = ARRAY_SIZE(ctlModesFor11g) - SUB_NUM_CTL_MODES_AT_2G_40;
        pCtlMode = ctlModesFor11g;
 
@@ -671,7 +656,6 @@ static void ath9k_hw_4k_set_txpower(struct ath_hw *ah,
                                    struct ath9k_channel *chan,
                                    u16 cfgCtl,
                                    u8 twiceAntennaReduction,
-                                   u8 twiceMaxRegulatoryPower,
                                    u8 powerLimit, bool test)
 {
        struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah);
@@ -691,7 +675,6 @@ static void ath9k_hw_4k_set_txpower(struct ath_hw *ah,
        ath9k_hw_set_4k_power_per_rate_table(ah, chan,
                                             &ratesArray[0], cfgCtl,
                                             twiceAntennaReduction,
-                                            twiceMaxRegulatoryPower,
                                             powerLimit);
 
        ath9k_hw_set_4k_power_cal_table(ah, chan);
index 6698b722b604e8a4c9b5f1c29b50ec8a6584c7a1..90d771fa2dea26b4523ac2b20c2b3df5b5d27d3a 100644 (file)
@@ -336,6 +336,9 @@ static u32 ath9k_hw_ar9287_get_eeprom(struct ath_hw *ah,
                        return pBase->tempSensSlopePalOn;
                else
                        return 0;
+       case EEP_ANTENNA_GAIN_2G:
+               return max_t(u8, pModal->antennaGainCh[0],
+                                pModal->antennaGainCh[1]);
        default:
                return 0;
        }
@@ -554,8 +557,7 @@ static void ath9k_hw_set_ar9287_power_per_rate_table(struct ath_hw *ah,
                                                     struct ath9k_channel *chan,
                                                     int16_t *ratesArray,
                                                     u16 cfgCtl,
-                                                    u16 AntennaReduction,
-                                                    u16 twiceMaxRegulatoryPower,
+                                                    u16 antenna_reduction,
                                                     u16 powerLimit)
 {
 #define CMP_CTL \
@@ -569,12 +571,8 @@ static void ath9k_hw_set_ar9287_power_per_rate_table(struct ath_hw *ah,
 #define REDUCE_SCALED_POWER_BY_TWO_CHAIN     6
 #define REDUCE_SCALED_POWER_BY_THREE_CHAIN   10
 
-       struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah);
        u16 twiceMaxEdgePower = MAX_RATE_POWER;
-       static const u16 tpScaleReductionTable[5] =
-               { 0, 3, 6, 9, MAX_RATE_POWER };
        int i;
-       int16_t twiceLargestAntenna;
        struct cal_ctl_data_ar9287 *rep;
        struct cal_target_power_leg targetPowerOfdm = {0, {0, 0, 0, 0} },
                                    targetPowerCck = {0, {0, 0, 0, 0} };
@@ -582,7 +580,7 @@ static void ath9k_hw_set_ar9287_power_per_rate_table(struct ath_hw *ah,
                                    targetPowerCckExt = {0, {0, 0, 0, 0} };
        struct cal_target_power_ht targetPowerHt20,
                                    targetPowerHt40 = {0, {0, 0, 0, 0} };
-       u16 scaledPower = 0, minCtlPower, maxRegAllowedPower;
+       u16 scaledPower = 0, minCtlPower;
        static const u16 ctlModesFor11g[] = {
                CTL_11B, CTL_11G, CTL_2GHT20,
                CTL_11B_EXT, CTL_11G_EXT, CTL_2GHT40
@@ -597,24 +595,7 @@ static void ath9k_hw_set_ar9287_power_per_rate_table(struct ath_hw *ah,
        tx_chainmask = ah->txchainmask;
 
        ath9k_hw_get_channel_centers(ah, chan, &centers);
-
-       /* Compute TxPower reduction due to Antenna Gain */
-       twiceLargestAntenna = max(pEepData->modalHeader.antennaGainCh[0],
-                                 pEepData->modalHeader.antennaGainCh[1]);
-       twiceLargestAntenna = (int16_t)min((AntennaReduction) -
-                                          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);
+       scaledPower = powerLimit - antenna_reduction;
 
        /*
         * Reduce scaled Power by number of chains active
@@ -815,7 +796,6 @@ static void ath9k_hw_set_ar9287_power_per_rate_table(struct ath_hw *ah,
 static void ath9k_hw_ar9287_set_txpower(struct ath_hw *ah,
                                        struct ath9k_channel *chan, u16 cfgCtl,
                                        u8 twiceAntennaReduction,
-                                       u8 twiceMaxRegulatoryPower,
                                        u8 powerLimit, bool test)
 {
        struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah);
@@ -834,7 +814,6 @@ static void ath9k_hw_ar9287_set_txpower(struct ath_hw *ah,
        ath9k_hw_set_ar9287_power_per_rate_table(ah, chan,
                                                 &ratesArray[0], cfgCtl,
                                                 twiceAntennaReduction,
-                                                twiceMaxRegulatoryPower,
                                                 powerLimit);
 
        ath9k_hw_set_ar9287_power_cal_table(ah, chan);
index eda681fc7ba6d8bd00283bea564b263305d2a2aa..e175e2078a3921b0d7aa5df9757305f1534d8f43 100644 (file)
@@ -400,6 +400,7 @@ static u32 ath9k_hw_def_get_eeprom(struct ath_hw *ah,
        struct ar5416_eeprom_def *eep = &ah->eeprom.def;
        struct modal_eep_header *pModal = eep->modalHeader;
        struct base_eep_header *pBase = &eep->baseEepHeader;
+       int band = 0;
 
        switch (param) {
        case EEP_NFTHRESH_5:
@@ -467,6 +468,14 @@ static u32 ath9k_hw_def_get_eeprom(struct ath_hw *ah,
                        return pBase->pwr_table_offset;
                else
                        return AR5416_PWR_TABLE_OFFSET_DB;
+       case EEP_ANTENNA_GAIN_2G:
+               band = 1;
+               /* fall through */
+       case EEP_ANTENNA_GAIN_5G:
+               return max_t(u8, max_t(u8,
+                       pModal[band].antennaGainCh[0],
+                       pModal[band].antennaGainCh[1]),
+                       pModal[band].antennaGainCh[2]);
        default:
                return 0;
        }
@@ -986,21 +995,15 @@ static void ath9k_hw_set_def_power_per_rate_table(struct ath_hw *ah,
                                                  struct ath9k_channel *chan,
                                                  int16_t *ratesArray,
                                                  u16 cfgCtl,
-                                                 u16 AntennaReduction,
-                                                 u16 twiceMaxRegulatoryPower,
+                                                 u16 antenna_reduction,
                                                  u16 powerLimit)
 {
 #define REDUCE_SCALED_POWER_BY_TWO_CHAIN     6  /* 10*log10(2)*2 */
 #define REDUCE_SCALED_POWER_BY_THREE_CHAIN   9 /* 10*log10(3)*2 */
 
-       struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah);
        struct ar5416_eeprom_def *pEepData = &ah->eeprom.def;
        u16 twiceMaxEdgePower = MAX_RATE_POWER;
-       static const u16 tpScaleReductionTable[5] =
-               { 0, 3, 6, 9, MAX_RATE_POWER };
-
        int i;
-       int16_t twiceLargestAntenna;
        struct cal_ctl_data *rep;
        struct cal_target_power_leg targetPowerOfdm, targetPowerCck = {
                0, { 0, 0, 0, 0}
@@ -1012,7 +1015,7 @@ static void ath9k_hw_set_def_power_per_rate_table(struct ath_hw *ah,
        struct cal_target_power_ht targetPowerHt20, targetPowerHt40 = {
                0, {0, 0, 0, 0}
        };
-       u16 scaledPower = 0, minCtlPower, maxRegAllowedPower;
+       u16 scaledPower = 0, minCtlPower;
        static const u16 ctlModesFor11a[] = {
                CTL_11A, CTL_5GHT20, CTL_11A_EXT, CTL_5GHT40
        };
@@ -1031,27 +1034,7 @@ static void ath9k_hw_set_def_power_per_rate_table(struct ath_hw *ah,
 
        ath9k_hw_get_channel_centers(ah, chan, &centers);
 
-       twiceLargestAntenna = max(
-               pEepData->modalHeader
-                       [IS_CHAN_2GHZ(chan)].antennaGainCh[0],
-               pEepData->modalHeader
-                       [IS_CHAN_2GHZ(chan)].antennaGainCh[1]);
-
-       twiceLargestAntenna = max((u8)twiceLargestAntenna,
-                                 pEepData->modalHeader
-                                 [IS_CHAN_2GHZ(chan)].antennaGainCh[2]);
-
-       twiceLargestAntenna = (int16_t)min(AntennaReduction -
-                                          twiceLargestAntenna, 0);
-
-       maxRegAllowedPower = twiceMaxRegulatoryPower + twiceLargestAntenna;
-
-       if (regulatory->tp_scale != ATH9K_TP_SCALE_MAX) {
-               maxRegAllowedPower -=
-                       (tpScaleReductionTable[(regulatory->tp_scale)] * 2);
-       }
-
-       scaledPower = min(powerLimit, maxRegAllowedPower);
+       scaledPower = powerLimit - antenna_reduction;
 
        switch (ar5416_get_ntxchains(tx_chainmask)) {
        case 1:
@@ -1256,7 +1239,6 @@ static void ath9k_hw_def_set_txpower(struct ath_hw *ah,
                                    struct ath9k_channel *chan,
                                    u16 cfgCtl,
                                    u8 twiceAntennaReduction,
-                                   u8 twiceMaxRegulatoryPower,
                                    u8 powerLimit, bool test)
 {
 #define RT_AR_DELTA(x) (ratesArray[x] - cck_ofdm_delta)
@@ -1278,7 +1260,6 @@ static void ath9k_hw_def_set_txpower(struct ath_hw *ah,
        ath9k_hw_set_def_power_per_rate_table(ah, chan,
                                               &ratesArray[0], cfgCtl,
                                               twiceAntennaReduction,
-                                              twiceMaxRegulatoryPower,
                                               powerLimit);
 
        ath9k_hw_set_def_power_cal_table(ah, chan);
index 42ebe8fb053a62575afcc6ed2ec695dbe7725dc0..949656d928d36c39cb03128880feaf7590822a5d 100644 (file)
@@ -433,7 +433,6 @@ static void ath9k_hw_init_defaults(struct ath_hw *ah)
 
        regulatory->country_code = CTRY_DEFAULT;
        regulatory->power_limit = MAX_RATE_POWER;
-       regulatory->tp_scale = ATH9K_TP_SCALE_MAX;
 
        ah->hw_version.magic = AR5416_MAGIC;
        ah->hw_version.subvendorid = 0;
@@ -1389,9 +1388,7 @@ static bool ath9k_hw_chip_reset(struct ath_hw *ah,
 static bool ath9k_hw_channel_change(struct ath_hw *ah,
                                    struct ath9k_channel *chan)
 {
-       struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah);
        struct ath_common *common = ath9k_hw_common(ah);
-       struct ieee80211_channel *channel = chan->chan;
        u32 qnum;
        int r;
 
@@ -1416,14 +1413,7 @@ static bool ath9k_hw_channel_change(struct ath_hw *ah,
                return false;
        }
        ath9k_hw_set_clockrate(ah);
-
-       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);
-
+       ath9k_hw_apply_txpower(ah, chan);
        ath9k_hw_rfbus_done(ah);
 
        if (IS_CHAN_OFDM(chan) || IS_CHAN_HT(chan))
@@ -2498,23 +2488,56 @@ bool ath9k_hw_disable(struct ath_hw *ah)
 }
 EXPORT_SYMBOL(ath9k_hw_disable);
 
+static int get_antenna_gain(struct ath_hw *ah, struct ath9k_channel *chan)
+{
+       enum eeprom_param gain_param;
+
+       if (IS_CHAN_2GHZ(chan))
+               gain_param = EEP_ANTENNA_GAIN_2G;
+       else
+               gain_param = EEP_ANTENNA_GAIN_5G;
+
+       return ah->eep_ops->get_eeprom(ah, gain_param);
+}
+
+void ath9k_hw_apply_txpower(struct ath_hw *ah, struct ath9k_channel *chan)
+{
+       struct ath_regulatory *reg = ath9k_hw_regulatory(ah);
+       struct ieee80211_channel *channel;
+       int chan_pwr, new_pwr, max_gain;
+       int ant_gain, ant_reduction = 0;
+
+       if (!chan)
+               return;
+
+       channel = chan->chan;
+       chan_pwr = min_t(int, channel->max_power * 2, MAX_RATE_POWER);
+       new_pwr = min_t(int, chan_pwr, reg->power_limit);
+       max_gain = chan_pwr - new_pwr + channel->max_antenna_gain * 2;
+
+       ant_gain = get_antenna_gain(ah, chan);
+       if (ant_gain > max_gain)
+               ant_reduction = ant_gain - max_gain;
+
+       ah->eep_ops->set_txpower(ah, chan,
+                                ath9k_regd_get_ctl(reg, chan),
+                                ant_reduction, new_pwr, false);
+}
+
 void ath9k_hw_set_txpowerlimit(struct ath_hw *ah, u32 limit, bool test)
 {
-       struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah);
+       struct ath_regulatory *reg = 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, limit);
-       int chan_pwr = channel->max_power * 2;
 
+       reg->power_limit = min_t(int, limit, MAX_RATE_POWER);
        if (test)
-               reg_pwr = chan_pwr = MAX_RATE_POWER;
+               channel->max_power = MAX_RATE_POWER / 2;
 
-       regulatory->power_limit = reg_pwr;
+       ath9k_hw_apply_txpower(ah, chan);
 
-       ah->eep_ops->set_txpower(ah, chan,
-                                ath9k_regd_get_ctl(regulatory, chan),
-                                channel->max_antenna_gain * 2,
-                                chan_pwr, reg_pwr, test);
+       if (test)
+               channel->max_power = DIV_ROUND_UP(reg->max_power_level, 2);
 }
 EXPORT_SYMBOL(ath9k_hw_set_txpowerlimit);
 
index 24889f78a0536426d593ed0da3bd950e99f358f0..684c33c4897c9656a5e7757f3d4de1e10e53af35 100644 (file)
@@ -390,14 +390,6 @@ enum ath9k_power_mode {
        ATH9K_PM_UNDEFINED
 };
 
-enum ath9k_tp_scale {
-       ATH9K_TP_SCALE_MAX = 0,
-       ATH9K_TP_SCALE_50,
-       ATH9K_TP_SCALE_25,
-       ATH9K_TP_SCALE_12,
-       ATH9K_TP_SCALE_MIN
-};
-
 enum ser_reg_mode {
        SER_REG_MODE_OFF = 0,
        SER_REG_MODE_ON = 1,
@@ -968,6 +960,7 @@ void ath9k_hw_htc_resetinit(struct ath_hw *ah);
 /* PHY */
 void ath9k_hw_get_delta_slope_vals(struct ath_hw *ah, u32 coef_scaled,
                                   u32 *coef_mantissa, u32 *coef_exponent);
+void ath9k_hw_apply_txpower(struct ath_hw *ah, struct ath9k_channel *chan);
 
 /*
  * Code Specific to AR5008, AR9001 or AR9002,
index 39514de044efea39f966e2a6d111600e8fb3344d..af1b325495319aeb7398b4045b4995534d24da97 100644 (file)
@@ -626,7 +626,6 @@ 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];
@@ -635,7 +634,6 @@ static void ath9k_init_band_txpower(struct ath_softc *sc, int band)
                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;
        }
 }