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

Adrian Chadd adrian at FreeBSD.org
Wed Aug 24 04:06:22 UTC 2011


Author: adrian
Date: Wed Aug 24 04:06:21 2011
New Revision: 225127
URL: http://svn.freebsd.org/changeset/base/225127

Log:
  * Begin fleshing out ath_buf_clone() - a method of cloning
    buffers for reuse during software retransmit
  
  * Break out the buffer reclaimation code into ath_freebuf(),
    which doesn't recycle the mbuf/node or call the net80211
    callback.
  
  * Change _ath_getbuf_locked() to use ath_freebuf(). This
    changes the order of DMA unmap and buffer free, so keep
    that in mind.
  
  The (eventual) aim of ath_freebuf() is to allow a buffer
  to be cloned, and the original buffer to then be returned.
  The caller can blank the node/mbuf and call ath_freebuf().

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 Aug 24 03:09:02 2011	(r225126)
+++ user/adrian/if_ath_tx/sys/dev/ath/if_ath.c	Wed Aug 24 04:06:21 2011	(r225127)
@@ -1895,6 +1895,61 @@ _ath_getbuf_locked(struct ath_softc *sc)
 	return bf;
 }
 
+/*
+ * When retrying a software frame, buffers marked ATH_BUF_BUSY
+ * can't be thrown back on the queue as they could still be
+ * in use by the hardware.
+ *
+ * This duplicates the buffer, or returns NULL.
+ *
+ * The descriptor is also copied but the link pointers and
+ * the DMA segments aren't copied; this frame should thus
+ * be again passed through the descriptor setup/chain routines
+ * so the link is correct.
+ *
+ * XXX TODO: the source buffer is still valid; so the mbuf
+ * XXX will be freed when that buffer is freed! The bf callback
+ * XXX will be called too, etc, etc.
+ * XXX so the caller must handle this somehow!
+ */
+struct ath_buf *
+ath_buf_clone(struct ath_softc *sc, const struct ath_buf *bf)
+{
+	struct ath_buf *tbf;
+
+	tbf = ath_getbuf(sc);
+	if (tbf == NULL)
+		return NULL;	/* XXX failure? Why? */
+
+	/* Copy basics */
+	tbf->bf_next = bf->bf_next;
+	tbf->bf_nseg = bf->bf_nseg;
+	tbf->bf_txflags = bf->bf_txflags;
+	tbf->bf_flags = bf->bf_flags;
+	tbf->bf_status = bf->bf_status;
+	tbf->bf_m = bf->bf_m;
+	tbf->bf_node = bf->bf_node;
+	/* will be setup by the chain/setup function */
+	tbf->bf_lastds = NULL;
+	/* for now, last == self */
+	tbf->bf_last = tbf;
+	tbf->bf_comp = bf->bf_comp;
+
+	/* NOTE: DMA segments will be setup by the setup/chain functions */
+
+	/*
+	 * Copy the descriptor contents - just the active
+	 * number of segments.
+	 */
+	memcpy(tbf->bf_desc, bf->bf_desc,
+	    bf->bf_nseg * sizeof(struct ath_desc));
+
+	/* Copy status */
+	memcpy(&tbf->bf_state, &bf->bf_state, sizeof(bf->bf_state));
+
+	return tbf;
+}
+
 struct ath_buf *
 ath_getbuf(struct ath_softc *sc)
 {
@@ -4515,6 +4570,22 @@ ath_tx_sched_proc_sched(struct ath_softc
 }
 
 /*
+ * Return a buffer to the pool.
+ * The caller must free the mbuf and recycle the node reference.
+ */
+void
+ath_freebuf(struct ath_softc *sc, struct ath_buf *bf)
+{
+	bus_dmamap_unload(sc->sc_dmat, bf->bf_dmamap);
+
+	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);
+	TAILQ_INSERT_TAIL(&sc->sc_txbuf, bf, bf_list);
+	ATH_TXBUF_UNLOCK(sc);
+}
+
+/*
  * This is currently used by ath_tx_draintxq() and
  * ath_tx_tid_free_pkts().
  *
@@ -4523,31 +4594,30 @@ ath_tx_sched_proc_sched(struct ath_softc
 void
 ath_tx_freebuf(struct ath_softc *sc, struct ath_buf *bf, int status)
 {
-	struct ieee80211_node *ni;
+	struct ieee80211_node *ni = bf->bf_node;
+	struct mbuf *m0 = bf->bf_m;
 
-	bus_dmamap_unload(sc->sc_dmat, bf->bf_dmamap);
-	ni = bf->bf_node;
 	bf->bf_node = NULL;
+	bf->bf_m = NULL;
+
+	/* Free the buffer, it's not needed any longer */
+	ath_freebuf(sc, bf);
+
 	if (ni != NULL) {
 		/*
 		 * Do any callback and reclaim the node reference.
 		 */
-		if (bf->bf_m->m_flags & M_TXCB)
-			ieee80211_process_callback(ni, bf->bf_m, status);
+		if (m0->m_flags & M_TXCB)
+			ieee80211_process_callback(ni, m0, status);
 		ieee80211_free_node(ni);
 	}
-	m_freem(bf->bf_m);
-	bf->bf_m = NULL;
+	m_freem(m0);
 
 	/*
-	 * XXX This is incorrect. Check what the -HEAD code is doing.
-	 * XXX The TDMA code will be broken if this isn't properly repaired.
+	 * XXX the buffer used to be freed -after-, but the DMA map was
+	 * freed where ath_freebuf() now is. I've no idea what this
+	 * will do.
 	 */
-	bf->bf_flags &= ~ATH_BUF_BUSY;
-
-	ATH_TXBUF_LOCK(sc);
-	TAILQ_INSERT_TAIL(&sc->sc_txbuf, bf, bf_list);
-	ATH_TXBUF_UNLOCK(sc);
 }
 
 void

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 Aug 24 03:09:02 2011	(r225126)
+++ user/adrian/if_ath_tx/sys/dev/ath/if_ath_misc.h	Wed Aug 24 04:06:21 2011	(r225127)
@@ -52,6 +52,9 @@ extern int ath_tx_findrix(const struct a
 
 extern struct ath_buf * ath_getbuf(struct ath_softc *sc);
 extern struct ath_buf * _ath_getbuf_locked(struct ath_softc *sc);
+extern struct ath_buf * ath_buf_clone(struct ath_softc *sc,
+	    const struct ath_buf *bf);
+extern void ath_freebuf(struct ath_softc *sc, struct ath_buf *bf);
 
 extern int ath_reset(struct ifnet *);
 extern void ath_tx_draintxq(struct ath_softc *sc, struct ath_txq *txq);


More information about the svn-src-user mailing list