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).
This commit is contained in:
Bernhard Schmidt 2011-04-15 20:17:52 +00:00
parent d052a1cc33
commit af2e228dc4
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=220667
2 changed files with 64 additions and 48 deletions

View File

@ -123,10 +123,9 @@ static struct ieee80211_node *iwn_node_alloc(struct ieee80211vap *,
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_node *, struct mbuf *,
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, enum ieee80211_state nstate, int arg)
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, enum ieee80211_state nstate, int arg)
*/
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, enum ieee80211_state nstate, int arg)
/*
* 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, enum ieee80211_state nstate, int arg)
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, enum ieee80211_state nstate, int arg)
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 iwn_rx_desc *desc,
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, struct iwn_rx_desc *desc,
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, struct mbuf *m,
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;
if_printf(ifp, "device timeout\n");
ieee80211_runtask(ic, &sc->sc_reinit_task);
IWN_LOCK_ASSERT(sc);
KASSERT(ifp->if_drv_flags & IFF_DRV_RUNNING, ("not running"));
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 ieee80211vap *vap)
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 ieee80211vap *vap)
/* 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. */

View File

@ -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;