]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
ath9k: fix yet another buffer leak in the tx aggregation code
authorFelix Fietkau <nbd@openwrt.org>
Fri, 23 Jul 2010 01:53:16 +0000 (03:53 +0200)
committerGreg Kroah-Hartman <gregkh@suse.de>
Tue, 10 Aug 2010 17:54:11 +0000 (10:54 -0700)
commit 4cee78614cfa046a26c4fbf313d5bbacb3ad8efc upstream.

When an aggregation session is being cleaned up, while the tx status
for some frames is being processed, the TID is flushed and its buffers
are sent out.

Unfortunately that left the pending un-acked frames unprocessed, thus
leaking buffers. Fix this by reordering the code so that those frames
are processed first, before the TID is flushed.

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 aba1a2e50c2ad2426dd6c95f9ca401de32c2eca8..0b2ade3b61129d8e487e9a256127ee232c308532 100644 (file)
@@ -453,6 +453,14 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,
                bf = bf_next;
        }
 
+       /* prepend un-acked frames to the beginning of the pending frame queue */
+       if (!list_empty(&bf_pending)) {
+               spin_lock_bh(&txq->axq_lock);
+               list_splice(&bf_pending, &tid->buf_q);
+               ath_tx_queue_tid(txq, tid);
+               spin_unlock_bh(&txq->axq_lock);
+       }
+
        if (tid->state & AGGR_CLEANUP) {
                if (tid->baw_head == tid->baw_tail) {
                        tid->state &= ~AGGR_ADDBA_COMPLETE;
@@ -465,14 +473,6 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,
                return;
        }
 
-       /* prepend un-acked frames to the beginning of the pending frame queue */
-       if (!list_empty(&bf_pending)) {
-               spin_lock_bh(&txq->axq_lock);
-               list_splice(&bf_pending, &tid->buf_q);
-               ath_tx_queue_tid(txq, tid);
-               spin_unlock_bh(&txq->axq_lock);
-       }
-
        rcu_read_unlock();
 
        if (needreset)