Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 30 Jul 2011 13:30: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: r224514 - in head/sys/dev/ath/ath_hal: ar5212 ar5416
Message-ID:  <201107301330.p6UDUPgN001834@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
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);
 }
 
 /*



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201107301330.p6UDUPgN001834>