diff options
author | adrian <adrian@FreeBSD.org> | 2012-02-17 03:46:38 +0000 |
---|---|---|
committer | adrian <adrian@FreeBSD.org> | 2012-02-17 03:46:38 +0000 |
commit | 0f8150f67bf4ba4dd5ad5e2d5865395cd77511cd (patch) | |
tree | c27c07e57f22abeef306d535c7df6c14a73b2192 /sys/dev/ath/if_ath.c | |
parent | df4d2c12bbb3e9ed1ff4bf6266bdddf68fe69f9c (diff) | |
download | FreeBSD-src-0f8150f67bf4ba4dd5ad5e2d5865395cd77511cd.zip FreeBSD-src-0f8150f67bf4ba4dd5ad5e2d5865395cd77511cd.tar.gz |
Enforce some consistent ordering and handling of interrupt disable/enable
with RX/TX halting.
* Always disable/enable interrupts during a channel change, just to simply
things.
* Ensure that the ath taskqueue has completed and is paused before
continuing.
This dramatically reduces the instances of overlapping RX and reset
conditions.
PR: kern/165220
Diffstat (limited to 'sys/dev/ath/if_ath.c')
-rw-r--r-- | sys/dev/ath/if_ath.c | 20 |
1 files changed, 8 insertions, 12 deletions
diff --git a/sys/dev/ath/if_ath.c b/sys/dev/ath/if_ath.c index 1ea1548..2725bc2 100644 --- a/sys/dev/ath/if_ath.c +++ b/sys/dev/ath/if_ath.c @@ -1934,6 +1934,7 @@ ath_txrx_stop_locked(struct ath_softc *sc) } #undef MAX_TXRX_ITERATIONS +#if 0 static void ath_txrx_stop(struct ath_softc *sc) { @@ -1944,6 +1945,7 @@ ath_txrx_stop(struct ath_softc *sc) ath_txrx_stop_locked(sc); ATH_PCU_UNLOCK(sc); } +#endif static void ath_txrx_start(struct ath_softc *sc) @@ -2049,11 +2051,12 @@ ath_reset(struct ifnet *ifp, ATH_RESET_TYPE reset_type) ATH_UNLOCK_ASSERT(sc); ATH_PCU_LOCK(sc); + ath_hal_intrset(ah, 0); /* disable interrupts */ + ath_txrx_stop_locked(sc); /* Ensure TX/RX is stopped */ if (ath_reset_grablock(sc, 1) == 0) { device_printf(sc->sc_dev, "%s: concurrent reset! Danger!\n", __func__); } - ath_hal_intrset(ah, 0); /* disable interrupts */ ATH_PCU_UNLOCK(sc); /* @@ -2061,7 +2064,6 @@ ath_reset(struct ifnet *ifp, ATH_RESET_TYPE reset_type) * and block future ones from occuring. This needs to be * done before the TX queue is drained. */ - ath_txrx_stop(sc); ath_draintxq(sc, reset_type); /* stop xmit side */ /* @@ -5383,21 +5385,16 @@ ath_chan_set(struct ath_softc *sc, struct ieee80211_channel *chan) struct ieee80211com *ic = ifp->if_l2com; struct ath_hal *ah = sc->sc_ah; int ret = 0; - int dointr = 0; /* Treat this as an interface reset */ ATH_PCU_LOCK(sc); + ath_hal_intrset(ah, 0); /* Stop new RX/TX completion */ + ath_txrx_stop_locked(sc); /* Stop pending RX/TX completion */ if (ath_reset_grablock(sc, 1) == 0) { device_printf(sc->sc_dev, "%s: concurrent reset! Danger!\n", __func__); } - if (chan != sc->sc_curchan) { - dointr = 1; - /* XXX only do this if inreset_cnt is 1? */ - ath_hal_intrset(ah, 0); - } ATH_PCU_UNLOCK(sc); - ath_txrx_stop(sc); DPRINTF(sc, ATH_DEBUG_RESET, "%s: %u (%u MHz, flags 0x%x)\n", __func__, ieee80211_chan2ieee(ic, chan), @@ -5466,10 +5463,10 @@ ath_chan_set(struct ath_softc *sc, struct ieee80211_channel *chan) ath_beacon_config(sc, NULL); } -#if 0 /* * Re-enable interrupts. */ +#if 0 ath_hal_intrset(ah, sc->sc_imask); #endif } @@ -5478,8 +5475,7 @@ finish: ATH_PCU_LOCK(sc); sc->sc_inreset_cnt--; /* XXX only do this if sc_inreset_cnt == 0? */ - if (dointr) - ath_hal_intrset(ah, sc->sc_imask); + ath_hal_intrset(ah, sc->sc_imask); ATH_PCU_UNLOCK(sc); /* XXX do this inside of IF_LOCK? */ |