mirror of
https://github.com/edk2-porting/linux-next.git
synced 2024-12-20 19:23:57 +08:00
ath9k: fix an issue in ath_atx_tid paused flag management
I noticed a possible issue in the paused flag management of the ath_atx_tid data structure. In particular, in a noisy environment and under heavy load, I observed that the AGGR session establishment could fail several times consecutively causing values of the paused flag greater than one for this TID (ath_tx_pause_tid is called more than once from ath_tx_aggr_start). Considering that the session for this TID can not be established also after the mac80211 stack calls the ieee80211_agg_tx_operational() since the ath_tx_aggr_resume() lowers the paused flag only by one. This patch also replaces some BUG_ON calls with WARN_ON, as even if these unlikely conditions happen, it's not fatal enough to justify a BUG_ON. Signed-off-by: Lorenzo Bianconi <lorenzo.bianconi83@gmail.com> Signed-off-by: Felix Fietkau <nbd@openwrt.org> Signed-off-by: John W. Linville <linville@tuxdriver.com>
This commit is contained in:
parent
824b185adf
commit
7540184942
@ -120,26 +120,14 @@ static void ath_tx_queue_tid(struct ath_txq *txq, struct ath_atx_tid *tid)
|
||||
list_add_tail(&ac->list, &txq->axq_acq);
|
||||
}
|
||||
|
||||
static void ath_tx_pause_tid(struct ath_softc *sc, struct ath_atx_tid *tid)
|
||||
{
|
||||
struct ath_txq *txq = &sc->tx.txq[tid->ac->qnum];
|
||||
|
||||
spin_lock_bh(&txq->axq_lock);
|
||||
tid->paused++;
|
||||
spin_unlock_bh(&txq->axq_lock);
|
||||
}
|
||||
|
||||
static void ath_tx_resume_tid(struct ath_softc *sc, struct ath_atx_tid *tid)
|
||||
{
|
||||
struct ath_txq *txq = &sc->tx.txq[tid->ac->qnum];
|
||||
|
||||
BUG_ON(tid->paused <= 0);
|
||||
WARN_ON(!tid->paused);
|
||||
|
||||
spin_lock_bh(&txq->axq_lock);
|
||||
|
||||
tid->paused--;
|
||||
|
||||
if (tid->paused > 0)
|
||||
goto unlock;
|
||||
tid->paused = false;
|
||||
|
||||
if (list_empty(&tid->buf_q))
|
||||
goto unlock;
|
||||
@ -157,15 +145,10 @@ static void ath_tx_flush_tid(struct ath_softc *sc, struct ath_atx_tid *tid)
|
||||
struct list_head bf_head;
|
||||
INIT_LIST_HEAD(&bf_head);
|
||||
|
||||
BUG_ON(tid->paused <= 0);
|
||||
WARN_ON(!tid->paused);
|
||||
|
||||
spin_lock_bh(&txq->axq_lock);
|
||||
|
||||
tid->paused--;
|
||||
|
||||
if (tid->paused > 0) {
|
||||
spin_unlock_bh(&txq->axq_lock);
|
||||
return;
|
||||
}
|
||||
tid->paused = false;
|
||||
|
||||
while (!list_empty(&tid->buf_q)) {
|
||||
bf = list_first_entry(&tid->buf_q, struct ath_buf, list);
|
||||
@ -811,7 +794,7 @@ void ath_tx_aggr_start(struct ath_softc *sc, struct ieee80211_sta *sta,
|
||||
an = (struct ath_node *)sta->drv_priv;
|
||||
txtid = ATH_AN_2_TID(an, tid);
|
||||
txtid->state |= AGGR_ADDBA_PROGRESS;
|
||||
ath_tx_pause_tid(sc, txtid);
|
||||
txtid->paused = true;
|
||||
*ssn = txtid->seq_start;
|
||||
}
|
||||
|
||||
@ -835,10 +818,9 @@ void ath_tx_aggr_stop(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid)
|
||||
return;
|
||||
}
|
||||
|
||||
ath_tx_pause_tid(sc, txtid);
|
||||
|
||||
/* drop all software retried frames and mark this TID */
|
||||
spin_lock_bh(&txq->axq_lock);
|
||||
txtid->paused = true;
|
||||
while (!list_empty(&txtid->buf_q)) {
|
||||
bf = list_first_entry(&txtid->buf_q, struct ath_buf, list);
|
||||
if (!bf_isretried(bf)) {
|
||||
|
Loading…
Reference in New Issue
Block a user