Date: Sat, 9 Aug 2014 09:12:25 +0000 (UTC) From: Adrian Chadd <adrian@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r269748 - head/sys/contrib/dev/ath/ath_hal/ar9300 Message-ID: <53e5e5f9.2eeb.7727ac5c@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: adrian Date: Sat Aug 9 09:12:25 2014 New Revision: 269748 URL: http://svnweb.freebsd.org/changeset/base/269748 Log: Work around some rather annoying chip hangs in the AR9331 chip. If powersave is enabled and there are any transitions to network or full sleep - even if they're pretty damned brief - eventually something messes up somewhere and the bus glue between the AR9331 SoC and the AR9331 wifi stops working. It shows up as stuck DMA and LOCAL_TIMEOUT interrupts. Both ath9k and the reference driver does a full chip reset if things get stuck. So: * teach the AR9330 HAL about the force_full_reset option I added a couple of years ago; * if the chip is currently in full-sleep, do a full-reset; * if TX DMA and/or RX DMA are still enabled (eg, they did get stuck during reset) then do a full-reset. Tested: * AR9331 SoC, STA mode Modified: head/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_reset.c Modified: head/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_reset.c ============================================================================== --- head/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_reset.c Sat Aug 9 09:11:26 2014 (r269747) +++ head/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_reset.c Sat Aug 9 09:12:25 2014 (r269748) @@ -1987,13 +1987,25 @@ HAL_BOOL ar9300_chip_reset(struct ath_hal *ah, struct ieee80211_channel *chan) { struct ath_hal_9300 *ahp = AH9300(ah); + int type = HAL_RESET_WARM; OS_MARK(ah, AH_MARK_CHIPRESET, chan ? chan->ic_freq : 0); /* * Warm reset is optimistic. - */ - if (!ar9300_set_reset_reg(ah, HAL_RESET_WARM)) { + * + * If the TX/RX DMA engines aren't shut down (eg, they're + * wedged) then we're better off doing a full cold reset + * to try and shake that condition. + */ + if (ahp->ah_chip_full_sleep || + (ah->ah_config.ah_force_full_reset == 1) || + OS_REG_READ(ah, AR_Q_TXE) || + (OS_REG_READ(ah, AR_CR) & AR_CR_RXE)) { + type = HAL_RESET_COLD; + } + + if (!ar9300_set_reset_reg(ah, type)) { return AH_FALSE; }
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?53e5e5f9.2eeb.7727ac5c>