ath9k: fix per-packet tx power configuration
authorLorenzo Bianconi <lorenzo.bianconi83@gmail.com>
Wed, 8 Apr 2015 18:51:57 +0000 (20:51 +0200)
committerKalle Valo <kvalo@codeaurora.org>
Sun, 3 May 2015 20:54:38 +0000 (23:54 +0300)
Do not use ieee80211_vif pointer in ath_get_rate_txpower() since it has been
overwritten by setup_frame_info() and it will result in a corrupted tx power
configuration. Set per-packet tx power in setup_frame_info() according to
current vif tx power.

Signed-off-by: Lorenzo Bianconi <lorenzo.bianconi83@gmail.com>
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
drivers/net/wireless/ath/ath9k/xmit.c

index 0acd079ba96bd3d2f60602ebf5f889f36da9f908..3ad79bb4f2c21c94b6c41c526a7e033e0937ed77 100644 (file)
@@ -1103,28 +1103,14 @@ static u8 ath_get_rate_txpower(struct ath_softc *sc, struct ath_buf *bf,
        struct sk_buff *skb;
        struct ath_frame_info *fi;
        struct ieee80211_tx_info *info;
-       struct ieee80211_vif *vif;
        struct ath_hw *ah = sc->sc_ah;
 
        if (sc->tx99_state || !ah->tpc_enabled)
                return MAX_RATE_POWER;
 
        skb = bf->bf_mpdu;
-       info = IEEE80211_SKB_CB(skb);
-       vif = info->control.vif;
-
-       if (!vif) {
-               max_power = sc->cur_chan->cur_txpower;
-               goto out;
-       }
-
-       if (vif->bss_conf.txpower_type != NL80211_TX_POWER_LIMITED) {
-               max_power = min_t(u8, sc->cur_chan->cur_txpower,
-                                 2 * vif->bss_conf.txpower);
-               goto out;
-       }
-
        fi = get_frame_info(skb);
+       info = IEEE80211_SKB_CB(skb);
 
        if (!AR_SREV_9300_20_OR_LATER(ah)) {
                int txpower = fi->tx_power;
@@ -1161,25 +1147,26 @@ static u8 ath_get_rate_txpower(struct ath_softc *sc, struct ath_buf *bf,
                        txpower -= 2;
 
                txpower = max(txpower, 0);
-               max_power = min_t(u8, ah->tx_power[rateidx],
-                                 2 * vif->bss_conf.txpower);
-               max_power = min_t(u8, max_power, txpower);
+               max_power = min_t(u8, ah->tx_power[rateidx], txpower);
+
+               /* XXX: clamp minimum TX power at 1 for AR9160 since if
+                * max_power is set to 0, frames are transmitted at max
+                * TX power
+                */
+               if (!max_power && !AR_SREV_9280_20_OR_LATER(ah))
+                       max_power = 1;
        } else if (!bf->bf_state.bfs_paprd) {
                if (rateidx < 8 && (info->flags & IEEE80211_TX_CTL_STBC))
                        max_power = min_t(u8, ah->tx_power_stbc[rateidx],
-                                         2 * vif->bss_conf.txpower);
+                                         fi->tx_power);
                else
                        max_power = min_t(u8, ah->tx_power[rateidx],
-                                         2 * vif->bss_conf.txpower);
-               max_power = min(max_power, fi->tx_power);
+                                         fi->tx_power);
        } else {
                max_power = ah->paprd_training_power;
        }
-out:
-       /* XXX: clamp minimum TX power at 1 for AR9160 since if max_power
-        * is set to 0, frames are transmitted at max TX power
-        */
-       return (!max_power && !AR_SREV_9280_20_OR_LATER(ah)) ? 1 : max_power;
+
+       return max_power;
 }
 
 static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf,
@@ -2129,6 +2116,7 @@ static void setup_frame_info(struct ieee80211_hw *hw,
        struct ath_node *an = NULL;
        enum ath9k_key_type keytype;
        bool short_preamble = false;
+       u8 txpower;
 
        /*
         * We check if Short Preamble is needed for the CTS rate by
@@ -2145,6 +2133,16 @@ static void setup_frame_info(struct ieee80211_hw *hw,
        if (sta)
                an = (struct ath_node *) sta->drv_priv;
 
+       if (tx_info->control.vif) {
+               struct ieee80211_vif *vif = tx_info->control.vif;
+
+               txpower = 2 * vif->bss_conf.txpower;
+       } else {
+               struct ath_softc *sc = hw->priv;
+
+               txpower = sc->cur_chan->cur_txpower;
+       }
+
        memset(fi, 0, sizeof(*fi));
        fi->txq = -1;
        if (hw_key)
@@ -2155,7 +2153,7 @@ static void setup_frame_info(struct ieee80211_hw *hw,
                fi->keyix = ATH9K_TXKEYIX_INVALID;
        fi->keytype = keytype;
        fi->framelen = framelen;
-       fi->tx_power = MAX_RATE_POWER;
+       fi->tx_power = txpower;
 
        if (!rate)
                return;