The diff below enables periodic ADC/IQ calibration on athn(4) devices.
Without this calibration athn devices might perform suboptimally
as they warm up during operation.
The code is already there, it was just not being called yet.
I don't know why it was left disabled but it seems to cause no harm on
my access points, though it doesn't make any notable difference either.
I would like to get some test reports to see whether enabling
calibration causes problems or behaviour changes for anyone.
Index: athn.c
===================================================================
RCS file: /cvs/src/sys/dev/ic/athn.c,v
retrieving revision 1.99
diff -u -p -r1.99 athn.c
--- athn.c 26 Apr 2018 12:50:07 -0000 1.99
+++ athn.c 29 Jan 2019 19:45:21 -0000
@@ -1268,9 +1268,20 @@ athn_calib_to(void *arg)
#ifdef notyet
/* XXX ANI. */
athn_ani_monitor(sc);
-
- ops->next_calib(sc);
#endif
+
+ /* Do periodic (every 30 seconds) ADC/IQ calibration. */
+ if (sc->cur_calib_mask != 0) {
+ ops->next_calib(sc);
+ sc->iqcal_ticks = ticks;
+ } else if (sc->sup_calib_mask != 0 &&
+ ticks >= sc->iqcal_ticks + 30 * hz) {
+ memset(&sc->calib, 0, sizeof(sc->calib));
+ sc->cur_calib_mask = sc->sup_calib_mask;
+ ops->do_calib(sc);
+ sc->iqcal_ticks = ticks;
+ }
+
if (ic->ic_fixed_rate == -1) {
if (ic->ic_opmode == IEEE80211_M_STA)
athn_iter_calib(sc, ic->ic_bss);
@@ -2552,7 +2563,7 @@ athn_newstate(struct ieee80211com *ic, e
if (sc->sup_calib_mask != 0) {
memset(&sc->calib, 0, sizeof(sc->calib));
sc->cur_calib_mask = sc->sup_calib_mask;
- /* ops->do_calib(sc); */
+ sc->ops.do_calib(sc);
}
/* XXX Start ANI. */
Index: athnvar.h
===================================================================
RCS file: /cvs/src/sys/dev/ic/athnvar.h,v
retrieving revision 1.37
diff -u -p -r1.37 athnvar.h
--- athnvar.h 12 Jan 2017 16:32:28 -0000 1.37
+++ athnvar.h 29 Jan 2019 18:15:34 -0000
@@ -494,6 +494,7 @@ struct athn_softc {
int8_t pdadc;
int8_t tcomp;
int olpc_ticks;
+ int iqcal_ticks;
/* PA predistortion. */
uint16_t gain1[AR_MAX_CHAINS];