mirror of
				git://git.openwrt.org/openwrt/openwrt.git
				synced 2025-11-03 14:34:27 -05:00 
			
		
		
		
	ath9k: use external reset on AR91xx and QCA955x to improve stability
Signed-off-by: Felix Fietkau <nbd@nbd.name>
This commit is contained in:
		
							parent
							
								
									a176168a85
								
							
						
					
					
						commit
						98e4b504b4
					
				@ -0,0 +1,25 @@
 | 
			
		||||
From: Felix Fietkau <nbd@nbd.name>
 | 
			
		||||
Date: Sat, 9 Jul 2016 15:25:24 +0200
 | 
			
		||||
Subject: [PATCH] ath9k_hw: reset AHB-WMAC interface on AR91xx
 | 
			
		||||
 | 
			
		||||
Should fix a few stability issues
 | 
			
		||||
 | 
			
		||||
Signed-off-by: Felix Fietkau <nbd@nbd.name>
 | 
			
		||||
---
 | 
			
		||||
 | 
			
		||||
--- a/drivers/net/wireless/ath/ath9k/hw.c
 | 
			
		||||
+++ b/drivers/net/wireless/ath/ath9k/hw.c
 | 
			
		||||
@@ -1398,8 +1398,12 @@ static bool ath9k_hw_set_reset(struct at
 | 
			
		||||
 	if (!AR_SREV_9100(ah))
 | 
			
		||||
 		REG_WRITE(ah, AR_RC, 0);
 | 
			
		||||
 
 | 
			
		||||
-	if (AR_SREV_9100(ah))
 | 
			
		||||
+	if (AR_SREV_9100(ah)) {
 | 
			
		||||
+		/* Reset the AHB-WMAC interface */
 | 
			
		||||
+		if (ah->external_reset)
 | 
			
		||||
+			ah->external_reset();
 | 
			
		||||
 		udelay(50);
 | 
			
		||||
+	}
 | 
			
		||||
 
 | 
			
		||||
 	return true;
 | 
			
		||||
 }
 | 
			
		||||
@ -0,0 +1,125 @@
 | 
			
		||||
From: Felix Fietkau <nbd@nbd.name>
 | 
			
		||||
Date: Sat, 9 Jul 2016 15:26:44 +0200
 | 
			
		||||
Subject: [PATCH] ath9k_hw: issue external reset for QCA9550
 | 
			
		||||
 | 
			
		||||
The RTC interface on the SoC needs to be reset along with the rest of
 | 
			
		||||
the WMAC.
 | 
			
		||||
 | 
			
		||||
Signed-off-by: Felix Fietkau <nbd@nbd.name>
 | 
			
		||||
---
 | 
			
		||||
 | 
			
		||||
--- a/drivers/net/wireless/ath/ath9k/hw.c
 | 
			
		||||
+++ b/drivers/net/wireless/ath/ath9k/hw.c
 | 
			
		||||
@@ -1275,39 +1275,56 @@ void ath9k_hw_get_delta_slope_vals(struc
 | 
			
		||||
 	*coef_exponent = coef_exp - 16;
 | 
			
		||||
 }
 | 
			
		||||
 
 | 
			
		||||
-/* AR9330 WAR:
 | 
			
		||||
- * call external reset function to reset WMAC if:
 | 
			
		||||
- * - doing a cold reset
 | 
			
		||||
- * - we have pending frames in the TX queues.
 | 
			
		||||
- */
 | 
			
		||||
-static bool ath9k_hw_ar9330_reset_war(struct ath_hw *ah, int type)
 | 
			
		||||
+static bool ath9k_hw_need_external_reset(struct ath_hw *ah, int type)
 | 
			
		||||
 {
 | 
			
		||||
-	int i, npend = 0;
 | 
			
		||||
+	int i;
 | 
			
		||||
 
 | 
			
		||||
-	for (i = 0; i < AR_NUM_QCU; i++) {
 | 
			
		||||
-		npend = ath9k_hw_numtxpending(ah, i);
 | 
			
		||||
-		if (npend)
 | 
			
		||||
-			break;
 | 
			
		||||
+	if (type == ATH9K_RESET_COLD)
 | 
			
		||||
+		return true;
 | 
			
		||||
+
 | 
			
		||||
+	if (AR_SREV_9550(ah))
 | 
			
		||||
+		return true;
 | 
			
		||||
+
 | 
			
		||||
+	/* AR9330 WAR:
 | 
			
		||||
+	 * call external reset function to reset WMAC if:
 | 
			
		||||
+	 * - doing a cold reset
 | 
			
		||||
+	 * - we have pending frames in the TX queues.
 | 
			
		||||
+	 */
 | 
			
		||||
+	if (AR_SREV_9330(ah)) {
 | 
			
		||||
+		for (i = 0; i < AR_NUM_QCU; i++) {
 | 
			
		||||
+			if (ath9k_hw_numtxpending(ah, i))
 | 
			
		||||
+				return true;
 | 
			
		||||
+		}
 | 
			
		||||
 	}
 | 
			
		||||
 
 | 
			
		||||
-	if (ah->external_reset &&
 | 
			
		||||
-	    (npend || type == ATH9K_RESET_COLD)) {
 | 
			
		||||
-		int reset_err = 0;
 | 
			
		||||
+	return false;
 | 
			
		||||
+}
 | 
			
		||||
 
 | 
			
		||||
-		ath_dbg(ath9k_hw_common(ah), RESET,
 | 
			
		||||
-			"reset MAC via external reset\n");
 | 
			
		||||
+static bool ath9k_hw_external_reset(struct ath_hw *ah, int type)
 | 
			
		||||
+{
 | 
			
		||||
+	int err;
 | 
			
		||||
 
 | 
			
		||||
-		reset_err = ah->external_reset();
 | 
			
		||||
-		if (reset_err) {
 | 
			
		||||
-			ath_err(ath9k_hw_common(ah),
 | 
			
		||||
-				"External reset failed, err=%d\n",
 | 
			
		||||
-				reset_err);
 | 
			
		||||
-			return false;
 | 
			
		||||
-		}
 | 
			
		||||
+	if (!ah->external_reset || !ath9k_hw_need_external_reset(ah, type))
 | 
			
		||||
+		return true;
 | 
			
		||||
 
 | 
			
		||||
-		REG_WRITE(ah, AR_RTC_RESET, 1);
 | 
			
		||||
+	ath_dbg(ath9k_hw_common(ah), RESET,
 | 
			
		||||
+		"reset MAC via external reset\n");
 | 
			
		||||
+
 | 
			
		||||
+	err = ah->external_reset();
 | 
			
		||||
+	if (err) {
 | 
			
		||||
+		ath_err(ath9k_hw_common(ah),
 | 
			
		||||
+			"External reset failed, err=%d\n", err);
 | 
			
		||||
+		return false;
 | 
			
		||||
+	}
 | 
			
		||||
+
 | 
			
		||||
+	if (AR_SREV_9550(ah)) {
 | 
			
		||||
+		REG_WRITE(ah, AR_RTC_RESET, 0);
 | 
			
		||||
+		udelay(10);
 | 
			
		||||
 	}
 | 
			
		||||
 
 | 
			
		||||
+	REG_WRITE(ah, AR_RTC_RESET, 1);
 | 
			
		||||
+	udelay(10);
 | 
			
		||||
+
 | 
			
		||||
 	return true;
 | 
			
		||||
 }
 | 
			
		||||
 
 | 
			
		||||
@@ -1360,24 +1377,23 @@ static bool ath9k_hw_set_reset(struct at
 | 
			
		||||
 			rst_flags |= AR_RTC_RC_MAC_COLD;
 | 
			
		||||
 	}
 | 
			
		||||
 
 | 
			
		||||
-	if (AR_SREV_9330(ah)) {
 | 
			
		||||
-		if (!ath9k_hw_ar9330_reset_war(ah, type))
 | 
			
		||||
-			return false;
 | 
			
		||||
-	}
 | 
			
		||||
-
 | 
			
		||||
 	if (ath9k_hw_mci_is_enabled(ah))
 | 
			
		||||
 		ar9003_mci_check_gpm_offset(ah);
 | 
			
		||||
 
 | 
			
		||||
 	/* DMA HALT added to resolve ar9300 and ar9580 bus error during
 | 
			
		||||
-	 * RTC_RC reg read
 | 
			
		||||
+	 * RTC_RC reg read. Also needed for AR9550 external reset
 | 
			
		||||
 	 */
 | 
			
		||||
-	if (AR_SREV_9300(ah) || AR_SREV_9580(ah)) {
 | 
			
		||||
+	if (AR_SREV_9300(ah) || AR_SREV_9580(ah) || AR_SREV_9550(ah)) {
 | 
			
		||||
 		REG_SET_BIT(ah, AR_CFG, AR_CFG_HALT_REQ);
 | 
			
		||||
 		ath9k_hw_wait(ah, AR_CFG, AR_CFG_HALT_ACK, AR_CFG_HALT_ACK,
 | 
			
		||||
 			      20 * AH_WAIT_TIMEOUT);
 | 
			
		||||
-		REG_CLR_BIT(ah, AR_CFG, AR_CFG_HALT_REQ);
 | 
			
		||||
 	}
 | 
			
		||||
 
 | 
			
		||||
+	ath9k_hw_external_reset(ah, type);
 | 
			
		||||
+
 | 
			
		||||
+	if (AR_SREV_9300(ah) || AR_SREV_9580(ah))
 | 
			
		||||
+		REG_CLR_BIT(ah, AR_CFG, AR_CFG_HALT_REQ);
 | 
			
		||||
+
 | 
			
		||||
 	REG_WRITE(ah, AR_RTC_RC, rst_flags);
 | 
			
		||||
 
 | 
			
		||||
 	REGWRITE_BUFFER_FLUSH(ah);
 | 
			
		||||
@ -94,7 +94,7 @@
 | 
			
		||||
 struct ath_gen_timer *ath_gen_timer_alloc(struct ath_hw *ah,
 | 
			
		||||
--- a/drivers/net/wireless/ath/ath9k/hw.c
 | 
			
		||||
+++ b/drivers/net/wireless/ath/ath9k/hw.c
 | 
			
		||||
@@ -1821,6 +1821,20 @@ u32 ath9k_hw_get_tsf_offset(struct times
 | 
			
		||||
@@ -1841,6 +1841,20 @@ u32 ath9k_hw_get_tsf_offset(struct times
 | 
			
		||||
 }
 | 
			
		||||
 EXPORT_SYMBOL(ath9k_hw_get_tsf_offset);
 | 
			
		||||
 
 | 
			
		||||
@ -115,7 +115,7 @@
 | 
			
		||||
 int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,
 | 
			
		||||
 		   struct ath9k_hw_cal_data *caldata, bool fastcc)
 | 
			
		||||
 {
 | 
			
		||||
@@ -2029,6 +2043,7 @@ int ath9k_hw_reset(struct ath_hw *ah, st
 | 
			
		||||
@@ -2049,6 +2063,7 @@ int ath9k_hw_reset(struct ath_hw *ah, st
 | 
			
		||||
 		ar9003_hw_disable_phy_restart(ah);
 | 
			
		||||
 
 | 
			
		||||
 	ath9k_hw_apply_gpio_override(ah);
 | 
			
		||||
 | 
			
		||||
@ -20,9 +20,9 @@
 | 
			
		||||
 /******************/
 | 
			
		||||
 /* Chip Revisions */
 | 
			
		||||
 /******************/
 | 
			
		||||
@@ -1397,6 +1410,9 @@ static bool ath9k_hw_set_reset(struct at
 | 
			
		||||
 	if (AR_SREV_9100(ah))
 | 
			
		||||
@@ -1417,6 +1430,9 @@ static bool ath9k_hw_set_reset(struct at
 | 
			
		||||
 		udelay(50);
 | 
			
		||||
 	}
 | 
			
		||||
 
 | 
			
		||||
+	if (AR_SREV_9330(ah) || AR_SREV_9340(ah))
 | 
			
		||||
+		ath9k_hw_disable_pll_lock_detect(ah);
 | 
			
		||||
@ -30,7 +30,7 @@
 | 
			
		||||
 	return true;
 | 
			
		||||
 }
 | 
			
		||||
 
 | 
			
		||||
@@ -1496,6 +1512,9 @@ static bool ath9k_hw_chip_reset(struct a
 | 
			
		||||
@@ -1516,6 +1532,9 @@ static bool ath9k_hw_chip_reset(struct a
 | 
			
		||||
 		ar9003_hw_internal_regulator_apply(ah);
 | 
			
		||||
 	ath9k_hw_init_pll(ah, chan);
 | 
			
		||||
 
 | 
			
		||||
@ -40,7 +40,7 @@
 | 
			
		||||
 	return true;
 | 
			
		||||
 }
 | 
			
		||||
 
 | 
			
		||||
@@ -1799,8 +1818,14 @@ static int ath9k_hw_do_fastcc(struct ath
 | 
			
		||||
@@ -1819,8 +1838,14 @@ static int ath9k_hw_do_fastcc(struct ath
 | 
			
		||||
 	if (AR_SREV_9271(ah))
 | 
			
		||||
 		ar9002_hw_load_ani_reg(ah, chan);
 | 
			
		||||
 
 | 
			
		||||
@ -55,7 +55,7 @@
 | 
			
		||||
 	return -EINVAL;
 | 
			
		||||
 }
 | 
			
		||||
 
 | 
			
		||||
@@ -2054,6 +2079,9 @@ int ath9k_hw_reset(struct ath_hw *ah, st
 | 
			
		||||
@@ -2074,6 +2099,9 @@ int ath9k_hw_reset(struct ath_hw *ah, st
 | 
			
		||||
 		ath9k_hw_set_radar_params(ah);
 | 
			
		||||
 	}
 | 
			
		||||
 
 | 
			
		||||
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user