[ath_hal] Add get/set NAV functions

The NAV (network allocation vector) register reflects the current MAC
tracking of NAV - when it will stay quiet before transmitting.

Other devices transmit their frame durations in their 802.11 PHY headers
and all devices that hear a frame - even if it's one in an encoding
they don't understand - will understand the low bitrate PHY header that
includes the frame duration.  So, they'll set NAV to this value so
they'll stay quiet until the transmit completes.

Anyway, sometimes the PHY NAV header is garbled and sometimes, notably
older broadcom devices, will fake a long NAV so they can get "cleaner" air
for local calibration.  When this happens, the hardware will stay quiet
for quite some time and this can lead to missed/stuck beacons, or
(for Very Large Values) a MAC hang.

This code just adds the ability to get/set the NAV; the driver will
need to take care of using it during transmit hangs and beacon misses
to see if it's due to a trash looking NAV.
This commit is contained in:
Adrian Chadd 2021-03-31 09:38:15 -07:00
parent dead34f822
commit bed90bf8ed
11 changed files with 106 additions and 0 deletions

View File

@ -69,6 +69,23 @@ ar9300_get_next_tbtt(struct ath_hal *ah)
return (OS_REG_READ(ah, AR_NEXT_TBTT_TIMER));
}
static u_int
ar9300_get_nav(struct ath_hal *ah)
{
uint32_t reg;
reg = OS_REG_READ(ah, AR_NAV);
if (reg == 0xdeadbeef)
return 0;
return reg;
}
static void
ar9300_set_nav(struct ath_hal *ah, u_int nav)
{
OS_REG_WRITE(ah, AR_NAV, nav);
}
/*
* TODO: implement the antenna diversity control for AR9485 and
@ -484,6 +501,8 @@ ar9300_attach_freebsd_ops(struct ath_hal *ah)
/* ah_get11nExtBusy */
ah->ah_set11nMac2040 = ar9300_set_11n_mac2040;
ah->ah_setChainMasks = ar9300SetChainMasks;
ah->ah_getNav = ar9300_get_nav;
ah->ah_setNav = ar9300_set_nav;
/* ah_get11nRxClear */
/* ah_set11nRxClear */

View File

@ -1404,6 +1404,8 @@ struct ath_hal {
HAL_QUIET_FLAG flag);
void __ahdecl(*ah_setChainMasks)(struct ath_hal *,
uint32_t, uint32_t);
u_int __ahdecl(*ah_getNav)(struct ath_hal*);
void __ahdecl(*ah_setNav)(struct ath_hal*, u_int);
/* DFS functions */
void __ahdecl(*ah_enableDfs)(struct ath_hal *ah,

View File

@ -269,6 +269,8 @@ extern void ar5210SetChainMasks(struct ath_hal *, uint32_t, uint32_t);
extern void ar5210EnableDfs(struct ath_hal *, HAL_PHYERR_PARAM *);
extern void ar5210GetDfsThresh(struct ath_hal *, HAL_PHYERR_PARAM *);
extern void ar5210UpdateDiagReg(struct ath_hal *ah, uint32_t val);
extern void ar5210SetNav(struct ath_hal *ah, u_int val);
extern u_int ar5210GetNav(struct ath_hal *ah);
extern u_int ar5210GetKeyCacheSize(struct ath_hal *);
extern HAL_BOOL ar5210IsKeyCacheEntryValid(struct ath_hal *, uint16_t);

View File

@ -145,6 +145,8 @@ static const struct ath_hal_private ar5210hal = {{
.ah_getDfsThresh = ar5210GetDfsThresh,
/* XXX procRadarEvent */
/* XXX isFastClockEnabled */
.ah_getNav = ar5210GetNav,
.ah_setNav = ar5210SetNav,
/* Key Cache Functions */
.ah_getKeyCacheSize = ar5210GetKeyCacheSize,

View File

@ -710,3 +710,26 @@ ar5210UpdateDiagReg(struct ath_hal *ah, uint32_t val)
val |= AR_DIAG_SW_DIS_CRYPTO;
OS_REG_WRITE(ah, AR_DIAG_SW, val);
}
/*
* Get the current NAV value from the hardware.
*/
u_int
ar5210GetNav(struct ath_hal *ah)
{
uint32_t reg;
reg = OS_REG_READ(ah, AR_NAV);
return (reg);
}
/*
* Set the current NAV value to the hardware.
*/
void
ar5210SetNav(struct ath_hal *ah, u_int val)
{
OS_REG_WRITE(ah, AR_NAV, val);
}

View File

@ -291,6 +291,8 @@ extern uint32_t ar5211Get11nExtBusy(struct ath_hal *);
extern HAL_BOOL ar5211GetMibCycleCounts(struct ath_hal *,
HAL_SURVEY_SAMPLE *);
extern void ar5211SetChainMasks(struct ath_hal *ah, uint32_t, uint32_t);
extern void ar5211SetNav(struct ath_hal *ah, u_int);
extern u_int ar5211GetNav(struct ath_hal *ah);
extern void ar5211EnableDfs(struct ath_hal *, HAL_PHYERR_PARAM *);
extern void ar5211GetDfsThresh(struct ath_hal *, HAL_PHYERR_PARAM *);

View File

@ -145,6 +145,8 @@ static const struct ath_hal_private ar5211hal = {{
.ah_getDfsThresh = ar5211GetDfsThresh,
/* XXX procRadarEvent */
/* XXX isFastClockEnabled */
.ah_setNav = ar5211SetNav,
.ah_getNav = ar5211GetNav,
/* Key Cache Functions */
.ah_getKeyCacheSize = ar5211GetKeyCacheSize,

View File

@ -733,3 +733,26 @@ void
ar5211GetDfsThresh(struct ath_hal *ah, HAL_PHYERR_PARAM *pe)
{
}
/*
* Get the current NAV value from the hardware.
*/
u_int
ar5211GetNav(struct ath_hal *ah)
{
uint32_t reg;
reg = OS_REG_READ(ah, AR_NAV);
return (reg);
}
/*
* Set the current NAV value to the hardware.
*/
void
ar5211SetNav(struct ath_hal *ah, u_int val)
{
OS_REG_WRITE(ah, AR_NAV, val);
}

View File

@ -529,6 +529,8 @@ extern HAL_STATUS ar5212SetQuiet(struct ath_hal *ah, uint32_t period,
extern HAL_BOOL ar5212GetMibCycleCounts(struct ath_hal *,
HAL_SURVEY_SAMPLE *);
extern void ar5212SetChainMasks(struct ath_hal *, uint32_t, uint32_t);
extern u_int ar5212GetNav(struct ath_hal *);
extern void ar5212SetNav(struct ath_hal *, u_int);
extern HAL_BOOL ar5212SetPowerMode(struct ath_hal *ah, HAL_POWER_MODE mode,
int setChip);

View File

@ -137,6 +137,8 @@ static const struct ath_hal_private ar5212hal = {{
.ah_setQuiet = ar5212SetQuiet,
.ah_getMibCycleCounts = ar5212GetMibCycleCounts,
.ah_setChainMasks = ar5212SetChainMasks,
.ah_getNav = ar5212GetNav,
.ah_setNav = ar5212SetNav,
/* DFS Functions */
.ah_enableDfs = ar5212EnableDfs,

View File

@ -1458,3 +1458,30 @@ ar5212SetChainMasks(struct ath_hal *ah, uint32_t tx_chainmask,
uint32_t rx_chainmask)
{
}
/*
* Get the current NAV value from the hardware.
*
* 0xdeadbeef indicates the hardware is currently powered off.
*/
u_int
ar5212GetNav(struct ath_hal *ah)
{
uint32_t reg;
reg = OS_REG_READ(ah, AR_NAV);
if (reg == 0xdeadbeef)
return (0);
return (reg);
}
/*
* Set the current NAV value to the hardware.
*/
void
ar5212SetNav(struct ath_hal *ah, u_int val)
{
OS_REG_WRITE(ah, AR_NAV, val);
}