Skip site navigation (1)Skip section navigation (2)
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>