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.
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 13:39:55 -0000
@@ -98,9 +98,9 @@ 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_do_calib(struct athn_softc *);
void ar5008_next_calib(struct athn_softc *);
@@ -176,6 +176,8 @@ 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->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 +1878,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 +1898,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,24 +1929,44 @@ 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)
{
- 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);
+ 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);
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 13:58:47 -0000
@@ -105,9 +105,9 @@ 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 *);
int ar9003_init_calib(struct athn_softc *);
void ar9003_do_calib(struct athn_softc *);
@@ -185,6 +185,8 @@ 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->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 +1978,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 +2036,36 @@ ar9003_bb_load_noisefloor(struct athn_so
}
void
-ar9300_noisefloor_calib(struct athn_softc *sc)
+ar9003_apply_noisefloor(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);
+ 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);
}
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 14:27:55 -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,7 @@ 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. */
+ athn_start_noisefloor_calib(sc, 1);
return (0);
}
@@ -1236,6 +1240,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 +1350,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) {
@@ -1296,7 +1399,6 @@ int
athn_init_calib(struct athn_softc *sc, struct ieee80211_channel *c,
struct ieee80211_channel *extc)
{
- struct athn_ops *ops = &sc->ops;
int error;
if (AR_SREV_9380_10_OR_LATER(sc))
@@ -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. */
+ athn_start_noisefloor_calib(sc, 1);
+
if (AR_SREV_9160_10_OR_LATER(sc)) {
/* Support IQ calibration. */
sc->sup_calib_mask = ATHN_CAL_IQ;
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 14:07:51 -0000
@@ -408,6 +408,8 @@ struct athn_ops {
void (*disable_phy)(struct athn_softc *);
void (*set_rxchains)(struct athn_softc *);
void (*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 +552,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;