diff options
author | Lorenzo Bianconi <lorenzo.bianconi83@gmail.com> | 2014-12-30 17:10:19 -0500 |
---|---|---|
committer | Kalle Valo <kvalo@codeaurora.org> | 2015-01-15 07:47:16 -0500 |
commit | 9ddad58bee51663001ff118d65cc9166bafcd122 (patch) | |
tree | c375ab0c939e24a4c5d627126d299429bac8ca5b | |
parent | c08267dc9a3641c78846bfac92abfc54984c6694 (diff) |
ath9k: add TPC to TX path for AR9002 based chips
Add TPC capability to TX descriptor path for AR9002 based chips. Scale
per-packet TX power according to eeprom power bias, power adjustments for
HT40 mode and open loop CCK rates. Cap per-packet TX power according to
TX power per-rate tables
Signed-off-by: Lorenzo Bianconi <lorenzo.bianconi83@gmail.com>
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
-rw-r--r-- | drivers/net/wireless/ath/ath9k/xmit.c | 68 |
1 files changed, 56 insertions, 12 deletions
diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c index 52d63de4a93d..9c332f9c3fc5 100644 --- a/drivers/net/wireless/ath/ath9k/xmit.c +++ b/drivers/net/wireless/ath/ath9k/xmit.c | |||
@@ -1097,24 +1097,65 @@ void ath_update_max_aggr_framelen(struct ath_softc *sc, int queue, int txop) | |||
1097 | } | 1097 | } |
1098 | 1098 | ||
1099 | static u8 ath_get_rate_txpower(struct ath_softc *sc, struct ath_buf *bf, | 1099 | static u8 ath_get_rate_txpower(struct ath_softc *sc, struct ath_buf *bf, |
1100 | u8 rateidx) | 1100 | u8 rateidx, bool is_40, bool is_cck) |
1101 | { | 1101 | { |
1102 | u8 max_power; | 1102 | u8 max_power; |
1103 | struct sk_buff *skb; | ||
1104 | struct ath_frame_info *fi; | ||
1105 | struct ieee80211_tx_info *info; | ||
1103 | struct ath_hw *ah = sc->sc_ah; | 1106 | struct ath_hw *ah = sc->sc_ah; |
1104 | 1107 | ||
1105 | if (sc->tx99_state) | 1108 | if (sc->tx99_state || !ah->tpc_enabled) |
1106 | return MAX_RATE_POWER; | 1109 | return MAX_RATE_POWER; |
1107 | 1110 | ||
1111 | skb = bf->bf_mpdu; | ||
1112 | fi = get_frame_info(skb); | ||
1113 | info = IEEE80211_SKB_CB(skb); | ||
1114 | |||
1108 | if (!AR_SREV_9300_20_OR_LATER(ah)) { | 1115 | if (!AR_SREV_9300_20_OR_LATER(ah)) { |
1109 | /* ar9002 does not support TPC for the moment */ | 1116 | int txpower = fi->tx_power; |
1110 | return MAX_RATE_POWER; | ||
1111 | } | ||
1112 | 1117 | ||
1113 | if (!bf->bf_state.bfs_paprd) { | 1118 | if (is_40) { |
1114 | struct sk_buff *skb = bf->bf_mpdu; | 1119 | u8 power_ht40delta; |
1115 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | 1120 | struct ar5416_eeprom_def *eep = &ah->eeprom.def; |
1116 | struct ath_frame_info *fi = get_frame_info(skb); | ||
1117 | 1121 | ||
1122 | if (AR5416_VER_MASK >= AR5416_EEP_MINOR_VER_2) { | ||
1123 | bool is_2ghz; | ||
1124 | struct modal_eep_header *pmodal; | ||
1125 | |||
1126 | is_2ghz = info->band == IEEE80211_BAND_2GHZ; | ||
1127 | pmodal = &eep->modalHeader[is_2ghz]; | ||
1128 | power_ht40delta = pmodal->ht40PowerIncForPdadc; | ||
1129 | } else { | ||
1130 | power_ht40delta = 2; | ||
1131 | } | ||
1132 | txpower += power_ht40delta; | ||
1133 | } | ||
1134 | |||
1135 | if (AR_SREV_9287(ah) || AR_SREV_9285(ah) || | ||
1136 | AR_SREV_9271(ah)) { | ||
1137 | txpower -= 2 * AR9287_PWR_TABLE_OFFSET_DB; | ||
1138 | } else if (AR_SREV_9280_20_OR_LATER(ah)) { | ||
1139 | s8 power_offset; | ||
1140 | |||
1141 | power_offset = ah->eep_ops->get_eeprom(ah, | ||
1142 | EEP_PWR_TABLE_OFFSET); | ||
1143 | txpower -= 2 * power_offset; | ||
1144 | } | ||
1145 | |||
1146 | if (OLC_FOR_AR9280_20_LATER && is_cck) | ||
1147 | txpower -= 2; | ||
1148 | |||
1149 | txpower = max(txpower, 0); | ||
1150 | max_power = min_t(u8, ah->tx_power[rateidx], txpower); | ||
1151 | |||
1152 | /* XXX: clamp minimum TX power at 1 for AR9160 since if | ||
1153 | * max_power is set to 0, frames are transmitted at max | ||
1154 | * TX power | ||
1155 | */ | ||
1156 | if (!max_power && !AR_SREV_9280_20_OR_LATER(ah)) | ||
1157 | max_power = 1; | ||
1158 | } else if (!bf->bf_state.bfs_paprd) { | ||
1118 | if (rateidx < 8 && (info->flags & IEEE80211_TX_CTL_STBC)) | 1159 | if (rateidx < 8 && (info->flags & IEEE80211_TX_CTL_STBC)) |
1119 | max_power = min(ah->tx_power_stbc[rateidx], | 1160 | max_power = min(ah->tx_power_stbc[rateidx], |
1120 | fi->tx_power); | 1161 | fi->tx_power); |
@@ -1152,7 +1193,7 @@ static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf, | |||
1152 | info->rtscts_rate = fi->rtscts_rate; | 1193 | info->rtscts_rate = fi->rtscts_rate; |
1153 | 1194 | ||
1154 | for (i = 0; i < ARRAY_SIZE(bf->rates); i++) { | 1195 | for (i = 0; i < ARRAY_SIZE(bf->rates); i++) { |
1155 | bool is_40, is_sgi, is_sp; | 1196 | bool is_40, is_sgi, is_sp, is_cck; |
1156 | int phy; | 1197 | int phy; |
1157 | 1198 | ||
1158 | if (!rates[i].count || (rates[i].idx < 0)) | 1199 | if (!rates[i].count || (rates[i].idx < 0)) |
@@ -1198,7 +1239,8 @@ static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf, | |||
1198 | if (rix < 8 && (tx_info->flags & IEEE80211_TX_CTL_STBC)) | 1239 | if (rix < 8 && (tx_info->flags & IEEE80211_TX_CTL_STBC)) |
1199 | info->rates[i].RateFlags |= ATH9K_RATESERIES_STBC; | 1240 | info->rates[i].RateFlags |= ATH9K_RATESERIES_STBC; |
1200 | 1241 | ||
1201 | info->txpower[i] = ath_get_rate_txpower(sc, bf, rix); | 1242 | info->txpower[i] = ath_get_rate_txpower(sc, bf, rix, |
1243 | is_40, false); | ||
1202 | continue; | 1244 | continue; |
1203 | } | 1245 | } |
1204 | 1246 | ||
@@ -1227,7 +1269,9 @@ static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf, | |||
1227 | info->rates[i].PktDuration = ath9k_hw_computetxtime(sc->sc_ah, | 1269 | info->rates[i].PktDuration = ath9k_hw_computetxtime(sc->sc_ah, |
1228 | phy, rate->bitrate * 100, len, rix, is_sp); | 1270 | phy, rate->bitrate * 100, len, rix, is_sp); |
1229 | 1271 | ||
1230 | info->txpower[i] = ath_get_rate_txpower(sc, bf, rix); | 1272 | is_cck = IS_CCK_RATE(info->rates[i].Rate); |
1273 | info->txpower[i] = ath_get_rate_txpower(sc, bf, rix, false, | ||
1274 | is_cck); | ||
1231 | } | 1275 | } |
1232 | 1276 | ||
1233 | /* For AR5416 - RTS cannot be followed by a frame larger than 8K */ | 1277 | /* For AR5416 - RTS cannot be followed by a frame larger than 8K */ |