aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net
diff options
context:
space:
mode:
authorSujith <Sujith.Manoharan@atheros.com>2009-01-16 11:08:51 -0500
committerJohn W. Linville <linville@tuxdriver.com>2009-01-29 16:00:41 -0500
commit6ef9b13db24757a9856f2feb1e571f34938567c9 (patch)
tree3a5a787949754f72a1cb509b77bea86a29a160c0 /drivers/net
parent059d806cdcad3848582519f0546cf8b3bfede7a3 (diff)
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')
-rw-r--r--drivers/net/wireless/ath9k/xmit.c19
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)
2082 if (bf->bf_status & ATH_BUFSTATUS_STALE) { 2082 if (bf->bf_status & ATH_BUFSTATUS_STALE) {
2083 bf_held = bf; 2083 bf_held = bf;
2084 if (list_is_last(&bf_held->list, &txq->axq_q)) { 2084 if (list_is_last(&bf_held->list, &txq->axq_q)) {
2085 /* FIXME: 2085 txq->axq_link = NULL;
2086 txq->axq_linkbuf = NULL;
2087 spin_unlock_bh(&txq->axq_lock);
2088
2089 /*
2086 * The holding descriptor is the last 2090 * The holding descriptor is the last
2087 * descriptor in queue. It's safe to remove 2091 * descriptor in queue. It's safe to remove
2088 * the last holding descriptor in BH context. 2092 * the last holding descriptor in BH context.
2089 */ 2093 */
2090 spin_unlock_bh(&txq->axq_lock); 2094 spin_lock_bh(&sc->tx.txbuflock);
2095 list_move_tail(&bf_held->list, &sc->tx.txbuf);
2096 spin_unlock_bh(&sc->tx.txbuflock);
2097
2091 break; 2098 break;
2092 } else { 2099 } else {
2093 bf = list_entry(bf_held->list.next, 2100 bf = list_entry(bf_held->list.next,
2094 struct ath_buf, list); 2101 struct ath_buf, list);
2095 } 2102 }
2096 } 2103 }
2097 2104
@@ -2115,24 +2122,20 @@ static void ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq)
2115 */ 2122 */
2116 lastbf->bf_status |= ATH_BUFSTATUS_STALE; 2123 lastbf->bf_status |= ATH_BUFSTATUS_STALE;
2117 INIT_LIST_HEAD(&bf_head); 2124 INIT_LIST_HEAD(&bf_head);
2118
2119 if (!list_is_singular(&lastbf->list)) 2125 if (!list_is_singular(&lastbf->list))
2120 list_cut_position(&bf_head, 2126 list_cut_position(&bf_head,
2121 &txq->axq_q, lastbf->list.prev); 2127 &txq->axq_q, lastbf->list.prev);
2122 2128
2123 txq->axq_depth--; 2129 txq->axq_depth--;
2124
2125 if (bf_isaggr(bf)) 2130 if (bf_isaggr(bf))
2126 txq->axq_aggr_depth--; 2131 txq->axq_aggr_depth--;
2127 2132
2128 txok = (ds->ds_txstat.ts_status == 0); 2133 txok = (ds->ds_txstat.ts_status == 0);
2129
2130 spin_unlock_bh(&txq->axq_lock); 2134 spin_unlock_bh(&txq->axq_lock);
2131 2135
2132 if (bf_held) { 2136 if (bf_held) {
2133 list_del(&bf_held->list);
2134 spin_lock_bh(&sc->tx.txbuflock); 2137 spin_lock_bh(&sc->tx.txbuflock);
2135 list_add_tail(&bf_held->list, &sc->tx.txbuf); 2138 list_move_tail(&bf_held->list, &sc->tx.txbuf);
2136 spin_unlock_bh(&sc->tx.txbuflock); 2139 spin_unlock_bh(&sc->tx.txbuflock);
2137 } 2140 }
2138 2141