From: Felix Fietkau <nbd@openwrt.org>
Date: Wed, 22 Oct 2014 16:26:56 +0000 (+0000)
Subject: ath9k: fix tx power reporting
X-Git-Tag: reboot~5543
X-Git-Url: http://git.cdn.openwrt.org/?a=commitdiff_plain;h=d9ea3d2aa8bfdd6665ad9caa7a9296cadb73662d;p=openwrt%2Fstaging%2Fpepe2k.git

ath9k: fix tx power reporting

Signed-off-by: Felix Fietkau <nbd@openwrt.org>

SVN-Revision: 43032
---

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 <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
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 <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);
+ 
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 <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,
+ };
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