Date: Wed, 20 Jan 2016 23:55:39 +0000 (UTC) From: Andriy Voskoboinyk <avos@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r294473 - head/sys/dev/usb/wlan Message-ID: <201601202355.u0KNtdWh076127@repo.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: avos Date: Wed Jan 20 23:55:39 2016 New Revision: 294473 URL: https://svnweb.freebsd.org/changeset/base/294473 Log: urtwn: add temperature calibration Redo LC calibration if temperature changed significantly since last calibration. Tested with RTL8188EU/RTL8188CUS in STA mode. Reviewed by: kevlo Approved by: adrian (mentor) Obtained from: NetBSD (mostly) Differential Revision: https://reviews.freebsd.org/D4966 Modified: head/sys/dev/usb/wlan/if_urtwn.c head/sys/dev/usb/wlan/if_urtwnreg.h head/sys/dev/usb/wlan/if_urtwnvar.h Modified: head/sys/dev/usb/wlan/if_urtwn.c ============================================================================== --- head/sys/dev/usb/wlan/if_urtwn.c Wed Jan 20 23:33:58 2016 (r294472) +++ head/sys/dev/usb/wlan/if_urtwn.c Wed Jan 20 23:55:39 2016 (r294473) @@ -286,6 +286,9 @@ static void urtwn_ibss_recv_mgmt(struct const struct ieee80211_rx_stats *, int, int); static int urtwn_newstate(struct ieee80211vap *, enum ieee80211_state, int); +static void urtwn_calib_to(void *); +static void urtwn_calib_cb(struct urtwn_softc *, + union sec_param *); static void urtwn_watchdog(void *); static void urtwn_update_avgrssi(struct urtwn_softc *, int, int8_t); static int8_t urtwn_get_rssi(struct urtwn_softc *, int, void *); @@ -353,6 +356,7 @@ static void urtwn_set_chan(struct urtwn struct ieee80211_channel *); static void urtwn_iq_calib(struct urtwn_softc *); static void urtwn_lc_calib(struct urtwn_softc *); +static void urtwn_temp_calib(struct urtwn_softc *); static int urtwn_init(struct urtwn_softc *); static void urtwn_stop(struct urtwn_softc *); static void urtwn_abort_xfers(struct urtwn_softc *); @@ -481,6 +485,7 @@ urtwn_attach(device_t self) MTX_NETWORK_LOCK, MTX_DEF); URTWN_CMDQ_LOCK_INIT(sc); URTWN_NT_LOCK_INIT(sc); + callout_init(&sc->sc_calib_to, 0); callout_init(&sc->sc_watchdog_ch, 0); mbufq_init(&sc->sc_snd, ifqmaxlen); @@ -626,6 +631,7 @@ urtwn_detach(device_t self) urtwn_stop(sc); callout_drain(&sc->sc_watchdog_ch); + callout_drain(&sc->sc_calib_to); /* stop all USB transfers */ usbd_transfer_unsetup(sc->sc_xfer, URTWN_N_TRANSFER); @@ -2313,6 +2319,9 @@ urtwn_newstate(struct ieee80211vap *vap, callout_stop(&sc->sc_watchdog_ch); if (ostate == IEEE80211_S_RUN) { + /* Stop calibration. */ + callout_stop(&sc->sc_calib_to); + /* Turn link LED off. */ urtwn_set_led(sc, URTWN_LED_LINK, 0); @@ -2450,8 +2459,10 @@ urtwn_newstate(struct ieee80211vap *vap, sc->avg_pwdb = -1; /* Reset average RSSI. */ /* Reset temperature calibration state machine. */ - sc->thcal_state = 0; + sc->sc_flags &= ~URTWN_TEMP_MEASURED; sc->thcal_lctemp = 0; + /* Start periodic calibration. */ + callout_reset(&sc->sc_calib_to, 2*hz, urtwn_calib_to, sc); end_run: ieee80211_free_node(ni); @@ -2466,6 +2477,25 @@ end_run: } static void +urtwn_calib_to(void *arg) +{ + struct urtwn_softc *sc = arg; + + /* Do it in a process context. */ + urtwn_cmd_sleepable(sc, NULL, 0, urtwn_calib_cb); +} + +static void +urtwn_calib_cb(struct urtwn_softc *sc, union sec_param *data) +{ + /* Do temperature compensation. */ + urtwn_temp_calib(sc); + + if ((urtwn_read_1(sc, R92C_MSR) & R92C_MSR_MASK) != R92C_MSR_NOLINK) + callout_reset(&sc->sc_calib_to, 2*hz, urtwn_calib_to, sc); +} + +static void urtwn_watchdog(void *arg) { struct urtwn_softc *sc = arg; @@ -4557,6 +4587,64 @@ urtwn_lc_calib(struct urtwn_softc *sc) } } +static void +urtwn_temp_calib(struct urtwn_softc *sc) +{ + uint8_t temp; + + URTWN_ASSERT_LOCKED(sc); + + if (!(sc->sc_flags & URTWN_TEMP_MEASURED)) { + /* Start measuring temperature. */ + URTWN_DPRINTF(sc, URTWN_DEBUG_TEMP, + "%s: start measuring temperature\n", __func__); + if (sc->chip & URTWN_CHIP_88E) { + urtwn_rf_write(sc, 0, R88E_RF_T_METER, + R88E_RF_T_METER_START); + } else { + urtwn_rf_write(sc, 0, R92C_RF_T_METER, + R92C_RF_T_METER_START); + } + sc->sc_flags |= URTWN_TEMP_MEASURED; + return; + } + sc->sc_flags &= ~URTWN_TEMP_MEASURED; + + /* Read measured temperature. */ + if (sc->chip & URTWN_CHIP_88E) { + temp = MS(urtwn_rf_read(sc, 0, R88E_RF_T_METER), + R88E_RF_T_METER_VAL); + } else { + temp = MS(urtwn_rf_read(sc, 0, R92C_RF_T_METER), + R92C_RF_T_METER_VAL); + } + if (temp == 0) { /* Read failed, skip. */ + URTWN_DPRINTF(sc, URTWN_DEBUG_TEMP, + "%s: temperature read failed, skipping\n", __func__); + return; + } + + URTWN_DPRINTF(sc, URTWN_DEBUG_TEMP, + "%s: temperature: previous %u, current %u\n", + __func__, sc->thcal_lctemp, temp); + + /* + * Redo LC calibration if temperature changed significantly since + * last calibration. + */ + if (sc->thcal_lctemp == 0) { + /* First LC calibration is performed in urtwn_init(). */ + sc->thcal_lctemp = temp; + } else if (abs(temp - sc->thcal_lctemp) > 1) { + URTWN_DPRINTF(sc, URTWN_DEBUG_TEMP, + "%s: LC calib triggered by temp: %u -> %u\n", + __func__, sc->thcal_lctemp, temp); + urtwn_lc_calib(sc); + /* Record temperature of last LC calibration. */ + sc->thcal_lctemp = temp; + } +} + static int urtwn_init(struct urtwn_softc *sc) { @@ -4804,7 +4892,8 @@ urtwn_stop(struct urtwn_softc *sc) return; } - sc->sc_flags &= ~URTWN_RUNNING; + sc->sc_flags &= ~(URTWN_RUNNING | URTWN_TEMP_MEASURED); + sc->thcal_lctemp = 0; callout_stop(&sc->sc_watchdog_ch); urtwn_abort_xfers(sc); Modified: head/sys/dev/usb/wlan/if_urtwnreg.h ============================================================================== --- head/sys/dev/usb/wlan/if_urtwnreg.h Wed Jan 20 23:33:58 2016 (r294472) +++ head/sys/dev/usb/wlan/if_urtwnreg.h Wed Jan 20 23:55:39 2016 (r294473) @@ -813,6 +813,7 @@ #define R92C_RF_SYN_G(i) (0x25 + (i)) #define R92C_RF_RCK_OS 0x30 #define R92C_RF_TXPA_G(i) (0x31 + (i)) +#define R88E_RF_T_METER 0x42 /* Bits for R92C_RF_AC. */ #define R92C_RF_AC_MODE_M 0x70000 @@ -826,6 +827,16 @@ #define R88E_RF_CHNLBW_BW20 0x00c00 #define R92C_RF_CHNLBW_LCSTART 0x08000 +/* Bits for R92C_RF_T_METER. */ +#define R92C_RF_T_METER_START 0x60 +#define R92C_RF_T_METER_VAL_M 0x1f +#define R92C_RF_T_METER_VAL_S 0 + +/* Bits for R88E_RF_T_METER. */ +#define R88E_RF_T_METER_VAL_M 0x0fc00 +#define R88E_RF_T_METER_VAL_S 10 +#define R88E_RF_T_METER_START 0x30000 + /* * CAM entries. Modified: head/sys/dev/usb/wlan/if_urtwnvar.h ============================================================================== --- head/sys/dev/usb/wlan/if_urtwnvar.h Wed Jan 20 23:33:58 2016 (r294472) +++ head/sys/dev/usb/wlan/if_urtwnvar.h Wed Jan 20 23:55:39 2016 (r294473) @@ -156,6 +156,7 @@ struct urtwn_softc { #define URTWN_FLAG_CCK_HIPWR 0x01 #define URTWN_DETACHED 0x02 #define URTWN_RUNNING 0x04 +#define URTWN_TEMP_MEASURED 0x10 u_int chip; #define URTWN_CHIP_92C 0x01 @@ -180,8 +181,7 @@ struct urtwn_softc { int8_t ofdm_tx_pwr_diff; int8_t bw20_tx_pwr_diff; int avg_pwdb; - int thcal_state; - int thcal_lctemp; + uint8_t thcal_lctemp; int ntxchains; int nrxchains; int ledlink; @@ -203,7 +203,8 @@ struct urtwn_softc { union urtwn_rom rom; uint16_t last_rom_addr; - + + struct callout sc_calib_to; struct callout sc_watchdog_ch; struct mtx sc_mtx; uint32_t keys_bmap;
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201601202355.u0KNtdWh076127>