ath9k: fix aggregation pause/restart handling under heavy load (thx to Lorenzo Bianconi)
authorFelix Fietkau <nbd@openwrt.org>
Sun, 1 Aug 2010 16:33:50 +0000 (16:33 +0000)
committerFelix Fietkau <nbd@openwrt.org>
Sun, 1 Aug 2010 16:33:50 +0000 (16:33 +0000)
SVN-Revision: 22457

package/mac80211/patches/530-ath9k_aggr_state_fix.patch [new file with mode: 0644]

diff --git a/package/mac80211/patches/530-ath9k_aggr_state_fix.patch b/package/mac80211/patches/530-ath9k_aggr_state_fix.patch
new file mode 100644 (file)
index 0000000..d3a7849
--- /dev/null
@@ -0,0 +1,72 @@
+--- a/drivers/net/wireless/ath/ath9k/xmit.c
++++ b/drivers/net/wireless/ath/ath9k/xmit.c
+@@ -120,26 +120,14 @@ static void ath_tx_queue_tid(struct ath_
+       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);
+-      spin_lock_bh(&txq->axq_lock);
+-
+-      tid->paused--;
++      WARN_ON(!tid->paused);
+-      if (tid->paused > 0)
+-              goto unlock;
++      spin_lock_bh(&txq->axq_lock);
++      tid->paused = false;
+       if (list_empty(&tid->buf_q))
+               goto unlock;
+@@ -157,15 +145,10 @@ static void ath_tx_flush_tid(struct ath_
+       struct list_head bf_head;
+       INIT_LIST_HEAD(&bf_head);
+-      BUG_ON(tid->paused <= 0);
+-      spin_lock_bh(&txq->axq_lock);
++      WARN_ON(!tid->paused);
+-      tid->paused--;
+-
+-      if (tid->paused > 0) {
+-              spin_unlock_bh(&txq->axq_lock);
+-              return;
+-      }
++      spin_lock_bh(&txq->axq_lock);
++      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 
+       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 *
+               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)) {