diff options
author | Sujith <Sujith.Manoharan@atheros.com> | 2009-01-16 21:38:51 +0530 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2009-01-29 16:00:41 -0500 |
commit | 6ef9b13db24757a9856f2feb1e571f34938567c9 (patch) | |
tree | 3a5a787949754f72a1cb509b77bea86a29a160c0 /drivers/net/wireless/ath9k/xmit.c | |
parent | 059d806cdcad3848582519f0546cf8b3bfede7a3 (diff) | |
download | blackbird-op-linux-6ef9b13db24757a9856f2feb1e571f34938567c9.tar.gz blackbird-op-linux-6ef9b13db24757a9856f2feb1e571f34938567c9.zip |
ath9k: Handle holding descriptor in TX completion properly
If the current holding descriptor is the last one in the TX queue,
*and* it has been marked as STALE, then move it to the free list
and bail out, as it has already been processed.
Signed-off-by: Sujith <Sujith.Manoharan@atheros.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/ath9k/xmit.c')
-rw-r--r-- | drivers/net/wireless/ath9k/xmit.c | 19 |
1 files changed, 11 insertions, 8 deletions
diff --git a/drivers/net/wireless/ath9k/xmit.c b/drivers/net/wireless/ath9k/xmit.c index 841bd9c54108..d7cec0fee34c 100644 --- a/drivers/net/wireless/ath9k/xmit.c +++ b/drivers/net/wireless/ath9k/xmit.c @@ -2082,16 +2082,23 @@ static void ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq) if (bf->bf_status & ATH_BUFSTATUS_STALE) { bf_held = bf; if (list_is_last(&bf_held->list, &txq->axq_q)) { - /* FIXME: + txq->axq_link = NULL; + txq->axq_linkbuf = NULL; + spin_unlock_bh(&txq->axq_lock); + + /* * The holding descriptor is the last * descriptor in queue. It's safe to remove * the last holding descriptor in BH context. */ - spin_unlock_bh(&txq->axq_lock); + spin_lock_bh(&sc->tx.txbuflock); + list_move_tail(&bf_held->list, &sc->tx.txbuf); + spin_unlock_bh(&sc->tx.txbuflock); + break; } else { bf = list_entry(bf_held->list.next, - struct ath_buf, list); + struct ath_buf, list); } } @@ -2115,24 +2122,20 @@ static void ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq) */ lastbf->bf_status |= ATH_BUFSTATUS_STALE; INIT_LIST_HEAD(&bf_head); - if (!list_is_singular(&lastbf->list)) list_cut_position(&bf_head, &txq->axq_q, lastbf->list.prev); txq->axq_depth--; - if (bf_isaggr(bf)) txq->axq_aggr_depth--; txok = (ds->ds_txstat.ts_status == 0); - spin_unlock_bh(&txq->axq_lock); if (bf_held) { - list_del(&bf_held->list); spin_lock_bh(&sc->tx.txbuflock); - list_add_tail(&bf_held->list, &sc->tx.txbuf); + list_move_tail(&bf_held->list, &sc->tx.txbuf); spin_unlock_bh(&sc->tx.txbuflock); } |