openwrtv4/package/kernel/mac80211/patches/322-ath9k_hw-issue-external-reset-for-QCA9550.patch
Felix Fietkau 98e4b504b4 ath9k: use external reset on AR91xx and QCA955x to improve stability
Signed-off-by: Felix Fietkau <nbd@nbd.name>
2016-07-15 14:19:13 +02:00

125 lines
3 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 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);