Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 15 Aug 2012 08:14:16 +0000 (UTC)
From:      Adrian Chadd <adrian@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r239290 - head/sys/dev/ath
Message-ID:  <201208150814.q7F8EGm8024602@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: adrian
Date: Wed Aug 15 08:14:16 2012
New Revision: 239290
URL: http://svn.freebsd.org/changeset/base/239290

Log:
  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.

Modified:
  head/sys/dev/ath/if_ath_tx.c

Modified: head/sys/dev/ath/if_ath_tx.c
==============================================================================
--- head/sys/dev/ath/if_ath_tx.c	Wed Aug 15 08:06:06 2012	(r239289)
+++ head/sys/dev/ath/if_ath_tx.c	Wed Aug 15 08:14:16 2012	(r239290)
@@ -302,9 +302,10 @@ ath_tx_chaindesclist(struct ath_softc *s
 {
 	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 *s
 	/*
 	 * 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 *s
 		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 *s
 			__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);
 }



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201208150814.q7F8EGm8024602>