From: Sven Eckelmann <sven.eckelmann@open-mesh.com>
To: ath9k-devel@lists.ath9k.org
Cc: linux-wireless@vger.kernel.org, ath9k-devel@qca.qualcomm.com,
Simon Wunderlich <simon.wunderlich@open-mesh.com>,
Sven Eckelmann <sven.eckelmann@open-mesh.com>
Subject: [RFC v2 1/2] ath9k: work around AR_CFG 0xdeadbeef chip hang
Date: Thu, 17 Nov 2016 09:36:13 +0100 [thread overview]
Message-ID: <20161117083614.19188-1-sven.eckelmann@open-mesh.com> (raw)
From: Simon Wunderlich <simon.wunderlich@open-mesh.com>
QCA 802.11n chips (especially AR9330/AR9340) sometimes end up in a state in
which a read of AR_CFG always returns 0xdeadbeef. This should not happen
when when the power_mode of the device is ATH9K_PM_AWAKE.
This problem is not yet detected by any other workaround in ath9k. No way
is known to reproduce the problem easily.
Signed-off-by: Simon Wunderlich <simon.wunderlich@open-mesh.com>
[sven.eckelmann@open-mesh.com: port to recent ath9k, add commit message]
Signed-off-by: Sven Eckelmann <sven.eckelmann@open-mesh.com>
---
v2:
- reduce amount of possible goto-raptor attacks by one (thanks Kalle Valo)
This was discussed 4 years ago on the OpenWrt mailing list. The most
relevant post is
https://lists.openwrt.org/pipermail/openwrt-devel/2012-September/016708.html
---
drivers/net/wireless/ath/ath9k/ath9k.h | 3 +++
drivers/net/wireless/ath/ath9k/debug.c | 1 +
drivers/net/wireless/ath/ath9k/debug.h | 1 +
drivers/net/wireless/ath/ath9k/init.c | 1 +
drivers/net/wireless/ath/ath9k/link.c | 31 +++++++++++++++++++++++++++++++
drivers/net/wireless/ath/ath9k/main.c | 4 ++++
6 files changed, 41 insertions(+)
diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h
index 26fc8ec..9c6fee7 100644
--- a/drivers/net/wireless/ath/ath9k/ath9k.h
+++ b/drivers/net/wireless/ath/ath9k/ath9k.h
@@ -710,11 +710,13 @@ void ath9k_csa_update(struct ath_softc *sc);
#define ATH_ANI_MAX_SKIP_COUNT 10
#define ATH_PAPRD_TIMEOUT 100 /* msecs */
#define ATH_PLL_WORK_INTERVAL 100
+#define ATH_HANG_WORK_INTERVAL 30000
void ath_tx_complete_poll_work(struct work_struct *work);
void ath_reset_work(struct work_struct *work);
bool ath_hw_check(struct ath_softc *sc);
void ath_hw_pll_work(struct work_struct *work);
+void ath_hw_hang_work(struct work_struct *work);
void ath_paprd_calibrate(struct work_struct *work);
void ath_ani_calibrate(unsigned long data);
void ath_start_ani(struct ath_softc *sc);
@@ -1014,6 +1016,7 @@ struct ath_softc {
#endif
struct delayed_work tx_complete_work;
struct delayed_work hw_pll_work;
+ struct delayed_work hw_hang_work;
struct timer_list sleep_timer;
#ifdef CONFIG_ATH9K_BTCOEX_SUPPORT
diff --git a/drivers/net/wireless/ath/ath9k/debug.c b/drivers/net/wireless/ath/ath9k/debug.c
index c56e40f..608b370 100644
--- a/drivers/net/wireless/ath/ath9k/debug.c
+++ b/drivers/net/wireless/ath/ath9k/debug.c
@@ -767,6 +767,7 @@ static int read_file_reset(struct seq_file *file, void *data)
[RESET_TYPE_CALIBRATION] = "Calibration error",
[RESET_TX_DMA_ERROR] = "Tx DMA stop error",
[RESET_RX_DMA_ERROR] = "Rx DMA stop error",
+ [RESET_TYPE_DEADBEEF] = "deadbeef hang",
};
int i;
diff --git a/drivers/net/wireless/ath/ath9k/debug.h b/drivers/net/wireless/ath/ath9k/debug.h
index cd68c5f..0d77abbf6 100644
--- a/drivers/net/wireless/ath/ath9k/debug.h
+++ b/drivers/net/wireless/ath/ath9k/debug.h
@@ -52,6 +52,7 @@ enum ath_reset_type {
RESET_TYPE_CALIBRATION,
RESET_TX_DMA_ERROR,
RESET_RX_DMA_ERROR,
+ RESET_TYPE_DEADBEEF,
__RESET_TYPE_MAX
};
diff --git a/drivers/net/wireless/ath/ath9k/init.c b/drivers/net/wireless/ath/ath9k/init.c
index 368d9b3..9bc7d1c 100644
--- a/drivers/net/wireless/ath/ath9k/init.c
+++ b/drivers/net/wireless/ath/ath9k/init.c
@@ -638,6 +638,7 @@ static int ath9k_init_softc(u16 devid, struct ath_softc *sc,
INIT_WORK(&sc->hw_reset_work, ath_reset_work);
INIT_WORK(&sc->paprd_work, ath_paprd_calibrate);
INIT_DELAYED_WORK(&sc->hw_pll_work, ath_hw_pll_work);
+ INIT_DELAYED_WORK(&sc->hw_hang_work, ath_hw_hang_work);
ath9k_init_channel_context(sc);
diff --git a/drivers/net/wireless/ath/ath9k/link.c b/drivers/net/wireless/ath/ath9k/link.c
index 5ad0fee..04195d5 100644
--- a/drivers/net/wireless/ath/ath9k/link.c
+++ b/drivers/net/wireless/ath/ath9k/link.c
@@ -138,6 +138,37 @@ void ath_hw_pll_work(struct work_struct *work)
msecs_to_jiffies(ATH_PLL_WORK_INTERVAL));
}
+static bool ath_hw_hang_deadbeef(struct ath_softc *sc)
+{
+ struct ath_common *common = ath9k_hw_common(sc->sc_ah);
+ u32 reg;
+
+ /* check for stucked MAC */
+ ath9k_ps_wakeup(sc);
+ reg = REG_READ(sc->sc_ah, AR_CFG);
+ ath9k_ps_restore(sc);
+
+ if (reg != 0xdeadbeef)
+ return false;
+
+ ath_dbg(common, RESET,
+ "0xdeadbeef hang is detected. Schedule chip reset\n");
+ ath9k_queue_reset(sc, RESET_TYPE_DEADBEEF);
+
+ return true;
+}
+
+void ath_hw_hang_work(struct work_struct *work)
+{
+ struct ath_softc *sc = container_of(work, struct ath_softc,
+ hw_hang_work.work);
+
+ ath_hw_hang_deadbeef(sc);
+
+ ieee80211_queue_delayed_work(sc->hw, &sc->hw_hang_work,
+ msecs_to_jiffies(ATH_HANG_WORK_INTERVAL));
+}
+
/*
* PA Pre-distortion.
*/
diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c
index e9f32b5..4d3e216 100644
--- a/drivers/net/wireless/ath/ath9k/main.c
+++ b/drivers/net/wireless/ath/ath9k/main.c
@@ -183,6 +183,7 @@ static void __ath_cancel_work(struct ath_softc *sc)
cancel_work_sync(&sc->paprd_work);
cancel_delayed_work_sync(&sc->tx_complete_work);
cancel_delayed_work_sync(&sc->hw_pll_work);
+ cancel_delayed_work_sync(&sc->hw_hang_work);
#ifdef CONFIG_ATH9K_BTCOEX_SUPPORT
if (ath9k_hw_mci_is_enabled(sc->sc_ah))
@@ -204,6 +205,9 @@ void ath_restart_work(struct ath_softc *sc)
ieee80211_queue_delayed_work(sc->hw, &sc->hw_pll_work,
msecs_to_jiffies(ATH_PLL_WORK_INTERVAL));
+ ieee80211_queue_delayed_work(sc->hw, &sc->hw_hang_work,
+ msecs_to_jiffies(ATH_HANG_WORK_INTERVAL));
+
ath_start_ani(sc);
}
--
2.10.2
next reply other threads:[~2016-11-17 8:36 UTC|newest]
Thread overview: 5+ messages / expand[flat|nested] mbox.gz Atom feed top
2016-11-17 8:36 Sven Eckelmann [this message]
2016-11-17 8:36 ` [RFC v2 2/2] ath9k: Reset chip on potential deaf state Sven Eckelmann
2016-11-21 9:07 ` [ath9k-devel] " Ferry Huberts
2016-11-21 9:10 ` Sven Eckelmann
2016-11-21 9:15 ` Ferry Huberts
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20161117083614.19188-1-sven.eckelmann@open-mesh.com \
--to=sven.eckelmann@open-mesh.com \
--cc=ath9k-devel@lists.ath9k.org \
--cc=ath9k-devel@qca.qualcomm.com \
--cc=linux-wireless@vger.kernel.org \
--cc=simon.wunderlich@open-mesh.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).