From 522bba5e421e47323975876faa0fee091ed8eb0b Mon Sep 17 00:00:00 2001
From: Felix Fietkau <nbd@openwrt.org>
Date: Sun, 7 Feb 2016 13:29:08 +0000
Subject: [PATCH] ath9k: merge fix for noise floor calibration

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

SVN-Revision: 48641
---
 ...F-load-complete-quickly-and-reliably.patch | 87 +++++++++++++++++++
 .../522-mac80211_configure_antenna_gain.patch |  6 +-
 .../patches/530-ath9k_extra_leds.patch        |  6 +-
 3 files changed, 93 insertions(+), 6 deletions(-)
 create mode 100644 package/kernel/mac80211/patches/326-ath9k-make-NF-load-complete-quickly-and-reliably.patch

diff --git a/package/kernel/mac80211/patches/326-ath9k-make-NF-load-complete-quickly-and-reliably.patch b/package/kernel/mac80211/patches/326-ath9k-make-NF-load-complete-quickly-and-reliably.patch
new file mode 100644
index 0000000000..71f7a40433
--- /dev/null
+++ b/package/kernel/mac80211/patches/326-ath9k-make-NF-load-complete-quickly-and-reliably.patch
@@ -0,0 +1,87 @@
+From: Miaoqing Pan <miaoqing@codeaurora.org>
+Date: Fri, 5 Feb 2016 09:45:50 +0800
+Subject: [PATCH] ath9k: make NF load complete quickly and reliably
+
+Make NF load complete quickly and reliably. NF load execution
+is delayed by HW to end of frame if frame Rx or Tx is ongoing.
+Increasing timeout to max frame duration. If NF cal is ongoing
+before NF load, stop it before load, and restart it afterwards.
+
+Signed-off-by: Miaoqing Pan <miaoqing@codeaurora.org>
+---
+
+--- a/drivers/net/wireless/ath/ath9k/calib.c
++++ b/drivers/net/wireless/ath/ath9k/calib.c
+@@ -241,6 +241,7 @@ int ath9k_hw_loadnf(struct ath_hw *ah, s
+ 	u8 chainmask = (ah->rxchainmask << 3) | ah->rxchainmask;
+ 	struct ath_common *common = ath9k_hw_common(ah);
+ 	s16 default_nf = ath9k_hw_get_default_nf(ah, chan);
++	u32 bb_agc_ctl = REG_READ(ah, AR_PHY_AGC_CONTROL);
+ 
+ 	if (ah->caldata)
+ 		h = ah->caldata->nfCalHist;
+@@ -264,6 +265,16 @@ int ath9k_hw_loadnf(struct ath_hw *ah, s
+ 	}
+ 
+ 	/*
++	 * stop NF cal if ongoing to ensure NF load completes immediately
++	 * (or after end rx/tx frame if ongoing)
++	 */
++	if (bb_agc_ctl & AR_PHY_AGC_CONTROL_NF) {
++		REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_NF);
++		REG_RMW_BUFFER_FLUSH(ah);
++		ENABLE_REG_RMW_BUFFER(ah);
++	}
++
++	/*
+ 	 * Load software filtered NF value into baseband internal minCCApwr
+ 	 * variable.
+ 	 */
+@@ -276,18 +287,33 @@ int ath9k_hw_loadnf(struct ath_hw *ah, s
+ 
+ 	/*
+ 	 * Wait for load to complete, should be fast, a few 10s of us.
+-	 * The max delay was changed from an original 250us to 10000us
+-	 * since 250us often results in NF load timeout and causes deaf
+-	 * condition during stress testing 12/12/2009
++	 * The max delay was changed from an original 250us to 22.2 msec.
++	 * This would increase timeout to the longest possible frame
++	 * (11n max length 22.1 msec)
+ 	 */
+-	for (j = 0; j < 10000; j++) {
++	for (j = 0; j < 22200; j++) {
+ 		if ((REG_READ(ah, AR_PHY_AGC_CONTROL) &
+-		     AR_PHY_AGC_CONTROL_NF) == 0)
++			      AR_PHY_AGC_CONTROL_NF) == 0)
+ 			break;
+ 		udelay(10);
+ 	}
+ 
+ 	/*
++	 * Restart NF so it can continue.
++	 */
++	if (bb_agc_ctl & AR_PHY_AGC_CONTROL_NF) {
++		ENABLE_REG_RMW_BUFFER(ah);
++		if (bb_agc_ctl & AR_PHY_AGC_CONTROL_ENABLE_NF)
++			REG_SET_BIT(ah, AR_PHY_AGC_CONTROL,
++				    AR_PHY_AGC_CONTROL_ENABLE_NF);
++		if (bb_agc_ctl & AR_PHY_AGC_CONTROL_NO_UPDATE_NF)
++			REG_SET_BIT(ah, AR_PHY_AGC_CONTROL,
++				    AR_PHY_AGC_CONTROL_NO_UPDATE_NF);
++		REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_NF);
++		REG_RMW_BUFFER_FLUSH(ah);
++	}
++
++	/*
+ 	 * We timed out waiting for the noisefloor to load, probably due to an
+ 	 * in-progress rx. Simply return here and allow the load plenty of time
+ 	 * to complete before the next calibration interval.  We need to avoid
+@@ -296,7 +322,7 @@ int ath9k_hw_loadnf(struct ath_hw *ah, s
+ 	 * here, the baseband nf cal will just be capped by our present
+ 	 * noisefloor until the next calibration timer.
+ 	 */
+-	if (j == 10000) {
++	if (j == 22200) {
+ 		ath_dbg(common, ANY,
+ 			"Timeout while waiting for nf to load: AR_PHY_AGC_CONTROL=0x%x\n",
+ 			REG_READ(ah, AR_PHY_AGC_CONTROL));
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 ef9258b418..e151a12967 100644
--- a/package/kernel/mac80211/patches/522-mac80211_configure_antenna_gain.patch
+++ b/package/kernel/mac80211/patches/522-mac80211_configure_antenna_gain.patch
@@ -18,7 +18,7 @@
  				const u8 *addr);
 --- a/include/net/mac80211.h
 +++ b/include/net/mac80211.h
-@@ -1282,6 +1282,7 @@ enum ieee80211_smps_mode {
+@@ -1286,6 +1286,7 @@ enum ieee80211_smps_mode {
   *
   * @power_level: requested transmit power (in dBm), backward compatibility
   *	value only that is set to the minimum of all interfaces
@@ -26,7 +26,7 @@
   *
   * @chandef: the channel definition to tune to
   * @radar_enabled: whether radar detection is enabled
-@@ -1302,6 +1303,7 @@ enum ieee80211_smps_mode {
+@@ -1306,6 +1307,7 @@ enum ieee80211_smps_mode {
  struct ieee80211_conf {
  	u32 flags;
  	int power_level, dynamic_ps_timeout;
@@ -87,7 +87,7 @@
  	CFG80211_TESTMODE_CMD(ieee80211_testmode_cmd)
 --- a/net/mac80211/ieee80211_i.h
 +++ b/net/mac80211/ieee80211_i.h
-@@ -1317,6 +1317,7 @@ struct ieee80211_local {
+@@ -1318,6 +1318,7 @@ struct ieee80211_local {
  	int dynamic_ps_forced_timeout;
  
  	int user_power_level; /* in dBm, for all interfaces */
diff --git a/package/kernel/mac80211/patches/530-ath9k_extra_leds.patch b/package/kernel/mac80211/patches/530-ath9k_extra_leds.patch
index 50ddd0b9d9..5a5e4643f5 100644
--- a/package/kernel/mac80211/patches/530-ath9k_extra_leds.patch
+++ b/package/kernel/mac80211/patches/530-ath9k_extra_leds.patch
@@ -54,7 +54,8 @@
 +			  (brightness != LED_OFF) ^ led->gpio->active_low);
 +	ath9k_ps_restore(sc);
 +}
-+
+ 
+-	ath9k_hw_set_gpio(sc->sc_ah, sc->sc_ah->led_pin, val);
 +static int ath_add_led(struct ath_softc *sc, struct ath_led *led)
 +{
 +	const struct gpio_led *gpio = led->gpio;
@@ -63,8 +64,7 @@
 +	led->cdev.name = gpio->name;
 +	led->cdev.default_trigger = gpio->default_trigger;
 +	led->cdev.brightness_set = ath_led_brightness;
- 
--	ath9k_hw_set_gpio(sc->sc_ah, sc->sc_ah->led_pin, val);
++
 +	ret = led_classdev_register(wiphy_dev(sc->hw->wiphy), &led->cdev);
 +	if (ret < 0)
 +		return ret;
-- 
2.25.1