diff --git a/patches/openwrt/0005-mac80211-ath9k-add-WAR-for-deaf-RX-state.patch b/patches/openwrt/0005-mac80211-ath9k-add-WAR-for-deaf-RX-state.patch new file mode 100644 index 00000000..c4c7639e --- /dev/null +++ b/patches/openwrt/0005-mac80211-ath9k-add-WAR-for-deaf-RX-state.patch @@ -0,0 +1,126 @@ +From: David Bauer +Date: Fri, 25 Jun 2021 21:19:02 +0200 +Subject: mac80211: ath9k: add WAR for deaf RX state + +Add a WAR dropped from OpenWrt tree with OpenWrt 18.06. It triggers a +chip reset when there is no RX activity for more than 15 seconds. + +Suggested-by: Jan-Tarek Butt +Signed-off-by: David Bauer + +diff --git a/package/kernel/mac80211/patches/ath/359-ath9k-check-for-deaf-rx-path-state.patch b/package/kernel/mac80211/patches/ath/359-ath9k-check-for-deaf-rx-path-state.patch +new file mode 100644 +index 0000000000000000000000000000000000000000..bb36f513530caebe5745def86c0b73467c82366e +--- /dev/null ++++ b/package/kernel/mac80211/patches/ath/359-ath9k-check-for-deaf-rx-path-state.patch +@@ -0,0 +1,110 @@ ++From: Felix Fietkau ++Date: Wed, 25 Jan 2017 13:00:58 +0100 ++Subject: [PATCH] ath9k: check for deaf rx path state ++ ++Various chips occasionally run into a state where the tx path still ++appears to be working normally, but the rx path is deaf. ++ ++There is no known register signature to check for this state explicitly, ++so use the lack of rx interrupts as an indicator. ++ ++This detection is prone to false positives, since a device could also ++simply be in an environment where there are no frames on the air. ++However, in this case doing a reset should be harmless since it's ++obviously not interrupting any real activity. To avoid confusion, call ++the reset counters in this case "Rx path inactive" instead of something ++like "Rx path deaf", since it may not be an indication of a real ++hardware failure. ++ ++Signed-off-by: Felix Fietkau ++[increase timeout for deaf RX state] ++Signed-off-by: David Bauer ++--- ++ ++--- a/drivers/net/wireless/ath/ath9k/ath9k.h +++++ b/drivers/net/wireless/ath/ath9k/ath9k.h ++@@ -111,6 +111,7 @@ int ath_descdma_setup(struct ath_softc * ++ #define ATH_HW_CHECK_POLL_INT 1000 ++ #define ATH_TXFIFO_DEPTH 8 ++ #define ATH_TX_ERROR 0x01 +++#define ATH_RX_STUCK_WAR_TIMEOUT 15000 ++ ++ #define ATH_AIRTIME_QUANTUM 300 /* usec */ ++ ++@@ -1029,6 +1030,7 @@ struct ath_softc { ++ ++ u8 gtt_cnt; ++ u32 intrstatus; +++ u32 rx_active; ++ u16 ps_flags; /* PS_* */ ++ bool ps_enabled; ++ bool ps_idle; ++--- a/drivers/net/wireless/ath/ath9k/debug.c +++++ b/drivers/net/wireless/ath/ath9k/debug.c ++@@ -763,6 +763,7 @@ static int read_file_reset(struct seq_fi ++ [RESET_TYPE_BEACON_STUCK] = "Stuck Beacon", ++ [RESET_TYPE_MCI] = "MCI Reset", ++ [RESET_TYPE_CALIBRATION] = "Calibration error", +++ [RESET_TYPE_RX_INACTIVE] = "Rx path inactive", ++ [RESET_TX_DMA_ERROR] = "Tx DMA stop error", ++ [RESET_RX_DMA_ERROR] = "Rx DMA stop error", ++ }; ++--- a/drivers/net/wireless/ath/ath9k/debug.h +++++ b/drivers/net/wireless/ath/ath9k/debug.h ++@@ -50,6 +50,7 @@ enum ath_reset_type { ++ RESET_TYPE_BEACON_STUCK, ++ RESET_TYPE_MCI, ++ RESET_TYPE_CALIBRATION, +++ RESET_TYPE_RX_INACTIVE, ++ RESET_TX_DMA_ERROR, ++ RESET_RX_DMA_ERROR, ++ __RESET_TYPE_MAX ++--- a/drivers/net/wireless/ath/ath9k/link.c +++++ b/drivers/net/wireless/ath/ath9k/link.c ++@@ -53,13 +53,27 @@ reset: ++ ++ } ++ +++static bool ath_rx_active_check(struct ath_softc *sc) +++{ +++ if (sc->rx_active) { +++ sc->rx_active--; +++ return true; +++ } +++ +++ ath_err(ath9k_hw_common(sc->sc_ah), +++ "rx path inactive, resetting the chip\n"); +++ ath9k_queue_reset(sc, RESET_TYPE_RX_INACTIVE); +++ return false; +++} +++ ++ void ath_hw_check_work(struct work_struct *work) ++ { ++ struct ath_softc *sc = container_of(work, struct ath_softc, ++ hw_check_work.work); ++ ++ if (!ath_hw_check(sc) || ++- !ath_tx_complete_check(sc)) +++ !ath_tx_complete_check(sc) || +++ !ath_rx_active_check(sc)) ++ return; ++ ++ ieee80211_queue_delayed_work(sc->hw, &sc->hw_check_work, ++--- a/drivers/net/wireless/ath/ath9k/main.c +++++ b/drivers/net/wireless/ath/ath9k/main.c ++@@ -270,6 +270,7 @@ static bool ath_complete_reset(struct at ++ } ++ ++ sc->gtt_cnt = 0; +++ sc->rx_active = ATH_RX_STUCK_WAR_TIMEOUT; ++ ++ ath9k_hw_set_interrupts(ah); ++ ath9k_hw_enable_interrupts(ah); ++@@ -446,6 +447,7 @@ void ath9k_tasklet(unsigned long data) ++ ath_rx_tasklet(sc, 0, true); ++ ++ ath_rx_tasklet(sc, 0, false); +++ sc->rx_active = ATH_RX_STUCK_WAR_TIMEOUT; ++ } ++ ++ if (status & ATH9K_INT_TX) {