ssb: update ssb to version from linux-next-20110311
[openwrt/svn-archive/archive.git] / package / mac80211 / patches / 572-ath9k_fix_tx_flush.patch
1 --- a/drivers/net/wireless/ath/ath9k/main.c
2 +++ b/drivers/net/wireless/ath/ath9k/main.c
3 @@ -2149,56 +2149,42 @@ static void ath9k_set_coverage_class(str
4
5 static void ath9k_flush(struct ieee80211_hw *hw, bool drop)
6 {
7 -#define ATH_FLUSH_TIMEOUT 60 /* ms */
8 struct ath_softc *sc = hw->priv;
9 - struct ath_txq *txq = NULL;
10 - struct ath_hw *ah = sc->sc_ah;
11 - struct ath_common *common = ath9k_hw_common(ah);
12 - int i, j, npend = 0;
13 + int timeout = 200; /* ms */
14 + int i, j;
15
16 + ath9k_ps_wakeup(sc);
17 mutex_lock(&sc->mutex);
18
19 cancel_delayed_work_sync(&sc->tx_complete_work);
20
21 - for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) {
22 - if (!ATH_TXQ_SETUP(sc, i))
23 - continue;
24 - txq = &sc->tx.txq[i];
25 -
26 - if (!drop) {
27 - for (j = 0; j < ATH_FLUSH_TIMEOUT; j++) {
28 - if (!ath9k_has_pending_frames(sc, txq))
29 - break;
30 - usleep_range(1000, 2000);
31 - }
32 - }
33 + if (drop)
34 + timeout = 1;
35 +
36 + for (j = 0; j < timeout; j++) {
37 + int npend = 0;
38 +
39 + if (j)
40 + usleep_range(1000, 2000);
41
42 - if (drop || ath9k_has_pending_frames(sc, txq)) {
43 - ath_dbg(common, ATH_DBG_QUEUE, "Drop frames from hw queue:%d\n",
44 - txq->axq_qnum);
45 - spin_lock_bh(&txq->axq_lock);
46 - txq->txq_flush_inprogress = true;
47 - spin_unlock_bh(&txq->axq_lock);
48 -
49 - ath9k_ps_wakeup(sc);
50 - ath9k_hw_stoptxdma(ah, txq->axq_qnum);
51 - npend = ath9k_hw_numtxpending(ah, txq->axq_qnum);
52 - ath9k_ps_restore(sc);
53 - if (npend)
54 - break;
55 + for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) {
56 + if (!ATH_TXQ_SETUP(sc, i))
57 + continue;
58
59 - ath_draintxq(sc, txq, false);
60 - txq->txq_flush_inprogress = false;
61 + npend += ath9k_has_pending_frames(sc, &sc->tx.txq[i]);
62 }
63 +
64 + if (!npend)
65 + goto out;
66 }
67
68 - if (npend) {
69 + if (!ath_drain_all_txq(sc, false))
70 ath_reset(sc, false);
71 - txq->txq_flush_inprogress = false;
72 - }
73
74 +out:
75 ieee80211_queue_delayed_work(hw, &sc->tx_complete_work, 0);
76 mutex_unlock(&sc->mutex);
77 + ath9k_ps_restore(sc);
78 }
79
80 struct ieee80211_ops ath9k_ops = {
81 --- a/drivers/net/wireless/ath/ath9k/ath9k.h
82 +++ b/drivers/net/wireless/ath/ath9k/ath9k.h
83 @@ -189,7 +189,6 @@ struct ath_txq {
84 u32 axq_ampdu_depth;
85 bool stopped;
86 bool axq_tx_inprogress;
87 - bool txq_flush_inprogress;
88 struct list_head axq_acq;
89 struct list_head txq_fifo[ATH_TXFIFO_DEPTH];
90 struct list_head txq_fifo_pending;
91 --- a/drivers/net/wireless/ath/ath9k/xmit.c
92 +++ b/drivers/net/wireless/ath/ath9k/xmit.c
93 @@ -2091,8 +2091,7 @@ static void ath_tx_processq(struct ath_s
94 spin_lock_bh(&txq->axq_lock);
95 if (list_empty(&txq->axq_q)) {
96 txq->axq_link = NULL;
97 - if (sc->sc_flags & SC_OP_TXAGGR &&
98 - !txq->txq_flush_inprogress)
99 + if (sc->sc_flags & SC_OP_TXAGGR)
100 ath_txq_schedule(sc, txq);
101 spin_unlock_bh(&txq->axq_lock);
102 break;
103 @@ -2173,7 +2172,7 @@ static void ath_tx_processq(struct ath_s
104
105 spin_lock_bh(&txq->axq_lock);
106
107 - if (sc->sc_flags & SC_OP_TXAGGR && !txq->txq_flush_inprogress)
108 + if (sc->sc_flags & SC_OP_TXAGGR)
109 ath_txq_schedule(sc, txq);
110 spin_unlock_bh(&txq->axq_lock);
111 }
112 @@ -2317,18 +2316,17 @@ void ath_tx_edma_tasklet(struct ath_soft
113
114 spin_lock_bh(&txq->axq_lock);
115
116 - if (!txq->txq_flush_inprogress) {
117 - if (!list_empty(&txq->txq_fifo_pending)) {
118 - INIT_LIST_HEAD(&bf_head);
119 - bf = list_first_entry(&txq->txq_fifo_pending,
120 - struct ath_buf, list);
121 - list_cut_position(&bf_head,
122 - &txq->txq_fifo_pending,
123 - &bf->bf_lastbf->list);
124 - ath_tx_txqaddbuf(sc, txq, &bf_head);
125 - } else if (sc->sc_flags & SC_OP_TXAGGR)
126 - ath_txq_schedule(sc, txq);
127 - }
128 + if (!list_empty(&txq->txq_fifo_pending)) {
129 + INIT_LIST_HEAD(&bf_head);
130 + bf = list_first_entry(&txq->txq_fifo_pending,
131 + struct ath_buf, list);
132 + list_cut_position(&bf_head,
133 + &txq->txq_fifo_pending,
134 + &bf->bf_lastbf->list);
135 + ath_tx_txqaddbuf(sc, txq, &bf_head);
136 + } else if (sc->sc_flags & SC_OP_TXAGGR)
137 + ath_txq_schedule(sc, txq);
138 +
139 spin_unlock_bh(&txq->axq_lock);
140 }
141 }