aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net
diff options
context:
space:
mode:
authorLorenzo Bianconi <lorenzo.bianconi83@gmail.com>2010-08-01 09:47:32 -0400
committerJohn W. Linville <linville@tuxdriver.com>2010-08-04 15:27:38 -0400
commit754018494216e07f43c611d342d7d8bd25b22140 (patch)
treec8918b551fe0a793a3f98ae54415f45f9062e831 /drivers/net
parent824b185adf86163e57892f22a878f97bc4bc69ab (diff)
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>
Diffstat (limited to 'drivers/net')
-rw-r--r--drivers/net/wireless/ath/ath9k/xmit.c34
1 files changed, 8 insertions, 26 deletions
diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c
index 700ba8dee5a5..4dda14e36227 100644
--- 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_txq *txq, struct ath_atx_tid *tid)
120 list_add_tail(&ac->list, &txq->axq_acq); 120 list_add_tail(&ac->list, &txq->axq_acq);
121} 121}
122 122
123static void ath_tx_pause_tid(struct ath_softc *sc, struct ath_atx_tid *tid)
124{
125 struct ath_txq *txq = &sc->tx.txq[tid->ac->qnum];
126
127 spin_lock_bh(&txq->axq_lock);
128 tid->paused++;
129 spin_unlock_bh(&txq->axq_lock);
130}
131
132static void ath_tx_resume_tid(struct ath_softc *sc, struct ath_atx_tid *tid) 123static void ath_tx_resume_tid(struct ath_softc *sc, struct ath_atx_tid *tid)
133{ 124{
134 struct ath_txq *txq = &sc->tx.txq[tid->ac->qnum]; 125 struct ath_txq *txq = &sc->tx.txq[tid->ac->qnum];
135 126
136 BUG_ON(tid->paused <= 0); 127 WARN_ON(!tid->paused);
137 spin_lock_bh(&txq->axq_lock);
138
139 tid->paused--;
140 128
141 if (tid->paused > 0) 129 spin_lock_bh(&txq->axq_lock);
142 goto unlock; 130 tid->paused = false;
143 131
144 if (list_empty(&tid->buf_q)) 132 if (list_empty(&tid->buf_q))
145 goto unlock; 133 goto unlock;
@@ -157,15 +145,10 @@ static void ath_tx_flush_tid(struct ath_softc *sc, struct ath_atx_tid *tid)
157 struct list_head bf_head; 145 struct list_head bf_head;
158 INIT_LIST_HEAD(&bf_head); 146 INIT_LIST_HEAD(&bf_head);
159 147
160 BUG_ON(tid->paused <= 0); 148 WARN_ON(!tid->paused);
161 spin_lock_bh(&txq->axq_lock);
162 149
163 tid->paused--; 150 spin_lock_bh(&txq->axq_lock);
164 151 tid->paused = false;
165 if (tid->paused > 0) {
166 spin_unlock_bh(&txq->axq_lock);
167 return;
168 }
169 152
170 while (!list_empty(&tid->buf_q)) { 153 while (!list_empty(&tid->buf_q)) {
171 bf = list_first_entry(&tid->buf_q, struct ath_buf, list); 154 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,
811 an = (struct ath_node *)sta->drv_priv; 794 an = (struct ath_node *)sta->drv_priv;
812 txtid = ATH_AN_2_TID(an, tid); 795 txtid = ATH_AN_2_TID(an, tid);
813 txtid->state |= AGGR_ADDBA_PROGRESS; 796 txtid->state |= AGGR_ADDBA_PROGRESS;
814 ath_tx_pause_tid(sc, txtid); 797 txtid->paused = true;
815 *ssn = txtid->seq_start; 798 *ssn = txtid->seq_start;
816} 799}
817 800
@@ -835,10 +818,9 @@ void ath_tx_aggr_stop(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid)
835 return; 818 return;
836 } 819 }
837 820
838 ath_tx_pause_tid(sc, txtid);
839
840 /* drop all software retried frames and mark this TID */ 821 /* drop all software retried frames and mark this TID */
841 spin_lock_bh(&txq->axq_lock); 822 spin_lock_bh(&txq->axq_lock);
823 txtid->paused = true;
842 while (!list_empty(&txtid->buf_q)) { 824 while (!list_empty(&txtid->buf_q)) {
843 bf = list_first_entry(&txtid->buf_q, struct ath_buf, list); 825 bf = list_first_entry(&txtid->buf_q, struct ath_buf, list);
844 if (!bf_isretried(bf)) { 826 if (!bf_isretried(bf)) {