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

Adrian Chadd adrian at
Thu Mar 8 23:53:39 UTC 2012

Author: adrian
Date: Thu Mar  8 23:53:38 2012
New Revision: 232707

  Correctly initialise the TXQ link pointer to the last descriptor in
  the last buffer in the list.
  The current behaviour (due to me, so pointy hat is firmly on my head here)
  was incorrect - it was setting the link pointer to the last descriptor
  of the _first_ buffer in the TXQ.  Instead, it should have set it to the
  last descriptor in the _last_ buffer in the TXQ.
  This showed up as occasional TX stalls with frames in the TXQ but no
  TX progress being made.  Further inspection showed the TXQ looked like
  it contained multiple "lists" of frames - there'd be a list of correct
  frames, then a NULL link pointer, but there'd be a next buffer in the
  Since this code is only called upon an interface reset, it's likely
  this only began showing up when I started doing stress testing
  in environments which annoy the radios enough to cause lockups.
  I've not yet any TX stalls with this patch applied.
  PR:		kern/165866


Modified: head/sys/dev/ath/if_ath_tx.c
--- head/sys/dev/ath/if_ath_tx.c	Thu Mar  8 23:52:22 2012	(r232706)
+++ head/sys/dev/ath/if_ath_tx.c	Thu Mar  8 23:53:38 2012	(r232707)
@@ -623,19 +623,22 @@ void
 ath_txq_restart_dma(struct ath_softc *sc, struct ath_txq *txq)
 	struct ath_hal *ah = sc->sc_ah;
-	struct ath_buf *bf;
+	struct ath_buf *bf, *bf_last;
 	/* This is always going to be cleared, empty or not */
 	txq->axq_flags &= ~ATH_TXQ_PUTPENDING;
+	/* XXX make this ATH_TXQ_FIRST */
 	bf = TAILQ_FIRST(&txq->axq_q);
+	bf_last = ATH_TXQ_LAST(txq, axq_q_s);
 	if (bf == NULL)
 	ath_hal_puttxbuf(ah, txq->axq_qnum, bf->bf_daddr);
-	txq->axq_link = &bf->bf_lastds->ds_link;
+	txq->axq_link = &bf_last->bf_lastds->ds_link;
 	ath_hal_txstart(ah, txq->axq_qnum);

More information about the svn-src-head mailing list