From 46efbaf202c025a8e4dbbfff0cf154f54415212b Mon Sep 17 00:00:00 2001 From: Stefan Sperling Date: Fri, 1 Feb 2019 16:15:08 +0000 Subject: Complete athn(4) noisefloor calibration code and enable it. Update default/min/max noisefloor values to those used by Linux ath9k. Tested by jmc, juanfra, kn, and myself, on 9280 and 9271 devices. --- sys/dev/ic/ar5008.c | 50 ++++++++++++++++++---- sys/dev/ic/ar5416.c | 7 ++- sys/dev/ic/ar5416reg.h | 7 ++- sys/dev/ic/ar9003.c | 64 +++++++++++++++++----------- sys/dev/ic/ar9280.c | 7 ++- sys/dev/ic/ar9280reg.h | 8 +++- sys/dev/ic/ar9285.c | 13 +++++- sys/dev/ic/ar9285reg.h | 7 ++- sys/dev/ic/ar9287.c | 5 ++- sys/dev/ic/ar9287reg.h | 5 ++- sys/dev/ic/athn.c | 113 +++++++++++++++++++++++++++++++++++++++++++++++-- sys/dev/ic/athnreg.h | 4 +- sys/dev/ic/athnvar.h | 9 +++- 13 files changed, 241 insertions(+), 58 deletions(-) (limited to 'sys') diff --git a/sys/dev/ic/ar5008.c b/sys/dev/ic/ar5008.c index e0188134edd..4eb38555957 100644 --- a/sys/dev/ic/ar5008.c +++ b/sys/dev/ic/ar5008.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ar5008.c,v 1.46 2017/11/28 04:35:39 stsp Exp $ */ +/* $OpenBSD: ar5008.c,v 1.47 2019/02/01 16:15:07 stsp Exp $ */ /*- * Copyright (c) 2009 Damien Bergamini @@ -98,10 +98,11 @@ void ar5008_init_chains(struct athn_softc *); 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_softc *sc, int16_t *nf, int16_t *nf_ext) 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 *sc, struct ieee80211_channel *c) } 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_softc *sc) 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_softc *sc) } 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); diff --git a/sys/dev/ic/ar5416.c b/sys/dev/ic/ar5416.c index 1cb5d545068..c2b0d05b3fe 100644 --- a/sys/dev/ic/ar5416.c +++ b/sys/dev/ic/ar5416.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ar5416.c,v 1.20 2017/01/12 16:32:28 stsp Exp $ */ +/* $OpenBSD: ar5416.c,v 1.21 2019/02/01 16:15:07 stsp Exp $ */ /*- * Copyright (c) 2009 Damien Bergamini @@ -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 diff --git a/sys/dev/ic/ar5416reg.h b/sys/dev/ic/ar5416reg.h index 826d8078f34..bb952828e8b 100644 --- a/sys/dev/ic/ar5416reg.h +++ b/sys/dev/ic/ar5416reg.h @@ -1,4 +1,4 @@ -/* $OpenBSD: ar5416reg.h,v 1.6 2016/01/05 18:41:15 stsp Exp $ */ +/* $OpenBSD: ar5416reg.h,v 1.7 2019/02/01 16:15:07 stsp Exp $ */ /*- * Copyright (c) 2009 Damien Bergamini @@ -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. diff --git a/sys/dev/ic/ar9003.c b/sys/dev/ic/ar9003.c index 15a6173e16f..ba520b645d9 100644 --- a/sys/dev/ic/ar9003.c +++ b/sys/dev/ic/ar9003.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ar9003.c,v 1.46 2017/05/19 11:42:48 stsp Exp $ */ +/* $OpenBSD: ar9003.c,v 1.47 2019/02/01 16:15:07 stsp Exp $ */ /*- * Copyright (c) 2010 Damien Bergamini @@ -105,10 +105,11 @@ void ar9003_init_chains(struct athn_softc *); 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_softc *sc, int16_t *nf, int16_t *nf_ext) 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_softc *sc) } 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 diff --git a/sys/dev/ic/ar9280.c b/sys/dev/ic/ar9280.c index 4c3c549daf0..acb00c62ed2 100644 --- a/sys/dev/ic/ar9280.c +++ b/sys/dev/ic/ar9280.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ar9280.c,v 1.26 2017/01/12 16:32:28 stsp Exp $ */ +/* $OpenBSD: ar9280.c,v 1.27 2019/02/01 16:15:07 stsp Exp $ */ /*- * Copyright (c) 2009 Damien Bergamini @@ -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; diff --git a/sys/dev/ic/ar9280reg.h b/sys/dev/ic/ar9280reg.h index a7753ad5dc0..7fcff328809 100644 --- a/sys/dev/ic/ar9280reg.h +++ b/sys/dev/ic/ar9280reg.h @@ -1,4 +1,4 @@ -/* $OpenBSD: ar9280reg.h,v 1.7 2016/01/05 18:41:15 stsp Exp $ */ +/* $OpenBSD: ar9280reg.h,v 1.8 2019/02/01 16:15:07 stsp Exp $ */ /*- * Copyright (c) 2009 Damien Bergamini @@ -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 diff --git a/sys/dev/ic/ar9285.c b/sys/dev/ic/ar9285.c index a817b0dcef6..057ea48e06b 100644 --- a/sys/dev/ic/ar9285.c +++ b/sys/dev/ic/ar9285.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ar9285.c,v 1.27 2017/01/12 16:32:28 stsp Exp $ */ +/* $OpenBSD: ar9285.c,v 1.28 2019/02/01 16:15:07 stsp Exp $ */ /*- * Copyright (c) 2009-2010 Damien Bergamini @@ -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; diff --git a/sys/dev/ic/ar9285reg.h b/sys/dev/ic/ar9285reg.h index 0a11b9fbf85..13f889c0f61 100644 --- a/sys/dev/ic/ar9285reg.h +++ b/sys/dev/ic/ar9285reg.h @@ -1,4 +1,4 @@ -/* $OpenBSD: ar9285reg.h,v 1.8 2016/01/05 18:41:15 stsp Exp $ */ +/* $OpenBSD: ar9285reg.h,v 1.9 2019/02/01 16:15:07 stsp Exp $ */ /*- * Copyright (c) 2009 Damien Bergamini @@ -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 diff --git a/sys/dev/ic/ar9287.c b/sys/dev/ic/ar9287.c index e61f78427c0..74025dba1af 100644 --- a/sys/dev/ic/ar9287.c +++ b/sys/dev/ic/ar9287.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ar9287.c,v 1.25 2017/01/12 16:32:28 stsp Exp $ */ +/* $OpenBSD: ar9287.c,v 1.26 2019/02/01 16:15:07 stsp Exp $ */ /*- * Copyright (c) 2009 Damien Bergamini @@ -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; diff --git a/sys/dev/ic/ar9287reg.h b/sys/dev/ic/ar9287reg.h index d00f8fd6458..340b28c2f84 100644 --- a/sys/dev/ic/ar9287reg.h +++ b/sys/dev/ic/ar9287reg.h @@ -1,4 +1,4 @@ -/* $OpenBSD: ar9287reg.h,v 1.4 2016/01/05 18:41:15 stsp Exp $ */ +/* $OpenBSD: ar9287reg.h,v 1.5 2019/02/01 16:15:07 stsp Exp $ */ /*- * Copyright (c) 2009 Damien Bergamini @@ -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. diff --git a/sys/dev/ic/athn.c b/sys/dev/ic/athn.c index ff3bfbc622d..af5296bfd5e 100644 --- a/sys/dev/ic/athn.c +++ b/sys/dev/ic/athn.c @@ -1,4 +1,4 @@ -/* $OpenBSD: athn.c,v 1.100 2019/01/31 11:38:52 stsp Exp $ */ +/* $OpenBSD: athn.c,v 1.101 2019/02/01 16:15:07 stsp Exp $ */ /*- * Copyright (c) 2009 Damien Bergamini @@ -95,6 +95,10 @@ int athn_set_key(struct ieee80211com *, struct ieee80211_node *, 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, struct ieee80211_channel *c, 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 ieee80211_node *ni) 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, struct ieee80211_channel *c, 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, enum ieee80211_state nstate, int arg) } /* XXX Start ANI. */ + athn_start_noisefloor_calib(sc, 1); timeout_add_msec(&sc->calib_to, 500); break; } diff --git a/sys/dev/ic/athnreg.h b/sys/dev/ic/athnreg.h index e8dd7005980..0f5eba6c25e 100644 --- a/sys/dev/ic/athnreg.h +++ b/sys/dev/ic/athnreg.h @@ -1,4 +1,4 @@ -/* $OpenBSD: athnreg.h,v 1.21 2017/11/28 04:35:39 stsp Exp $ */ +/* $OpenBSD: athnreg.h,v 1.22 2019/02/01 16:15:07 stsp Exp $ */ /*- * Copyright (c) 2009 Damien Bergamini @@ -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. diff --git a/sys/dev/ic/athnvar.h b/sys/dev/ic/athnvar.h index ac873da792e..68fd90a042e 100644 --- a/sys/dev/ic/athnvar.h +++ b/sys/dev/ic/athnvar.h @@ -1,4 +1,4 @@ -/* $OpenBSD: athnvar.h,v 1.38 2019/01/31 11:38:52 stsp Exp $ */ +/* $OpenBSD: athnvar.h,v 1.39 2019/02/01 16:15:07 stsp Exp $ */ /*- * Copyright (c) 2009 Damien Bergamini @@ -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; -- cgit v1.2.3