From 6b28e6577015b720d1c2c073aa43558e13f1999f Mon Sep 17 00:00:00 2001 From: Sepherosa Ziehau Date: Fri, 6 Jun 2008 10:47:14 +0000 Subject: [PATCH] Add periodic rf calibration support for acx111 part. This seems to stablize performance during long time TX stress. --- sys/dev/netif/acx/_acxcmd.h | 3 ++- sys/dev/netif/acx/acx111.c | 33 ++++++++++++++++++++++++- sys/dev/netif/acx/if_acx.c | 45 +++++++++++++++++++++++++++++++++-- sys/dev/netif/acx/if_acxvar.h | 7 +++++- 4 files changed, 83 insertions(+), 5 deletions(-) diff --git a/sys/dev/netif/acx/_acxcmd.h b/sys/dev/netif/acx/_acxcmd.h index 87c060f4b6..ed457e72fd 100644 --- a/sys/dev/netif/acx/_acxcmd.h +++ b/sys/dev/netif/acx/_acxcmd.h @@ -31,7 +31,7 @@ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $DragonFly: src/sys/dev/netif/acx/_acxcmd.h,v 1.1 2006/04/01 02:55:36 sephe Exp $ + * $DragonFly: src/sys/dev/netif/acx/_acxcmd.h,v 1.2 2008/06/06 10:47:14 sephe Exp $ */ #ifndef _X_ACXCMD_H @@ -52,6 +52,7 @@ #define ACXCMD_TMPLT_NULL_DATA 0x15 #define ACXCMD_TMPLT_PROBE_REQ 0x16 #define ACXCMD_INIT_RADIO 0x18 +#define ACXCMD_CALIBRATE 0x19 /* acx111 */ #if 0 /* diff --git a/sys/dev/netif/acx/acx111.c b/sys/dev/netif/acx/acx111.c index a885ae1723..5cbb4ba7a1 100644 --- a/sys/dev/netif/acx/acx111.c +++ b/sys/dev/netif/acx/acx111.c @@ -31,7 +31,7 @@ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $DragonFly: src/sys/dev/netif/acx/acx111.c,v 1.14 2008/06/01 04:01:24 sephe Exp $ + * $DragonFly: src/sys/dev/netif/acx/acx111.c,v 1.15 2008/06/06 10:47:14 sephe Exp $ */ #include @@ -113,6 +113,19 @@ struct acx111_bss_join { uint8_t dtim_intvl; } __packed; +struct acx111_calib { + uint32_t calib; /* ACX111_CALIB_ */ + uint32_t interval; /* TU */ +} __packed; + +#define ACX111_CALIB_AUTO 0x80000000 +#define ACX111_CALIB_DC 0x00000001 +#define ACX111_CALIB_AFE_DC 0x00000002 +#define ACX111_CALIB_TX_MISMATCH 0x00000004 +#define ACX111_CALIB_TX_EQUAL 0x00000008 + +#define ACX111_FW_CALIB_INTVL IEEE80211_MS_TO_TU(60000) /* 60sec */ + struct acx111_conf_mem { struct acx_conf confcom; @@ -298,6 +311,7 @@ static void acx111_init_fw_txring(struct acx_softc *, uint32_t); static int acx111_write_config(struct acx_softc *, struct acx_config *); static void acx111_set_bss_join_param(struct acx_softc *, void *, int); +static int acx111_calibrate(struct acx_softc *); static void *acx111_ratectl_attach(struct ieee80211com *, u_int); @@ -356,6 +370,7 @@ acx111_set_param(device_t dev) sc->chip_gpio_pled = ACX111_GPIO_POWER_LED; sc->chip_ee_eaddr_ofs = ACX111_EE_EADDR_OFS; sc->chip_rssi_corr = ACX111_RSSI_CORR; + sc->chip_calibrate = acx111_calibrate; sc->chip_phymode = IEEE80211_MODE_11G; sc->chip_chan_flags = IEEE80211_CHAN_CCK | @@ -747,3 +762,19 @@ acx111_tx_complete_amrr(struct acx_softc *sc, struct acx_txbuf *tx_buf, _acx111_tx_complete(sc, tx_buf, frame_len, is_fail, acx111_amrr_tries); } + +static int +acx111_calibrate(struct acx_softc *sc) +{ + struct acx111_calib calib; + + calib.calib = htole32(ACX111_CALIB_AUTO | + ACX111_CALIB_DC | + ACX111_CALIB_AFE_DC | + ACX111_CALIB_TX_MISMATCH | + ACX111_CALIB_TX_EQUAL); + calib.interval = htole32(ACX111_FW_CALIB_INTVL); + + return acx_exec_command(sc, ACXCMD_CALIBRATE, &calib, sizeof(calib), + NULL, 0); +} diff --git a/sys/dev/netif/acx/if_acx.c b/sys/dev/netif/acx/if_acx.c index 556b9709be..026fcf67ff 100644 --- a/sys/dev/netif/acx/if_acx.c +++ b/sys/dev/netif/acx/if_acx.c @@ -31,7 +31,7 @@ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $DragonFly: src/sys/dev/netif/acx/if_acx.c,v 1.28 2008/05/31 13:12:59 sephe Exp $ + * $DragonFly: src/sys/dev/netif/acx/if_acx.c,v 1.29 2008/06/06 10:47:14 sephe Exp $ */ /* @@ -134,6 +134,7 @@ static int acx_read_config(struct acx_softc *, struct acx_config *); static int acx_write_config(struct acx_softc *, struct acx_config *); static int acx_rx_config(struct acx_softc *, int); static int acx_set_crypt_keys(struct acx_softc *); +static void acx_calibrate(void *); static int acx_dma_alloc(struct acx_softc *); static void acx_dma_free(struct acx_softc *); @@ -319,9 +320,12 @@ acx_attach(device_t dev) goto fail; } - /* Initilize channel scanning timer */ + /* Initialize channel scanning timer */ callout_init(&sc->sc_scan_timer); + /* Initialize calibration timer */ + callout_init(&sc->sc_calibrate_timer); + /* Allocate busdma stuffs */ error = acx_dma_alloc(sc); if (error) @@ -380,6 +384,7 @@ acx_attach(device_t dev) sc->sc_long_retry_limit = 4; sc->sc_msdu_lifetime = 4096; sc->sc_scan_dwell = 200; /* 200 milliseconds */ + sc->sc_calib_intvl = 3 * 60; /* 3 minutes */ sysctl_ctx_init(&sc->sc_sysctl_ctx); sc->sc_sysctl_tree = SYSCTL_ADD_NODE(&sc->sc_sysctl_ctx, @@ -406,6 +411,10 @@ acx_attach(device_t dev) SYSCTL_CHILDREN(sc->sc_sysctl_tree), OID_AUTO, "scan_dwell", CTLFLAG_RW, &sc->sc_scan_dwell, 0, "Scan channel dwell time (ms)"); + SYSCTL_ADD_INT(&sc->sc_sysctl_ctx, + SYSCTL_CHILDREN(sc->sc_sysctl_tree), OID_AUTO, + "calib_intvl", CTLFLAG_RW, + &sc->sc_calib_intvl, 0, "Calibration interval (second)"); /* * Nodes for firmware operation @@ -1964,6 +1973,7 @@ acx_newstate(struct ieee80211com *ic, enum ieee80211_state nstate, int arg) ieee80211_ratectl_newstate(ic, nstate); callout_stop(&sc->sc_scan_timer); + callout_stop(&sc->sc_calibrate_timer); switch (nstate) { case IEEE80211_S_SCAN: @@ -2020,6 +2030,21 @@ acx_newstate(struct ieee80211com *ic, enum ieee80211_state nstate, int arg) } } + if (nstate == IEEE80211_S_RUN) { + int interval = sc->sc_calib_intvl; + + if (sc->chip_calibrate != NULL) { + error = sc->chip_calibrate(sc); + if (error) { + /* + * Restart calibration some time later + */ + interval = 10; + } + callout_reset(&sc->sc_calibrate_timer, + hz * interval, acx_calibrate, sc); + } + } error = 0; back: if (error) { @@ -2750,3 +2775,19 @@ acx_set_chan(struct acx_softc *sc, struct ieee80211_channel *c) htole16(flags); return 0; } + +static void +acx_calibrate(void *xsc) +{ + struct acx_softc *sc = xsc; + struct ifnet *ifp = &sc->sc_ic.ic_if; + + lwkt_serialize_enter(ifp->if_serializer); + if (sc->chip_calibrate != NULL && + sc->sc_ic.ic_state == IEEE80211_S_RUN) { + sc->chip_calibrate(sc); + callout_reset(&sc->sc_calibrate_timer, hz * sc->sc_calib_intvl, + acx_calibrate, sc); + } + lwkt_serialize_exit(ifp->if_serializer); +} diff --git a/sys/dev/netif/acx/if_acxvar.h b/sys/dev/netif/acx/if_acxvar.h index cf45911ed8..38c8574a5b 100644 --- a/sys/dev/netif/acx/if_acxvar.h +++ b/sys/dev/netif/acx/if_acxvar.h @@ -31,7 +31,7 @@ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $DragonFly: src/sys/dev/netif/acx/if_acxvar.h,v 1.12 2008/02/06 08:21:22 sephe Exp $ + * $DragonFly: src/sys/dev/netif/acx/if_acxvar.h,v 1.13 2008/06/06 10:47:14 sephe Exp $ */ #ifndef _IF_ACXVAR_H @@ -459,6 +459,7 @@ struct acx_softc { */ int sc_msdu_lifetime; int sc_scan_dwell; /* unit: millisecond */ + int sc_calib_intvl; /* unit: minute */ int (*sc_newstate) (struct ieee80211com *, @@ -490,6 +491,10 @@ struct acx_softc { void (*chip_proc_wep_rxbuf) (struct acx_softc *, struct mbuf *, int *); + + struct callout sc_calibrate_timer; + int (*chip_calibrate) + (struct acx_softc *); }; #define ACX_FLAG_FW_LOADED 0x1 -- 2.41.0