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);
 }
_______________________________________________
svn-src-head@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to