svn commit: r250229 - head/sys/dev/ath

Adrian Chadd adrian at FreeBSD.org
Sat May 4 04:03:51 UTC 2013


Author: adrian
Date: Sat May  4 04:03:50 2013
New Revision: 250229
URL: http://svnweb.freebsd.org/changeset/base/250229

Log:
  The holding buffer logic needs to be used for _all_ transmission, not
  just "when the queue is busy."
  
  After talking with the MAC team, it turns out that the linked list
  implementation sometimes will not accept a TxDP update and will
  instead re-read the link pointer.  So even if the hardware has
  finished transmitting a chain and has hit EOL/VEOL, it may still
  re-read the link pointer to begin transmitting again.
  
  So, always set ATH_BUF_BUSY on the last buffer in the chain (to
  mark the last descriptor as the holding descriptor) and never
  blank the axq_link pointer.
  
  Tested:
  
  * AR5416, STA mode
  
  TODO:
  
  * much more thorough testing with the pre-11n NICs, just to verify
    that they behave the same way.
  * test TDMA on the 11n and non-11n hardware.

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

Modified: head/sys/dev/ath/if_ath.c
==============================================================================
--- head/sys/dev/ath/if_ath.c	Sat May  4 00:31:41 2013	(r250228)
+++ head/sys/dev/ath/if_ath.c	Sat May  4 04:03:50 2013	(r250229)
@@ -3928,19 +3928,20 @@ ath_tx_processq(struct ath_softc *sc, st
 			break;
 		}
 		ATH_TXQ_REMOVE(txq, bf, bf_list);
-		if (txq->axq_depth > 0) {
-			/*
-			 * More frames follow.  Mark the buffer busy
-			 * so it's not re-used while the hardware may
-			 * still re-read the link field in the descriptor.
-			 *
-			 * Use the last buffer in an aggregate as that
-			 * is where the hardware may be - intermediate
-			 * descriptors won't be "busy".
-			 */
-			bf->bf_last->bf_flags |= ATH_BUF_BUSY;
-		} else
-			txq->axq_link = NULL;
+
+		/*
+		 * Always mark the last buffer in this list as busy.
+		 *
+		 * The hardware may re-read the holding descriptor
+		 * even if we hit the end of the list and try writing
+		 * a new TxDP.
+		 *
+		 * If there's no holding descriptor then this is the
+		 * last buffer in the list of buffers after a fresh
+		 * reset; it'll soon become the holding buffer.
+		 */
+		bf->bf_last->bf_flags |= ATH_BUF_BUSY;
+
 		if (bf->bf_state.bfs_aggr)
 			txq->axq_aggr_depth--;
 


More information about the svn-src-head mailing list