mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-05-05 09:49:58 -04:00
ath5k: fix race condition in tx desc processing
As pointed out by Benoit Papillault, there is a potential
race condition between the host and the hardware in reading
the next link in the transmit descriptor list:
cpu0 hw
tx for buf completed
raise tx_ok interrupt
process buf
buf->ds_link = 0
read buf->ds_link
This change checks txdp before processing a descriptor
(if there are any subsequent descriptors) to see if
hardware moved on. We'll then process this descriptor on
the next tasklet.
Signed-off-by: Bob Copeland <me@bobcopeland.com>
Acked-by: Bruno Randolf <br1@einfach.org>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
This commit is contained in:
committed by
John W. Linville
parent
6b5d117edd
commit
a05988bbbe
@@ -2083,6 +2083,17 @@ ath5k_tx_processq(struct ath5k_softc *sc, struct ath5k_txq *txq)
|
||||
list_for_each_entry_safe(bf, bf0, &txq->q, list) {
|
||||
ds = bf->desc;
|
||||
|
||||
/*
|
||||
* It's possible that the hardware can say the buffer is
|
||||
* completed when it hasn't yet loaded the ds_link from
|
||||
* host memory and moved on. If there are more TX
|
||||
* descriptors in the queue, wait for TXDP to change
|
||||
* before processing this one.
|
||||
*/
|
||||
if (ath5k_hw_get_txdp(sc->ah, txq->qnum) == bf->daddr &&
|
||||
!list_is_last(&bf->list, &txq->q))
|
||||
break;
|
||||
|
||||
ret = sc->ah->ah_proc_tx_desc(sc->ah, ds, &ts);
|
||||
if (unlikely(ret == -EINPROGRESS))
|
||||
break;
|
||||
|
||||
Reference in New Issue
Block a user