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