ath9k: fix some locking issues in the tx fifo cleanup patch
SVN-Revision: 26947
This commit is contained in:
parent
f2c86a3835
commit
512be5ce46
1 changed files with 23 additions and 35 deletions
|
@ -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 {
|
||||||
|
|
Loading…
Reference in a new issue