aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/ath/ath9k/main.c
diff options
context:
space:
mode:
authorVasanthakumar Thiagarajan <vasanth@atheros.com>2011-02-19 04:13:42 -0500
committerJohn W. Linville <linville@tuxdriver.com>2011-02-21 15:39:56 -0500
commit69081624c7b2138b137738e307cb67e2dafd6e9b (patch)
tree9aff5e8a5f4140efc2578f2f8616db0796a9aa62 /drivers/net/wireless/ath/ath9k/main.c
parent0aec516ce4cfd44f48b3ae0c54bc2f1eab007173 (diff)
ath9k: Implement op_flush()
When op_flush() is called with no drop (drop=false), the driver tries to tx as many frames as possible in about 100ms on every hw queue. During this time period frames from sw queue are also scheduled on to respective hw queue. Signed-off-by: Vasanthakumar Thiagarajan <vasanth@atheros.com> 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.c71
1 files changed, 71 insertions, 0 deletions
diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c
index 1d2c7c3cc5ca..a71550049d84 100644
--- a/drivers/net/wireless/ath/ath9k/main.c
+++ b/drivers/net/wireless/ath/ath9k/main.c
@@ -15,6 +15,7 @@
15 */ 15 */
16 16
17#include <linux/nl80211.h> 17#include <linux/nl80211.h>
18#include <linux/delay.h>
18#include "ath9k.h" 19#include "ath9k.h"
19#include "btcoex.h" 20#include "btcoex.h"
20 21
@@ -53,6 +54,21 @@ static u8 parse_mpdudensity(u8 mpdudensity)
53 } 54 }
54} 55}
55 56
57static bool ath9k_has_pending_frames(struct ath_softc *sc, struct ath_txq *txq)
58{
59 bool pending = false;
60
61 spin_lock_bh(&txq->axq_lock);
62
63 if (txq->axq_depth || !list_empty(&txq->axq_acq))
64 pending = true;
65 else if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA)
66 pending = !list_empty(&txq->txq_fifo_pending);
67
68 spin_unlock_bh(&txq->axq_lock);
69 return pending;
70}
71
56bool ath9k_setpower(struct ath_softc *sc, enum ath9k_power_mode mode) 72bool ath9k_setpower(struct ath_softc *sc, enum ath9k_power_mode mode)
57{ 73{
58 unsigned long flags; 74 unsigned long flags;
@@ -2111,6 +2127,60 @@ static void ath9k_set_coverage_class(struct ieee80211_hw *hw, u8 coverage_class)
2111 mutex_unlock(&sc->mutex); 2127 mutex_unlock(&sc->mutex);
2112} 2128}
2113 2129
2130static void ath9k_flush(struct ieee80211_hw *hw, bool drop)
2131{
2132#define ATH_FLUSH_TIMEOUT 60 /* ms */
2133 struct ath_softc *sc = hw->priv;
2134 struct ath_txq *txq;
2135 struct ath_hw *ah = sc->sc_ah;
2136 struct ath_common *common = ath9k_hw_common(ah);
2137 int i, j, npend = 0;
2138
2139 mutex_lock(&sc->mutex);
2140
2141 cancel_delayed_work_sync(&sc->tx_complete_work);
2142
2143 for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) {
2144 if (!ATH_TXQ_SETUP(sc, i))
2145 continue;
2146 txq = &sc->tx.txq[i];
2147
2148 if (!drop) {
2149 for (j = 0; j < ATH_FLUSH_TIMEOUT; j++) {
2150 if (!ath9k_has_pending_frames(sc, txq))
2151 break;
2152 usleep_range(1000, 2000);
2153 }
2154 }
2155
2156 if (drop || ath9k_has_pending_frames(sc, txq)) {
2157 ath_dbg(common, ATH_DBG_QUEUE, "Drop frames from hw queue:%d\n",
2158 txq->axq_qnum);
2159 spin_lock_bh(&txq->axq_lock);
2160 txq->txq_flush_inprogress = true;
2161 spin_unlock_bh(&txq->axq_lock);
2162
2163 ath9k_ps_wakeup(sc);
2164 ath9k_hw_stoptxdma(ah, txq->axq_qnum);
2165 npend = ath9k_hw_numtxpending(ah, txq->axq_qnum);
2166 ath9k_ps_restore(sc);
2167 if (npend)
2168 break;
2169
2170 ath_draintxq(sc, txq, false);
2171 txq->txq_flush_inprogress = false;
2172 }
2173 }
2174
2175 if (npend) {
2176 ath_reset(sc, false);
2177 txq->txq_flush_inprogress = false;
2178 }
2179
2180 ieee80211_queue_delayed_work(hw, &sc->tx_complete_work, 0);
2181 mutex_unlock(&sc->mutex);
2182}
2183
2114struct ieee80211_ops ath9k_ops = { 2184struct ieee80211_ops ath9k_ops = {
2115 .tx = ath9k_tx, 2185 .tx = ath9k_tx,
2116 .start = ath9k_start, 2186 .start = ath9k_start,
@@ -2132,4 +2202,5 @@ struct ieee80211_ops ath9k_ops = {
2132 .get_survey = ath9k_get_survey, 2202 .get_survey = ath9k_get_survey,
2133 .rfkill_poll = ath9k_rfkill_poll_state, 2203 .rfkill_poll = ath9k_rfkill_poll_state,
2134 .set_coverage_class = ath9k_set_coverage_class, 2204 .set_coverage_class = ath9k_set_coverage_class,
2205 .flush = ath9k_flush,
2135}; 2206};