c9c68c7177
An external reset patch for AR955x accidentally led to external reset being issued twice on AR913x, once before the RTC reset and once after. This may be causing some stability issues. Signed-off-by: Felix Fietkau <nbd@nbd.name>
126 lines
3.1 KiB
Diff
126 lines
3.1 KiB
Diff
From: Felix Fietkau <nbd@nbd.name>
|
|
Date: Sat, 9 Jul 2016 15:26:44 +0200
|
|
Subject: [PATCH] ath9k_hw: issue external reset for QCA955x
|
|
|
|
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
|
|
@@ -1271,39 +1271,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;
|
|
}
|
|
|
|
@@ -1356,24 +1373,24 @@ 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);
|
|
}
|
|
|
|
+ if (!AR_SREV_9100(ah))
|
|
+ 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);
|