summaryrefslogtreecommitdiffstats
path: root/sys/dev/ath/if_ath_tx.c
diff options
context:
space:
mode:
authoradrian <adrian@FreeBSD.org>2012-08-15 08:14:16 +0000
committeradrian <adrian@FreeBSD.org>2012-08-15 08:14:16 +0000
commit0424c6d691509dd56bc5d8b799edda55b441f96c (patch)
tree8424a18f569751bf1a76e0bfa0f825c524b1760b /sys/dev/ath/if_ath_tx.c
parent709a1cd8d6309d52974ffe82525c418620d675a5 (diff)
downloadFreeBSD-src-0424c6d691509dd56bc5d8b799edda55b441f96c.zip
FreeBSD-src-0424c6d691509dd56bc5d8b799edda55b441f96c.tar.gz
Extend the non-aggregate TX descriptor chain routine to be aware of:
* the descriptor ID, and * the multi-buffer support that the EDMA chips support. This is required for successful MAC transmission of multi-descriptor frames. The MAC simply hangs if there are NULL buffers + 0 length pointers, but the descriptor did have TxMore set. This won't be done for the 11n aggregate path, as that will be modified to use the newer API (ie, ath_hal_filltxdesc() and then set first|middle| last_aggr), which will deprecate some of the current code. TODO: * Populate the numTxMaps field in the HAL, then make sure that's fetched by the driver. Then I can undo that hack. Tested: * AR9380, AP mode, TX'ing non-aggregate 802.11n frames; * AR9280, STA/AP mode, doing aggregate and non-aggregate traffic.
Diffstat (limited to 'sys/dev/ath/if_ath_tx.c')
-rw-r--r--sys/dev/ath/if_ath_tx.c58
1 files changed, 49 insertions, 9 deletions
diff --git a/sys/dev/ath/if_ath_tx.c b/sys/dev/ath/if_ath_tx.c
index 2649085..6433307 100644
--- a/sys/dev/ath/if_ath_tx.c
+++ b/sys/dev/ath/if_ath_tx.c
@@ -302,9 +302,10 @@ ath_tx_chaindesclist(struct ath_softc *sc, struct ath_buf *bf)
{
struct ath_hal *ah = sc->sc_ah;
struct ath_desc *ds, *ds0;
- int i;
+ int i, bp, dsp;
HAL_DMA_ADDR bufAddrList[4];
uint32_t segLenList[4];
+ int numTxMaps = 1;
/*
* XXX There's txdma and txdma_mgmt; the descriptor
@@ -315,20 +316,47 @@ ath_tx_chaindesclist(struct ath_softc *sc, struct ath_buf *bf)
/*
* Fillin the remainder of the descriptor info.
*/
+
+ /*
+ * For now the HAL doesn't implement halNumTxMaps for non-EDMA
+ * (ie it's 0.) So just work around it.
+ *
+ * XXX TODO: populate halNumTxMaps for each HAL chip and
+ * then undo this hack.
+ */
+ if (sc->sc_ah->ah_magic == 0x19741014)
+ numTxMaps = 4;
+
+ /*
+ * For EDMA and later chips ensure the TX map is fully populated
+ * before advancing to the next descriptor.
+ */
ds0 = ds = bf->bf_desc;
- for (i = 0; i < bf->bf_nseg; i++, ds++) {
- bufAddrList[0] = bf->bf_segs[i].ds_addr;
- segLenList[0] = bf->bf_segs[i].ds_len;
+ bp = dsp = 0;
+ bzero(bufAddrList, sizeof(bufAddrList));
+ bzero(segLenList, sizeof(segLenList));
+ for (i = 0; i < bf->bf_nseg; i++) {
+ bufAddrList[bp] = bf->bf_segs[i].ds_addr;
+ segLenList[bp] = bf->bf_segs[i].ds_len;
+ bp++;
+
+ /*
+ * Go to the next segment if this isn't the last segment
+ * and there's space in the current TX map.
+ */
+ if ((i != bf->bf_nseg - 1) && (bp < numTxMaps))
+ continue;
- /* Blank this out until multi-buf support is added for AR9300 */
- bufAddrList[1] = bufAddrList[2] = bufAddrList[3] = 0;
- segLenList[1] = segLenList[2] = segLenList[3] = 0;
+ /*
+ * Last segment or we're out of buffer pointers.
+ */
+ bp = 0;
if (i == bf->bf_nseg - 1)
ath_hal_settxdesclink(ah, ds, 0);
else
ath_hal_settxdesclink(ah, ds,
- bf->bf_daddr + dd->dd_descsize * (i + 1));
+ bf->bf_daddr + dd->dd_descsize * (dsp + 1));
/*
* XXX this assumes that bfs_txq is the actual destination
@@ -339,7 +367,7 @@ ath_tx_chaindesclist(struct ath_softc *sc, struct ath_buf *bf)
ath_hal_filltxdesc(ah, ds
, bufAddrList
, segLenList
- , 0 /* XXX desc id */
+ , bf->bf_descid /* XXX desc id */
, bf->bf_state.bfs_txq->axq_qnum /* XXX multicast? */
, i == 0 /* first segment */
, i == bf->bf_nseg - 1 /* last segment */
@@ -350,6 +378,18 @@ ath_tx_chaindesclist(struct ath_softc *sc, struct ath_buf *bf)
__func__, i, ds->ds_link, ds->ds_data,
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.
+ */
+ ds++;
+ dsp++;
+
+ /*
+ * .. and don't forget to blank these out!
+ */
+ bzero(bufAddrList, sizeof(bufAddrList));
+ bzero(segLenList, sizeof(segLenList));
}
bus_dmamap_sync(sc->sc_dmat, bf->bf_dmamap, BUS_DMASYNC_PREWRITE);
}
OpenPOWER on IntegriCloud