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)
This commit is contained in:
parent
3bf351b29a
commit
0a2cefc676
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=256139
@ -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))
|
||||
|
||||
|
@ -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;
|
||||
|
||||
txFrameCount = OS_REG_READ(ah, AR_TFCNT);
|
||||
rxFrameCount = OS_REG_READ(ah, AR_RFCNT);
|
||||
cycleCount = OS_REG_READ(ah, AR_CCCNT);
|
||||
/*
|
||||
* 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);
|
||||
}
|
||||
|
||||
aniState = ahp->ah_curani;
|
||||
if (aniState->cycleCount == 0 || aniState->cycleCount > cycleCount) {
|
||||
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++;
|
||||
}
|
||||
|
||||
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 *ah)
|
||||
*/
|
||||
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 struct ieee80211_channel *chan)
|
||||
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 */
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user