| 1 | --- a/drivers/net/wireless/ath/ath9k/eeprom.h |
| 2 | +++ b/drivers/net/wireless/ath/ath9k/eeprom.h |
| 3 | @@ -680,7 +680,8 @@ struct eeprom_ops { |
| 4 | void (*set_addac)(struct ath_hw *hw, struct ath9k_channel *chan); |
| 5 | void (*set_txpower)(struct ath_hw *hw, struct ath9k_channel *chan, |
| 6 | u16 cfgCtl, u8 twiceAntennaReduction, |
| 7 | - u8 twiceMaxRegulatoryPower, u8 powerLimit); |
| 8 | + u8 twiceMaxRegulatoryPower, u8 powerLimit, |
| 9 | + bool test); |
| 10 | u16 (*get_spur_channel)(struct ath_hw *ah, u16 i, bool is2GHz); |
| 11 | }; |
| 12 | |
| 13 | --- a/drivers/net/wireless/ath/ath9k/eeprom_4k.c |
| 14 | +++ b/drivers/net/wireless/ath/ath9k/eeprom_4k.c |
| 15 | @@ -726,7 +726,7 @@ static void ath9k_hw_4k_set_txpower(stru |
| 16 | u16 cfgCtl, |
| 17 | u8 twiceAntennaReduction, |
| 18 | u8 twiceMaxRegulatoryPower, |
| 19 | - u8 powerLimit) |
| 20 | + u8 powerLimit, bool test) |
| 21 | { |
| 22 | struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah); |
| 23 | struct ar5416_eeprom_4k *pEepData = &ah->eeprom.map4k; |
| 24 | @@ -751,15 +751,20 @@ static void ath9k_hw_4k_set_txpower(stru |
| 25 | |
| 26 | ath9k_hw_set_4k_power_cal_table(ah, chan, &txPowerIndexOffset); |
| 27 | |
| 28 | + regulatory->max_power_level = 0; |
| 29 | for (i = 0; i < ARRAY_SIZE(ratesArray); i++) { |
| 30 | ratesArray[i] = (int16_t)(txPowerIndexOffset + ratesArray[i]); |
| 31 | if (ratesArray[i] > AR5416_MAX_RATE_POWER) |
| 32 | ratesArray[i] = AR5416_MAX_RATE_POWER; |
| 33 | + |
| 34 | + if (ratesArray[i] > regulatory->max_power_level) |
| 35 | + regulatory->max_power_level = ratesArray[i]; |
| 36 | } |
| 37 | |
| 38 | + if (test) |
| 39 | + return; |
| 40 | |
| 41 | /* Update regulatory */ |
| 42 | - |
| 43 | i = rate6mb; |
| 44 | if (IS_CHAN_HT40(chan)) |
| 45 | i = rateHt40_0; |
| 46 | --- a/drivers/net/wireless/ath/ath9k/eeprom_9287.c |
| 47 | +++ b/drivers/net/wireless/ath/ath9k/eeprom_9287.c |
| 48 | @@ -853,7 +853,7 @@ static void ath9k_hw_ar9287_set_txpower( |
| 49 | struct ath9k_channel *chan, u16 cfgCtl, |
| 50 | u8 twiceAntennaReduction, |
| 51 | u8 twiceMaxRegulatoryPower, |
| 52 | - u8 powerLimit) |
| 53 | + u8 powerLimit, bool test) |
| 54 | { |
| 55 | struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah); |
| 56 | struct ar9287_eeprom *pEepData = &ah->eeprom.map9287; |
| 57 | @@ -877,12 +877,26 @@ static void ath9k_hw_ar9287_set_txpower( |
| 58 | |
| 59 | ath9k_hw_set_ar9287_power_cal_table(ah, chan, &txPowerIndexOffset); |
| 60 | |
| 61 | + regulatory->max_power_level = 0; |
| 62 | for (i = 0; i < ARRAY_SIZE(ratesArray); i++) { |
| 63 | ratesArray[i] = (int16_t)(txPowerIndexOffset + ratesArray[i]); |
| 64 | if (ratesArray[i] > AR9287_MAX_RATE_POWER) |
| 65 | ratesArray[i] = AR9287_MAX_RATE_POWER; |
| 66 | + |
| 67 | + if (ratesArray[i] > regulatory->max_power_level) |
| 68 | + regulatory->max_power_level = ratesArray[i]; |
| 69 | } |
| 70 | |
| 71 | + if (test) |
| 72 | + return; |
| 73 | + |
| 74 | + if (IS_CHAN_2GHZ(chan)) |
| 75 | + i = rate1l; |
| 76 | + else |
| 77 | + i = rate6mb; |
| 78 | + |
| 79 | + regulatory->max_power_level = ratesArray[i]; |
| 80 | + |
| 81 | if (AR_SREV_9280_20_OR_LATER(ah)) { |
| 82 | for (i = 0; i < Ar5416RateSize; i++) |
| 83 | ratesArray[i] -= AR9287_PWR_TABLE_OFFSET_DB * 2; |
| 84 | @@ -971,17 +985,6 @@ static void ath9k_hw_ar9287_set_txpower( |
| 85 | | ATH9K_POW_SM(ratesArray[rateDupOfdm], 8) |
| 86 | | ATH9K_POW_SM(ratesArray[rateDupCck], 0)); |
| 87 | } |
| 88 | - |
| 89 | - if (IS_CHAN_2GHZ(chan)) |
| 90 | - i = rate1l; |
| 91 | - else |
| 92 | - i = rate6mb; |
| 93 | - |
| 94 | - if (AR_SREV_9280_20_OR_LATER(ah)) |
| 95 | - regulatory->max_power_level = |
| 96 | - ratesArray[i] + AR9287_PWR_TABLE_OFFSET_DB * 2; |
| 97 | - else |
| 98 | - regulatory->max_power_level = ratesArray[i]; |
| 99 | } |
| 100 | |
| 101 | static void ath9k_hw_ar9287_set_addac(struct ath_hw *ah, |
| 102 | --- a/drivers/net/wireless/ath/ath9k/eeprom_def.c |
| 103 | +++ b/drivers/net/wireless/ath/ath9k/eeprom_def.c |
| 104 | @@ -1258,7 +1258,7 @@ static void ath9k_hw_def_set_txpower(str |
| 105 | u16 cfgCtl, |
| 106 | u8 twiceAntennaReduction, |
| 107 | u8 twiceMaxRegulatoryPower, |
| 108 | - u8 powerLimit) |
| 109 | + u8 powerLimit, bool test) |
| 110 | { |
| 111 | #define RT_AR_DELTA(x) (ratesArray[x] - cck_ofdm_delta) |
| 112 | struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah); |
| 113 | @@ -1285,12 +1285,44 @@ static void ath9k_hw_def_set_txpower(str |
| 114 | |
| 115 | ath9k_hw_set_def_power_cal_table(ah, chan, &txPowerIndexOffset); |
| 116 | |
| 117 | + regulatory->max_power_level = 0; |
| 118 | for (i = 0; i < ARRAY_SIZE(ratesArray); i++) { |
| 119 | ratesArray[i] = (int16_t)(txPowerIndexOffset + ratesArray[i]); |
| 120 | if (ratesArray[i] > AR5416_MAX_RATE_POWER) |
| 121 | ratesArray[i] = AR5416_MAX_RATE_POWER; |
| 122 | + if (ratesArray[i] > regulatory->max_power_level) |
| 123 | + regulatory->max_power_level = ratesArray[i]; |
| 124 | } |
| 125 | |
| 126 | + if (!test) { |
| 127 | + i = rate6mb; |
| 128 | + |
| 129 | + if (IS_CHAN_HT40(chan)) |
| 130 | + i = rateHt40_0; |
| 131 | + else if (IS_CHAN_HT20(chan)) |
| 132 | + i = rateHt20_0; |
| 133 | + |
| 134 | + regulatory->max_power_level = ratesArray[i]; |
| 135 | + } |
| 136 | + |
| 137 | + switch(ar5416_get_ntxchains(ah->txchainmask)) { |
| 138 | + case 1: |
| 139 | + break; |
| 140 | + case 2: |
| 141 | + regulatory->max_power_level += INCREASE_MAXPOW_BY_TWO_CHAIN; |
| 142 | + break; |
| 143 | + case 3: |
| 144 | + regulatory->max_power_level += INCREASE_MAXPOW_BY_THREE_CHAIN; |
| 145 | + break; |
| 146 | + default: |
| 147 | + ath_print(ath9k_hw_common(ah), ATH_DBG_EEPROM, |
| 148 | + "Invalid chainmask configuration\n"); |
| 149 | + break; |
| 150 | + } |
| 151 | + |
| 152 | + if (test) |
| 153 | + return; |
| 154 | + |
| 155 | if (AR_SREV_9280_20_OR_LATER(ah)) { |
| 156 | for (i = 0; i < Ar5416RateSize; i++) { |
| 157 | int8_t pwr_table_offset; |
| 158 | @@ -1387,34 +1419,6 @@ static void ath9k_hw_def_set_txpower(str |
| 159 | REG_WRITE(ah, AR_PHY_POWER_TX_SUB, |
| 160 | ATH9K_POW_SM(pModal->pwrDecreaseFor3Chain, 6) |
| 161 | | ATH9K_POW_SM(pModal->pwrDecreaseFor2Chain, 0)); |
| 162 | - |
| 163 | - i = rate6mb; |
| 164 | - |
| 165 | - if (IS_CHAN_HT40(chan)) |
| 166 | - i = rateHt40_0; |
| 167 | - else if (IS_CHAN_HT20(chan)) |
| 168 | - i = rateHt20_0; |
| 169 | - |
| 170 | - if (AR_SREV_9280_20_OR_LATER(ah)) |
| 171 | - regulatory->max_power_level = |
| 172 | - ratesArray[i] + AR5416_PWR_TABLE_OFFSET_DB * 2; |
| 173 | - else |
| 174 | - regulatory->max_power_level = ratesArray[i]; |
| 175 | - |
| 176 | - switch(ar5416_get_ntxchains(ah->txchainmask)) { |
| 177 | - case 1: |
| 178 | - break; |
| 179 | - case 2: |
| 180 | - regulatory->max_power_level += INCREASE_MAXPOW_BY_TWO_CHAIN; |
| 181 | - break; |
| 182 | - case 3: |
| 183 | - regulatory->max_power_level += INCREASE_MAXPOW_BY_THREE_CHAIN; |
| 184 | - break; |
| 185 | - default: |
| 186 | - ath_print(ath9k_hw_common(ah), ATH_DBG_EEPROM, |
| 187 | - "Invalid chainmask configuration\n"); |
| 188 | - break; |
| 189 | - } |
| 190 | } |
| 191 | |
| 192 | static u8 ath9k_hw_def_get_num_ant_config(struct ath_hw *ah, |
| 193 | --- a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c |
| 194 | +++ b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c |
| 195 | @@ -2131,7 +2131,7 @@ static void ath9k_hw_ar9300_set_txpower( |
| 196 | struct ath9k_channel *chan, u16 cfgCtl, |
| 197 | u8 twiceAntennaReduction, |
| 198 | u8 twiceMaxRegulatoryPower, |
| 199 | - u8 powerLimit) |
| 200 | + u8 powerLimit, bool test) |
| 201 | { |
| 202 | struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah); |
| 203 | struct ath_common *common = ath9k_hw_common(ah); |
| 204 | @@ -2145,7 +2145,16 @@ static void ath9k_hw_ar9300_set_txpower( |
| 205 | twiceMaxRegulatoryPower, |
| 206 | powerLimit); |
| 207 | |
| 208 | - while (i < ar9300RateSize) { |
| 209 | + regulatory->max_power_level = 0; |
| 210 | + for (i = 0; i < ar9300RateSize; i++) { |
| 211 | + if (targetPowerValT2[i] > regulatory->max_power_level) |
| 212 | + regulatory->max_power_level = targetPowerValT2[i]; |
| 213 | + } |
| 214 | + |
| 215 | + if (test) |
| 216 | + return; |
| 217 | + |
| 218 | + for (i = 0; i < ar9300RateSize; i++) { |
| 219 | ath_print(common, ATH_DBG_EEPROM, |
| 220 | "TPC[%02d] 0x%08x ", i, targetPowerValT2[i]); |
| 221 | i++; |
| 222 | @@ -2160,9 +2169,6 @@ static void ath9k_hw_ar9300_set_txpower( |
| 223 | i++; |
| 224 | } |
| 225 | |
| 226 | - /* Write target power array to registers */ |
| 227 | - ar9003_hw_tx_power_regwrite(ah, targetPowerValT2); |
| 228 | - |
| 229 | /* |
| 230 | * This is the TX power we send back to driver core, |
| 231 | * and it can use to pass to userspace to display our |
| 232 | @@ -2181,8 +2187,10 @@ static void ath9k_hw_ar9300_set_txpower( |
| 233 | i = ALL_TARGET_HT20_0_8_16; /* ht20 */ |
| 234 | |
| 235 | ah->txpower_limit = targetPowerValT2[i]; |
| 236 | - regulatory->max_power_level = ratesArray[i]; |
| 237 | + regulatory->max_power_level = targetPowerValT2[i]; |
| 238 | |
| 239 | + /* Write target power array to registers */ |
| 240 | + ar9003_hw_tx_power_regwrite(ah, targetPowerValT2); |
| 241 | ar9003_hw_calibration_apply(ah, chan->channel); |
| 242 | } |
| 243 | |
| 244 | --- a/drivers/net/wireless/ath/ath9k/hw.c |
| 245 | +++ b/drivers/net/wireless/ath/ath9k/hw.c |
| 246 | @@ -1178,7 +1178,7 @@ static bool ath9k_hw_channel_change(stru |
| 247 | channel->max_antenna_gain * 2, |
| 248 | channel->max_power * 2, |
| 249 | min((u32) MAX_RATE_POWER, |
| 250 | - (u32) regulatory->power_limit)); |
| 251 | + (u32) regulatory->power_limit), false); |
| 252 | |
| 253 | ath9k_hw_rfbus_done(ah); |
| 254 | |
| 255 | @@ -2177,7 +2177,7 @@ bool ath9k_hw_disable(struct ath_hw *ah) |
| 256 | } |
| 257 | EXPORT_SYMBOL(ath9k_hw_disable); |
| 258 | |
| 259 | -void ath9k_hw_set_txpowerlimit(struct ath_hw *ah, u32 limit) |
| 260 | +void ath9k_hw_set_txpowerlimit(struct ath_hw *ah, u32 limit, bool test) |
| 261 | { |
| 262 | struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah); |
| 263 | struct ath9k_channel *chan = ah->curchan; |
| 264 | @@ -2190,7 +2190,7 @@ void ath9k_hw_set_txpowerlimit(struct at |
| 265 | channel->max_antenna_gain * 2, |
| 266 | channel->max_power * 2, |
| 267 | min((u32) MAX_RATE_POWER, |
| 268 | - (u32) regulatory->power_limit)); |
| 269 | + (u32) regulatory->power_limit), test); |
| 270 | } |
| 271 | EXPORT_SYMBOL(ath9k_hw_set_txpowerlimit); |
| 272 | |
| 273 | --- a/drivers/net/wireless/ath/ath9k/hw.h |
| 274 | +++ b/drivers/net/wireless/ath/ath9k/hw.h |
| 275 | @@ -860,7 +860,7 @@ u32 ath9k_hw_getrxfilter(struct ath_hw * |
| 276 | void ath9k_hw_setrxfilter(struct ath_hw *ah, u32 bits); |
| 277 | bool ath9k_hw_phy_disable(struct ath_hw *ah); |
| 278 | bool ath9k_hw_disable(struct ath_hw *ah); |
| 279 | -void ath9k_hw_set_txpowerlimit(struct ath_hw *ah, u32 limit); |
| 280 | +void ath9k_hw_set_txpowerlimit(struct ath_hw *ah, u32 limit, bool test); |
| 281 | void ath9k_hw_setopmode(struct ath_hw *ah); |
| 282 | void ath9k_hw_setmcastfilter(struct ath_hw *ah, u32 filter0, u32 filter1); |
| 283 | void ath9k_hw_setbssidmask(struct ath_hw *ah); |
| 284 | --- a/drivers/net/wireless/ath/ath9k/main.c |
| 285 | +++ b/drivers/net/wireless/ath/ath9k/main.c |
| 286 | @@ -24,7 +24,7 @@ static void ath_update_txpow(struct ath_ |
| 287 | struct ath_hw *ah = sc->sc_ah; |
| 288 | |
| 289 | if (sc->curtxpow != sc->config.txpowlimit) { |
| 290 | - ath9k_hw_set_txpowerlimit(ah, sc->config.txpowlimit); |
| 291 | + ath9k_hw_set_txpowerlimit(ah, sc->config.txpowlimit, false); |
| 292 | /* read back in case value is clamped */ |
| 293 | sc->curtxpow = ath9k_hw_regulatory(ah)->power_limit; |
| 294 | } |
| 295 | --- a/drivers/net/wireless/ath/ath9k/ar9003_phy.c |
| 296 | +++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.c |
| 297 | @@ -614,7 +614,7 @@ static int ar9003_hw_process_ini(struct |
| 298 | channel->max_antenna_gain * 2, |
| 299 | channel->max_power * 2, |
| 300 | min((u32) MAX_RATE_POWER, |
| 301 | - (u32) regulatory->power_limit)); |
| 302 | + (u32) regulatory->power_limit), false); |
| 303 | |
| 304 | return 0; |
| 305 | } |
| 306 | --- a/drivers/net/wireless/ath/ath9k/ar5008_phy.c |
| 307 | +++ b/drivers/net/wireless/ath/ath9k/ar5008_phy.c |
| 308 | @@ -875,7 +875,7 @@ static int ar5008_hw_process_ini(struct |
| 309 | channel->max_antenna_gain * 2, |
| 310 | channel->max_power * 2, |
| 311 | min((u32) MAX_RATE_POWER, |
| 312 | - (u32) regulatory->power_limit)); |
| 313 | + (u32) regulatory->power_limit), false); |
| 314 | |
| 315 | /* Write analog registers */ |
| 316 | if (!ath9k_hw_set_rf_regs(ah, chan, freqIndex)) { |
| 317 | --- a/drivers/net/wireless/ath/ath9k/htc_drv_main.c |
| 318 | +++ b/drivers/net/wireless/ath/ath9k/htc_drv_main.c |
| 319 | @@ -29,7 +29,7 @@ static void ath_update_txpow(struct ath9 |
| 320 | struct ath_hw *ah = priv->ah; |
| 321 | |
| 322 | if (priv->curtxpow != priv->txpowlimit) { |
| 323 | - ath9k_hw_set_txpowerlimit(ah, priv->txpowlimit); |
| 324 | + ath9k_hw_set_txpowerlimit(ah, priv->txpowlimit, false); |
| 325 | /* read back in case value is clamped */ |
| 326 | priv->curtxpow = ath9k_hw_regulatory(ah)->power_limit; |
| 327 | } |
| 328 | |