Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 15 Apr 2011 20:17:52 +0000 (UTC)
From:      Bernhard Schmidt <bschmidt@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r220667 - head/sys/dev/iwn
Message-ID:  <201104152017.p3FKHqgh080624@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: bschmidt
Date: Fri Apr 15 20:17:52 2011
New Revision: 220667
URL: http://svn.freebsd.org/changeset/base/220667

Log:
  Split up watchdog and calibration callout. This allows us to use different
  timing on both and to remove some monitor mode specific hacks (which has
  no calibration).

Modified:
  head/sys/dev/iwn/if_iwn.c
  head/sys/dev/iwn/if_iwnvar.h

Modified: head/sys/dev/iwn/if_iwn.c
==============================================================================
--- head/sys/dev/iwn/if_iwn.c	Fri Apr 15 19:50:38 2011	(r220666)
+++ head/sys/dev/iwn/if_iwn.c	Fri Apr 15 20:17:52 2011	(r220667)
@@ -123,10 +123,9 @@ static struct ieee80211_node *iwn_node_a
 		    const uint8_t mac[IEEE80211_ADDR_LEN]);
 static int	iwn_media_change(struct ifnet *);
 static int	iwn_newstate(struct ieee80211vap *, enum ieee80211_state, int);
+static void	iwn_calib_timeout(void *);
 static void	iwn_rx_phy(struct iwn_softc *, struct iwn_rx_desc *,
 		    struct iwn_rx_data *);
-static void	iwn_timer_timeout(void *);
-static void	iwn_calib_reset(struct iwn_softc *);
 static void	iwn_rx_done(struct iwn_softc *, struct iwn_rx_desc *,
 		    struct iwn_rx_data *);
 #if 0	/* HT */
@@ -161,7 +160,7 @@ static int	iwn_raw_xmit(struct ieee80211
 		    const struct ieee80211_bpf_params *);
 static void	iwn_start(struct ifnet *);
 static void	iwn_start_locked(struct ifnet *);
-static void	iwn_watchdog(struct iwn_softc *sc);
+static void	iwn_watchdog(void *);
 static int	iwn_ioctl(struct ifnet *, u_long, caddr_t);
 static int	iwn_cmd(struct iwn_softc *, int, const void *, int, int);
 static int	iwn4965_add_node(struct iwn_softc *, struct iwn_node_info *,
@@ -475,7 +474,6 @@ iwn_attach(device_t dev)
 	}
 
 	IWN_LOCK_INIT(sc);
-	callout_init_mtx(&sc->sc_timer_to, &sc->sc_mtx, 0);
 	TASK_INIT(&sc->sc_reinit_task, 0, iwn_hw_reset, sc );
 	TASK_INIT(&sc->sc_radioon_task, 0, iwn_radio_on, sc );
 	TASK_INIT(&sc->sc_radiooff_task, 0, iwn_radio_off, sc );
@@ -668,6 +666,10 @@ iwn_attach(device_t dev)
 #endif
 
 	iwn_radiotap_attach(sc);
+
+	callout_init_mtx(&sc->calib_to, &sc->sc_mtx, 0);
+	callout_init_mtx(&sc->watchdog_to, &sc->sc_mtx, 0);
+
 	iwn_sysctlattach(sc);
 
 	/*
@@ -860,7 +862,8 @@ iwn_detach(device_t dev)
 		ieee80211_draintask(ic, &sc->sc_radiooff_task);
 
 		iwn_stop(sc);
-		callout_drain(&sc->sc_timer_to);
+		callout_drain(&sc->watchdog_to);
+		callout_drain(&sc->calib_to);
 		ieee80211_ifdetach(ic);
 	}
 
@@ -1942,7 +1945,7 @@ iwn_newstate(struct ieee80211vap *vap, e
 
 	IEEE80211_UNLOCK(ic);
 	IWN_LOCK(sc);
-	callout_stop(&sc->sc_timer_to);
+	callout_stop(&sc->calib_to);
 
 	switch (nstate) {
 	case IEEE80211_S_ASSOC:
@@ -1959,7 +1962,8 @@ iwn_newstate(struct ieee80211vap *vap, e
 		 */
 		sc->rxon.associd = 0;
 		sc->rxon.filter &= ~htole32(IWN_FILTER_BSS);
-		iwn_calib_reset(sc);
+		sc->calib.state = IWN_CALIB_STATE_INIT;
+
 		error = iwn_auth(sc, vap);
 		break;
 
@@ -1967,9 +1971,8 @@ iwn_newstate(struct ieee80211vap *vap, e
 		/*
 		 * RUN -> RUN transition; Just restart the timers.
 		 */
-		if (vap->iv_state == IEEE80211_S_RUN &&
-		    vap->iv_opmode != IEEE80211_M_MONITOR) {
-			iwn_calib_reset(sc);
+		if (vap->iv_state == IEEE80211_S_RUN) {
+			sc->calib_cnt = 0;
 			break;
 		}
 
@@ -1981,6 +1984,10 @@ iwn_newstate(struct ieee80211vap *vap, e
 		error = iwn_run(sc, vap);
 		break;
 
+	case IEEE80211_S_INIT:
+		sc->calib.state = IWN_CALIB_STATE_INIT;
+		break;
+
 	default:
 		break;
 	}
@@ -1989,6 +1996,27 @@ iwn_newstate(struct ieee80211vap *vap, e
 	return ivp->iv_newstate(vap, nstate, arg);
 }
 
+static void
+iwn_calib_timeout(void *arg)
+{
+	struct iwn_softc *sc = arg;
+
+	IWN_LOCK_ASSERT(sc);
+
+	/* Force automatic TX power calibration every 60 secs. */
+	if (++sc->calib_cnt >= 120) {
+		uint32_t flags = 0;
+
+		DPRINTF(sc, IWN_DEBUG_CALIBRATE, "%s\n",
+		    "sending request for statistics");
+		(void)iwn_cmd(sc, IWN_CMD_GET_STATISTICS, &flags,
+		    sizeof flags, 1);
+		sc->calib_cnt = 0;
+	}
+	callout_reset(&sc->calib_to, msecs_to_ticks(500), iwn_calib_timeout,
+	    sc);
+}
+
 /*
  * Process an RX_PHY firmware notification.  This is usually immediately
  * followed by an MPDU_RX_DONE notification.
@@ -2007,32 +2035,6 @@ iwn_rx_phy(struct iwn_softc *sc, struct 
 	sc->last_rx_valid = 1;
 }
 
-static void
-iwn_timer_timeout(void *arg)
-{
-	struct iwn_softc *sc = arg;
-	uint32_t flags = 0;
-
-	IWN_LOCK_ASSERT(sc);
-
-	if (sc->calib_cnt && --sc->calib_cnt == 0) {
-		DPRINTF(sc, IWN_DEBUG_CALIBRATE, "%s\n",
-		    "send statistics request");
-		(void) iwn_cmd(sc, IWN_CMD_GET_STATISTICS, &flags,
-		    sizeof flags, 1);
-		sc->calib_cnt = 60;	/* do calibration every 60s */
-	}
-	iwn_watchdog(sc);		/* NB: piggyback tx watchdog */
-	callout_reset(&sc->sc_timer_to, hz, iwn_timer_timeout, sc);
-}
-
-static void
-iwn_calib_reset(struct iwn_softc *sc)
-{
-	callout_reset(&sc->sc_timer_to, hz, iwn_timer_timeout, sc);
-	sc->calib_cnt = 60;		/* do calibration every 60s */
-}
-
 /*
  * Process an RX_DONE (4965AGN only) or MPDU_RX_DONE firmware notification.
  * Each MPDU_RX_DONE notification must be preceded by an RX_PHY one.
@@ -2222,7 +2224,7 @@ iwn_rx_statistics(struct iwn_softc *sc, 
 
 	bus_dmamap_sync(sc->rxq.data_dmat, data->map, BUS_DMASYNC_POSTREAD);
 	DPRINTF(sc, IWN_DEBUG_CALIBRATE, "%s: cmd %d\n", __func__, desc->type);
-	iwn_calib_reset(sc);	/* Reset TX power calibration timeout. */
+	sc->calib_cnt = 0;	/* Reset TX power calibration timeout. */
 
 	/* Test if temperature has changed. */
 	if (stats->general.temp != sc->rawtemp) {
@@ -3306,6 +3308,8 @@ iwn_raw_xmit(struct ieee80211_node *ni, 
 		ieee80211_free_node(ni);
 		ifp->if_oerrors++;
 	}
+	sc->sc_tx_timer = 5;
+
 	IWN_UNLOCK(sc);
 	return error;
 }
@@ -3352,15 +3356,24 @@ iwn_start_locked(struct ifnet *ifp)
 }
 
 static void
-iwn_watchdog(struct iwn_softc *sc)
+iwn_watchdog(void *arg)
 {
-	if (sc->sc_tx_timer > 0 && --sc->sc_tx_timer == 0) {
-		struct ifnet *ifp = sc->sc_ifp;
-		struct ieee80211com *ic = ifp->if_l2com;
+	struct iwn_softc *sc = arg;
+	struct ifnet *ifp = sc->sc_ifp;
+	struct ieee80211com *ic = ifp->if_l2com;
+
+	IWN_LOCK_ASSERT(sc);
+
+	KASSERT(ifp->if_drv_flags & IFF_DRV_RUNNING, ("not running"));
 
-		if_printf(ifp, "device timeout\n");
-		ieee80211_runtask(ic, &sc->sc_reinit_task);
+	if (sc->sc_tx_timer > 0 || counter == 50) {
+		if (--sc->sc_tx_timer == 0 || counter == 50) {
+			if_printf(ifp, "device timeout\n");
+			ieee80211_runtask(ic, &sc->sc_reinit_task);
+			return;
+		}
 	}
+	callout_reset(&sc->watchdog_to, hz, iwn_watchdog, sc);
 }
 
 static int
@@ -4760,8 +4773,6 @@ iwn_auth(struct iwn_softc *sc, struct ie
 	struct ieee80211_node *ni = vap->iv_bss;
 	int error;
 
-	sc->calib.state = IWN_CALIB_STATE_INIT;
-
 	/* Update adapter configuration. */
 	IEEE80211_ADDR_COPY(sc->rxon.bssid, ni->ni_bssid);
 	sc->rxon.chan = ieee80211_chan2ieee(ic, ni->ni_chan);
@@ -4954,7 +4965,9 @@ iwn_run(struct iwn_softc *sc, struct iee
 
 	/* Start periodic calibration timer. */
 	sc->calib.state = IWN_CALIB_STATE_ASSOC;
-	iwn_calib_reset(sc);
+	sc->calib_cnt = 0;
+	callout_reset(&sc->calib_to, msecs_to_ticks(500), iwn_calib_timeout,
+	    sc);
 
 	/* Link LED always on while associated. */
 	iwn_set_led(sc, IWN_LED_LINK, 0, 1);
@@ -6406,6 +6419,7 @@ iwn_init_locked(struct iwn_softc *sc)
 	ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
 	ifp->if_drv_flags |= IFF_DRV_RUNNING;
 
+	callout_reset(&sc->watchdog_to, hz, iwn_watchdog, sc);
 	return;
 
 fail:
@@ -6435,7 +6449,8 @@ iwn_stop_locked(struct iwn_softc *sc)
 	IWN_LOCK_ASSERT(sc);
 
 	sc->sc_tx_timer = 0;
-	callout_stop(&sc->sc_timer_to);
+	callout_stop(&sc->watchdog_to);
+	callout_stop(&sc->calib_to);
 	ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
 
 	/* Power OFF hardware. */

Modified: head/sys/dev/iwn/if_iwnvar.h
==============================================================================
--- head/sys/dev/iwn/if_iwnvar.h	Fri Apr 15 19:50:38 2011	(r220666)
+++ head/sys/dev/iwn/if_iwnvar.h	Fri Apr 15 20:17:52 2011	(r220667)
@@ -260,8 +260,10 @@ struct iwn_softc {
 	struct task		sc_radioon_task;
 	struct task		sc_radiooff_task;
 
+	struct callout		calib_to;
 	int			calib_cnt;
 	struct iwn_calib_state	calib;
+	struct callout		watchdog_to;
 	u_int			calib_init;
 	u_int			calib_runtime;
 #define	IWN_CALIB_XTAL			(1 << IWN_CALIB_IDX_XTAL)
@@ -312,7 +314,6 @@ struct iwn_softc {
 	uint8_t			rxchainmask;
 	uint8_t			chainmask;
 
-	struct callout		sc_timer_to;
 	int			sc_tx_timer;
 
 	struct iwn_rx_radiotap_header sc_rxtap;



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201104152017.p3FKHqgh080624>