diff options
author | Felix Fietkau <nbd@openwrt.org> | 2011-03-11 21:38:19 +0100 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2011-03-14 14:46:58 -0400 |
commit | 86271e460a66003dc1f4cbfd845adafb790b7587 (patch) | |
tree | aac8bd62df92a0a8975d0d1604cd9bb62a7c5f5a /drivers/net/wireless/ath/ath9k/main.c | |
parent | 0d51cccc2436fa4d978efc3764552779e163d840 (diff) |
ath9k: fix the .flush driver op implementation
This patch simplifies the flush op and reuses ath_drain_all_txq for
flushing out pending frames if necessary. It also uses a global timeout
of 200ms instead of the per-queue 60ms timeout.
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.c | 56 |
1 files changed, 21 insertions, 35 deletions
diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index 2e228aada1a9..115f162c617a 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c @@ -2128,56 +2128,42 @@ static void ath9k_set_coverage_class(struct ieee80211_hw *hw, u8 coverage_class) static void ath9k_flush(struct ieee80211_hw *hw, bool drop) { -#define ATH_FLUSH_TIMEOUT 60 /* ms */ struct ath_softc *sc = hw->priv; - struct ath_txq *txq = NULL; - struct ath_hw *ah = sc->sc_ah; - struct ath_common *common = ath9k_hw_common(ah); - int i, j, npend = 0; + int timeout = 200; /* ms */ + int i, j; + ath9k_ps_wakeup(sc); mutex_lock(&sc->mutex); cancel_delayed_work_sync(&sc->tx_complete_work); - for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) { - if (!ATH_TXQ_SETUP(sc, i)) - continue; - txq = &sc->tx.txq[i]; + if (drop) + timeout = 1; - if (!drop) { - for (j = 0; j < ATH_FLUSH_TIMEOUT; j++) { - if (!ath9k_has_pending_frames(sc, txq)) - break; - usleep_range(1000, 2000); - } - } + for (j = 0; j < timeout; j++) { + int npend = 0; + + if (j) + usleep_range(1000, 2000); - if (drop || ath9k_has_pending_frames(sc, txq)) { - ath_dbg(common, ATH_DBG_QUEUE, "Drop frames from hw queue:%d\n", - txq->axq_qnum); - spin_lock_bh(&txq->axq_lock); - txq->txq_flush_inprogress = true; - spin_unlock_bh(&txq->axq_lock); - - ath9k_ps_wakeup(sc); - ath9k_hw_stoptxdma(ah, txq->axq_qnum); - npend = ath9k_hw_numtxpending(ah, txq->axq_qnum); - ath9k_ps_restore(sc); - if (npend) - break; - - ath_draintxq(sc, txq, false); - txq->txq_flush_inprogress = false; + for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) { + if (!ATH_TXQ_SETUP(sc, i)) + continue; + + npend += ath9k_has_pending_frames(sc, &sc->tx.txq[i]); } + + if (!npend) + goto out; } - if (npend) { + if (!ath_drain_all_txq(sc, false)) ath_reset(sc, false); - txq->txq_flush_inprogress = false; - } +out: ieee80211_queue_delayed_work(hw, &sc->tx_complete_work, 0); mutex_unlock(&sc->mutex); + ath9k_ps_restore(sc); } struct ieee80211_ops ath9k_ops = { |