summaryrefslogtreecommitdiff
path: root/sys/dev/ic
diff options
context:
space:
mode:
authorStefan Sperling <stsp@cvs.openbsd.org>2019-02-01 16:15:08 +0000
committerStefan Sperling <stsp@cvs.openbsd.org>2019-02-01 16:15:08 +0000
commit46efbaf202c025a8e4dbbfff0cf154f54415212b (patch)
tree5b87b71827aa7ffefdb2ecd5a7dd69bcaae95044 /sys/dev/ic
parentf1fef60d11b5f73972babd61e2a5e188505039e5 (diff)
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.
Diffstat (limited to 'sys/dev/ic')
-rw-r--r--sys/dev/ic/ar5008.c50
-rw-r--r--sys/dev/ic/ar5416.c7
-rw-r--r--sys/dev/ic/ar5416reg.h7
-rw-r--r--sys/dev/ic/ar9003.c64
-rw-r--r--sys/dev/ic/ar9280.c7
-rw-r--r--sys/dev/ic/ar9280reg.h8
-rw-r--r--sys/dev/ic/ar9285.c13
-rw-r--r--sys/dev/ic/ar9285reg.h7
-rw-r--r--sys/dev/ic/ar9287.c5
-rw-r--r--sys/dev/ic/ar9287reg.h5
-rw-r--r--sys/dev/ic/athn.c113
-rw-r--r--sys/dev/ic/athnreg.h4
-rw-r--r--sys/dev/ic/athnvar.h9
13 files changed, 241 insertions, 58 deletions
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 <damien.bergamini@free.fr>
@@ -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 <damien.bergamini@free.fr>
@@ -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 <damien.bergamini@free.fr>
@@ -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 <damien.bergamini@free.fr>
@@ -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 <damien.bergamini@free.fr>
@@ -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 <damien.bergamini@free.fr>
@@ -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 <damien.bergamini@free.fr>
@@ -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;
@@ -116,6 +115,16 @@ ar9285_attach(struct athn_softc *sc)
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;
else
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 <damien.bergamini@free.fr>
@@ -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 <damien.bergamini@free.fr>
@@ -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 <damien.bergamini@free.fr>
@@ -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 <damien.bergamini@free.fr>
@@ -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 <damien.bergamini@free.fr>
@@ -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 <damien.bergamini@free.fr>
@@ -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;