[OpenWrt-Devel] [PATCH 2/2] ath5k: fix reset race

Sergey Ryazanov ryazanov.s.a at gmail.com
Tue Mar 3 21:47:02 EST 2015


Signed-off-by: Sergey Ryazanov <ryazanov.s.a at gmail.com>
---
 .../patches/332-ath5k-fix-reset-race.patch         | 104 +++++++++++++++++++++
 1 file changed, 104 insertions(+)
 create mode 100644 package/kernel/mac80211/patches/332-ath5k-fix-reset-race.patch

diff --git a/package/kernel/mac80211/patches/332-ath5k-fix-reset-race.patch b/package/kernel/mac80211/patches/332-ath5k-fix-reset-race.patch
new file mode 100644
index 0000000..4a3abaa
--- /dev/null
+++ b/package/kernel/mac80211/patches/332-ath5k-fix-reset-race.patch
@@ -0,0 +1,104 @@
+From d8d4050dff457b79ad7e9356103cad557c338532 Mon Sep 17 00:00:00 2001
+From: Sergey Ryazanov <ryazanov.s.a at gmail.com>
+Date: Wed, 4 Mar 2015 03:16:34 +0300
+Subject: [PATCH] ath5k: fix reset race
+
+To prepare for reset ath5k should finish all asynchronous tasks. At
+first, it disables the interrupt generation, then it waits for the
+interrupt handler and tasklets completion, and then proceeds to the HW
+configuration update. But it does not consider that the interrupt
+handler or tasklet re-enables the interrupt generation. And we fall in a
+situation when ath5k assumes that interrupts are disabled, but it is
+not.
+
+This can lead to different consequences, such as reception of the frame,
+when we do not expect it. Under certain circumstances, this can lead to
+the following warning:
+
+  WARNING: at ath5k/base.c:589 ath5k_tasklet_rx+0x318/0x6ec [ath5k]()
+  invalid hw_rix: 1a
+  [..]
+  Call Trace:
+  [<802656a8>] show_stack+0x48/0x70
+  [<802dd92c>] warn_slowpath_common+0x88/0xbc
+  [<802dd98c>] warn_slowpath_fmt+0x2c/0x38
+  [<81b51be8>] ath5k_tasklet_rx+0x318/0x6ec [ath5k]
+  [<8028ac64>] tasklet_action+0x8c/0xf0
+  [<80075804>] __do_softirq+0x180/0x32c
+  [<80196ce8>] irq_exit+0x54/0x70
+  [<80041848>] ret_from_irq+0x0/0x4
+  [<80182fdc>] ioread32+0x4/0xc
+  [<81b4c42c>] ath5k_hw_set_sleep_clock+0x2ec/0x474 [ath5k]
+  [<81b4cf28>] ath5k_hw_reset+0x50/0xeb8 [ath5k]
+  [<81b50900>] ath5k_reset+0xd4/0x310 [ath5k]
+  [<81b557e8>] ath5k_config+0x4c/0x104 [ath5k]
+  [<80d01770>] ieee80211_hw_config+0x2f4/0x35c [mac80211]
+  [<80d09aa8>] ieee80211_scan_work+0x2e4/0x414 [mac80211]
+  [<8022c3f4>] process_one_work+0x28c/0x400
+  [<802df8f8>] worker_thread+0x258/0x3c0
+  [<801b5710>] kthread+0xe0/0xec
+  [<800418a8>] ret_from_kernel_thread+0x14/0x1c
+
+Fix this issue by adding a new status flag, which forbids to re-enable
+the interrupt generation until the HW configuration is completed.
+
+Note: previous patch, which reorders the Rx disable code helps to avoid
+the above warning, but not fixes the root cause of unexpected frame
+receiving.
+
+CC: Jiri Slaby <jirislaby at gmail.com>
+CC: Nick Kossifidis <mickflemm at gmail.com>
+CC: Luis R. Rodriguez <mcgrof at do-not-panic.com>
+Reported-by: Christophe Prevotaux <cprevotaux at nltinc.com>
+Tested-by: Christophe Prevotaux <cprevotaux at nltinc.com>
+Tested-by: Eric Bree <ebree at nltinc.com>
+Signed-off-by: Sergey Ryazanov <ryazanov.s.a at gmail.com>
+---
+ drivers/net/wireless/ath/ath5k/ath5k.h | 1 +
+ drivers/net/wireless/ath/ath5k/base.c  | 7 +++++++
+ 2 files changed, 8 insertions(+)
+
+diff --git a/drivers/net/wireless/ath/ath5k/ath5k.h b/drivers/net/wireless/ath/ath5k/ath5k.h
+index 1ed7a88..7ca0d6f 100644
+--- a/drivers/net/wireless/ath/ath5k/ath5k.h
++++ b/drivers/net/wireless/ath/ath5k/ath5k.h
+@@ -1283,6 +1283,7 @@ struct ath5k_hw {
+ #define ATH_STAT_PROMISC	1
+ #define ATH_STAT_LEDSOFT	2		/* enable LED gpio status */
+ #define ATH_STAT_STARTED	3		/* opened & irqs enabled */
++#define ATH_STAT_RESET		4		/* hw reset */
+ 
+ 	unsigned int		filter_flags;	/* HW flags, AR5K_RX_FILTER_* */
+ 	unsigned int		fif_filter_flags; /* Current FIF_* filter flags */
+diff --git a/drivers/net/wireless/ath/ath5k/base.c b/drivers/net/wireless/ath/ath5k/base.c
+index 34b2f15..41848e1 100644
+--- a/drivers/net/wireless/ath/ath5k/base.c
++++ b/drivers/net/wireless/ath/ath5k/base.c
+@@ -1523,6 +1523,9 @@ ath5k_set_current_imask(struct ath5k_hw *ah)
+ 	enum ath5k_int imask;
+ 	unsigned long flags;
+ 
++	if (test_bit(ATH_STAT_RESET, ah->status))
++		return;
++
+ 	spin_lock_irqsave(&ah->irqlock, flags);
+ 	imask = ah->imask;
+ 	if (ah->rx_pending)
+@@ -2862,6 +2865,8 @@ ath5k_reset(struct ath5k_hw *ah, struct ieee80211_channel *chan,
+ 
+ 	ATH5K_DBG(ah, ATH5K_DEBUG_RESET, "resetting\n");
+ 
++	__set_bit(ATH_STAT_RESET, ah->status);
++
+ 	ath5k_hw_set_imr(ah, 0);
+ 	synchronize_irq(ah->irq);
+ 	ath5k_stop_tasklets(ah);
+@@ -2952,6 +2957,8 @@ ath5k_reset(struct ath5k_hw *ah, struct ieee80211_channel *chan,
+ 	 */
+ /*	ath5k_chan_change(ah, c); */
+ 
++	__clear_bit(ATH_STAT_RESET, ah->status);
++
+ 	ath5k_beacon_config(ah);
+ 	/* intrs are enabled by ath5k_beacon_config */
+ 
-- 
2.0.4
_______________________________________________
openwrt-devel mailing list
openwrt-devel at lists.openwrt.org
https://lists.openwrt.org/cgi-bin/mailman/listinfo/openwrt-devel



More information about the openwrt-devel mailing list