Browse Source

ath9k: fix aggregation pause/restart handling under heavy load (thx to Lorenzo Bianconi)

SVN-Revision: 22457
Felix Fietkau 15 years ago
parent
commit
31239d3332
1 changed files with 72 additions and 0 deletions
  1. 72 0
      package/mac80211/patches/530-ath9k_aggr_state_fix.patch

+ 72 - 0
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)) {