aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFelix Fietkau <nbd@openwrt.org>2010-08-01 16:33:50 +0000
committerFelix Fietkau <nbd@openwrt.org>2010-08-01 16:33:50 +0000
commit505c98f1f6e6b7c08eb88e9c6385684a5305dc1d (patch)
tree68a42d30369d093cf4434b94a42419ab777b6f27
parentea27eb515b700eee13c13503071ceceb15fe31f8 (diff)
downloadupstream-505c98f1f6e6b7c08eb88e9c6385684a5305dc1d.tar.gz
upstream-505c98f1f6e6b7c08eb88e9c6385684a5305dc1d.tar.bz2
upstream-505c98f1f6e6b7c08eb88e9c6385684a5305dc1d.zip
ath9k: fix aggregation pause/restart handling under heavy load (thx to Lorenzo Bianconi)
git-svn-id: svn://svn.openwrt.org/openwrt/trunk@22457 3c298f89-4303-0410-b956-a3cf2f4a3e73
-rw-r--r--package/mac80211/patches/530-ath9k_aggr_state_fix.patch72
1 files changed, 72 insertions, 0 deletions
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
index 0000000000..d3a7849484
--- /dev/null
+++ b/package/mac80211/patches/530-ath9k_aggr_state_fix.patch
@@ -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)) {