diff options
author | Sujith <Sujith.Manoharan@atheros.com> | 2009-01-16 11:08:51 -0500 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2009-01-29 16:00:41 -0500 |
commit | 6ef9b13db24757a9856f2feb1e571f34938567c9 (patch) | |
tree | 3a5a787949754f72a1cb509b77bea86a29a160c0 /drivers/net | |
parent | 059d806cdcad3848582519f0546cf8b3bfede7a3 (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.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) | |||
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 | ||