From 1fc910862211b857e81c50adf890d26a4e90dbe2 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Wed, 22 Oct 2014 16:26:56 +0000 Subject: [PATCH] ath9k: fix tx power reporting Signed-off-by: Felix Fietkau git-svn-id: svn://svn.openwrt.org/openwrt/trunk@43032 3c298f89-4303-0410-b956-a3cf2f4a3e73 --- ...upport-for-driver-tx-power-reporting.patch | 43 +++++++ ...ays-update-value-in-ath9k_cmn_update.patch | 31 +++++ ...t-for-reporting-tx-power-to-mac80211.patch | 118 ++++++++++++++++++ .../410-ath9k_allow_adhoc_and_ap.patch | 2 +- .../mac80211/patches/501-ath9k_ahb_init.patch | 2 +- .../patches/520-mac80211_cur_txpower.patch | 33 ----- .../patches/521-ath9k_cur_txpower.patch | 24 ---- .../522-mac80211_configure_antenna_gain.patch | 8 +- .../patches/530-ath9k_extra_leds.patch | 6 +- .../patches/542-ath9k_debugfs_diag.patch | 2 +- .../patches/543-ath9k_entropy_from_adc.patch | 6 +- 11 files changed, 205 insertions(+), 70 deletions(-) create mode 100644 package/kernel/mac80211/patches/340-mac80211-add-support-for-driver-tx-power-reporting.patch create mode 100644 package/kernel/mac80211/patches/341-ath9k_common-always-update-value-in-ath9k_cmn_update.patch create mode 100644 package/kernel/mac80211/patches/342-ath9k-add-support-for-reporting-tx-power-to-mac80211.patch delete mode 100644 package/kernel/mac80211/patches/520-mac80211_cur_txpower.patch delete mode 100644 package/kernel/mac80211/patches/521-ath9k_cur_txpower.patch diff --git a/package/kernel/mac80211/patches/340-mac80211-add-support-for-driver-tx-power-reporting.patch b/package/kernel/mac80211/patches/340-mac80211-add-support-for-driver-tx-power-reporting.patch new file mode 100644 index 0000000000..6998584a59 --- /dev/null +++ b/package/kernel/mac80211/patches/340-mac80211-add-support-for-driver-tx-power-reporting.patch @@ -0,0 +1,43 @@ +From: Felix Fietkau +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 +--- + +--- 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 diff --git a/package/kernel/mac80211/patches/341-ath9k_common-always-update-value-in-ath9k_cmn_update.patch b/package/kernel/mac80211/patches/341-ath9k_common-always-update-value-in-ath9k_cmn_update.patch new file mode 100644 index 0000000000..625bd425b4 --- /dev/null +++ b/package/kernel/mac80211/patches/341-ath9k_common-always-update-value-in-ath9k_cmn_update.patch @@ -0,0 +1,31 @@ +From: Felix Fietkau +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 +--- + +--- 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); + diff --git a/package/kernel/mac80211/patches/342-ath9k-add-support-for-reporting-tx-power-to-mac80211.patch b/package/kernel/mac80211/patches/342-ath9k-add-support-for-reporting-tx-power-to-mac80211.patch new file mode 100644 index 0000000000..8bb41bd34a --- /dev/null +++ b/package/kernel/mac80211/patches/342-ath9k-add-support-for-reporting-tx-power-to-mac80211.patch @@ -0,0 +1,118 @@ +From: Felix Fietkau +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 +--- + +--- 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, + }; diff --git a/package/kernel/mac80211/patches/410-ath9k_allow_adhoc_and_ap.patch b/package/kernel/mac80211/patches/410-ath9k_allow_adhoc_and_ap.patch index ffd39b341f..ebcb34c381 100644 --- a/package/kernel/mac80211/patches/410-ath9k_allow_adhoc_and_ap.patch +++ b/package/kernel/mac80211/patches/410-ath9k_allow_adhoc_and_ap.patch @@ -1,6 +1,6 @@ --- a/drivers/net/wireless/ath/ath9k/init.c +++ b/drivers/net/wireless/ath/ath9k/init.c -@@ -677,6 +677,7 @@ static const struct ieee80211_iface_limi +@@ -680,6 +680,7 @@ static const struct ieee80211_iface_limi BIT(NL80211_IFTYPE_AP) }, { .max = 1, .types = BIT(NL80211_IFTYPE_P2P_CLIENT) | BIT(NL80211_IFTYPE_P2P_GO) }, diff --git a/package/kernel/mac80211/patches/501-ath9k_ahb_init.patch b/package/kernel/mac80211/patches/501-ath9k_ahb_init.patch index a32c4bbc0a..eaae68d40b 100644 --- a/package/kernel/mac80211/patches/501-ath9k_ahb_init.patch +++ b/package/kernel/mac80211/patches/501-ath9k_ahb_init.patch @@ -1,6 +1,6 @@ --- a/drivers/net/wireless/ath/ath9k/init.c +++ b/drivers/net/wireless/ath/ath9k/init.c -@@ -986,23 +986,23 @@ static int __init ath9k_init(void) +@@ -989,23 +989,23 @@ static int __init ath9k_init(void) { int error; diff --git a/package/kernel/mac80211/patches/520-mac80211_cur_txpower.patch b/package/kernel/mac80211/patches/520-mac80211_cur_txpower.patch deleted file mode 100644 index db1e89069e..0000000000 --- a/package/kernel/mac80211/patches/520-mac80211_cur_txpower.patch +++ /dev/null @@ -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; - } - diff --git a/package/kernel/mac80211/patches/521-ath9k_cur_txpower.patch b/package/kernel/mac80211/patches/521-ath9k_cur_txpower.patch deleted file mode 100644 index 638e774664..0000000000 --- a/package/kernel/mac80211/patches/521-ath9k_cur_txpower.patch +++ /dev/null @@ -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); diff --git a/package/kernel/mac80211/patches/522-mac80211_configure_antenna_gain.patch b/package/kernel/mac80211/patches/522-mac80211_configure_antenna_gain.patch index fc7432e835..ddf5ef624b 100644 --- a/package/kernel/mac80211/patches/522-mac80211_configure_antenna_gain.patch +++ b/package/kernel/mac80211/patches/522-mac80211_configure_antenna_gain.patch @@ -57,7 +57,7 @@ __NL80211_ATTR_AFTER_LAST, --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c -@@ -2091,6 +2091,19 @@ static int ieee80211_get_tx_power(struct +@@ -2092,6 +2092,19 @@ static int ieee80211_get_tx_power(struct return 0; } @@ -77,7 +77,7 @@ static int ieee80211_set_wds_peer(struct wiphy *wiphy, struct net_device *dev, const u8 *addr) { -@@ -3572,6 +3585,7 @@ const struct cfg80211_ops mac80211_confi +@@ -3573,6 +3586,7 @@ const struct cfg80211_ops mac80211_confi .set_wiphy_params = ieee80211_set_wiphy_params, .set_tx_power = ieee80211_set_tx_power, .get_tx_power = ieee80211_get_tx_power, @@ -118,8 +118,8 @@ + if (local->hw.conf.power_level != power) { changed |= IEEE80211_CONF_CHANGE_POWER; - local->hw.cur_power_level = power; -@@ -586,6 +592,7 @@ struct ieee80211_hw *ieee80211_alloc_hw( + local->hw.conf.power_level = power; +@@ -585,6 +591,7 @@ struct ieee80211_hw *ieee80211_alloc_hw( IEEE80211_RADIOTAP_MCS_HAVE_BW; local->hw.radiotap_vht_details = IEEE80211_RADIOTAP_VHT_KNOWN_GI | IEEE80211_RADIOTAP_VHT_KNOWN_BANDWIDTH; diff --git a/package/kernel/mac80211/patches/530-ath9k_extra_leds.patch b/package/kernel/mac80211/patches/530-ath9k_extra_leds.patch index d13a23b50d..b383fd3a9a 100644 --- a/package/kernel/mac80211/patches/530-ath9k_extra_leds.patch +++ b/package/kernel/mac80211/patches/530-ath9k_extra_leds.patch @@ -1,6 +1,6 @@ --- a/drivers/net/wireless/ath/ath9k/ath9k.h +++ b/drivers/net/wireless/ath/ath9k/ath9k.h -@@ -811,6 +811,9 @@ static inline int ath9k_dump_btcoex(stru +@@ -812,6 +812,9 @@ static inline int ath9k_dump_btcoex(stru void ath_init_leds(struct ath_softc *sc); void ath_deinit_leds(struct ath_softc *sc); void ath_fill_led_pin(struct ath_softc *sc); @@ -10,7 +10,7 @@ #else static inline void ath_init_leds(struct ath_softc *sc) { -@@ -951,6 +954,13 @@ void ath_ant_comb_scan(struct ath_softc +@@ -952,6 +955,13 @@ void ath_ant_comb_scan(struct ath_softc #define ATH9K_NUM_CHANCTX 2 /* supports 2 operating channels */ @@ -162,7 +162,7 @@ void ath_fill_led_pin(struct ath_softc *sc) --- a/drivers/net/wireless/ath/ath9k/init.c +++ b/drivers/net/wireless/ath/ath9k/init.c -@@ -899,7 +899,7 @@ int ath9k_init_device(u16 devid, struct +@@ -902,7 +902,7 @@ int ath9k_init_device(u16 devid, struct #ifdef CPTCFG_MAC80211_LEDS /* must be initialized before ieee80211_register_hw */ diff --git a/package/kernel/mac80211/patches/542-ath9k_debugfs_diag.patch b/package/kernel/mac80211/patches/542-ath9k_debugfs_diag.patch index 5b6aee632d..c8f9243d18 100644 --- a/package/kernel/mac80211/patches/542-ath9k_debugfs_diag.patch +++ b/package/kernel/mac80211/patches/542-ath9k_debugfs_diag.patch @@ -125,7 +125,7 @@ REG_SET_BIT(ah, AR_BTCOEX_WL_LNADIV, AR_BTCOEX_WL_LNADIV_FORCE_ON); --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c -@@ -535,6 +535,11 @@ irqreturn_t ath_isr(int irq, void *dev) +@@ -532,6 +532,11 @@ irqreturn_t ath_isr(int irq, void *dev) ath9k_debug_sync_cause(sc, sync_cause); status &= ah->imask; /* discard unasked-for bits */ diff --git a/package/kernel/mac80211/patches/543-ath9k_entropy_from_adc.patch b/package/kernel/mac80211/patches/543-ath9k_entropy_from_adc.patch index 18cc86c2e8..e536e1e9ed 100644 --- a/package/kernel/mac80211/patches/543-ath9k_entropy_from_adc.patch +++ b/package/kernel/mac80211/patches/543-ath9k_entropy_from_adc.patch @@ -55,7 +55,7 @@ ops->spectral_scan_config = ar9003_hw_spectral_scan_config; --- a/drivers/net/wireless/ath/ath9k/init.c +++ b/drivers/net/wireless/ath/ath9k/init.c -@@ -665,7 +665,8 @@ static void ath9k_init_txpower_limits(st +@@ -668,7 +668,8 @@ static void ath9k_init_txpower_limits(st if (ah->caps.hw_caps & ATH9K_HW_CAP_5GHZ) ath9k_init_band_txpower(sc, IEEE80211_BAND_5GHZ); @@ -65,7 +65,7 @@ } static const struct ieee80211_iface_limit if_limits[] = { -@@ -856,6 +857,18 @@ static void ath9k_set_hw_capab(struct at +@@ -859,6 +860,18 @@ static void ath9k_set_hw_capab(struct at SET_IEEE80211_PERM_ADDR(hw, common->macaddr); } @@ -84,7 +84,7 @@ int ath9k_init_device(u16 devid, struct ath_softc *sc, const struct ath_bus_ops *bus_ops) { -@@ -904,6 +917,8 @@ int ath9k_init_device(u16 devid, struct +@@ -907,6 +920,8 @@ int ath9k_init_device(u16 devid, struct ARRAY_SIZE(ath9k_tpt_blink)); #endif