ath9k: fix a potential buffer leak in the STA teardown path
It looks like it might be possible for a TID to be paused, while still holding some queued buffers, however ath_tx_node_cleanup currently only iterates over active TIDs. Fix this by always checking every allocated TID for the STA that is being cleaned up. Signed-off-by: Felix Fietkau <nbd@openwrt.org> Cc: stable@kernel.org Signed-off-by: John W. Linville <linville@tuxdriver.com>
This commit is contained in:
parent
60ea385ff2
commit
2b40994cab
1 changed files with 25 additions and 25 deletions
|
@ -2430,37 +2430,37 @@ void ath_tx_node_init(struct ath_softc *sc, struct ath_node *an)
|
||||||
|
|
||||||
void ath_tx_node_cleanup(struct ath_softc *sc, struct ath_node *an)
|
void ath_tx_node_cleanup(struct ath_softc *sc, struct ath_node *an)
|
||||||
{
|
{
|
||||||
int i;
|
struct ath_atx_ac *ac;
|
||||||
struct ath_atx_ac *ac, *ac_tmp;
|
struct ath_atx_tid *tid;
|
||||||
struct ath_atx_tid *tid, *tid_tmp;
|
|
||||||
struct ath_txq *txq;
|
struct ath_txq *txq;
|
||||||
|
int i, tidno;
|
||||||
|
|
||||||
for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) {
|
for (tidno = 0, tid = &an->tid[tidno];
|
||||||
if (ATH_TXQ_SETUP(sc, i)) {
|
tidno < WME_NUM_TID; tidno++, tid++) {
|
||||||
txq = &sc->tx.txq[i];
|
i = tid->ac->qnum;
|
||||||
|
|
||||||
spin_lock_bh(&txq->axq_lock);
|
if (!ATH_TXQ_SETUP(sc, i))
|
||||||
|
continue;
|
||||||
|
|
||||||
list_for_each_entry_safe(ac,
|
txq = &sc->tx.txq[i];
|
||||||
ac_tmp, &txq->axq_acq, list) {
|
ac = tid->ac;
|
||||||
tid = list_first_entry(&ac->tid_q,
|
|
||||||
struct ath_atx_tid, list);
|
|
||||||
if (tid && tid->an != an)
|
|
||||||
continue;
|
|
||||||
list_del(&ac->list);
|
|
||||||
ac->sched = false;
|
|
||||||
|
|
||||||
list_for_each_entry_safe(tid,
|
spin_lock_bh(&txq->axq_lock);
|
||||||
tid_tmp, &ac->tid_q, list) {
|
|
||||||
list_del(&tid->list);
|
|
||||||
tid->sched = false;
|
|
||||||
ath_tid_drain(sc, txq, tid);
|
|
||||||
tid->state &= ~AGGR_ADDBA_COMPLETE;
|
|
||||||
tid->state &= ~AGGR_CLEANUP;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
spin_unlock_bh(&txq->axq_lock);
|
if (tid->sched) {
|
||||||
|
list_del(&tid->list);
|
||||||
|
tid->sched = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (ac->sched) {
|
||||||
|
list_del(&ac->list);
|
||||||
|
tid->ac->sched = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
ath_tid_drain(sc, txq, tid);
|
||||||
|
tid->state &= ~AGGR_ADDBA_COMPLETE;
|
||||||
|
tid->state &= ~AGGR_CLEANUP;
|
||||||
|
|
||||||
|
spin_unlock_bh(&txq->axq_lock);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue