aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFelix Fietkau <nbd@openwrt.org>2011-09-02 19:40:25 -0400
committerJohn W. Linville <linville@tuxdriver.com>2011-09-14 13:56:20 -0400
commit236de5149b9cbec3e76aef00a4663a8de7feeebe (patch)
tree3086a9d4b4bcd0e5a5ccfba94b02545e765f56bc
parente8cfe9f8c488f5b345ab557148c7af57af4fbe25 (diff)
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>
-rw-r--r--drivers/net/wireless/ath/ath9k/ath9k.h3
-rw-r--r--drivers/net/wireless/ath/ath9k/beacon.c4
-rw-r--r--drivers/net/wireless/ath/ath9k/init.c1
-rw-r--r--drivers/net/wireless/ath/ath9k/main.c17
-rw-r--r--drivers/net/wireless/ath/ath9k/xmit.c14
5 files changed, 26 insertions, 13 deletions
diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h
index 5d9a9aabe476..b2992d4097c3 100644
--- a/drivers/net/wireless/ath/ath9k/ath9k.h
+++ b/drivers/net/wireless/ath/ath9k/ath9k.h
@@ -425,6 +425,7 @@ void ath9k_set_beaconing_status(struct ath_softc *sc, bool status);
425 425
426#define ATH_PAPRD_TIMEOUT 100 /* msecs */ 426#define ATH_PAPRD_TIMEOUT 100 /* msecs */
427 427
428void ath_reset_work(struct work_struct *work);
428void ath_hw_check(struct work_struct *work); 429void ath_hw_check(struct work_struct *work);
429void ath_hw_pll_work(struct work_struct *work); 430void ath_hw_pll_work(struct work_struct *work);
430void ath_paprd_calibrate(struct work_struct *work); 431void ath_paprd_calibrate(struct work_struct *work);
@@ -604,6 +605,7 @@ struct ath_softc {
604 struct mutex mutex; 605 struct mutex mutex;
605 struct work_struct paprd_work; 606 struct work_struct paprd_work;
606 struct work_struct hw_check_work; 607 struct work_struct hw_check_work;
608 struct work_struct hw_reset_work;
607 struct completion paprd_complete; 609 struct completion paprd_complete;
608 610
609 unsigned int hw_busy_count; 611 unsigned int hw_busy_count;
@@ -650,7 +652,6 @@ struct ath_softc {
650}; 652};
651 653
652void ath9k_tasklet(unsigned long data); 654void ath9k_tasklet(unsigned long data);
653int ath_reset(struct ath_softc *sc, bool retry_tx);
654int ath_cabq_update(struct ath_softc *); 655int ath_cabq_update(struct ath_softc *);
655 656
656static inline void ath_read_cachesize(struct ath_common *common, int *csz) 657static inline void ath_read_cachesize(struct ath_common *common, int *csz)
diff --git a/drivers/net/wireless/ath/ath9k/beacon.c b/drivers/net/wireless/ath/ath9k/beacon.c
index 0c757c9f978a..22e8e2580116 100644
--- a/drivers/net/wireless/ath/ath9k/beacon.c
+++ b/drivers/net/wireless/ath/ath9k/beacon.c
@@ -386,9 +386,7 @@ void ath_beacon_tasklet(unsigned long data)
386 ath_dbg(common, ATH_DBG_BSTUCK, 386 ath_dbg(common, ATH_DBG_BSTUCK,
387 "beacon is officially stuck\n"); 387 "beacon is officially stuck\n");
388 sc->sc_flags |= SC_OP_TSF_RESET; 388 sc->sc_flags |= SC_OP_TSF_RESET;
389 spin_lock(&sc->sc_pcu_lock); 389 ieee80211_queue_work(sc->hw, &sc->hw_reset_work);
390 ath_reset(sc, true);
391 spin_unlock(&sc->sc_pcu_lock);
392 } 390 }
393 391
394 return; 392 return;
diff --git a/drivers/net/wireless/ath/ath9k/init.c b/drivers/net/wireless/ath/ath9k/init.c
index 50da6421728b..be302fbdc3dc 100644
--- a/drivers/net/wireless/ath/ath9k/init.c
+++ b/drivers/net/wireless/ath/ath9k/init.c
@@ -777,6 +777,7 @@ int ath9k_init_device(u16 devid, struct ath_softc *sc,
777 goto error_world; 777 goto error_world;
778 } 778 }
779 779
780 INIT_WORK(&sc->hw_reset_work, ath_reset_work);
780 INIT_WORK(&sc->hw_check_work, ath_hw_check); 781 INIT_WORK(&sc->hw_check_work, ath_hw_check);
781 INIT_WORK(&sc->paprd_work, ath_paprd_calibrate); 782 INIT_WORK(&sc->paprd_work, ath_paprd_calibrate);
782 INIT_DELAYED_WORK(&sc->hw_pll_work, ath_hw_pll_work); 783 INIT_DELAYED_WORK(&sc->hw_pll_work, ath_hw_pll_work);
diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c
index 9ff73e007d34..9a6db2964b18 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,
236 del_timer_sync(&common->ani.timer); 236 del_timer_sync(&common->ani.timer);
237 cancel_work_sync(&sc->paprd_work); 237 cancel_work_sync(&sc->paprd_work);
238 cancel_work_sync(&sc->hw_check_work); 238 cancel_work_sync(&sc->hw_check_work);
239 cancel_work_sync(&sc->hw_reset_work);
239 cancel_delayed_work_sync(&sc->tx_complete_work); 240 cancel_delayed_work_sync(&sc->tx_complete_work);
240 cancel_delayed_work_sync(&sc->hw_pll_work); 241 cancel_delayed_work_sync(&sc->hw_pll_work);
241 242
@@ -608,9 +609,7 @@ void ath9k_tasklet(unsigned long data)
608 609
609 if ((status & ATH9K_INT_FATAL) || 610 if ((status & ATH9K_INT_FATAL) ||
610 (status & ATH9K_INT_BB_WATCHDOG)) { 611 (status & ATH9K_INT_BB_WATCHDOG)) {
611 spin_lock(&sc->sc_pcu_lock); 612 ieee80211_queue_work(sc->hw, &sc->hw_reset_work);
612 ath_reset(sc, true);
613 spin_unlock(&sc->sc_pcu_lock);
614 return; 613 return;
615 } 614 }
616 615
@@ -901,7 +900,7 @@ void ath_radio_disable(struct ath_softc *sc, struct ieee80211_hw *hw)
901 ath9k_ps_restore(sc); 900 ath9k_ps_restore(sc);
902} 901}
903 902
904int ath_reset(struct ath_softc *sc, bool retry_tx) 903static int ath_reset(struct ath_softc *sc, bool retry_tx)
905{ 904{
906 struct ath_hw *ah = sc->sc_ah; 905 struct ath_hw *ah = sc->sc_ah;
907 struct ath_common *common = ath9k_hw_common(ah); 906 struct ath_common *common = ath9k_hw_common(ah);
@@ -969,6 +968,15 @@ int ath_reset(struct ath_softc *sc, bool retry_tx)
969 return r; 968 return r;
970} 969}
971 970
971void ath_reset_work(struct work_struct *work)
972{
973 struct ath_softc *sc = container_of(work, struct ath_softc, hw_reset_work);
974
975 spin_lock_bh(&sc->sc_pcu_lock);
976 ath_reset(sc, true);
977 spin_unlock_bh(&sc->sc_pcu_lock);
978}
979
972void ath_hw_check(struct work_struct *work) 980void ath_hw_check(struct work_struct *work)
973{ 981{
974 struct ath_softc *sc = container_of(work, struct ath_softc, hw_check_work); 982 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)
1230 cancel_delayed_work_sync(&sc->hw_pll_work); 1238 cancel_delayed_work_sync(&sc->hw_pll_work);
1231 cancel_work_sync(&sc->paprd_work); 1239 cancel_work_sync(&sc->paprd_work);
1232 cancel_work_sync(&sc->hw_check_work); 1240 cancel_work_sync(&sc->hw_check_work);
1241 cancel_work_sync(&sc->hw_reset_work);
1233 1242
1234 if (sc->sc_flags & SC_OP_INVALID) { 1243 if (sc->sc_flags & SC_OP_INVALID) {
1235 ath_dbg(common, ATH_DBG_ANY, "Device not present\n"); 1244 ath_dbg(common, ATH_DBG_ANY, "Device not present\n");
diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c
index 0fb8fb57b5c8..cb37047e71d2 100644
--- a/drivers/net/wireless/ath/ath9k/xmit.c
+++ b/drivers/net/wireless/ath/ath9k/xmit.c
@@ -582,7 +582,7 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,
582 rcu_read_unlock(); 582 rcu_read_unlock();
583 583
584 if (needreset) 584 if (needreset)
585 ath_reset(sc, false); 585 ieee80211_queue_work(sc->hw, &sc->hw_reset_work);
586} 586}
587 587
588static bool ath_lookup_legacy(struct ath_buf *bf) 588static bool ath_lookup_legacy(struct ath_buf *bf)
@@ -1333,7 +1333,7 @@ void ath_txq_schedule(struct ath_softc *sc, struct ath_txq *txq)
1333 struct ath_atx_ac *ac, *ac_tmp, *last_ac; 1333 struct ath_atx_ac *ac, *ac_tmp, *last_ac;
1334 struct ath_atx_tid *tid, *last_tid; 1334 struct ath_atx_tid *tid, *last_tid;
1335 1335
1336 if (list_empty(&txq->axq_acq) || 1336 if (work_pending(&sc->hw_reset_work) || list_empty(&txq->axq_acq) ||
1337 txq->axq_ampdu_depth >= ATH_AGGR_MIN_QDEPTH) 1337 txq->axq_ampdu_depth >= ATH_AGGR_MIN_QDEPTH)
1338 return; 1338 return;
1339 1339
@@ -2148,6 +2148,9 @@ static void ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq)
2148 2148
2149 spin_lock_bh(&txq->axq_lock); 2149 spin_lock_bh(&txq->axq_lock);
2150 for (;;) { 2150 for (;;) {
2151 if (work_pending(&sc->hw_reset_work))
2152 break;
2153
2151 if (list_empty(&txq->axq_q)) { 2154 if (list_empty(&txq->axq_q)) {
2152 txq->axq_link = NULL; 2155 txq->axq_link = NULL;
2153 if (sc->sc_flags & SC_OP_TXAGGR) 2156 if (sc->sc_flags & SC_OP_TXAGGR)
@@ -2235,9 +2238,7 @@ static void ath_tx_complete_poll_work(struct work_struct *work)
2235 if (needreset) { 2238 if (needreset) {
2236 ath_dbg(ath9k_hw_common(sc->sc_ah), ATH_DBG_RESET, 2239 ath_dbg(ath9k_hw_common(sc->sc_ah), ATH_DBG_RESET,
2237 "tx hung, resetting the chip\n"); 2240 "tx hung, resetting the chip\n");
2238 spin_lock_bh(&sc->sc_pcu_lock); 2241 ieee80211_queue_work(sc->hw, &sc->hw_reset_work);
2239 ath_reset(sc, true);
2240 spin_unlock_bh(&sc->sc_pcu_lock);
2241 } 2242 }
2242 2243
2243 ieee80211_queue_delayed_work(sc->hw, &sc->tx_complete_work, 2244 ieee80211_queue_delayed_work(sc->hw, &sc->tx_complete_work,
@@ -2270,6 +2271,9 @@ void ath_tx_edma_tasklet(struct ath_softc *sc)
2270 int status; 2271 int status;
2271 2272
2272 for (;;) { 2273 for (;;) {
2274 if (work_pending(&sc->hw_reset_work))
2275 break;
2276
2273 status = ath9k_hw_txprocdesc(ah, NULL, (void *)&ts); 2277 status = ath9k_hw_txprocdesc(ah, NULL, (void *)&ts);
2274 if (status == -EINPROGRESS) 2278 if (status == -EINPROGRESS)
2275 break; 2279 break;