ath9k: fix some locking issues in the tx fifo cleanup patch

SVN-Revision: 26947
owl
Felix Fietkau 2011-05-19 09:33:45 +00:00
parent f2c86a3835
commit 512be5ce46
1 changed files with 23 additions and 35 deletions

View File

@ -467,7 +467,7 @@
} }
static void ath_tx_complete_poll_work(struct work_struct *work) static void ath_tx_complete_poll_work(struct work_struct *work)
@@ -2237,17 +2193,17 @@ void ath_tx_tasklet(struct ath_softc *sc @@ -2237,17 +2193,16 @@ void ath_tx_tasklet(struct ath_softc *sc
void ath_tx_edma_tasklet(struct ath_softc *sc) void ath_tx_edma_tasklet(struct ath_softc *sc)
{ {
@ -481,14 +481,13 @@
int status; int status;
- int txok; - int txok;
+ spin_lock_bh(&txq->axq_lock);
for (;;) { for (;;) {
- status = ath9k_hw_txprocdesc(ah, NULL, (void *)&txs); - status = ath9k_hw_txprocdesc(ah, NULL, (void *)&txs);
+ status = ath9k_hw_txprocdesc(ah, NULL, (void *)&ts); + status = ath9k_hw_txprocdesc(ah, NULL, (void *)&ts);
if (status == -EINPROGRESS) if (status == -EINPROGRESS)
break; break;
if (status == -EIO) { if (status == -EIO) {
@@ -2257,16 +2213,16 @@ void ath_tx_edma_tasklet(struct ath_soft @@ -2257,12 +2212,13 @@ void ath_tx_edma_tasklet(struct ath_soft
} }
/* Skip beacon completions */ /* Skip beacon completions */
@ -497,22 +496,14 @@
continue; continue;
- txq = &sc->tx.txq[txs.qid]; - txq = &sc->tx.txq[txs.qid];
+ ath_dbg(common, ATH_DBG_XMIT,
+ "Tx status, descid=%04x\n", ts.desc_id);
- spin_lock_bh(&txq->axq_lock);
- if (list_empty(&txq->txq_fifo[txq->txq_tailidx])) {
- spin_unlock_bh(&txq->axq_lock);
- return;
- }
+ txq = &sc->tx.txq[ts.qid]; + txq = &sc->tx.txq[ts.qid];
+
+ if (list_empty(&txq->txq_fifo[txq->txq_tailidx]))
+ break;
bf = list_first_entry(&txq->txq_fifo[txq->txq_tailidx], spin_lock_bh(&txq->axq_lock);
struct ath_buf, list); +
@@ -2275,43 +2231,24 @@ void ath_tx_edma_tasklet(struct ath_soft if (list_empty(&txq->txq_fifo[txq->txq_tailidx])) {
spin_unlock_bh(&txq->axq_lock);
return;
@@ -2275,41 +2231,21 @@ void ath_tx_edma_tasklet(struct ath_soft
INIT_LIST_HEAD(&bf_head); INIT_LIST_HEAD(&bf_head);
list_cut_position(&bf_head, &txq->txq_fifo[txq->txq_tailidx], list_cut_position(&bf_head, &txq->txq_fifo[txq->txq_tailidx],
&lastbf->list); &lastbf->list);
@ -524,31 +515,25 @@
- spin_unlock_bh(&txq->axq_lock); - spin_unlock_bh(&txq->axq_lock);
- txok = !(txs.ts_status & ATH9K_TXERR_MASK); - txok = !(txs.ts_status & ATH9K_TXERR_MASK);
+ if (list_empty(&txq->txq_fifo[txq->txq_tailidx])) { -
+ INCR(txq->txq_tailidx, ATH_TXFIFO_DEPTH);
- if (!bf_isampdu(bf)) { - if (!bf_isampdu(bf)) {
- if (txs.ts_status & ATH9K_TXERR_XRETRY) - if (txs.ts_status & ATH9K_TXERR_XRETRY)
- bf->bf_state.bf_type |= BUF_XRETRY; - bf->bf_state.bf_type |= BUF_XRETRY;
- ath_tx_rc_status(sc, bf, &txs, 1, txok ? 0 : 1, txok, true); - ath_tx_rc_status(sc, bf, &txs, 1, txok ? 0 : 1, txok, true);
- } - }
+ if (!list_empty(&txq->axq_q)) { -
+ struct list_head bf_q;
- if (bf_isampdu(bf)) - if (bf_isampdu(bf))
- ath_tx_complete_aggr(sc, txq, bf, &bf_head, &txs, - ath_tx_complete_aggr(sc, txq, bf, &bf_head, &txs,
- txok, true); - txok, true);
- else - else
- ath_tx_complete_buf(sc, bf, txq, &bf_head, - ath_tx_complete_buf(sc, bf, txq, &bf_head,
- &txs, txok, 0); - &txs, txok, 0);
- + if (list_empty(&txq->txq_fifo[txq->txq_tailidx])) {
+ INCR(txq->txq_tailidx, ATH_TXFIFO_DEPTH);
- spin_lock_bh(&txq->axq_lock); - spin_lock_bh(&txq->axq_lock);
+ INIT_LIST_HEAD(&bf_q); + if (!list_empty(&txq->axq_q)) {
+ txq->axq_link = NULL; + struct list_head bf_q;
+ list_splice_tail_init(&txq->axq_q, &bf_q);
+ ath_tx_txqaddbuf(sc, txq, &bf_q, true);
+ }
+ }
- if (!list_empty(&txq->txq_fifo_pending)) { - if (!list_empty(&txq->txq_fifo_pending)) {
- INIT_LIST_HEAD(&bf_head); - INIT_LIST_HEAD(&bf_head);
@ -560,14 +545,17 @@
- ath_tx_txqaddbuf(sc, txq, &bf_head); - ath_tx_txqaddbuf(sc, txq, &bf_head);
- } else if (sc->sc_flags & SC_OP_TXAGGR) - } else if (sc->sc_flags & SC_OP_TXAGGR)
- ath_txq_schedule(sc, txq); - ath_txq_schedule(sc, txq);
+ INIT_LIST_HEAD(&bf_q);
+ txq->axq_link = NULL;
+ list_splice_tail_init(&txq->axq_q, &bf_q);
+ ath_tx_txqaddbuf(sc, txq, &bf_q, true);
+ }
+ }
+ ath_tx_process_buffer(sc, txq, &ts, bf, &bf_head); + ath_tx_process_buffer(sc, txq, &ts, bf, &bf_head);
spin_unlock_bh(&txq->axq_lock);
- spin_unlock_bh(&txq->axq_lock);
} }
+ spin_unlock_bh(&txq->axq_lock);
} }
/*****************/
--- a/drivers/net/wireless/ath/ath9k/ath9k.h --- a/drivers/net/wireless/ath/ath9k/ath9k.h
+++ b/drivers/net/wireless/ath/ath9k/ath9k.h +++ b/drivers/net/wireless/ath/ath9k/ath9k.h
@@ -179,7 +179,7 @@ enum ATH_AGGR_STATUS { @@ -179,7 +179,7 @@ enum ATH_AGGR_STATUS {