Signed-off-by: Felix Fietkau <nbd@openwrt.org> SVN-Revision: 43032master
parent
c14e0807bd
commit
d9ea3d2aa8
@ -0,0 +1,43 @@ |
||||
From: Felix Fietkau <nbd@openwrt.org>
|
||||
Date: Wed, 22 Oct 2014 17:55:50 +0200
|
||||
Subject: [PATCH] mac80211: add support for driver tx power reporting
|
||||
|
||||
The configured tx power is often limited by hardware capabilities,
|
||||
channel settings, antenna configuration, etc.
|
||||
|
||||
Signed-off-by: Felix Fietkau <nbd@openwrt.org>
|
||||
---
|
||||
|
||||
--- a/include/net/mac80211.h
|
||||
+++ b/include/net/mac80211.h
|
||||
@@ -2838,6 +2838,9 @@ enum ieee80211_roc_type {
|
||||
* @get_expected_throughput: extract the expected throughput towards the
|
||||
* specified station. The returned value is expressed in Kbps. It returns 0
|
||||
* if the RC algorithm does not have proper data to provide.
|
||||
+ *
|
||||
+ * @get_txpower: get current maximum tx power (in dBm) based on configuration
|
||||
+ * and hardware limits.
|
||||
*/
|
||||
struct ieee80211_ops {
|
||||
void (*tx)(struct ieee80211_hw *hw,
|
||||
@@ -3039,6 +3042,8 @@ struct ieee80211_ops {
|
||||
int (*join_ibss)(struct ieee80211_hw *hw, struct ieee80211_vif *vif);
|
||||
void (*leave_ibss)(struct ieee80211_hw *hw, struct ieee80211_vif *vif);
|
||||
u32 (*get_expected_throughput)(struct ieee80211_sta *sta);
|
||||
+ int (*get_txpower)(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
|
||||
+ int *dbm);
|
||||
};
|
||||
|
||||
/**
|
||||
--- a/net/mac80211/cfg.c
|
||||
+++ b/net/mac80211/cfg.c
|
||||
@@ -2081,6 +2081,9 @@ static int ieee80211_get_tx_power(struct
|
||||
struct ieee80211_local *local = wiphy_priv(wiphy);
|
||||
struct ieee80211_sub_if_data *sdata = IEEE80211_WDEV_TO_SUB_IF(wdev);
|
||||
|
||||
+ if (local->ops->get_txpower)
|
||||
+ return local->ops->get_txpower(&local->hw, &sdata->vif, dbm);
|
||||
+
|
||||
if (!local->use_chanctx)
|
||||
*dbm = local->hw.conf.power_level;
|
||||
else
|
@ -0,0 +1,31 @@ |
||||
From: Felix Fietkau <nbd@openwrt.org>
|
||||
Date: Wed, 22 Oct 2014 18:16:14 +0200
|
||||
Subject: [PATCH] ath9k_common: always update value in
|
||||
ath9k_cmn_update_txpow
|
||||
|
||||
In some cases the limit may be the same as reg->power_limit, but the
|
||||
actual value that the hardware uses is not up to date. In that case, a
|
||||
wrong value for current tx power is tracked internally.
|
||||
Fix this by unconditionally updating it.
|
||||
|
||||
Signed-off-by: Felix Fietkau <nbd@openwrt.org>
|
||||
---
|
||||
|
||||
--- a/drivers/net/wireless/ath/ath9k/common.c
|
||||
+++ b/drivers/net/wireless/ath/ath9k/common.c
|
||||
@@ -368,11 +368,11 @@ void ath9k_cmn_update_txpow(struct ath_h
|
||||
{
|
||||
struct ath_regulatory *reg = ath9k_hw_regulatory(ah);
|
||||
|
||||
- if (reg->power_limit != new_txpow) {
|
||||
+ if (reg->power_limit != new_txpow)
|
||||
ath9k_hw_set_txpowerlimit(ah, new_txpow, false);
|
||||
- /* read back in case value is clamped */
|
||||
- *txpower = reg->max_power_level;
|
||||
- }
|
||||
+
|
||||
+ /* read back in case value is clamped */
|
||||
+ *txpower = reg->max_power_level;
|
||||
}
|
||||
EXPORT_SYMBOL(ath9k_cmn_update_txpow);
|
||||
|
@ -0,0 +1,118 @@ |
||||
From: Felix Fietkau <nbd@openwrt.org>
|
||||
Date: Wed, 22 Oct 2014 18:18:04 +0200
|
||||
Subject: [PATCH] ath9k: add support for reporting tx power to mac80211
|
||||
|
||||
Track it per channel context instead of in the softc
|
||||
|
||||
Signed-off-by: Felix Fietkau <nbd@openwrt.org>
|
||||
---
|
||||
|
||||
--- a/drivers/net/wireless/ath/ath9k/ath9k.h
|
||||
+++ b/drivers/net/wireless/ath/ath9k/ath9k.h
|
||||
@@ -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;
|
||||
--- a/drivers/net/wireless/ath/ath9k/init.c
|
||||
+++ b/drivers/net/wireless/ath/ath9k/init.c
|
||||
@@ -172,17 +172,20 @@ static void ath9k_reg_notifier(struct wi
|
||||
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);
|
||||
}
|
||||
|
||||
/*
|
||||
--- a/drivers/net/wireless/ath/ath9k/main.c
|
||||
+++ b/drivers/net/wireless/ath/ath9k/main.c
|
||||
@@ -233,8 +233,9 @@ static bool ath_complete_reset(struct at
|
||||
|
||||
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) {
|
||||
@@ -1471,8 +1472,9 @@ static int ath9k_config(struct ieee80211
|
||||
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);
|
||||
@@ -2594,6 +2596,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,
|
||||
@@ -2640,4 +2660,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,
|
||||
};
|
@ -1,33 +0,0 @@ |
||||
--- a/include/net/mac80211.h
|
||||
+++ b/include/net/mac80211.h
|
||||
@@ -1754,6 +1754,7 @@ struct ieee80211_hw {
|
||||
u8 max_tx_aggregation_subframes;
|
||||
u8 offchannel_tx_hw_queue;
|
||||
u8 radiotap_mcs_details;
|
||||
+ s8 cur_power_level;
|
||||
u16 radiotap_vht_details;
|
||||
netdev_features_t netdev_features;
|
||||
u8 uapsd_queues;
|
||||
--- a/net/mac80211/cfg.c
|
||||
+++ b/net/mac80211/cfg.c
|
||||
@@ -2081,7 +2081,9 @@ static int ieee80211_get_tx_power(struct
|
||||
struct ieee80211_local *local = wiphy_priv(wiphy);
|
||||
struct ieee80211_sub_if_data *sdata = IEEE80211_WDEV_TO_SUB_IF(wdev);
|
||||
|
||||
- if (!local->use_chanctx)
|
||||
+ if (local->hw.cur_power_level)
|
||||
+ *dbm = local->hw.cur_power_level;
|
||||
+ else if (!local->use_chanctx)
|
||||
*dbm = local->hw.conf.power_level;
|
||||
else
|
||||
*dbm = sdata->vif.bss_conf.txpower;
|
||||
--- a/net/mac80211/main.c
|
||||
+++ b/net/mac80211/main.c
|
||||
@@ -157,6 +157,7 @@ static u32 ieee80211_hw_conf_chan(struct
|
||||
|
||||
if (local->hw.conf.power_level != power) {
|
||||
changed |= IEEE80211_CONF_CHANGE_POWER;
|
||||
+ local->hw.cur_power_level = power;
|
||||
local->hw.conf.power_level = power;
|
||||
}
|
||||
|
@ -1,24 +0,0 @@ |
||||
--- a/drivers/net/wireless/ath/ath9k/main.c
|
||||
+++ b/drivers/net/wireless/ath/ath9k/main.c
|
||||
@@ -326,8 +326,12 @@ static int ath_reset_internal(struct ath
|
||||
sc->cur_chan->offchannel)
|
||||
ath9k_mci_set_txpower(sc, true, false);
|
||||
|
||||
- if (!ath_complete_reset(sc, true))
|
||||
+ if (!ath_complete_reset(sc, true)) {
|
||||
r = -EIO;
|
||||
+ goto out;
|
||||
+ }
|
||||
+
|
||||
+ sc->hw->cur_power_level = sc->curtxpow / 2;
|
||||
|
||||
out:
|
||||
spin_unlock_bh(&sc->sc_pcu_lock);
|
||||
@@ -1473,6 +1477,7 @@ static int ath9k_config(struct ieee80211
|
||||
sc->cur_chan->txpower = 2 * conf->power_level;
|
||||
ath9k_cmn_update_txpow(ah, sc->curtxpow,
|
||||
sc->cur_chan->txpower, &sc->curtxpow);
|
||||
+ hw->cur_power_level = sc->curtxpow / 2;
|
||||
}
|
||||
|
||||
mutex_unlock(&sc->mutex);
|
Loading…
Reference in new issue