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
This commit is contained in:
parent
17182b1351
commit
218592ceed
@ -286,6 +286,9 @@ static void urtwn_ibss_recv_mgmt(struct ieee80211_node *,
|
|||||||
const struct ieee80211_rx_stats *, int, int);
|
const struct ieee80211_rx_stats *, int, int);
|
||||||
static int urtwn_newstate(struct ieee80211vap *,
|
static int urtwn_newstate(struct ieee80211vap *,
|
||||||
enum ieee80211_state, int);
|
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_watchdog(void *);
|
||||||
static void urtwn_update_avgrssi(struct urtwn_softc *, int, int8_t);
|
static void urtwn_update_avgrssi(struct urtwn_softc *, int, int8_t);
|
||||||
static int8_t urtwn_get_rssi(struct urtwn_softc *, int, void *);
|
static int8_t urtwn_get_rssi(struct urtwn_softc *, int, void *);
|
||||||
@ -353,6 +356,7 @@ static void urtwn_set_chan(struct urtwn_softc *,
|
|||||||
struct ieee80211_channel *);
|
struct ieee80211_channel *);
|
||||||
static void urtwn_iq_calib(struct urtwn_softc *);
|
static void urtwn_iq_calib(struct urtwn_softc *);
|
||||||
static void urtwn_lc_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 int urtwn_init(struct urtwn_softc *);
|
||||||
static void urtwn_stop(struct urtwn_softc *);
|
static void urtwn_stop(struct urtwn_softc *);
|
||||||
static void urtwn_abort_xfers(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);
|
MTX_NETWORK_LOCK, MTX_DEF);
|
||||||
URTWN_CMDQ_LOCK_INIT(sc);
|
URTWN_CMDQ_LOCK_INIT(sc);
|
||||||
URTWN_NT_LOCK_INIT(sc);
|
URTWN_NT_LOCK_INIT(sc);
|
||||||
|
callout_init(&sc->sc_calib_to, 0);
|
||||||
callout_init(&sc->sc_watchdog_ch, 0);
|
callout_init(&sc->sc_watchdog_ch, 0);
|
||||||
mbufq_init(&sc->sc_snd, ifqmaxlen);
|
mbufq_init(&sc->sc_snd, ifqmaxlen);
|
||||||
|
|
||||||
@ -626,6 +631,7 @@ urtwn_detach(device_t self)
|
|||||||
urtwn_stop(sc);
|
urtwn_stop(sc);
|
||||||
|
|
||||||
callout_drain(&sc->sc_watchdog_ch);
|
callout_drain(&sc->sc_watchdog_ch);
|
||||||
|
callout_drain(&sc->sc_calib_to);
|
||||||
|
|
||||||
/* stop all USB transfers */
|
/* stop all USB transfers */
|
||||||
usbd_transfer_unsetup(sc->sc_xfer, URTWN_N_TRANSFER);
|
usbd_transfer_unsetup(sc->sc_xfer, URTWN_N_TRANSFER);
|
||||||
@ -2313,6 +2319,9 @@ urtwn_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
|
|||||||
callout_stop(&sc->sc_watchdog_ch);
|
callout_stop(&sc->sc_watchdog_ch);
|
||||||
|
|
||||||
if (ostate == IEEE80211_S_RUN) {
|
if (ostate == IEEE80211_S_RUN) {
|
||||||
|
/* Stop calibration. */
|
||||||
|
callout_stop(&sc->sc_calib_to);
|
||||||
|
|
||||||
/* Turn link LED off. */
|
/* Turn link LED off. */
|
||||||
urtwn_set_led(sc, URTWN_LED_LINK, 0);
|
urtwn_set_led(sc, URTWN_LED_LINK, 0);
|
||||||
|
|
||||||
@ -2450,8 +2459,10 @@ urtwn_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
|
|||||||
|
|
||||||
sc->avg_pwdb = -1; /* Reset average RSSI. */
|
sc->avg_pwdb = -1; /* Reset average RSSI. */
|
||||||
/* Reset temperature calibration state machine. */
|
/* Reset temperature calibration state machine. */
|
||||||
sc->thcal_state = 0;
|
sc->sc_flags &= ~URTWN_TEMP_MEASURED;
|
||||||
sc->thcal_lctemp = 0;
|
sc->thcal_lctemp = 0;
|
||||||
|
/* Start periodic calibration. */
|
||||||
|
callout_reset(&sc->sc_calib_to, 2*hz, urtwn_calib_to, sc);
|
||||||
|
|
||||||
end_run:
|
end_run:
|
||||||
ieee80211_free_node(ni);
|
ieee80211_free_node(ni);
|
||||||
@ -2465,6 +2476,25 @@ end_run:
|
|||||||
return (error != 0 ? error : uvp->newstate(vap, nstate, arg));
|
return (error != 0 ? error : uvp->newstate(vap, nstate, arg));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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
|
static void
|
||||||
urtwn_watchdog(void *arg)
|
urtwn_watchdog(void *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
|
static int
|
||||||
urtwn_init(struct urtwn_softc *sc)
|
urtwn_init(struct urtwn_softc *sc)
|
||||||
{
|
{
|
||||||
@ -4804,7 +4892,8 @@ urtwn_stop(struct urtwn_softc *sc)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
sc->sc_flags &= ~URTWN_RUNNING;
|
sc->sc_flags &= ~(URTWN_RUNNING | URTWN_TEMP_MEASURED);
|
||||||
|
sc->thcal_lctemp = 0;
|
||||||
callout_stop(&sc->sc_watchdog_ch);
|
callout_stop(&sc->sc_watchdog_ch);
|
||||||
urtwn_abort_xfers(sc);
|
urtwn_abort_xfers(sc);
|
||||||
|
|
||||||
|
@ -813,6 +813,7 @@
|
|||||||
#define R92C_RF_SYN_G(i) (0x25 + (i))
|
#define R92C_RF_SYN_G(i) (0x25 + (i))
|
||||||
#define R92C_RF_RCK_OS 0x30
|
#define R92C_RF_RCK_OS 0x30
|
||||||
#define R92C_RF_TXPA_G(i) (0x31 + (i))
|
#define R92C_RF_TXPA_G(i) (0x31 + (i))
|
||||||
|
#define R88E_RF_T_METER 0x42
|
||||||
|
|
||||||
/* Bits for R92C_RF_AC. */
|
/* Bits for R92C_RF_AC. */
|
||||||
#define R92C_RF_AC_MODE_M 0x70000
|
#define R92C_RF_AC_MODE_M 0x70000
|
||||||
@ -826,6 +827,16 @@
|
|||||||
#define R88E_RF_CHNLBW_BW20 0x00c00
|
#define R88E_RF_CHNLBW_BW20 0x00c00
|
||||||
#define R92C_RF_CHNLBW_LCSTART 0x08000
|
#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.
|
* CAM entries.
|
||||||
|
@ -156,6 +156,7 @@ struct urtwn_softc {
|
|||||||
#define URTWN_FLAG_CCK_HIPWR 0x01
|
#define URTWN_FLAG_CCK_HIPWR 0x01
|
||||||
#define URTWN_DETACHED 0x02
|
#define URTWN_DETACHED 0x02
|
||||||
#define URTWN_RUNNING 0x04
|
#define URTWN_RUNNING 0x04
|
||||||
|
#define URTWN_TEMP_MEASURED 0x10
|
||||||
|
|
||||||
u_int chip;
|
u_int chip;
|
||||||
#define URTWN_CHIP_92C 0x01
|
#define URTWN_CHIP_92C 0x01
|
||||||
@ -180,8 +181,7 @@ struct urtwn_softc {
|
|||||||
int8_t ofdm_tx_pwr_diff;
|
int8_t ofdm_tx_pwr_diff;
|
||||||
int8_t bw20_tx_pwr_diff;
|
int8_t bw20_tx_pwr_diff;
|
||||||
int avg_pwdb;
|
int avg_pwdb;
|
||||||
int thcal_state;
|
uint8_t thcal_lctemp;
|
||||||
int thcal_lctemp;
|
|
||||||
int ntxchains;
|
int ntxchains;
|
||||||
int nrxchains;
|
int nrxchains;
|
||||||
int ledlink;
|
int ledlink;
|
||||||
@ -203,7 +203,8 @@ struct urtwn_softc {
|
|||||||
|
|
||||||
union urtwn_rom rom;
|
union urtwn_rom rom;
|
||||||
uint16_t last_rom_addr;
|
uint16_t last_rom_addr;
|
||||||
|
|
||||||
|
struct callout sc_calib_to;
|
||||||
struct callout sc_watchdog_ch;
|
struct callout sc_watchdog_ch;
|
||||||
struct mtx sc_mtx;
|
struct mtx sc_mtx;
|
||||||
uint32_t keys_bmap;
|
uint32_t keys_bmap;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user