Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 8 Oct 2013 11:29:00 +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: r256139 - head/sys/dev/ath/ath_hal/ar5212
Message-ID:  <201310081129.r98BT0Fj061263@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: adrian
Date: Tue Oct  8 11:28:59 2013
New Revision: 256139
URL: http://svnweb.freebsd.org/changeset/base/256139

Log:
  Add channel survey support to the AR5212 HAL.
  
  The AR5212 series of MACs implement the same channel counters as the
  later 11n chips - except, of course, the 11n specific counter (extension
  channel busy.)
  
  This allows users of these NICs to use 'athsurvey' to see how busy their
  current channel is.
  
  Tested:
  
  * AR5212, AR2413 NICs, STA mode
  
  Approved by:	re@ (gleb)

Modified:
  head/sys/dev/ath/ath_hal/ar5212/ar5212.h
  head/sys/dev/ath/ath_hal/ar5212/ar5212_ani.c
  head/sys/dev/ath/ath_hal/ar5212/ar5212_misc.c

Modified: head/sys/dev/ath/ath_hal/ar5212/ar5212.h
==============================================================================
--- head/sys/dev/ath/ath_hal/ar5212/ar5212.h	Tue Oct  8 11:05:26 2013	(r256138)
+++ head/sys/dev/ath/ath_hal/ar5212/ar5212.h	Tue Oct  8 11:28:59 2013	(r256139)
@@ -335,6 +335,16 @@ struct ath_hal_5212 {
 
 	uint8_t		ah_txTrigLev;		/* current Tx trigger level */
 	uint8_t		ah_maxTxTrigLev;	/* max tx trigger level */
+
+	/*
+	 * Channel Tx, Rx, Rx Clear State
+	 */
+	uint32_t	ah_cycleCount;
+	uint32_t	ah_ctlBusy;
+	uint32_t	ah_rxBusy;
+	uint32_t	ah_txBusy;
+	uint32_t	ah_rx_chainmask;
+	uint32_t	ah_tx_chainmask;
 };
 #define	AH5212(_ah)	((struct ath_hal_5212 *)(_ah))
 

Modified: head/sys/dev/ath/ath_hal/ar5212/ar5212_ani.c
==============================================================================
--- head/sys/dev/ath/ath_hal/ar5212/ar5212_ani.c	Tue Oct  8 11:05:26 2013	(r256138)
+++ head/sys/dev/ath/ath_hal/ar5212/ar5212_ani.c	Tue Oct  8 11:28:59 2013	(r256139)
@@ -865,16 +865,40 @@ static int32_t
 ar5212AniGetListenTime(struct ath_hal *ah)
 {
 	struct ath_hal_5212 *ahp = AH5212(ah);
-	struct ar5212AniState *aniState;
-	uint32_t txFrameCount, rxFrameCount, cycleCount;
-	int32_t listenTime;
+	struct ar5212AniState *aniState = NULL;
+	int32_t listenTime = 0;
+	int good;
+	HAL_SURVEY_SAMPLE hs;
+	HAL_CHANNEL_SURVEY *cs = AH_NULL;
+
+	/*
+	 * We shouldn't see ah_curchan be NULL, but just in case..
+	 */
+	if (AH_PRIVATE(ah)->ah_curchan == AH_NULL) {
+		ath_hal_printf(ah, "%s: ah_curchan = NULL?\n", __func__);
+		return (0);
+	}
 
-	txFrameCount = OS_REG_READ(ah, AR_TFCNT);
-	rxFrameCount = OS_REG_READ(ah, AR_RFCNT);
-	cycleCount = OS_REG_READ(ah, AR_CCCNT);
+	cs = &ahp->ah_chansurvey;
+
+	/*
+	 * Fetch the current statistics, squirrel away the current
+	 * sample, bump the sequence/sample counter.
+	 */
+	OS_MEMZERO(&hs, sizeof(hs));
+	good = ar5212GetMibCycleCounts(ah, &hs);
+	if (cs != AH_NULL) {
+		OS_MEMCPY(&cs->samples[cs->cur_sample], &hs, sizeof(hs));
+		cs->samples[cs->cur_sample].seq_num = cs->cur_seq;
+		cs->cur_sample =
+		    (cs->cur_sample + 1) % CHANNEL_SURVEY_SAMPLE_COUNT;
+		cs->cur_seq++;
+	}
 
-	aniState = ahp->ah_curani;
-	if (aniState->cycleCount == 0 || aniState->cycleCount > cycleCount) {
+	if (ANI_ENA(ah))
+		aniState = ahp->ah_curani;
+
+	if (good == AH_FALSE) {
 		/*
 		 * Cycle counter wrap (or initial call); it's not possible
 		 * to accurately calculate a value because the registers
@@ -882,15 +906,29 @@ ar5212AniGetListenTime(struct ath_hal *a
 		 */
 		listenTime = 0;
 		ahp->ah_stats.ast_ani_lzero++;
-	} else {
-		int32_t ccdelta = cycleCount - aniState->cycleCount;
-		int32_t rfdelta = rxFrameCount - aniState->rxFrameCount;
-		int32_t tfdelta = txFrameCount - aniState->txFrameCount;
+	} else if (ANI_ENA(ah)) {
+		/*
+		 * Only calculate and update the cycle count if we have
+		 * an ANI state.
+		 */
+		int32_t ccdelta =
+		    AH5212(ah)->ah_cycleCount - aniState->cycleCount;
+		int32_t rfdelta =
+		    AH5212(ah)->ah_rxBusy - aniState->rxFrameCount;
+		int32_t tfdelta =
+		    AH5212(ah)->ah_txBusy - aniState->txFrameCount;
 		listenTime = (ccdelta - rfdelta - tfdelta) / CLOCK_RATE;
 	}
-	aniState->cycleCount = cycleCount;
-	aniState->txFrameCount = txFrameCount;
-	aniState->rxFrameCount = rxFrameCount;
+
+	/*
+	 * Again, only update ANI state if we have it.
+	 */
+	if (ANI_ENA(ah)) {
+		aniState->cycleCount = AH5212(ah)->ah_cycleCount;
+		aniState->rxFrameCount = AH5212(ah)->ah_rxBusy;
+		aniState->txFrameCount = AH5212(ah)->ah_txBusy;
+	}
+
 	return listenTime;
 }
 
@@ -956,13 +994,15 @@ ar5212AniPoll(struct ath_hal *ah, const 
 	const struct ar5212AniParams *params;
 	int32_t listenTime;
 
+	/* Always update from the MIB, for statistics gathering */
+	listenTime = ar5212AniGetListenTime(ah);
+
 	/* XXX can aniState be null? */
 	if (aniState == AH_NULL)
 		return;
 	if (!ANI_ENA(ah))
 		return;
 
-	listenTime = ar5212AniGetListenTime(ah);
 	if (listenTime < 0) {
 		ahp->ah_stats.ast_ani_lneg++;
 		/* restart ANI period if listenTime is invalid */

Modified: head/sys/dev/ath/ath_hal/ar5212/ar5212_misc.c
==============================================================================
--- head/sys/dev/ath/ath_hal/ar5212/ar5212_misc.c	Tue Oct  8 11:05:26 2013	(r256138)
+++ head/sys/dev/ath/ath_hal/ar5212/ar5212_misc.c	Tue Oct  8 11:28:59 2013	(r256139)
@@ -1405,13 +1405,47 @@ ar5212Get11nExtBusy(struct ath_hal *ah)
 }
 
 /*
- * There's no channel survey support for the AR5212.
+ * Channel survey support.
  */
 HAL_BOOL
 ar5212GetMibCycleCounts(struct ath_hal *ah, HAL_SURVEY_SAMPLE *hsample)
 {
+	struct ath_hal_5212 *ahp = AH5212(ah);
+	u_int32_t good = AH_TRUE;
 
-	return (AH_FALSE);
+	/* XXX freeze/unfreeze mib counters */
+	uint32_t rc = OS_REG_READ(ah, AR_RCCNT);
+	uint32_t rf = OS_REG_READ(ah, AR_RFCNT);
+	uint32_t tf = OS_REG_READ(ah, AR_TFCNT);
+	uint32_t cc = OS_REG_READ(ah, AR_CCCNT); /* read cycles last */
+
+	if (ahp->ah_cycleCount == 0 || ahp->ah_cycleCount > cc) {
+		/*
+		 * Cycle counter wrap (or initial call); it's not possible
+		 * to accurately calculate a value because the registers
+		 * right shift rather than wrap--so punt and return 0.
+		 */
+		HALDEBUG(ah, HAL_DEBUG_ANY,
+		    "%s: cycle counter wrap. ExtBusy = 0\n", __func__);
+		good = AH_FALSE;
+	} else {
+		hsample->cycle_count = cc - ahp->ah_cycleCount;
+		hsample->chan_busy = rc - ahp->ah_ctlBusy;
+		hsample->ext_chan_busy = 0;
+		hsample->rx_busy = rf - ahp->ah_rxBusy;
+		hsample->tx_busy = tf - ahp->ah_txBusy;
+	}
+
+	/*
+	 * Keep a copy of the MIB results so the next sample has something
+	 * to work from.
+	 */
+	ahp->ah_cycleCount = cc;
+	ahp->ah_rxBusy = rf;
+	ahp->ah_ctlBusy = rc;
+	ahp->ah_txBusy = tf;
+
+	return (good);
 }
 
 void



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