From owner-svn-src-user@FreeBSD.ORG Wed Aug 24 04:06:21 2011 Return-Path: Delivered-To: svn-src-user@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id E581D106564A; Wed, 24 Aug 2011 04:06:21 +0000 (UTC) (envelope-from adrian@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id D5A848FC08; Wed, 24 Aug 2011 04:06:21 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.4/8.14.4) with ESMTP id p7O46Lwf032538; Wed, 24 Aug 2011 04:06:21 GMT (envelope-from adrian@svn.freebsd.org) Received: (from adrian@localhost) by svn.freebsd.org (8.14.4/8.14.4/Submit) id p7O46L1s032535; Wed, 24 Aug 2011 04:06:21 GMT (envelope-from adrian@svn.freebsd.org) Message-Id: <201108240406.p7O46L1s032535@svn.freebsd.org> From: Adrian Chadd Date: Wed, 24 Aug 2011 04:06:21 +0000 (UTC) To: src-committers@freebsd.org, svn-src-user@freebsd.org X-SVN-Group: user MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r225127 - user/adrian/if_ath_tx/sys/dev/ath X-BeenThere: svn-src-user@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "SVN commit messages for the experimental " user" src tree" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 24 Aug 2011 04:06:22 -0000 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);