ddeeb145bdbd4394eada9155df23958271423a41
[openwrt-10.03/.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,40 @@ 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 -               if (drop || ath9k_has_pending_frames(sc, txq)) {
37 -                       ath_dbg(common, ATH_DBG_QUEUE, "Drop frames from hw queue:%d\n",
38 -                               txq->axq_qnum);
39 -                       spin_lock_bh(&txq->axq_lock);
40 -                       txq->txq_flush_inprogress = true;
41 -                       spin_unlock_bh(&txq->axq_lock);
42 -
43 -                       ath9k_ps_wakeup(sc);
44 -                       ath9k_hw_stoptxdma(ah, txq->axq_qnum);
45 -                       npend = ath9k_hw_numtxpending(ah, txq->axq_qnum);
46 -                       ath9k_ps_restore(sc);
47 -                       if (npend)
48 -                               break;
49 +       for (j = 0; j < timeout; j++) {
50 +               int npend = 0;
51 +               for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) {
52 +                       if (!ATH_TXQ_SETUP(sc, i))
53 +                               continue;
54  
55 -                       ath_draintxq(sc, txq, false);
56 -                       txq->txq_flush_inprogress = false;
57 +                       npend += ath9k_has_pending_frames(sc, &sc->tx.txq[i]);
58                 }
59 +
60 +               if (!npend)
61 +                   goto out;
62 +
63 +               usleep_range(1000, 2000);
64         }
65  
66 -       if (npend) {
67 +       if (!ath_drain_all_txq(sc, false))
68                 ath_reset(sc, false);
69 -               txq->txq_flush_inprogress = false;
70 -       }
71  
72 +out:
73         ieee80211_queue_delayed_work(hw, &sc->tx_complete_work, 0);
74         mutex_unlock(&sc->mutex);
75 +       ath9k_ps_restore(sc);
76  }
77  
78  struct ieee80211_ops ath9k_ops = {
79 --- a/drivers/net/wireless/ath/ath9k/ath9k.h
80 +++ b/drivers/net/wireless/ath/ath9k/ath9k.h
81 @@ -189,7 +189,6 @@ struct ath_txq {
82         u32 axq_ampdu_depth;
83         bool stopped;
84         bool axq_tx_inprogress;
85 -       bool txq_flush_inprogress;
86         struct list_head axq_acq;
87         struct list_head txq_fifo[ATH_TXFIFO_DEPTH];
88         struct list_head txq_fifo_pending;
89 --- a/drivers/net/wireless/ath/ath9k/xmit.c
90 +++ b/drivers/net/wireless/ath/ath9k/xmit.c
91 @@ -2091,8 +2091,7 @@ static void ath_tx_processq(struct ath_s
92                 spin_lock_bh(&txq->axq_lock);
93                 if (list_empty(&txq->axq_q)) {
94                         txq->axq_link = NULL;
95 -                       if (sc->sc_flags & SC_OP_TXAGGR &&
96 -                           !txq->txq_flush_inprogress)
97 +                       if (sc->sc_flags & SC_OP_TXAGGR)
98                                 ath_txq_schedule(sc, txq);
99                         spin_unlock_bh(&txq->axq_lock);
100                         break;
101 @@ -2173,7 +2172,7 @@ static void ath_tx_processq(struct ath_s
102  
103                 spin_lock_bh(&txq->axq_lock);
104  
105 -               if (sc->sc_flags & SC_OP_TXAGGR && !txq->txq_flush_inprogress)
106 +               if (sc->sc_flags & SC_OP_TXAGGR)
107                         ath_txq_schedule(sc, txq);
108                 spin_unlock_bh(&txq->axq_lock);
109         }
110 @@ -2317,18 +2316,17 @@ void ath_tx_edma_tasklet(struct ath_soft
111  
112                 spin_lock_bh(&txq->axq_lock);
113  
114 -               if (!txq->txq_flush_inprogress) {
115 -                       if (!list_empty(&txq->txq_fifo_pending)) {
116 -                               INIT_LIST_HEAD(&bf_head);
117 -                               bf = list_first_entry(&txq->txq_fifo_pending,
118 -                                                     struct ath_buf, list);
119 -                               list_cut_position(&bf_head,
120 -                                                 &txq->txq_fifo_pending,
121 -                                                 &bf->bf_lastbf->list);
122 -                               ath_tx_txqaddbuf(sc, txq, &bf_head);
123 -                       } else if (sc->sc_flags & SC_OP_TXAGGR)
124 -                               ath_txq_schedule(sc, txq);
125 -               }
126 +               if (!list_empty(&txq->txq_fifo_pending)) {
127 +                       INIT_LIST_HEAD(&bf_head);
128 +                       bf = list_first_entry(&txq->txq_fifo_pending,
129 +                                             struct ath_buf, list);
130 +                       list_cut_position(&bf_head,
131 +                                         &txq->txq_fifo_pending,
132 +                                         &bf->bf_lastbf->list);
133 +                       ath_tx_txqaddbuf(sc, txq, &bf_head);
134 +               } else if (sc->sc_flags & SC_OP_TXAGGR)
135 +                       ath_txq_schedule(sc, txq);
136 +
137                 spin_unlock_bh(&txq->axq_lock);
138         }
139  }