svn commit: r225137 - user/adrian/if_ath_tx/sys/dev/ath

Adrian Chadd adrian at FreeBSD.org
Wed Aug 24 08:32:52 UTC 2011


Author: adrian
Date: Wed Aug 24 08:32:51 2011
New Revision: 225137
URL: http://svn.freebsd.org/changeset/base/225137

Log:
  Fix a TX hang that crept in when I flipped in ATH_BUF_BUSY / TX buf cloning.
  This was due to an ATH_BUF_BUSY buffer ending up at the head of the txbuf list,
  causing ath_getbuf() to halt TX until the TX queue had caught up. Since the
  TX queue wasn't -really- full, TX would stay paused.
  
  The basic problem: because I just checked the busy flag, the:
  
  * buffer would be cloned; the ATH_BUF_BUSY tagged buffer would be freed
    and tossed onto the end of the list;
  * if the new cloned buffer (not busy) was already at max retries, the
    new non-busy buffer would be freed, and added to the end of the list;
    and thus the busy buffer isn't at the end of the list;
  * .. and bewm. The flag would never be cleared.
  
  Also, whilst I'm at it, add a comment about an error condition if the buffer
  can't be cloned - i may end up confusing the DMA code a bit. I'll sort that
  out later.

Modified:
  user/adrian/if_ath_tx/sys/dev/ath/if_ath_tx.c

Modified: user/adrian/if_ath_tx/sys/dev/ath/if_ath_tx.c
==============================================================================
--- user/adrian/if_ath_tx/sys/dev/ath/if_ath_tx.c	Wed Aug 24 08:27:00 2011	(r225136)
+++ user/adrian/if_ath_tx/sys/dev/ath/if_ath_tx.c	Wed Aug 24 08:32:51 2011	(r225137)
@@ -2372,6 +2372,7 @@ ath_tx_retry_clone(struct ath_softc *sc,
 		device_printf(sc->sc_dev,
 		    "%s: failed to setup dma for clone\n",
 		    __func__);
+		/* XXX this frees the dmasetup that failed above? */
 		ath_freebuf(sc, nbf);
 		return NULL;
 	}
@@ -2412,7 +2413,8 @@ ath_tx_aggr_retry_unaggr(struct ath_soft
 	 * to force the next bit of code to free the buffer
 	 * for us.
 	 */
-	if (bf->bf_flags & ATH_BUF_BUSY) {
+	if ((bf->bf_state.bfs_retries < SWMAX_RETRIES) &&
+	    (bf->bf_flags & ATH_BUF_BUSY)) {
 		struct ath_buf *nbf;
 		nbf = ath_tx_retry_clone(sc, bf);
 		if (nbf)
@@ -2517,7 +2519,8 @@ ath_tx_retry_subframe(struct ath_softc *
 	 * to force the next bit of code to free the buffer
 	 * for us.
 	 */
-	if (bf->bf_flags & ATH_BUF_BUSY) {
+	if ((bf->bf_state.bfs_retries < SWMAX_RETRIES) &&
+	    (bf->bf_flags & ATH_BUF_BUSY)) {
 		struct ath_buf *nbf;
 		nbf = ath_tx_retry_clone(sc, bf);
 		if (nbf)


More information about the svn-src-user mailing list