ath9k: add support for reporting tx power to mac80211
authorFelix Fietkau <nbd@openwrt.org>
Tue, 4 Nov 2014 15:56:57 +0000 (16:56 +0100)
committerJohn W. Linville <linville@tuxdriver.com>
Tue, 11 Nov 2014 21:31:12 +0000 (16:31 -0500)
Track it per channel context instead of in the softc

Signed-off-by: Felix Fietkau <nbd@openwrt.org>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
drivers/net/wireless/ath/ath9k/ath9k.h
drivers/net/wireless/ath/ath9k/init.c
drivers/net/wireless/ath/ath9k/main.c

index 85d74ff0767c733e6057cad23d934f5861bb4bf6..adb49a9813f14c5305cbc0d1aeeaf77a880b8895 100644 (file)
@@ -347,6 +347,7 @@ struct ath_chanctx {
 
        int flush_timeout;
        u16 txpower;
+       u16 cur_txpower;
        bool offchannel;
        bool stopped;
        bool active;
@@ -987,7 +988,6 @@ struct ath_softc {
        u8 gtt_cnt;
        u32 intrstatus;
        u16 ps_flags; /* PS_* */
-       u16 curtxpow;
        bool ps_enabled;
        bool ps_idle;
        short nbcnvifs;
index 2294109f79e9bfb96f02a66b37000638246d11b9..8d3c3364326a1f94f5e836a83e9ebf5e616002f1 100644 (file)
@@ -172,17 +172,20 @@ static void ath9k_reg_notifier(struct wiphy *wiphy,
        ath_reg_notifier_apply(wiphy, request, reg);
 
        /* Set tx power */
-       if (ah->curchan) {
-               sc->cur_chan->txpower = 2 * ah->curchan->chan->max_power;
-               ath9k_ps_wakeup(sc);
-               ath9k_hw_set_txpowerlimit(ah, sc->cur_chan->txpower, false);
-               sc->curtxpow = ath9k_hw_regulatory(ah)->power_limit;
-               /* synchronize DFS detector if regulatory domain changed */
-               if (sc->dfs_detector != NULL)
-                       sc->dfs_detector->set_dfs_domain(sc->dfs_detector,
-                                                        request->dfs_region);
-               ath9k_ps_restore(sc);
-       }
+       if (!ah->curchan)
+               return;
+
+       sc->cur_chan->txpower = 2 * ah->curchan->chan->max_power;
+       ath9k_ps_wakeup(sc);
+       ath9k_hw_set_txpowerlimit(ah, sc->cur_chan->txpower, false);
+       ath9k_cmn_update_txpow(ah, sc->cur_chan->cur_txpower,
+                              sc->cur_chan->txpower,
+                              &sc->cur_chan->cur_txpower);
+       /* synchronize DFS detector if regulatory domain changed */
+       if (sc->dfs_detector != NULL)
+               sc->dfs_detector->set_dfs_domain(sc->dfs_detector,
+                                                request->dfs_region);
+       ath9k_ps_restore(sc);
 }
 
 /*
index 45465d8e3f0a275959998df99878f2e1a553f4fe..3ab5f630062bb90b179332f2cf40a287785c7198 100644 (file)
@@ -233,8 +233,9 @@ static bool ath_complete_reset(struct ath_softc *sc, bool start)
 
        ath9k_calculate_summary_state(sc, sc->cur_chan);
        ath_startrecv(sc);
-       ath9k_cmn_update_txpow(ah, sc->curtxpow,
-                              sc->cur_chan->txpower, &sc->curtxpow);
+       ath9k_cmn_update_txpow(ah, sc->cur_chan->cur_txpower,
+                              sc->cur_chan->txpower,
+                              &sc->cur_chan->cur_txpower);
        clear_bit(ATH_OP_HW_RESET, &common->op_flags);
 
        if (!sc->cur_chan->offchannel && start) {
@@ -1468,8 +1469,9 @@ static int ath9k_config(struct ieee80211_hw *hw, u32 changed)
        if (changed & IEEE80211_CONF_CHANGE_POWER) {
                ath_dbg(common, CONFIG, "Set power: %d\n", conf->power_level);
                sc->cur_chan->txpower = 2 * conf->power_level;
-               ath9k_cmn_update_txpow(ah, sc->curtxpow,
-                                      sc->cur_chan->txpower, &sc->curtxpow);
+               ath9k_cmn_update_txpow(ah, sc->cur_chan->cur_txpower,
+                                      sc->cur_chan->txpower,
+                                      &sc->cur_chan->cur_txpower);
        }
 
        mutex_unlock(&sc->mutex);
@@ -2591,6 +2593,24 @@ void ath9k_fill_chanctx_ops(void)
 
 #endif
 
+static int ath9k_get_txpower(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
+                            int *dbm)
+{
+       struct ath_softc *sc = hw->priv;
+       struct ath_vif *avp = (void *)vif->drv_priv;
+
+       mutex_lock(&sc->mutex);
+       if (avp->chanctx)
+               *dbm = avp->chanctx->cur_txpower;
+       else
+               *dbm = sc->cur_chan->cur_txpower;
+       mutex_unlock(&sc->mutex);
+
+       *dbm /= 2;
+
+       return 0;
+}
+
 struct ieee80211_ops ath9k_ops = {
        .tx                 = ath9k_tx,
        .start              = ath9k_start,
@@ -2637,4 +2657,5 @@ struct ieee80211_ops ath9k_ops = {
 #endif
        .sw_scan_start      = ath9k_sw_scan_start,
        .sw_scan_complete   = ath9k_sw_scan_complete,
+       .get_txpower        = ath9k_get_txpower,
 };