Commit 450464de authored by Bob Copeland's avatar Bob Copeland Committed by John W. Linville

ath5k: disable tasklets during reset

Based on a patch from Bruno Randolf, attempting useful
work while we are resetting the chip just leads to interface
lockups and bad descriptor data, and possibly DMAing to
freed buffers.  Let's suspend all tasklets while
reprogramming the registers in the card to avoid such
problems.

In the future we can convert the tasklets to threaded
interrupt handlers to simplify things.
Signed-off-by: default avatarBob Copeland <me@bobcopeland.com>
Acked-by: default avatarBruno Randolf <br1@einfach.org>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent 5faaff74
...@@ -2639,6 +2639,15 @@ ath5k_stop_locked(struct ath5k_softc *sc) ...@@ -2639,6 +2639,15 @@ ath5k_stop_locked(struct ath5k_softc *sc)
return 0; return 0;
} }
static void stop_tasklets(struct ath5k_softc *sc)
{
tasklet_kill(&sc->rxtq);
tasklet_kill(&sc->txtq);
tasklet_kill(&sc->calib);
tasklet_kill(&sc->beacontq);
tasklet_kill(&sc->ani_tasklet);
}
/* /*
* Stop the device, grabbing the top-level lock to protect * Stop the device, grabbing the top-level lock to protect
* against concurrent entry through ath5k_init (which can happen * against concurrent entry through ath5k_init (which can happen
...@@ -2683,11 +2692,7 @@ ath5k_stop_hw(struct ath5k_softc *sc) ...@@ -2683,11 +2692,7 @@ ath5k_stop_hw(struct ath5k_softc *sc)
mmiowb(); mmiowb();
mutex_unlock(&sc->lock); mutex_unlock(&sc->lock);
tasklet_kill(&sc->rxtq); stop_tasklets(sc);
tasklet_kill(&sc->txtq);
tasklet_kill(&sc->calib);
tasklet_kill(&sc->beacontq);
tasklet_kill(&sc->ani_tasklet);
ath5k_rfkill_hw_stop(sc->ah); ath5k_rfkill_hw_stop(sc->ah);
...@@ -2937,8 +2942,11 @@ ath5k_reset(struct ath5k_softc *sc, struct ieee80211_channel *chan) ...@@ -2937,8 +2942,11 @@ ath5k_reset(struct ath5k_softc *sc, struct ieee80211_channel *chan)
ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "resetting\n"); ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "resetting\n");
ath5k_hw_set_imr(ah, 0);
synchronize_irq(sc->pdev->irq);
stop_tasklets(sc);
if (chan) { if (chan) {
ath5k_hw_set_imr(ah, 0);
ath5k_txq_cleanup(sc); ath5k_txq_cleanup(sc);
ath5k_rx_stop(sc); ath5k_rx_stop(sc);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment