ath9k: fix tx aggregation flush on AR9003
authorFelix Fietkau <nbd@openwrt.org>
Wed, 27 Oct 2010 00:15:05 +0000 (02:15 +0200)
committerGreg Kroah-Hartman <gregkh@suse.de>
Thu, 9 Dec 2010 21:32:03 +0000 (13:32 -0800)
commit e609e2ea2cdb3448e7849703179cd792a28dcc55 upstream.

Completing aggregate frames can lead to new buffers being pushed into
the tid queues due to software retransmission.
When the tx queues are being drained, all pending aggregates must be
completed before the tid queues get drained, otherwise buffers might be
leaked.

Signed-off-by: Felix Fietkau <nbd@openwrt.org>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
drivers/net/wireless/ath/ath9k/xmit.c

index e2ace49bd42972169fe00e123efe3c4bc7402749..a5c489ca34948a33602801fd41344321b04d34dd 100644 (file)
@@ -1101,15 +1101,6 @@ void ath_draintxq(struct ath_softc *sc, struct ath_txq *txq, bool retry_tx)
        txq->axq_tx_inprogress = false;
        spin_unlock_bh(&txq->axq_lock);
 
-       /* flush any pending frames if aggregation is enabled */
-       if (sc->sc_flags & SC_OP_TXAGGR) {
-               if (!retry_tx) {
-                       spin_lock_bh(&txq->axq_lock);
-                       ath_txq_drain_pending_buffers(sc, txq);
-                       spin_unlock_bh(&txq->axq_lock);
-               }
-       }
-
        if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) {
                spin_lock_bh(&txq->axq_lock);
                while (!list_empty(&txq->txq_fifo_pending)) {
@@ -1130,6 +1121,15 @@ void ath_draintxq(struct ath_softc *sc, struct ath_txq *txq, bool retry_tx)
                }
                spin_unlock_bh(&txq->axq_lock);
        }
+
+       /* flush any pending frames if aggregation is enabled */
+       if (sc->sc_flags & SC_OP_TXAGGR) {
+               if (!retry_tx) {
+                       spin_lock_bh(&txq->axq_lock);
+                       ath_txq_drain_pending_buffers(sc, txq);
+                       spin_unlock_bh(&txq->axq_lock);
+               }
+       }
 }
 
 void ath_drain_all_txq(struct ath_softc *sc, bool retry_tx)