aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBob Copeland <me@bobcopeland.com>2010-07-13 11:32:41 -0400
committerJohn W. Linville <linville@tuxdriver.com>2010-07-14 13:52:46 -0400
commit450464def78c94018d997ae6f823578499cdf879 (patch)
tree2d6285b15042a77a3298a83eee0856050488ef8c
parent5faaff747710dfb79d5aa72b9faface94ad4b3f3 (diff)
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: Bob Copeland <me@bobcopeland.com> Acked-by: Bruno Randolf <br1@einfach.org> Signed-off-by: John W. Linville <linville@tuxdriver.com>
-rw-r--r--drivers/net/wireless/ath/ath5k/base.c20
1 files changed, 14 insertions, 6 deletions
diff --git a/drivers/net/wireless/ath/ath5k/base.c b/drivers/net/wireless/ath/ath5k/base.c
index b290cc6c600f..b0e1ca99fcad 100644
--- a/drivers/net/wireless/ath/ath5k/base.c
+++ b/drivers/net/wireless/ath/ath5k/base.c
@@ -2639,6 +2639,15 @@ ath5k_stop_locked(struct ath5k_softc *sc)
2639 return 0; 2639 return 0;
2640} 2640}
2641 2641
2642static void stop_tasklets(struct ath5k_softc *sc)
2643{
2644 tasklet_kill(&sc->rxtq);
2645 tasklet_kill(&sc->txtq);
2646 tasklet_kill(&sc->calib);
2647 tasklet_kill(&sc->beacontq);
2648 tasklet_kill(&sc->ani_tasklet);
2649}
2650
2642/* 2651/*
2643 * Stop the device, grabbing the top-level lock to protect 2652 * Stop the device, grabbing the top-level lock to protect
2644 * against concurrent entry through ath5k_init (which can happen 2653 * against concurrent entry through ath5k_init (which can happen
@@ -2683,11 +2692,7 @@ ath5k_stop_hw(struct ath5k_softc *sc)
2683 mmiowb(); 2692 mmiowb();
2684 mutex_unlock(&sc->lock); 2693 mutex_unlock(&sc->lock);
2685 2694
2686 tasklet_kill(&sc->rxtq); 2695 stop_tasklets(sc);
2687 tasklet_kill(&sc->txtq);
2688 tasklet_kill(&sc->calib);
2689 tasklet_kill(&sc->beacontq);
2690 tasklet_kill(&sc->ani_tasklet);
2691 2696
2692 ath5k_rfkill_hw_stop(sc->ah); 2697 ath5k_rfkill_hw_stop(sc->ah);
2693 2698
@@ -2937,8 +2942,11 @@ ath5k_reset(struct ath5k_softc *sc, struct ieee80211_channel *chan)
2937 2942
2938 ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "resetting\n"); 2943 ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "resetting\n");
2939 2944
2945 ath5k_hw_set_imr(ah, 0);
2946 synchronize_irq(sc->pdev->irq);
2947 stop_tasklets(sc);
2948
2940 if (chan) { 2949 if (chan) {
2941 ath5k_hw_set_imr(ah, 0);
2942 ath5k_txq_cleanup(sc); 2950 ath5k_txq_cleanup(sc);
2943 ath5k_rx_stop(sc); 2951 ath5k_rx_stop(sc);
2944 2952