summaryrefslogtreecommitdiff
path: root/drivers/net/wireless/ath/ath9k/main.c
diff options
context:
space:
mode:
authorFelix Fietkau <nbd@openwrt.org>2011-09-02 23:40:25 (GMT)
committerJohn W. Linville <linville@tuxdriver.com>2011-09-14 17:56:20 (GMT)
commit236de5149b9cbec3e76aef00a4663a8de7feeebe (patch)
tree3086a9d4b4bcd0e5a5ccfba94b02545e765f56bc /drivers/net/wireless/ath/ath9k/main.c
parente8cfe9f8c488f5b345ab557148c7af57af4fbe25 (diff)
downloadlinux-fsl-qoriq-236de5149b9cbec3e76aef00a4663a8de7feeebe.tar.xz
ath9k: always call ath_reset from workqueue context
This makes it much easier to add further rework to avoid race conditions between reset and other work items. Move other functions to make ath_reset static. Signed-off-by: Felix Fietkau <nbd@openwrt.org> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/ath/ath9k/main.c')
-rw-r--r--drivers/net/wireless/ath/ath9k/main.c17
1 files changed, 13 insertions, 4 deletions
diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c
index 9ff73e0..9a6db29 100644
--- a/drivers/net/wireless/ath/ath9k/main.c
+++ b/drivers/net/wireless/ath/ath9k/main.c
@@ -236,6 +236,7 @@ static int ath_set_channel(struct ath_softc *sc, struct ieee80211_hw *hw,
del_timer_sync(&common->ani.timer);
cancel_work_sync(&sc->paprd_work);
cancel_work_sync(&sc->hw_check_work);
+ cancel_work_sync(&sc->hw_reset_work);
cancel_delayed_work_sync(&sc->tx_complete_work);
cancel_delayed_work_sync(&sc->hw_pll_work);
@@ -608,9 +609,7 @@ void ath9k_tasklet(unsigned long data)
if ((status & ATH9K_INT_FATAL) ||
(status & ATH9K_INT_BB_WATCHDOG)) {
- spin_lock(&sc->sc_pcu_lock);
- ath_reset(sc, true);
- spin_unlock(&sc->sc_pcu_lock);
+ ieee80211_queue_work(sc->hw, &sc->hw_reset_work);
return;
}
@@ -901,7 +900,7 @@ void ath_radio_disable(struct ath_softc *sc, struct ieee80211_hw *hw)
ath9k_ps_restore(sc);
}
-int ath_reset(struct ath_softc *sc, bool retry_tx)
+static int ath_reset(struct ath_softc *sc, bool retry_tx)
{
struct ath_hw *ah = sc->sc_ah;
struct ath_common *common = ath9k_hw_common(ah);
@@ -969,6 +968,15 @@ int ath_reset(struct ath_softc *sc, bool retry_tx)
return r;
}
+void ath_reset_work(struct work_struct *work)
+{
+ struct ath_softc *sc = container_of(work, struct ath_softc, hw_reset_work);
+
+ spin_lock_bh(&sc->sc_pcu_lock);
+ ath_reset(sc, true);
+ spin_unlock_bh(&sc->sc_pcu_lock);
+}
+
void ath_hw_check(struct work_struct *work)
{
struct ath_softc *sc = container_of(work, struct ath_softc, hw_check_work);
@@ -1230,6 +1238,7 @@ static void ath9k_stop(struct ieee80211_hw *hw)
cancel_delayed_work_sync(&sc->hw_pll_work);
cancel_work_sync(&sc->paprd_work);
cancel_work_sync(&sc->hw_check_work);
+ cancel_work_sync(&sc->hw_reset_work);
if (sc->sc_flags & SC_OP_INVALID) {
ath_dbg(common, ATH_DBG_ANY, "Device not present\n");