aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFelix Fietkau2013-02-25 13:51:07 -0600
committerJohn W. Linville2013-02-27 13:12:52 -0600
commit3412f2f086ea7531378fabe756bd4a1109994ae6 (patch)
tree7d0ef5f4d8b7ec58a2c9f0cc9a8c82577deafffb
parentf45dd363bee071a62e32398a0ae4a0214b8029eb (diff)
downloadam43-linux-kernel-3412f2f086ea7531378fabe756bd4a1109994ae6.tar.gz
am43-linux-kernel-3412f2f086ea7531378fabe756bd4a1109994ae6.tar.xz
am43-linux-kernel-3412f2f086ea7531378fabe756bd4a1109994ae6.zip
ath9k_hw: improve reset reliability after errors
On many different chips, important aspects of the MAC state are not fully cleared by a warm reset. This can show up as tx/rx hangs, those annoying "DMA failed to stop in 10 ms..." messages or other quirks. On AR933x, the chip can occasionally get stuck in a way that only a driver unload/reload or a reboot would bring it back to life. With this patch, a full reset is issued when bringing the chip out of FULL-SLEEP state (after idle), or if either Rx or Tx was not shut down properly. This makes the DMA related error messages disappear completely in my tests on AR933x, and the chip does not get stuck anymore. Cc: stable@vger.kernel.org Signed-off-by: Felix Fietkau <nbd@openwrt.org> Signed-off-by: John W. Linville <linville@tuxdriver.com>
-rw-r--r--drivers/net/wireless/ath/ath9k/hw.c4
1 files changed, 3 insertions, 1 deletions
diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c
index 42cf3c7f1e2..7b485e4d104 100644
--- a/drivers/net/wireless/ath/ath9k/hw.c
+++ b/drivers/net/wireless/ath/ath9k/hw.c
@@ -1463,7 +1463,9 @@ static bool ath9k_hw_chip_reset(struct ath_hw *ah,
1463 reset_type = ATH9K_RESET_POWER_ON; 1463 reset_type = ATH9K_RESET_POWER_ON;
1464 else 1464 else
1465 reset_type = ATH9K_RESET_COLD; 1465 reset_type = ATH9K_RESET_COLD;
1466 } 1466 } else if (ah->chip_fullsleep || REG_READ(ah, AR_Q_TXE) ||
1467 (REG_READ(ah, AR_CR) & AR_CR_RXE))
1468 reset_type = ATH9K_RESET_COLD;
1467 1469
1468 if (!ath9k_hw_set_reset_reg(ah, reset_type)) 1470 if (!ath9k_hw_set_reset_reg(ah, reset_type))
1469 return false; 1471 return false;