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

Adrian Chadd adrian at FreeBSD.org
Wed Oct 26 15:20:22 UTC 2011


Author: adrian
Date: Wed Oct 26 15:20:21 2011
New Revision: 226794
URL: http://svn.freebsd.org/changeset/base/226794

Log:
  Now that I've done a quick audit and made sure that the
  calls to ath_freebuf() occur during active TX completion,
  migrate the busy flag clear logic to inside ath_freebuf().
  
  ath_freebuf() is now only called for frames which have completed
  TX somehow (success or failure), or during TX queue flush (where
  we don't care about the busy flag any longer.) It must not be called
  for frames that haven't come from the TX completion or node flush
  logic.
  
  This fixes the code to compile/run/not hang w/ the TDMA
  option in the kernel (but I haven't tested TDMA yet, unfortunately)
  as now the tail buffer on the free list has the ATH_BUF_BUSY
  flag cleared on -each- completed subframe.
  
  (Again, this isn't the correct/full fix for using multiple TX
  DMA queues, but that's a later problem to fix. It's just as broken
  in -HEAD.)

Modified:
  user/adrian/if_ath_tx/sys/dev/ath/if_ath.c
  user/adrian/if_ath_tx/sys/dev/ath/if_ath_misc.h

Modified: user/adrian/if_ath_tx/sys/dev/ath/if_ath.c
==============================================================================
--- user/adrian/if_ath_tx/sys/dev/ath/if_ath.c	Wed Oct 26 15:17:42 2011	(r226793)
+++ user/adrian/if_ath_tx/sys/dev/ath/if_ath.c	Wed Oct 26 15:20:21 2011	(r226794)
@@ -4487,7 +4487,7 @@ ath_tx_update_ratectrl(struct ath_softc 
  * This should be called in the completion function once one
  * of the buffers has been used.
  */
-void
+static void
 ath_tx_update_busy(struct ath_softc *sc)
 {
 	struct ath_buf *last;
@@ -4501,11 +4501,10 @@ ath_tx_update_busy(struct ath_softc *sc)
 	 * and is no longer referencing the previous
 	 * descriptor.
 	 */
-	ATH_TXBUF_LOCK(sc);
+	ATH_TXBUF_LOCK_ASSERT(sc);
 	last = TAILQ_LAST(&sc->sc_txbuf, ath_bufhead_s);
 	if (last != NULL)
 		last->bf_flags &= ~ATH_BUF_BUSY;
-	ATH_TXBUF_UNLOCK(sc);
 }
 
 /*
@@ -4594,13 +4593,6 @@ ath_tx_processq(struct ath_softc *sc, st
 		}
 
 		/*
-		 * Mark the last frame on the buffer list as
-		 * not busy, as the hardware has now moved past
-		 * that "free" entry and onto the next one.
-		 */
-		ath_tx_update_busy(sc);
-
-		/*
 		 * Call the completion handler.
 		 * The completion handler is responsible for
 		 * calling the rate control code.
@@ -4754,7 +4746,14 @@ ath_tx_proc(void *arg, int npending)
 #undef	TXQACTIVE
 
 /*
- * Return a buffer to the pool.
+ * Return a buffer to the pool and update the 'busy' flag on the
+ * previous 'tail' entry.
+ *
+ * This _must_ only be called when the buffer is involved in a completed
+ * TX. The logic is that if it was part of an active TX, the previous
+ * buffer on the list is now not involved in a halted TX DMA queue, waiting
+ * for restart (eg for TDMA.)
+ *
  * The caller must free the mbuf and recycle the node reference.
  */
 void
@@ -4765,7 +4764,9 @@ ath_freebuf(struct ath_softc *sc, struct
 
 	KASSERT((bf->bf_node == NULL), ("%s: bf->bf_node != NULL\n", __func__));
 	KASSERT((bf->bf_m == NULL), ("%s: bf->bf_m != NULL\n", __func__));
+
 	ATH_TXBUF_LOCK(sc);
+	ath_tx_update_busy(sc);
 	TAILQ_INSERT_TAIL(&sc->sc_txbuf, bf, bf_list);
 	ATH_TXBUF_UNLOCK(sc);
 }

Modified: user/adrian/if_ath_tx/sys/dev/ath/if_ath_misc.h
==============================================================================
--- user/adrian/if_ath_tx/sys/dev/ath/if_ath_misc.h	Wed Oct 26 15:17:42 2011	(r226793)
+++ user/adrian/if_ath_tx/sys/dev/ath/if_ath_misc.h	Wed Oct 26 15:20:21 2011	(r226794)
@@ -63,7 +63,6 @@ extern void ath_tx_default_comp(struct a
 extern void ath_tx_update_ratectrl(struct ath_softc *sc,
 	    struct ieee80211_node *ni, struct ath_rc_series *rc,
 	    struct ath_tx_status *ts, int frmlen, int nframes, int nbad);
-extern void ath_tx_update_busy(struct ath_softc *sc);
 
 extern void ath_tx_freebuf(struct ath_softc *sc, struct ath_buf *bf,
     int status);


More information about the svn-src-user mailing list