void ath9k_hw_bstuck_nfcal(struct ath_hw *ah) { struct ath9k_hw_cal_data *caldata = ah->caldata; if (unlikely(!caldata)) return; if (!caldata->nfcal_pending) ath9k_hw_start_nfcal(ah, true); else if (!(REG_READ(ah, AR_PHY_AGC_CONTROL) & AR_PHY_AGC_CONTROL_NF)) ath9k_hw_getnf(ah, ah->curchan); caldata->nfcal_interference = true; }
bool ath9k_hw_calibrate(struct ath_hw *ah, struct ath9k_channel *chan, u8 rxchainmask, bool longcal) { bool iscaldone = true; struct ath9k_cal_list *currCal = ah->cal_list_curr; if (currCal && (currCal->calState == CAL_RUNNING || currCal->calState == CAL_WAITING)) { iscaldone = ath9k_hw_per_calibration(ah, chan, rxchainmask, currCal); if (iscaldone) { ah->cal_list_curr = currCal = currCal->calNext; if (currCal->calState == CAL_WAITING) { iscaldone = false; ath9k_hw_reset_calibration(ah, currCal); } } } /* Do NF cal only at longer intervals */ if (longcal) { /* Do periodic PAOffset Cal */ if (AR_SREV_9271(ah)) ath9k_hw_9271_pa_cal(ah); else if (AR_SREV_9285_11_OR_LATER(ah)) { if (!ah->pacal_info.skipcount) ath9k_hw_9285_pa_cal(ah, false); else ah->pacal_info.skipcount--; } if (OLC_FOR_AR9280_20_LATER || OLC_FOR_AR9287_10_LATER) ath9k_olc_temp_compensation(ah); /* Get the value from the previous NF cal and update history buffer */ ath9k_hw_getnf(ah, chan); /* * Load the NF from history buffer of the current channel. * NF is slow time-variant, so it is OK to use a historical value. */ ath9k_hw_loadnf(ah, ah->curchan); ath9k_hw_start_nfcal(ah); } return iscaldone; }
bool ath9k_hw_calibrate(struct ath_hal *ah, struct ath9k_channel *chan, u8 rxchainmask, bool longcal, bool *isCalDone) { struct ath_hal_5416 *ahp = AH5416(ah); struct hal_cal_list *currCal = ahp->ah_cal_list_curr; struct ath9k_channel *ichan = ath9k_regd_check_channel(ah, chan); *isCalDone = true; if (ichan == NULL) { DPRINTF(ah->ah_sc, ATH_DBG_CHANNEL, "invalid channel %u/0x%x; no mapping\n", chan->channel, chan->channelFlags); return false; } if (currCal && (currCal->calState == CAL_RUNNING || currCal->calState == CAL_WAITING)) { ath9k_hw_per_calibration(ah, ichan, rxchainmask, currCal, isCalDone); if (*isCalDone) { ahp->ah_cal_list_curr = currCal = currCal->calNext; if (currCal->calState == CAL_WAITING) { *isCalDone = false; ath9k_hw_reset_calibration(ah, currCal); } } } if (longcal) { ath9k_hw_getnf(ah, ichan); ath9k_hw_loadnf(ah, ah->ah_curchan); ath9k_hw_start_nfcal(ah); if ((ichan->channelFlags & CHANNEL_CW_INT) != 0) { chan->channelFlags |= CHANNEL_CW_INT; ichan->channelFlags &= ~CHANNEL_CW_INT; } } return true; }
void ath9k_hw_bstuck_nfcal(struct ath_hw *ah) { struct ath9k_hw_cal_data *caldata = ah->caldata; if (unlikely(!caldata)) return; /* * If beacons are stuck, the most likely cause is interference. * Triggering a noise floor calibration at this point helps the * hardware adapt to a noisy environment much faster. * To ensure that we recover from stuck beacons quickly, let * the baseband update the internal NF value itself, similar to * what is being done after a full reset. */ if (!caldata->nfcal_pending) ath9k_hw_start_nfcal(ah, true); else if (!(REG_READ(ah, AR_PHY_AGC_CONTROL) & AR_PHY_AGC_CONTROL_NF)) ath9k_hw_getnf(ah, ah->curchan); caldata->nfcal_interference = true; }