From owner-svn-src-all@FreeBSD.ORG Sat Jul 30 13:30:25 2011 Return-Path: Delivered-To: svn-src-all@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 5EF3F106566C; Sat, 30 Jul 2011 13:30:25 +0000 (UTC) (envelope-from adrian@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id 4D0068FC15; Sat, 30 Jul 2011 13:30:25 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.4/8.14.4) with ESMTP id p6UDUP2p001837; Sat, 30 Jul 2011 13:30:25 GMT (envelope-from adrian@svn.freebsd.org) Received: (from adrian@localhost) by svn.freebsd.org (8.14.4/8.14.4/Submit) id p6UDUPgN001834; Sat, 30 Jul 2011 13:30:25 GMT (envelope-from adrian@svn.freebsd.org) Message-Id: <201107301330.p6UDUPgN001834@svn.freebsd.org> From: Adrian Chadd Date: Sat, 30 Jul 2011 13:30:25 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r224514 - in head/sys/dev/ath/ath_hal: ar5212 ar5416 X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 30 Jul 2011 13:30:25 -0000 Author: adrian Date: Sat Jul 30 13:30:24 2011 New Revision: 224514 URL: http://svn.freebsd.org/changeset/base/224514 Log: Fix ANI handling to work correctly when (trying) to receive radar errors. * Teach the AR5212/AR5416 ANI code to use the RX filter methods, rather than calling the RX filter routines directly. * Make HAL_ANI_PRESENT and HAL_ANI_MODE unconditionally available, regardless of whether ah_ani_function is masking it. * (Mostly) fully disable ANI if interference mitigation is disabled. When disabled, the ANI code doesn't touch any ANI/PHY registers, leaving them the default value. This is in line with what the Atheros reference driver does. * Correctly set the ANI parameters during ANI reset, rather than when ANI is enabled. In this way, if ANI is disabled or enabled whilst the NIC is not active (and there's no current channel), bogus parameters or a NULL pointer deference doesn't occur. There's still some lingering issues - notably, the MIB events/interrupts aren't fully disabled, so MIB interrupts still occur. I'll worry about that later. Approved by: re (kib) Modified: head/sys/dev/ath/ath_hal/ar5212/ar5212_ani.c head/sys/dev/ath/ath_hal/ar5416/ar5416_ani.c Modified: head/sys/dev/ath/ath_hal/ar5212/ar5212_ani.c ============================================================================== --- head/sys/dev/ath/ath_hal/ar5212/ar5212_ani.c Sat Jul 30 13:28:11 2011 (r224513) +++ head/sys/dev/ath/ath_hal/ar5212/ar5212_ani.c Sat Jul 30 13:30:24 2011 (r224514) @@ -222,7 +222,14 @@ ar5212AniControl(struct ath_hal *ah, HAL typedef int TABLE[]; struct ath_hal_5212 *ahp = AH5212(ah); struct ar5212AniState *aniState = ahp->ah_curani; - const struct ar5212AniParams *params = aniState->params; + const struct ar5212AniParams *params = AH_NULL; + + /* + * This function may be called before there's a current + * channel (eg to disable ANI.) + */ + if (aniState != AH_NULL) + params = aniState->params; OS_MARK(ah, AH_MARK_ANI_CONTROL, cmd); @@ -343,8 +350,8 @@ ar5212AniControl(struct ath_hal *ah, HAL ahp->ah_procPhyErr &= ~HAL_ANI_ENA; /* Turn off HW counters if we have them */ ar5212AniDetach(ah); - ar5212SetRxFilter(ah, - ar5212GetRxFilter(ah) &~ HAL_RX_FILTER_PHYERR); + ah->ah_setRxFilter(ah, + ah->ah_getRxFilter(ah) &~ HAL_RX_FILTER_PHYERR); } else { /* normal/auto mode */ /* don't mess with state if already enabled */ if (ahp->ah_procPhyErr & HAL_ANI_ENA) @@ -358,8 +365,8 @@ ar5212AniControl(struct ath_hal *ah, HAL ahp->ah_curani->params: &ahp->ah_aniParams24 /*XXX*/); } else { - ar5212SetRxFilter(ah, - ar5212GetRxFilter(ah) | HAL_RX_FILTER_PHYERR); + ah->ah_setRxFilter(ah, + ah->ah_getRxFilter(ah) | HAL_RX_FILTER_PHYERR); } ahp->ah_procPhyErr |= HAL_ANI_ENA; } @@ -609,8 +616,20 @@ ar5212AniReset(struct ath_hal *ah, const /* * Turn off PHY error frame delivery while we futz with settings. */ - rxfilter = ar5212GetRxFilter(ah); - ar5212SetRxFilter(ah, rxfilter &~ HAL_RX_FILTER_PHYERR); + rxfilter = ah->ah_getRxFilter(ah); + ah->ah_setRxFilter(ah, rxfilter &~ HAL_RX_FILTER_PHYERR); + + /* + * If ANI is disabled at this point, don't set the default + * ANI parameter settings - leave the HAL settings there. + * This is (currently) needed for reliable radar detection. + */ + if (! ANI_ENA(ah)) { + HALDEBUG(ah, HAL_DEBUG_ANI, "%s: ANI disabled\n", + __func__); + goto finish; + } + /* * Automatic processing is done only in station mode right now. */ @@ -644,10 +663,15 @@ ar5212AniReset(struct ath_hal *ah, const ar5212AniControl(ah, HAL_ANI_FIRSTEP_LEVEL, 0); ichan->privFlags |= CHANNEL_ANI_SETUP; } + /* + * In case the counters haven't yet been setup; set them up. + */ + enableAniMIBCounters(ah, ahp->ah_curani->params); ar5212AniRestart(ah, aniState); +finish: /* restore RX filter mask */ - ar5212SetRxFilter(ah, rxfilter); + ah->ah_setRxFilter(ah, rxfilter); } /* Modified: head/sys/dev/ath/ath_hal/ar5416/ar5416_ani.c ============================================================================== --- head/sys/dev/ath/ath_hal/ar5416/ar5416_ani.c Sat Jul 30 13:28:11 2011 (r224513) +++ head/sys/dev/ath/ath_hal/ar5416/ar5416_ani.c Sat Jul 30 13:30:24 2011 (r224514) @@ -156,6 +156,8 @@ ar5416AniAttach(struct ath_hal *ah, cons /* * Cleanup any ANI state setup. + * + * This doesn't restore registers to their default settings! */ void ar5416AniDetach(struct ath_hal *ah) @@ -173,7 +175,43 @@ ar5416AniControl(struct ath_hal *ah, HAL typedef int TABLE[]; struct ath_hal_5212 *ahp = AH5212(ah); struct ar5212AniState *aniState = ahp->ah_curani; - const struct ar5212AniParams *params = aniState->params; + const struct ar5212AniParams *params = AH_NULL; + + /* + * This function may be called before there's a current + * channel (eg to disable ANI.) + */ + if (aniState != AH_NULL) + params = aniState->params; + + OS_MARK(ah, AH_MARK_ANI_CONTROL, cmd); + + /* These commands can't be disabled */ + if (cmd == HAL_ANI_PRESENT) + return AH_TRUE; + + if (cmd == HAL_ANI_MODE) { + if (param == 0) { + ahp->ah_procPhyErr &= ~HAL_ANI_ENA; + /* Turn off HW counters if we have them */ + ar5416AniDetach(ah); + } else { /* normal/auto mode */ + /* don't mess with state if already enabled */ + if (! (ahp->ah_procPhyErr & HAL_ANI_ENA)) { + /* Enable MIB Counters */ + /* + * XXX use 2.4ghz params if no channel is + * available + */ + enableAniMIBCounters(ah, + ahp->ah_curani != AH_NULL ? + ahp->ah_curani->params: + &ahp->ah_aniParams24); + ahp->ah_procPhyErr |= HAL_ANI_ENA; + } + } + return AH_TRUE; + } /* Check whether the particular function is enabled */ if (((1 << cmd) & AH5416(ah)->ah_ani_function) == 0) { @@ -183,7 +221,6 @@ ar5416AniControl(struct ath_hal *ah, HAL return AH_FALSE; } - OS_MARK(ah, AH_MARK_ANI_CONTROL, cmd); switch (cmd) { case HAL_ANI_NOISE_IMMUNITY_LEVEL: { @@ -317,23 +354,6 @@ ar5416AniControl(struct ath_hal *ah, HAL aniState->spurImmunityLevel = level; break; } - case HAL_ANI_PRESENT: - break; - case HAL_ANI_MODE: - if (param == 0) { - ahp->ah_procPhyErr &= ~HAL_ANI_ENA; - /* Turn off HW counters if we have them */ - ar5416AniDetach(ah); - } else { /* normal/auto mode */ - /* don't mess with state if already enabled */ - if (ahp->ah_procPhyErr & HAL_ANI_ENA) - break; - /* Enable MIB Counters */ - enableAniMIBCounters(ah, ahp->ah_curani != AH_NULL ? - ahp->ah_curani->params: &ahp->ah_aniParams24 /*XXX*/); - ahp->ah_procPhyErr |= HAL_ANI_ENA; - } - break; #ifdef AH_PRIVATE_DIAG case HAL_ANI_PHYERR_RESET: ahp->ah_stats.ast_ani_ofdmerrs = 0; @@ -548,8 +568,21 @@ ar5416AniReset(struct ath_hal *ah, const /* * Turn off PHY error frame delivery while we futz with settings. */ - rxfilter = ar5212GetRxFilter(ah); - ar5212SetRxFilter(ah, rxfilter &~ HAL_RX_FILTER_PHYERR); + rxfilter = ah->ah_getRxFilter(ah); + ah->ah_setRxFilter(ah, rxfilter &~ HAL_RX_FILTER_PHYERR); + + /* + * If ANI is disabled at this point, don't set the default + * ANI parameter settings - leave the HAL settings there. + * This is (currently) needed for reliable radar detection. + */ + if (! ANI_ENA(ah)) { + HALDEBUG(ah, HAL_DEBUG_ANI, "%s: ANI disabled\n", + __func__); + goto finish; + } + + /* * Automatic processing is done only in station mode right now. */ @@ -583,10 +616,16 @@ ar5416AniReset(struct ath_hal *ah, const ar5416AniControl(ah, HAL_ANI_FIRSTEP_LEVEL, 0); ichan->privFlags |= CHANNEL_ANI_SETUP; } + + /* + * In case the counters haven't yet been setup; set them up. + */ + enableAniMIBCounters(ah, aniState->params); ar5416AniRestart(ah, aniState); +finish: /* restore RX filter mask */ - ar5212SetRxFilter(ah, rxfilter); + ah->ah_setRxFilter(ah, rxfilter); } /*