[ath_hal] Return failure if noise floor calibration fails.

If we fail noise floor calibration then we may end up with a deaf NIC
which we can't recover without a full chip reset.

Earlier chips seem to get less stuck in this condition versus AR9280/later
and AR9300/later, but whilst here just fix up the AR5212 era chips to also
return NF calibration failures.

This HAL routine would only return failure if the channel was not configured.

This is a no-op until the driver side code for doing resets and the HAL
code for being told about the reset type (and then handling it!) is
implemented.

Tested:

* AR9280, STA mode
* AR2425, STA mode
* AR9380, STA mode
This commit is contained in:
Adrian Chadd 2018-06-08 18:21:57 +00:00
parent 7b1c2c4ec2
commit 8a97beff98
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=334849
4 changed files with 40 additions and 7 deletions

View File

@ -1188,6 +1188,15 @@ ar9300_ani_ar_poll(struct ath_hal *ah, const HAL_NODE_STATS *stats,
cck_phy_err_cnt - ani_state->cck_phy_err_count;
ani_state->cck_phy_err_count = cck_phy_err_cnt;
/*
* Note - the ANI code is using the aggregate listen time.
* The AR_PHY_CNT1/AR_PHY_CNT2 registers here are also
* free running, not clear-on-read and are free-running.
*
* So, ofdm_phy_err_rate / cck_phy_err_rate are accumulating
* the same as listenTime is accumulating.
*/
#if HAL_ANI_DEBUG
HALDEBUG(ah, HAL_DEBUG_ANI,
"%s: Errors: OFDM=0x%08x-0x0=%d CCK=0x%08x-0x0=%d\n",

View File

@ -704,11 +704,16 @@ ar9300_proc_rx_desc_freebsd(struct ath_hal *ah, struct ath_desc *ds,
(void *) ds));
}
/*
* This is the primary way the ANI code gets the node statistics per packet.
*/
void
ar9300_ani_rxmonitor_freebsd(struct ath_hal *ah, const HAL_NODE_STATS *stats,
const struct ieee80211_channel *chan)
{
struct ath_hal_9300 *ahp = AH9300(ah);
ahp->ah_stats.ast_nodestats.ns_avgbrssi = stats->ns_avgbrssi;
}
void

View File

@ -2493,15 +2493,23 @@ ar9300_calibration(struct ath_hal *ah, struct ieee80211_channel *chan, u_int8_t
chan->ic_state &= ~IEEE80211_CHANSTATE_CWINT;
if (nf_done) {
int ret;
/*
* Load the NF from history buffer of the current channel.
* NF is slow time-variant, so it is OK to use a historical value.
*/
ar9300_get_nf_hist_base(ah, ichan, is_scan, nf_buf);
ar9300_load_nf(ah, nf_buf);
ret = ar9300_load_nf(ah, nf_buf);
/* start NF calibration, without updating BB NF register*/
ar9300_start_nf_cal(ah);
ar9300_start_nf_cal(ah);
/*
* If we failed the NF cal then tell the upper layer that we
* failed so we can do a full reset
*/
if (! ret)
return AH_FALSE;
}
}
return AH_TRUE;
@ -4479,6 +4487,7 @@ First_NFCal(struct ath_hal *ah, HAL_CHANNEL_INTERNAL *ichan,
ar9300_reset_nf_hist_buff(ah, ichan);
ar9300_get_nf_hist_base(ah, ichan, is_scan, nf_buf);
ar9300_load_nf(ah, nf_buf);
/* XXX TODO: handle failure from load_nf */
stats = 0;
} else {
stats = 1;
@ -5303,6 +5312,7 @@ ar9300_reset(struct ath_hal *ah, HAL_OPMODE opmode, struct ieee80211_channel *ch
/* XXX FreeBSD is ichan appropariate? It was curchan.. */
ar9300_get_nf_hist_base(ah, ichan, is_scan, nf_buf);
ar9300_load_nf(ah, nf_buf);
/* XXX TODO: handle NF load failure */
if (nf_hist_buff_reset == 1)
{
nf_hist_buff_reset = 0;

View File

@ -36,7 +36,7 @@
#define NUM_NOISEFLOOR_READINGS 6 /* 3 chains * (ctl + ext) */
static void ar5416StartNFCal(struct ath_hal *ah);
static void ar5416LoadNF(struct ath_hal *ah, const struct ieee80211_channel *);
static HAL_BOOL ar5416LoadNF(struct ath_hal *ah, const struct ieee80211_channel *);
static int16_t ar5416GetNf(struct ath_hal *, struct ieee80211_channel *);
static uint16_t ar5416GetDefaultNF(struct ath_hal *ah, const struct ieee80211_channel *chan);
@ -513,6 +513,7 @@ ar5416PerCalibrationN(struct ath_hal *ah, struct ieee80211_channel *chan,
HALDEBUG(ah, HAL_DEBUG_UNMASKABLE, "%s: NF calibration"
" didn't finish; delaying CCA\n", __func__);
} else {
int ret;
/*
* NF calibration result is valid.
*
@ -520,10 +521,17 @@ ar5416PerCalibrationN(struct ath_hal *ah, struct ieee80211_channel *chan,
* NF is slow time-variant, so it is OK to use a
* historical value.
*/
ar5416LoadNF(ah, AH_PRIVATE(ah)->ah_curchan);
ret = ar5416LoadNF(ah, AH_PRIVATE(ah)->ah_curchan);
/* start NF calibration, without updating BB NF register*/
ar5416StartNFCal(ah);
/*
* If we failed calibration then tell the driver
* we failed and it should do a full chip reset
*/
if (! ret)
return AH_FALSE;
}
}
return AH_TRUE;
@ -578,7 +586,7 @@ ar5416StartNFCal(struct ath_hal *ah)
OS_REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_NF);
}
static void
static HAL_BOOL
ar5416LoadNF(struct ath_hal *ah, const struct ieee80211_channel *chan)
{
static const uint32_t ar5416_cca_regs[] = {
@ -657,7 +665,7 @@ ar5416LoadNF(struct ath_hal *ah, const struct ieee80211_channel *chan)
HALDEBUG(ah, HAL_DEBUG_UNMASKABLE, "Timeout while waiting for "
"nf to load: AR_PHY_AGC_CONTROL=0x%x\n",
OS_REG_READ(ah, AR_PHY_AGC_CONTROL));
return;
return AH_FALSE;
}
/*
@ -679,6 +687,7 @@ ar5416LoadNF(struct ath_hal *ah, const struct ieee80211_channel *chan)
OS_REG_WRITE(ah, ar5416_cca_regs[i], val);
}
}
return AH_TRUE;
}
/*