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];