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:
parent
bd68600c99
commit
42083b3d66
@ -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++;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
Loading…
Reference in New Issue
Block a user