On Thu, Jan 31, 2019 at 03:32:05PM +0100, Stefan Sperling wrote: > This diff completes noisefloor calibration code in our athn(4) driver. > Update default/min/max noisefloor values to those used by Linux. > > Tested on AR9280 on 2GHz and 5Ghz. Further tests are appreciated.
jmc@ found out the hard way that my previous diff broke association to other APs. Fixed in this version. Index: ar5008.c =================================================================== RCS file: /cvs/src/sys/dev/ic/ar5008.c,v retrieving revision 1.46 diff -u -p -r1.46 ar5008.c --- ar5008.c 28 Nov 2017 04:35:39 -0000 1.46 +++ ar5008.c 31 Jan 2019 15:17:00 -0000 @@ -98,10 +98,11 @@ void ar5008_init_chains(struct athn_soft void ar5008_set_rxchains(struct athn_softc *); void ar5008_read_noisefloor(struct athn_softc *, int16_t *, int16_t *); void ar5008_write_noisefloor(struct athn_softc *, int16_t *, int16_t *); -void ar5008_get_noisefloor(struct athn_softc *, struct ieee80211_channel *); +int ar5008_get_noisefloor(struct athn_softc *); +void ar5008_apply_noisefloor(struct athn_softc *); void ar5008_bb_load_noisefloor(struct athn_softc *); -void ar5008_noisefloor_calib(struct athn_softc *); void ar5008_do_noisefloor_calib(struct athn_softc *); +void ar5008_init_noisefloor_calib(struct athn_softc *); void ar5008_do_calib(struct athn_softc *); void ar5008_next_calib(struct athn_softc *); void ar5008_calib_iq(struct athn_softc *); @@ -176,6 +177,9 @@ ar5008_attach(struct athn_softc *sc) ops->disable_phy = ar5008_disable_phy; ops->set_rxchains = ar5008_set_rxchains; ops->noisefloor_calib = ar5008_do_noisefloor_calib; + ops->init_noisefloor_calib = ar5008_init_noisefloor_calib; + ops->get_noisefloor = ar5008_get_noisefloor; + ops->apply_noisefloor = ar5008_apply_noisefloor; ops->do_calib = ar5008_do_calib; ops->next_calib = ar5008_next_calib; ops->hw_init = ar5008_hw_init; @@ -1876,15 +1880,15 @@ ar5008_write_noisefloor(struct athn_soft AR_WRITE_BARRIER(sc); } -void -ar5008_get_noisefloor(struct athn_softc *sc, struct ieee80211_channel *c) +int +ar5008_get_noisefloor(struct athn_softc *sc) { int16_t nf[AR_MAX_CHAINS], nf_ext[AR_MAX_CHAINS]; int i; if (AR_READ(sc, AR_PHY_AGC_CONTROL) & AR_PHY_AGC_CONTROL_NF) { /* Noisefloor calibration not finished. */ - return; + return 0; } /* Noisefloor calibration is finished. */ ar5008_read_noisefloor(sc, nf, nf_ext); @@ -1896,6 +1900,7 @@ ar5008_get_noisefloor(struct athn_softc } if (++sc->nf_hist_cur >= ATHN_NF_CAL_HIST_MAX) sc->nf_hist_cur = 0; + return 1; } void @@ -1926,14 +1931,41 @@ ar5008_bb_load_noisefloor(struct athn_so return; } - /* Restore noisefloor values to initial (max) values. */ + /* + * Restore noisefloor values to initial (max) values. These will + * be used as initial values during the next NF calibration. + */ for (i = 0; i < AR_MAX_CHAINS; i++) nf[i] = nf_ext[i] = AR_DEFAULT_NOISE_FLOOR; ar5008_write_noisefloor(sc, nf, nf_ext); } void -ar5008_noisefloor_calib(struct athn_softc *sc) +ar5008_apply_noisefloor(struct athn_softc *sc) +{ + uint32_t agc_nfcal; + + agc_nfcal = AR_READ(sc, AR_PHY_AGC_CONTROL) & + (AR_PHY_AGC_CONTROL_NF | AR_PHY_AGC_CONTROL_ENABLE_NF | + AR_PHY_AGC_CONTROL_NO_UPDATE_NF); + + if (agc_nfcal & AR_PHY_AGC_CONTROL_NF) { + /* Pause running NF calibration while values are updated. */ + AR_CLRBITS(sc, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_NF); + AR_WRITE_BARRIER(sc); + } + + ar5008_bb_load_noisefloor(sc); + + if (agc_nfcal & AR_PHY_AGC_CONTROL_NF) { + /* Restart interrupted NF calibration. */ + AR_SETBITS(sc, AR_PHY_AGC_CONTROL, agc_nfcal); + AR_WRITE_BARRIER(sc); + } +} + +void +ar5008_do_noisefloor_calib(struct athn_softc *sc) { AR_SETBITS(sc, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_ENABLE_NF); AR_SETBITS(sc, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_NO_UPDATE_NF); @@ -1942,7 +1974,7 @@ ar5008_noisefloor_calib(struct athn_soft } void -ar5008_do_noisefloor_calib(struct athn_softc *sc) +ar5008_init_noisefloor_calib(struct athn_softc *sc) { AR_SETBITS(sc, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_NF); AR_WRITE_BARRIER(sc); Index: ar5416.c =================================================================== RCS file: /cvs/src/sys/dev/ic/ar5416.c,v retrieving revision 1.20 diff -u -p -r1.20 ar5416.c --- ar5416.c 12 Jan 2017 16:32:28 -0000 1.20 +++ ar5416.c 31 Jan 2019 12:13:37 -0000 @@ -112,7 +112,6 @@ ar5416_attach(struct athn_softc *sc) { sc->eep_base = AR5416_EEP_START_LOC; sc->eep_size = sizeof(struct ar5416_eeprom); - sc->def_nf = AR5416_PHY_CCA_MAX_GOOD_VALUE; sc->ngpiopins = 14; sc->led_pin = 1; sc->workaround = AR5416_WA_DEFAULT; @@ -123,6 +122,10 @@ ar5416_attach(struct athn_softc *sc) sc->ops.set_synth = ar5416_set_synth; sc->ops.spur_mitigate = ar5416_spur_mitigate; sc->ops.get_spur_chans = ar5416_get_spur_chans; + sc->cca_min_2g = AR5416_PHY_CCA_MIN_GOOD_VAL_2GHZ; + sc->cca_max_2g = AR5416_PHY_CCA_MAX_GOOD_VAL_2GHZ; + sc->cca_min_5g = AR5416_PHY_CCA_MIN_GOOD_VAL_5GHZ; + sc->cca_max_5g = AR5416_PHY_CCA_MAX_GOOD_VAL_5GHZ; if (AR_SREV_9160_10_OR_LATER(sc)) sc->ini = &ar9160_ini; else Index: ar5416reg.h =================================================================== RCS file: /cvs/src/sys/dev/ic/ar5416reg.h,v retrieving revision 1.6 diff -u -p -r1.6 ar5416reg.h --- ar5416reg.h 5 Jan 2016 18:41:15 -0000 1.6 +++ ar5416reg.h 31 Jan 2019 12:14:47 -0000 @@ -19,7 +19,10 @@ #define AR5416_MAX_CHAINS 3 -#define AR5416_PHY_CCA_MAX_GOOD_VALUE ( -85) +#define AR5416_PHY_CCA_MIN_GOOD_VAL_2GHZ (-100) +#define AR5416_PHY_CCA_MIN_GOOD_VAL_5GHZ (-110) +#define AR5416_PHY_CCA_MAX_GOOD_VAL_2GHZ (-80) +#define AR5416_PHY_CCA_MAX_GOOD_VAL_5GHZ (-90) /* * ROM layout used by AR5416, AR9160 and AR9280. Index: ar9003.c =================================================================== RCS file: /cvs/src/sys/dev/ic/ar9003.c,v retrieving revision 1.46 diff -u -p -r1.46 ar9003.c --- ar9003.c 19 May 2017 11:42:48 -0000 1.46 +++ ar9003.c 31 Jan 2019 15:20:23 -0000 @@ -105,10 +105,11 @@ void ar9003_init_chains(struct athn_soft void ar9003_set_rxchains(struct athn_softc *); void ar9003_read_noisefloor(struct athn_softc *, int16_t *, int16_t *); void ar9003_write_noisefloor(struct athn_softc *, int16_t *, int16_t *); -void ar9003_get_noisefloor(struct athn_softc *, struct ieee80211_channel *); +int ar9003_get_noisefloor(struct athn_softc *); +void ar9003_apply_noisefloor(struct athn_softc *); void ar9003_bb_load_noisefloor(struct athn_softc *); -void ar9300_noisefloor_calib(struct athn_softc *); void ar9003_do_noisefloor_calib(struct athn_softc *); +void ar9003_init_noisefloor_calib(struct athn_softc *); int ar9003_init_calib(struct athn_softc *); void ar9003_do_calib(struct athn_softc *); void ar9003_next_calib(struct athn_softc *); @@ -185,6 +186,9 @@ ar9003_attach(struct athn_softc *sc) ops->disable_phy = ar9003_disable_phy; ops->set_rxchains = ar9003_set_rxchains; ops->noisefloor_calib = ar9003_do_noisefloor_calib; + ops->init_noisefloor_calib = ar9003_init_noisefloor_calib; + ops->get_noisefloor = ar9003_get_noisefloor; + ops->apply_noisefloor = ar9003_apply_noisefloor; ops->do_calib = ar9003_do_calib; ops->next_calib = ar9003_next_calib; ops->hw_init = ar9003_hw_init; @@ -1976,43 +1980,27 @@ ar9003_write_noisefloor(struct athn_soft AR_WRITE_BARRIER(sc); } -void -ar9003_get_noisefloor(struct athn_softc *sc, struct ieee80211_channel *c) +int +ar9003_get_noisefloor(struct athn_softc *sc) { int16_t nf[AR_MAX_CHAINS], nf_ext[AR_MAX_CHAINS]; - int16_t min, max; int i; if (AR_READ(sc, AR_PHY_AGC_CONTROL) & AR_PHY_AGC_CONTROL_NF) { /* Noisefloor calibration not finished. */ - return; + return 0; } /* Noisefloor calibration is finished. */ ar9003_read_noisefloor(sc, nf, nf_ext); - if (IEEE80211_IS_CHAN_2GHZ(c)) { - min = sc->cca_min_2g; - max = sc->cca_max_2g; - } else { - min = sc->cca_min_5g; - max = sc->cca_max_5g; - } /* Update noisefloor history. */ for (i = 0; i < sc->nrxchains; i++) { - if (nf[i] < min) - nf[i] = min; - else if (nf[i] > max) - nf[i] = max; - if (nf_ext[i] < min) - nf_ext[i] = min; - else if (nf_ext[i] > max) - nf_ext[i] = max; - sc->nf_hist[sc->nf_hist_cur].nf[i] = nf[i]; sc->nf_hist[sc->nf_hist_cur].nf_ext[i] = nf_ext[i]; } if (++sc->nf_hist_cur >= ATHN_NF_CAL_HIST_MAX) sc->nf_hist_cur = 0; + return 1; } void @@ -2050,17 +2038,43 @@ ar9003_bb_load_noisefloor(struct athn_so } void -ar9300_noisefloor_calib(struct athn_softc *sc) +ar9003_apply_noisefloor(struct athn_softc *sc) +{ + uint32_t agc_nfcal; + + agc_nfcal = AR_READ(sc, AR_PHY_AGC_CONTROL) & + (AR_PHY_AGC_CONTROL_NF | AR_PHY_AGC_CONTROL_ENABLE_NF | + AR_PHY_AGC_CONTROL_NO_UPDATE_NF); + + if (agc_nfcal & AR_PHY_AGC_CONTROL_NF) { + /* Pause running NF calibration while values are updated. */ + AR_CLRBITS(sc, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_NF); + AR_WRITE_BARRIER(sc); + } + + ar9003_bb_load_noisefloor(sc); + + if (agc_nfcal & AR_PHY_AGC_CONTROL_NF) { + /* Restart interrupted NF calibration. */ + AR_SETBITS(sc, AR_PHY_AGC_CONTROL, agc_nfcal); + AR_WRITE_BARRIER(sc); + } +} + +void +ar9003_do_noisefloor_calib(struct athn_softc *sc) { AR_SETBITS(sc, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_ENABLE_NF); AR_SETBITS(sc, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_NO_UPDATE_NF); AR_SETBITS(sc, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_NF); + AR_WRITE_BARRIER(sc); } void -ar9003_do_noisefloor_calib(struct athn_softc *sc) +ar9003_init_noisefloor_calib(struct athn_softc *sc) { AR_SETBITS(sc, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_NF); + AR_WRITE_BARRIER(sc); } int Index: ar9280.c =================================================================== RCS file: /cvs/src/sys/dev/ic/ar9280.c,v retrieving revision 1.26 diff -u -p -r1.26 ar9280.c --- ar9280.c 12 Jan 2017 16:32:28 -0000 1.26 +++ ar9280.c 31 Jan 2019 12:46:31 -0000 @@ -93,7 +93,6 @@ ar9280_attach(struct athn_softc *sc) { sc->eep_base = AR5416_EEP_START_LOC; sc->eep_size = sizeof(struct ar5416_eeprom); - sc->def_nf = AR9280_PHY_CCA_MAX_GOOD_VALUE; sc->ngpiopins = (sc->flags & ATHN_FLAG_USB) ? 16 : 10; sc->led_pin = 1; sc->workaround = AR9280_WA_DEFAULT; @@ -106,6 +105,10 @@ ar9280_attach(struct athn_softc *sc) sc->ops.get_spur_chans = ar5416_get_spur_chans; sc->ops.olpc_init = ar9280_olpc_init; sc->ops.olpc_temp_compensation = ar9280_olpc_temp_compensation; + sc->cca_min_2g = AR9280_PHY_CCA_MIN_GOOD_VAL_2GHZ; + sc->cca_max_2g = AR9280_PHY_CCA_MAX_GOOD_VAL_2GHZ; + sc->cca_min_5g = AR9280_PHY_CCA_MIN_GOOD_VAL_5GHZ; + sc->cca_max_5g = AR9280_PHY_CCA_MAX_GOOD_VAL_5GHZ; sc->ini = &ar9280_2_0_ini; sc->serdes = &ar9280_2_0_serdes; Index: ar9280reg.h =================================================================== RCS file: /cvs/src/sys/dev/ic/ar9280reg.h,v retrieving revision 1.7 diff -u -p -r1.7 ar9280reg.h --- ar9280reg.h 5 Jan 2016 18:41:15 -0000 1.7 +++ ar9280reg.h 31 Jan 2019 12:14:27 -0000 @@ -20,7 +20,11 @@ #define AR9280_MAX_CHAINS 2 #define AR9280_PD_GAIN_BOUNDARY_DEFAULT 56 -#define AR9280_PHY_CCA_MAX_GOOD_VALUE (-112) + +#define AR9280_PHY_CCA_MIN_GOOD_VAL_2GHZ (-127) +#define AR9280_PHY_CCA_MIN_GOOD_VAL_5GHZ (-122) +#define AR9280_PHY_CCA_MAX_GOOD_VAL_2GHZ (-97) +#define AR9280_PHY_CCA_MAX_GOOD_VAL_5GHZ (-102) #define AR9280_PHY_SYNTH_CONTROL 0x9874 Index: ar9285.c =================================================================== RCS file: /cvs/src/sys/dev/ic/ar9285.c,v retrieving revision 1.27 diff -u -p -r1.27 ar9285.c --- ar9285.c 12 Jan 2017 16:32:28 -0000 1.27 +++ ar9285.c 31 Jan 2019 12:29:54 -0000 @@ -104,7 +104,6 @@ ar9285_attach(struct athn_softc *sc) { sc->eep_base = AR9285_EEP_START_LOC; sc->eep_size = sizeof(struct ar9285_eeprom); - sc->def_nf = AR9285_PHY_CCA_MAX_GOOD_VALUE; sc->ngpiopins = (sc->flags & ATHN_FLAG_USB) ? 16 : 12; sc->led_pin = (sc->flags & ATHN_FLAG_USB) ? 15 : 1; sc->workaround = AR9285_WA_DEFAULT; @@ -115,6 +114,16 @@ ar9285_attach(struct athn_softc *sc) sc->ops.set_synth = ar9280_set_synth; sc->ops.spur_mitigate = ar9280_spur_mitigate; sc->ops.get_spur_chans = ar9285_get_spur_chans; +#if NATHN_USB > 0 + if (AR_SREV_9271(sc)) { + sc->cca_min_2g = AR9271_PHY_CCA_MIN_GOOD_VAL_2GHZ; + sc->cca_max_2g = AR9271_PHY_CCA_MAX_GOOD_VAL_2GHZ; + } else +#endif + { + sc->cca_min_2g = AR9285_PHY_CCA_MIN_GOOD_VAL_2GHZ; + sc->cca_max_2g = AR9285_PHY_CCA_MAX_GOOD_VAL_2GHZ; + } #if NATHN_USB > 0 if (AR_SREV_9271(sc)) sc->ini = &ar9271_ini; Index: ar9285reg.h =================================================================== RCS file: /cvs/src/sys/dev/ic/ar9285reg.h,v retrieving revision 1.8 diff -u -p -r1.8 ar9285reg.h --- ar9285reg.h 5 Jan 2016 18:41:15 -0000 1.8 +++ ar9285reg.h 31 Jan 2019 12:14:09 -0000 @@ -19,7 +19,10 @@ #define AR9285_MAX_CHAINS 1 -#define AR9285_PHY_CCA_MAX_GOOD_VALUE (-118) +#define AR9285_PHY_CCA_MIN_GOOD_VAL_2GHZ (-127) +#define AR9285_PHY_CCA_MAX_GOOD_VAL_2GHZ (-108) +#define AR9271_PHY_CCA_MIN_GOOD_VAL_2GHZ (-127) +#define AR9271_PHY_CCA_MAX_GOOD_VAL_2GHZ (-116) #define AR9285_CL_CAL_REDO_THRESH 1 Index: ar9287.c =================================================================== RCS file: /cvs/src/sys/dev/ic/ar9287.c,v retrieving revision 1.25 diff -u -p -r1.25 ar9287.c --- ar9287.c 12 Jan 2017 16:32:28 -0000 1.25 +++ ar9287.c 31 Jan 2019 12:30:04 -0000 @@ -102,7 +102,6 @@ ar9287_attach(struct athn_softc *sc) { sc->eep_base = AR9287_EEP_START_LOC; sc->eep_size = sizeof(struct ar9287_eeprom); - sc->def_nf = AR9287_PHY_CCA_MAX_GOOD_VALUE; sc->ngpiopins = (sc->flags & ATHN_FLAG_USB) ? 16 : 11; sc->led_pin = 8; sc->workaround = AR9285_WA_DEFAULT; @@ -115,6 +114,8 @@ ar9287_attach(struct athn_softc *sc) sc->ops.get_spur_chans = ar9287_get_spur_chans; sc->ops.olpc_init = ar9287_olpc_init; sc->ops.olpc_temp_compensation = ar9287_olpc_temp_compensation; + sc->cca_min_2g = AR9287_PHY_CCA_MIN_GOOD_VAL_2GHZ; + sc->cca_max_2g = AR9287_PHY_CCA_MAX_GOOD_VAL_2GHZ; sc->ini = &ar9287_1_1_ini; sc->serdes = &ar9280_2_0_serdes; Index: ar9287reg.h =================================================================== RCS file: /cvs/src/sys/dev/ic/ar9287reg.h,v retrieving revision 1.4 diff -u -p -r1.4 ar9287reg.h --- ar9287reg.h 5 Jan 2016 18:41:15 -0000 1.4 +++ ar9287reg.h 31 Jan 2019 12:14:04 -0000 @@ -19,7 +19,8 @@ #define AR9287_MAX_CHAINS 2 -#define AR9287_PHY_CCA_MAX_GOOD_VALUE (-118) +#define AR9287_PHY_CCA_MIN_GOOD_VAL_2GHZ (-127) +#define AR9287_PHY_CCA_MAX_GOOD_VAL_2GHZ (-97) /* * Analog registers. Index: athn.c =================================================================== RCS file: /cvs/src/sys/dev/ic/athn.c,v retrieving revision 1.100 diff -u -p -r1.100 athn.c --- athn.c 31 Jan 2019 11:38:52 -0000 1.100 +++ athn.c 31 Jan 2019 15:19:15 -0000 @@ -95,6 +95,10 @@ int athn_set_key(struct ieee80211com *, void athn_delete_key(struct ieee80211com *, struct ieee80211_node *, struct ieee80211_key *); void athn_iter_calib(void *, struct ieee80211_node *); +int athn_cap_noisefloor(struct athn_softc *, int); +int athn_nf_hist_mid(int *, int); +void athn_filter_noisefloor(struct athn_softc *); +void athn_start_noisefloor_calib(struct athn_softc *, int); void athn_calib_to(void *); int athn_init_calib(struct athn_softc *, struct ieee80211_channel *, struct ieee80211_channel *); @@ -890,7 +894,6 @@ athn_set_chan(struct athn_softc *sc, str ops->set_delta_slope(sc, c, extc); ops->spur_mitigate(sc, c, extc); - /* XXX Load noisefloor values and start calibration. */ return (0); } @@ -1236,6 +1239,94 @@ athn_iter_calib(void *arg, struct ieee80 ieee80211_amrr_choose(&sc->amrr, ni, &an->amn); } +int +athn_cap_noisefloor(struct athn_softc *sc, int nf) +{ + int16_t min, max; + + if (nf == 0 || nf == -1) /* invalid measurement */ + return AR_DEFAULT_NOISE_FLOOR; + + if (IEEE80211_IS_CHAN_2GHZ(sc->sc_ic.ic_bss->ni_chan)) { + min = sc->cca_min_2g; + max = sc->cca_max_2g; + } else { + min = sc->cca_min_5g; + max = sc->cca_max_5g; + } + + if (nf < min) + return min; + if (nf > max) + return max; + + return nf; +} + +int +athn_nf_hist_mid(int *nf_vals, int nvalid) +{ + int nf_sorted[ATHN_NF_CAL_HIST_MAX]; + int i, j, nf; + + if (nvalid <= 1) + return nf_vals[0]; + + for (i = 0; i < nvalid; i++) + nf_sorted[i] = nf_vals[i]; + + for (i = 0; i < nvalid; i++) { + for (j = 1; j < nvalid - i; j++) { + if (nf_sorted[j] > nf_sorted[j - 1]) { + nf = nf_sorted[j]; + nf_sorted[j] = nf_sorted[j - 1]; + nf_sorted[j - 1] = nf; + } + } + } + + return nf_sorted[nvalid / 2]; +} + +void +athn_filter_noisefloor(struct athn_softc *sc) +{ + int nf_vals[ATHN_NF_CAL_HIST_MAX]; + int nf_ext_vals[ATHN_NF_CAL_HIST_MAX]; + int i, cur, n; + + for (i = 0; i < sc->ntxchains; i++) { + if (sc->nf_hist_cur > 0) + cur = sc->nf_hist_cur - 1; + else + cur = ATHN_NF_CAL_HIST_MAX - 1; + for (n = 0; n < sc->nf_hist_nvalid; n++) { + nf_vals[n] = sc->nf_hist[cur].nf[i]; + nf_ext_vals[n] = sc->nf_hist[cur].nf_ext[i]; + if (++cur >= ATHN_NF_CAL_HIST_MAX) + cur = 0; + } + sc->nf_priv[i] = athn_cap_noisefloor(sc, + athn_nf_hist_mid(nf_vals, sc->nf_hist_nvalid)); + sc->nf_ext_priv[i] = athn_cap_noisefloor(sc, + athn_nf_hist_mid(nf_ext_vals, sc->nf_hist_nvalid)); + } +} + +void +athn_start_noisefloor_calib(struct athn_softc *sc, int reset_history) +{ + extern int ticks; + + if (reset_history) + sc->nf_hist_nvalid = 0; + + sc->nf_calib_pending = 1; + sc->nf_calib_ticks = ticks; + + sc->ops.noisefloor_calib(sc); +} + void athn_calib_to(void *arg) { @@ -1258,6 +1349,17 @@ athn_calib_to(void *arg) ar9285_pa_calib(sc); } + /* Do periodic (every 4 minutes) NF calibration. */ + if (sc->nf_calib_pending && ops->get_noisefloor(sc)) { + if (sc->nf_hist_nvalid < ATHN_NF_CAL_HIST_MAX) + sc->nf_hist_nvalid++; + athn_filter_noisefloor(sc); + ops->apply_noisefloor(sc); + sc->nf_calib_pending = 0; + } + if (ticks - (sc->nf_calib_ticks + 240 * hz) >= 0) + athn_start_noisefloor_calib(sc, 0); + /* Do periodic (every 30 seconds) temperature compensation. */ if ((sc->flags & ATHN_FLAG_OLPC) && ticks >= sc->olpc_ticks + 30 * hz) { @@ -1318,9 +1420,11 @@ athn_init_calib(struct athn_softc *sc, s else ar9285_pa_calib(sc); } - /* Do noisefloor calibration. */ - ops->noisefloor_calib(sc); } + + /* Do noisefloor calibration. */ + ops->init_noisefloor_calib(sc); + if (AR_SREV_9160_10_OR_LATER(sc)) { /* Support IQ calibration. */ sc->sup_calib_mask = ATHN_CAL_IQ; @@ -2567,6 +2671,7 @@ athn_newstate(struct ieee80211com *ic, e } /* XXX Start ANI. */ + athn_start_noisefloor_calib(sc, 1); timeout_add_msec(&sc->calib_to, 500); break; } Index: athnreg.h =================================================================== RCS file: /cvs/src/sys/dev/ic/athnreg.h,v retrieving revision 1.21 diff -u -p -r1.21 athnreg.h --- athnreg.h 28 Nov 2017 04:35:39 -0000 1.21 +++ athnreg.h 31 Jan 2019 12:36:17 -0000 @@ -1449,7 +1449,7 @@ #define AR_CTL_2GHT40 7 #define AR_CTL_5GHT40 8 -#define AR_DEFAULT_NOISE_FLOOR (-95) +#define AR_DEFAULT_NOISE_FLOOR (-100) /* * Macros to access registers. Index: athnvar.h =================================================================== RCS file: /cvs/src/sys/dev/ic/athnvar.h,v retrieving revision 1.38 diff -u -p -r1.38 athnvar.h --- athnvar.h 31 Jan 2019 11:38:52 -0000 1.38 +++ athnvar.h 31 Jan 2019 15:16:00 -0000 @@ -408,6 +408,9 @@ struct athn_ops { void (*disable_phy)(struct athn_softc *); void (*set_rxchains)(struct athn_softc *); void (*noisefloor_calib)(struct athn_softc *); + void (*init_noisefloor_calib)(struct athn_softc *); + int (*get_noisefloor)(struct athn_softc *); + void (*apply_noisefloor)(struct athn_softc *); void (*do_calib)(struct athn_softc *); void (*next_calib)(struct athn_softc *); void (*hw_init)(struct athn_softc *, struct ieee80211_channel *, @@ -550,14 +553,16 @@ struct athn_softc { int16_t cca_max_2g; int16_t cca_min_5g; int16_t cca_max_5g; - int16_t def_nf; struct { int16_t nf[AR_MAX_CHAINS]; int16_t nf_ext[AR_MAX_CHAINS]; } nf_hist[ATHN_NF_CAL_HIST_MAX]; int nf_hist_cur; + int nf_hist_nvalid; int16_t nf_priv[AR_MAX_CHAINS]; int16_t nf_ext_priv[AR_MAX_CHAINS]; + int nf_calib_pending; + int nf_calib_ticks; int pa_calib_ticks; struct athn_calib calib;