Advance the descriptor pointer by sc->sc_tx_desclen bytes, rather than

sizeof(struct ath_desc).  This isn't correct for EDMA TX descriptors.

This popped up during iperf tests. Ping tests never created frames that
had enough segments to overflow into a second descriptor.  However,
an iperf TCP test would do that after a few seconds; the second descriptor
would almost always certainly have garbage.

Tested:

* AR9380, STA mode
* AR9280, STA mode (802.11n TX, legacy TX)
This commit is contained in:
Adrian Chadd 2012-08-20 06:02:09 +00:00
parent bd68600c99
commit 42083b3d66

View File

@ -301,12 +301,13 @@ static void
ath_tx_chaindesclist(struct ath_softc *sc, struct ath_buf *bf) ath_tx_chaindesclist(struct ath_softc *sc, struct ath_buf *bf)
{ {
struct ath_hal *ah = sc->sc_ah; struct ath_hal *ah = sc->sc_ah;
struct ath_desc *ds, *ds0; char *ds, *ds0;
int i, bp, dsp; int i, bp, dsp;
HAL_DMA_ADDR bufAddrList[4]; HAL_DMA_ADDR bufAddrList[4];
uint32_t segLenList[4]; uint32_t segLenList[4];
int numTxMaps = 1; int numTxMaps = 1;
int isFirstDesc = 1; int isFirstDesc = 1;
int qnum = 0; /* XXX update */
/* /*
* XXX There's txdma and txdma_mgmt; the descriptor * XXX There's txdma and txdma_mgmt; the descriptor
@ -332,7 +333,7 @@ ath_tx_chaindesclist(struct ath_softc *sc, struct ath_buf *bf)
* For EDMA and later chips ensure the TX map is fully populated * For EDMA and later chips ensure the TX map is fully populated
* before advancing to the next descriptor. * before advancing to the next descriptor.
*/ */
ds0 = ds = bf->bf_desc; ds0 = ds = (char *) bf->bf_desc;
bp = dsp = 0; bp = dsp = 0;
bzero(bufAddrList, sizeof(bufAddrList)); bzero(bufAddrList, sizeof(bufAddrList));
bzero(segLenList, sizeof(segLenList)); bzero(segLenList, sizeof(segLenList));
@ -354,9 +355,9 @@ ath_tx_chaindesclist(struct ath_softc *sc, struct ath_buf *bf)
bp = 0; bp = 0;
if (i == bf->bf_nseg - 1) if (i == bf->bf_nseg - 1)
ath_hal_settxdesclink(ah, ds, 0); ath_hal_settxdesclink(ah, (struct ath_desc *) ds, 0);
else else
ath_hal_settxdesclink(ah, ds, ath_hal_settxdesclink(ah, (struct ath_desc *) ds,
bf->bf_daddr + dd->dd_descsize * (dsp + 1)); bf->bf_daddr + dd->dd_descsize * (dsp + 1));
/* /*
@ -365,26 +366,24 @@ ath_tx_chaindesclist(struct ath_softc *sc, struct ath_buf *bf)
* it may actually be pointing to the multicast software * it may actually be pointing to the multicast software
* TXQ id. These must be fixed! * TXQ id. These must be fixed!
*/ */
ath_hal_filltxdesc(ah, ds ath_hal_filltxdesc(ah, (struct ath_desc *) ds
, bufAddrList , bufAddrList
, segLenList , segLenList
, bf->bf_descid /* XXX desc id */ , bf->bf_descid /* XXX desc id */
, bf->bf_state.bfs_txq->axq_qnum /* XXX multicast? */ , bf->bf_state.bfs_txq->axq_qnum /* XXX multicast? */
, isFirstDesc /* first segment */ , isFirstDesc /* first segment */
, i == bf->bf_nseg - 1 /* last segment */ , i == bf->bf_nseg - 1 /* last segment */
, ds0 /* first descriptor */ , (struct ath_desc *) ds0 /* first descriptor */
); );
isFirstDesc = 0; isFirstDesc = 0;
DPRINTF(sc, ATH_DEBUG_XMIT, if (sc->sc_debug & ATH_DEBUG_XMIT)
"%s: %d: %08x %08x %08x %08x %08x %08x\n", ath_printtxbuf(sc, bf, qnum, 0, 0);
__func__, i, ds->ds_link, ds->ds_data, bf->bf_lastds = (struct ath_desc *) ds;
ds->ds_ctl0, ds->ds_ctl1, ds->ds_hw[0], ds->ds_hw[1]);
bf->bf_lastds = ds;
/* /*
* Don't forget to skip to the next descriptor. * Don't forget to skip to the next descriptor.
*/ */
ds++; ds += sc->sc_tx_desclen;
dsp++; dsp++;
/* /*